summaryrefslogtreecommitdiff
path: root/Source/WebCore/bindings/js
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/bindings/js')
-rw-r--r--Source/WebCore/bindings/js/ArrayValue.cpp83
-rw-r--r--Source/WebCore/bindings/js/ArrayValue.h54
-rw-r--r--Source/WebCore/bindings/js/BufferSource.h64
-rw-r--r--Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp89
-rw-r--r--Source/WebCore/bindings/js/CachedModuleScriptLoader.h72
-rw-r--r--Source/WebCore/bindings/js/CachedModuleScriptLoaderClient.h41
-rw-r--r--Source/WebCore/bindings/js/CachedScriptFetcher.cpp68
-rw-r--r--Source/WebCore/bindings/js/CachedScriptFetcher.h67
-rw-r--r--Source/WebCore/bindings/js/CachedScriptSourceProvider.h24
-rw-r--r--Source/WebCore/bindings/js/CallbackFunction.cpp51
-rw-r--r--Source/WebCore/bindings/js/CallbackFunction.h58
-rw-r--r--Source/WebCore/bindings/js/CommonVM.cpp76
-rw-r--r--Source/WebCore/bindings/js/CommonVM.h (renamed from Source/WebCore/bindings/js/JSTrackEventCustom.cpp)34
-rw-r--r--Source/WebCore/bindings/js/DOMObjectHashTableMap.h59
-rw-r--r--Source/WebCore/bindings/js/DOMRequestState.h84
-rw-r--r--Source/WebCore/bindings/js/DOMWrapperWorld.cpp16
-rw-r--r--Source/WebCore/bindings/js/DOMWrapperWorld.h38
-rw-r--r--Source/WebCore/bindings/js/Dictionary.cpp106
-rw-r--r--Source/WebCore/bindings/js/Dictionary.h114
-rw-r--r--Source/WebCore/bindings/js/GCController.cpp106
-rw-r--r--Source/WebCore/bindings/js/GCController.h53
-rw-r--r--Source/WebCore/bindings/js/IDBBindingUtilities.cpp314
-rw-r--r--Source/WebCore/bindings/js/IDBBindingUtilities.h42
-rw-r--r--Source/WebCore/bindings/js/JSAnimationTimelineCustom.cpp56
-rw-r--r--Source/WebCore/bindings/js/JSAttrCustom.cpp22
-rw-r--r--Source/WebCore/bindings/js/JSAudioBufferSourceNodeCustom.cpp55
-rw-r--r--Source/WebCore/bindings/js/JSAudioContextCustom.cpp115
-rw-r--r--Source/WebCore/bindings/js/JSAudioTrackCustom.cpp45
-rw-r--r--Source/WebCore/bindings/js/JSAudioTrackListCustom.cpp17
-rw-r--r--Source/WebCore/bindings/js/JSBindingsAllInOne.cpp127
-rw-r--r--Source/WebCore/bindings/js/JSBiquadFilterNodeCustom.cpp63
-rw-r--r--Source/WebCore/bindings/js/JSBlobCustom.cpp101
-rw-r--r--Source/WebCore/bindings/js/JSCSSRuleCustom.cpp106
-rw-r--r--Source/WebCore/bindings/js/JSCSSRuleCustom.h9
-rw-r--r--Source/WebCore/bindings/js/JSCSSRuleListCustom.cpp10
-rw-r--r--Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp275
-rw-r--r--Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.h22
-rw-r--r--Source/WebCore/bindings/js/JSCSSValueCustom.cpp88
-rw-r--r--Source/WebCore/bindings/js/JSCallbackData.cpp69
-rw-r--r--Source/WebCore/bindings/js/JSCallbackData.h85
-rw-r--r--Source/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp82
-rw-r--r--Source/WebCore/bindings/js/JSCanvasRenderingContextCustom.cpp66
-rw-r--r--Source/WebCore/bindings/js/JSClipboardCustom.cpp44
-rw-r--r--Source/WebCore/bindings/js/JSCommandLineAPIHostCustom.cpp100
-rw-r--r--Source/WebCore/bindings/js/JSCryptoAlgorithmBuilder.cpp82
-rw-r--r--Source/WebCore/bindings/js/JSCryptoAlgorithmBuilder.h62
-rw-r--r--Source/WebCore/bindings/js/JSCryptoAlgorithmDictionary.cpp668
-rw-r--r--Source/WebCore/bindings/js/JSCryptoAlgorithmDictionary.h61
-rw-r--r--Source/WebCore/bindings/js/JSCryptoCustom.cpp29
-rw-r--r--Source/WebCore/bindings/js/JSCryptoKeyCustom.cpp91
-rw-r--r--Source/WebCore/bindings/js/JSCryptoKeySerializationJWK.cpp771
-rw-r--r--Source/WebCore/bindings/js/JSCryptoKeySerializationJWK.h73
-rw-r--r--Source/WebCore/bindings/js/JSCryptoOperationData.cpp53
-rw-r--r--Source/WebCore/bindings/js/JSCryptoOperationData.h44
-rw-r--r--Source/WebCore/bindings/js/JSCustomElementInterface.cpp315
-rw-r--r--Source/WebCore/bindings/js/JSCustomElementInterface.h111
-rw-r--r--Source/WebCore/bindings/js/JSCustomElementRegistryCustom.cpp216
-rw-r--r--Source/WebCore/bindings/js/JSCustomEventCustom.cpp (renamed from Source/WebCore/bindings/js/JSRTCStatsResponseCustom.cpp)41
-rw-r--r--Source/WebCore/bindings/js/JSCustomXPathNSResolver.cpp54
-rw-r--r--Source/WebCore/bindings/js/JSCustomXPathNSResolver.h45
-rw-r--r--Source/WebCore/bindings/js/JSDOMBinding.cpp536
-rw-r--r--Source/WebCore/bindings/js/JSDOMBinding.h661
-rw-r--r--Source/WebCore/bindings/js/JSDOMBindingCaller.h102
-rw-r--r--Source/WebCore/bindings/js/JSDOMBindingSecurity.cpp102
-rw-r--r--Source/WebCore/bindings/js/JSDOMBindingSecurity.h82
-rw-r--r--Source/WebCore/bindings/js/JSDOMBuiltinConstructor.h131
-rw-r--r--Source/WebCore/bindings/js/JSDOMBuiltinConstructorBase.cpp51
-rw-r--r--Source/WebCore/bindings/js/JSDOMBuiltinConstructorBase.h58
-rw-r--r--Source/WebCore/bindings/js/JSDOMConstructor.h79
-rw-r--r--Source/WebCore/bindings/js/JSDOMConstructorBase.cpp (renamed from Source/WebCore/bindings/js/JSDOMPluginCustom.cpp)28
-rw-r--r--Source/WebCore/bindings/js/JSDOMConstructorBase.h54
-rw-r--r--Source/WebCore/bindings/js/JSDOMConstructorNotConstructable.h84
-rw-r--r--Source/WebCore/bindings/js/JSDOMConstructorWithDocument.cpp (renamed from Source/WebCore/bindings/js/DOMObjectHashTableMap.cpp)16
-rw-r--r--Source/WebCore/bindings/js/JSDOMConstructorWithDocument.h (renamed from Source/WebCore/bindings/js/DOMConstructorWithDocument.h)28
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvert.h49
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertAny.h62
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertBase.h183
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertBoolean.h50
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertBufferSource.h122
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertCallbacks.h100
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertDate.cpp49
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertDate.h54
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertDictionary.h56
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertEnumeration.h59
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertEventListener.h48
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertIndexedDB.h71
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertInterface.h79
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertJSON.h51
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertNull.h50
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertNullable.h162
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertNumbers.cpp348
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertNumbers.h424
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertObject.h49
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertRecord.h166
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertSequences.h317
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertSerializedScriptValue.h50
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertStrings.cpp114
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertStrings.h119
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertUnion.h286
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertVariadic.h99
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertWebGL.h47
-rw-r--r--Source/WebCore/bindings/js/JSDOMConvertXPathNSResolver.h66
-rw-r--r--Source/WebCore/bindings/js/JSDOMExceptionHandling.cpp404
-rw-r--r--Source/WebCore/bindings/js/JSDOMExceptionHandling.h105
-rw-r--r--Source/WebCore/bindings/js/JSDOMFormDataCustom.cpp77
-rw-r--r--Source/WebCore/bindings/js/JSDOMGlobalObject.cpp183
-rw-r--r--Source/WebCore/bindings/js/JSDOMGlobalObject.h62
-rw-r--r--Source/WebCore/bindings/js/JSDOMGlobalObjectTask.cpp41
-rw-r--r--Source/WebCore/bindings/js/JSDOMGlobalObjectTask.h23
-rw-r--r--Source/WebCore/bindings/js/JSDOMIterator.cpp56
-rw-r--r--Source/WebCore/bindings/js/JSDOMIterator.h266
-rw-r--r--Source/WebCore/bindings/js/JSDOMMimeTypeArrayCustom.cpp44
-rw-r--r--Source/WebCore/bindings/js/JSDOMNamedConstructor.h79
-rw-r--r--Source/WebCore/bindings/js/JSDOMPluginArrayCustom.cpp42
-rw-r--r--Source/WebCore/bindings/js/JSDOMPromise.cpp189
-rw-r--r--Source/WebCore/bindings/js/JSDOMPromise.h270
-rw-r--r--Source/WebCore/bindings/js/JSDOMStringMapCustom.cpp67
-rw-r--r--Source/WebCore/bindings/js/JSDOMWindowBase.cpp335
-rw-r--r--Source/WebCore/bindings/js/JSDOMWindowBase.h45
-rw-r--r--Source/WebCore/bindings/js/JSDOMWindowCustom.cpp821
-rw-r--r--Source/WebCore/bindings/js/JSDOMWindowCustom.h7
-rw-r--r--Source/WebCore/bindings/js/JSDOMWindowProperties.cpp103
-rw-r--r--Source/WebCore/bindings/js/JSDOMWindowProperties.h61
-rw-r--r--Source/WebCore/bindings/js/JSDOMWindowShell.cpp41
-rw-r--r--Source/WebCore/bindings/js/JSDOMWindowShell.h24
-rw-r--r--Source/WebCore/bindings/js/JSDOMWrapper.cpp22
-rw-r--r--Source/WebCore/bindings/js/JSDOMWrapper.h84
-rw-r--r--Source/WebCore/bindings/js/JSDOMWrapperCache.cpp45
-rw-r--r--Source/WebCore/bindings/js/JSDOMWrapperCache.h206
-rw-r--r--Source/WebCore/bindings/js/JSDedicatedWorkerGlobalScopeCustom.cpp47
-rw-r--r--Source/WebCore/bindings/js/JSDeviceMotionEventCustom.cpp195
-rw-r--r--Source/WebCore/bindings/js/JSDeviceOrientationEventCustom.cpp121
-rw-r--r--Source/WebCore/bindings/js/JSDictionary.cpp279
-rw-r--r--Source/WebCore/bindings/js/JSDictionary.h193
-rw-r--r--Source/WebCore/bindings/js/JSDocumentCustom.cpp160
-rw-r--r--Source/WebCore/bindings/js/JSDocumentCustom.h (renamed from Source/WebCore/bindings/js/JSHTMLMediaElementCustom.cpp)27
-rw-r--r--Source/WebCore/bindings/js/JSDocumentFragmentCustom.cpp48
-rw-r--r--Source/WebCore/bindings/js/JSDynamicDowncast.h110
-rw-r--r--Source/WebCore/bindings/js/JSElementCustom.cpp41
-rw-r--r--Source/WebCore/bindings/js/JSElementCustom.h39
-rw-r--r--Source/WebCore/bindings/js/JSErrorHandler.cpp35
-rw-r--r--Source/WebCore/bindings/js/JSErrorHandler.h17
-rw-r--r--Source/WebCore/bindings/js/JSEventCustom.cpp34
-rw-r--r--Source/WebCore/bindings/js/JSEventCustom.h (renamed from Source/WebCore/bindings/js/ScriptProfileNode.h)20
-rw-r--r--Source/WebCore/bindings/js/JSEventListener.cpp172
-rw-r--r--Source/WebCore/bindings/js/JSEventListener.h172
-rw-r--r--Source/WebCore/bindings/js/JSEventTargetCustom.cpp44
-rw-r--r--Source/WebCore/bindings/js/JSEventTargetCustom.h78
-rw-r--r--Source/WebCore/bindings/js/JSExceptionBase.cpp29
-rw-r--r--Source/WebCore/bindings/js/JSExceptionBase.h12
-rw-r--r--Source/WebCore/bindings/js/JSFileReaderCustom.cpp55
-rw-r--r--Source/WebCore/bindings/js/JSFontFaceCustom.cpp56
-rw-r--r--Source/WebCore/bindings/js/JSFontFaceSetCustom.cpp44
-rw-r--r--Source/WebCore/bindings/js/JSGeolocationCustom.cpp145
-rw-r--r--Source/WebCore/bindings/js/JSHTMLAllCollectionCustom.cpp79
-rw-r--r--Source/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp8
-rw-r--r--Source/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp134
-rw-r--r--Source/WebCore/bindings/js/JSHTMLCollectionCustom.cpp46
-rw-r--r--Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp180
-rw-r--r--Source/WebCore/bindings/js/JSHTMLElementCustom.cpp95
-rw-r--r--Source/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp8
-rw-r--r--Source/WebCore/bindings/js/JSHTMLFormControlsCollectionCustom.cpp49
-rw-r--r--Source/WebCore/bindings/js/JSHTMLFormElementCustom.cpp62
-rw-r--r--Source/WebCore/bindings/js/JSHTMLFrameElementCustom.cpp65
-rw-r--r--Source/WebCore/bindings/js/JSHTMLFrameSetElementCustom.cpp31
-rw-r--r--Source/WebCore/bindings/js/JSHTMLInputElementCustom.cpp106
-rw-r--r--Source/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp8
-rw-r--r--Source/WebCore/bindings/js/JSHTMLOptionsCollectionCustom.cpp59
-rw-r--r--Source/WebCore/bindings/js/JSHTMLSelectElementCustom.cpp43
-rw-r--r--Source/WebCore/bindings/js/JSHTMLSelectElementCustom.h16
-rw-r--r--Source/WebCore/bindings/js/JSHTMLTemplateElementCustom.cpp16
-rw-r--r--Source/WebCore/bindings/js/JSHistoryCustom.cpp170
-rw-r--r--Source/WebCore/bindings/js/JSIDBAnyCustom.cpp115
-rw-r--r--Source/WebCore/bindings/js/JSIDBCursorCustom.cpp59
-rw-r--r--Source/WebCore/bindings/js/JSIDBCursorWithValueCustom.cpp (renamed from Source/WebCore/bindings/js/JSRequestAnimationFrameCallbackCustom.cpp)28
-rw-r--r--Source/WebCore/bindings/js/JSIDBDatabaseCustom.cpp85
-rw-r--r--Source/WebCore/bindings/js/JSIDBIndexCustom.cpp45
-rw-r--r--Source/WebCore/bindings/js/JSIDBObjectStoreCustom.cpp46
-rw-r--r--Source/WebCore/bindings/js/JSIDBTransactionCustom.cpp (renamed from Source/WebCore/bindings/js/JSHTMLLinkElementCustom.cpp)19
-rw-r--r--Source/WebCore/bindings/js/JSImageConstructor.cpp83
-rw-r--r--Source/WebCore/bindings/js/JSImageConstructor.h55
-rw-r--r--Source/WebCore/bindings/js/JSImageDataCustom.cpp30
-rw-r--r--Source/WebCore/bindings/js/JSInspectorFrontendHostCustom.cpp102
-rw-r--r--Source/WebCore/bindings/js/JSLazyEventListener.cpp112
-rw-r--r--Source/WebCore/bindings/js/JSLazyEventListener.h56
-rw-r--r--Source/WebCore/bindings/js/JSLocationCustom.cpp228
-rw-r--r--Source/WebCore/bindings/js/JSMainThreadExecState.cpp26
-rw-r--r--Source/WebCore/bindings/js/JSMainThreadExecState.h91
-rw-r--r--Source/WebCore/bindings/js/JSMainThreadExecStateInstrumentation.h24
-rw-r--r--Source/WebCore/bindings/js/JSMediaKeySessionCustom.cpp49
-rw-r--r--Source/WebCore/bindings/js/JSMediaListCustom.h9
-rw-r--r--Source/WebCore/bindings/js/JSMediaSourceStatesCustom.cpp92
-rw-r--r--Source/WebCore/bindings/js/JSMediaStreamCapabilitiesCustom.cpp21
-rw-r--r--Source/WebCore/bindings/js/JSMessageChannelCustom.cpp19
-rw-r--r--Source/WebCore/bindings/js/JSMessageEventCustom.cpp110
-rw-r--r--Source/WebCore/bindings/js/JSMessagePortCustom.cpp78
-rw-r--r--Source/WebCore/bindings/js/JSMessagePortCustom.h66
-rw-r--r--Source/WebCore/bindings/js/JSMockContentFilterSettingsCustom.cpp147
-rw-r--r--Source/WebCore/bindings/js/JSMutationCallback.cpp17
-rw-r--r--Source/WebCore/bindings/js/JSMutationCallback.h16
-rw-r--r--Source/WebCore/bindings/js/JSMutationObserverCustom.cpp32
-rw-r--r--Source/WebCore/bindings/js/JSNamedNodeMapCustom.cpp49
-rw-r--r--Source/WebCore/bindings/js/JSNodeCustom.cpp246
-rw-r--r--Source/WebCore/bindings/js/JSNodeCustom.h46
-rw-r--r--Source/WebCore/bindings/js/JSNodeFilterCondition.cpp86
-rw-r--r--Source/WebCore/bindings/js/JSNodeFilterCondition.h56
-rw-r--r--Source/WebCore/bindings/js/JSNodeFilterCustom.cpp75
-rw-r--r--Source/WebCore/bindings/js/JSNodeIteratorCustom.cpp16
-rw-r--r--Source/WebCore/bindings/js/JSNodeListCustom.cpp34
-rw-r--r--Source/WebCore/bindings/js/JSNodeListCustom.h42
-rw-r--r--Source/WebCore/bindings/js/JSOscillatorNodeCustom.cpp65
-rw-r--r--Source/WebCore/bindings/js/JSPannerNodeCustom.cpp89
-rw-r--r--Source/WebCore/bindings/js/JSPerformanceEntryCustom.cpp30
-rw-r--r--Source/WebCore/bindings/js/JSPluginElementFunctions.cpp84
-rw-r--r--Source/WebCore/bindings/js/JSPluginElementFunctions.h18
-rw-r--r--Source/WebCore/bindings/js/JSPopStateEventCustom.cpp51
-rw-r--r--Source/WebCore/bindings/js/JSRTCIceCandidateCustom.cpp70
-rw-r--r--Source/WebCore/bindings/js/JSRTCPeerConnectionCustom.cpp83
-rw-r--r--Source/WebCore/bindings/js/JSRTCSessionDescriptionCustom.cpp70
-rw-r--r--Source/WebCore/bindings/js/JSReadableStreamPrivateConstructors.cpp129
-rw-r--r--Source/WebCore/bindings/js/JSReadableStreamPrivateConstructors.h (renamed from Source/WebCore/bindings/js/JSDOMStringListCustom.cpp)33
-rw-r--r--Source/WebCore/bindings/js/JSReadableStreamSourceCustom.cpp85
-rw-r--r--Source/WebCore/bindings/js/JSSQLResultSetRowListCustom.cpp87
-rw-r--r--Source/WebCore/bindings/js/JSSQLStatementErrorCallbackCustom.cpp (renamed from Source/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp)19
-rw-r--r--Source/WebCore/bindings/js/JSSQLTransactionCustom.cpp122
-rw-r--r--Source/WebCore/bindings/js/JSSQLTransactionSyncCustom.cpp99
-rw-r--r--Source/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp52
-rw-r--r--Source/WebCore/bindings/js/JSSVGLengthCustom.cpp104
-rw-r--r--Source/WebCore/bindings/js/JSSVGPathSegCustom.cpp55
-rw-r--r--Source/WebCore/bindings/js/JSSharedWorkerCustom.cpp89
-rw-r--r--Source/WebCore/bindings/js/JSStorageCustom.cpp108
-rw-r--r--Source/WebCore/bindings/js/JSStyleSheetCustom.cpp37
-rw-r--r--Source/WebCore/bindings/js/JSStyleSheetCustom.h9
-rw-r--r--Source/WebCore/bindings/js/JSStyleSheetListCustom.cpp51
-rw-r--r--Source/WebCore/bindings/js/JSSubtleCryptoCustom.cpp1113
-rw-r--r--Source/WebCore/bindings/js/JSTextCustom.cpp42
-rw-r--r--Source/WebCore/bindings/js/JSTextTrackCueCustom.cpp48
-rw-r--r--Source/WebCore/bindings/js/JSTextTrackCustom.cpp46
-rw-r--r--Source/WebCore/bindings/js/JSTextTrackListCustom.cpp17
-rw-r--r--Source/WebCore/bindings/js/JSTouchCustom.cpp50
-rw-r--r--Source/WebCore/bindings/js/JSTouchListCustom.cpp50
-rw-r--r--Source/WebCore/bindings/js/JSTrackCustom.cpp45
-rw-r--r--Source/WebCore/bindings/js/JSTrackCustom.h15
-rw-r--r--Source/WebCore/bindings/js/JSTreeWalkerCustom.cpp16
-rw-r--r--Source/WebCore/bindings/js/JSUserMessageHandlersNamespaceCustom.cpp51
-rw-r--r--Source/WebCore/bindings/js/JSVideoTrackCustom.cpp45
-rw-r--r--Source/WebCore/bindings/js/JSVideoTrackListCustom.cpp18
-rw-r--r--Source/WebCore/bindings/js/JSWebGL2RenderingContextCustom.cpp (renamed from Source/WebCore/bindings/js/JSCDATASectionCustom.cpp)19
-rw-r--r--Source/WebCore/bindings/js/JSWebGLRenderingContextBaseCustom.cpp206
-rw-r--r--Source/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp727
-rw-r--r--Source/WebCore/bindings/js/JSWebKitPointCustom.cpp52
-rw-r--r--Source/WebCore/bindings/js/JSWebKitSubtleCryptoCustom.cpp705
-rw-r--r--Source/WebCore/bindings/js/JSWorkerCustom.cpp43
-rw-r--r--Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp109
-rw-r--r--Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.h43
-rw-r--r--Source/WebCore/bindings/js/JSWorkerGlobalScopeCustom.cpp98
-rw-r--r--Source/WebCore/bindings/js/JSXMLDocumentCustom.cpp52
-rw-r--r--Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp219
-rw-r--r--Source/WebCore/bindings/js/JSXPathNSResolverCustom.cpp50
-rw-r--r--Source/WebCore/bindings/js/JSXPathResultCustom.cpp24
-rw-r--r--Source/WebCore/bindings/js/JSXSLTProcessorCustom.cpp82
-rw-r--r--Source/WebCore/bindings/js/ModuleFetchFailureKind.h36
-rw-r--r--Source/WebCore/bindings/js/PageScriptDebugServer.cpp273
-rw-r--r--Source/WebCore/bindings/js/PageScriptDebugServer.h82
-rw-r--r--Source/WebCore/bindings/js/ReadableStreamDefaultController.cpp96
-rw-r--r--Source/WebCore/bindings/js/ReadableStreamDefaultController.h119
-rw-r--r--Source/WebCore/bindings/js/ScheduledAction.cpp66
-rw-r--r--Source/WebCore/bindings/js/ScheduledAction.h19
-rw-r--r--Source/WebCore/bindings/js/ScriptCachedFrameData.cpp48
-rw-r--r--Source/WebCore/bindings/js/ScriptCachedFrameData.h5
-rw-r--r--Source/WebCore/bindings/js/ScriptCallStackFactory.cpp209
-rw-r--r--Source/WebCore/bindings/js/ScriptCallStackFactory.h56
-rw-r--r--Source/WebCore/bindings/js/ScriptController.cpp444
-rw-r--r--Source/WebCore/bindings/js/ScriptController.h107
-rw-r--r--Source/WebCore/bindings/js/ScriptGlobalObject.cpp65
-rw-r--r--Source/WebCore/bindings/js/ScriptGlobalObject.h20
-rw-r--r--Source/WebCore/bindings/js/ScriptHeapSnapshot.h64
-rw-r--r--Source/WebCore/bindings/js/ScriptModuleLoader.cpp294
-rw-r--r--Source/WebCore/bindings/js/ScriptModuleLoader.h71
-rw-r--r--Source/WebCore/bindings/js/ScriptProfile.cpp107
-rw-r--r--Source/WebCore/bindings/js/ScriptProfile.h70
-rw-r--r--Source/WebCore/bindings/js/ScriptProfiler.cpp92
-rw-r--r--Source/WebCore/bindings/js/ScriptProfiler.h75
-rw-r--r--Source/WebCore/bindings/js/ScriptSourceCode.h35
-rw-r--r--Source/WebCore/bindings/js/ScriptState.cpp29
-rw-r--r--Source/WebCore/bindings/js/ScriptState.h15
-rw-r--r--Source/WebCore/bindings/js/ScriptWrappable.h21
-rw-r--r--Source/WebCore/bindings/js/ScriptWrappableInlines.h13
-rw-r--r--Source/WebCore/bindings/js/SerializedScriptValue.cpp1110
-rw-r--r--Source/WebCore/bindings/js/SerializedScriptValue.h111
-rw-r--r--Source/WebCore/bindings/js/StructuredClone.cpp97
-rw-r--r--Source/WebCore/bindings/js/StructuredClone.h (renamed from Source/WebCore/bindings/js/JSHTMLInputElementCustom.h)18
-rw-r--r--Source/WebCore/bindings/js/WebCoreBuiltinNames.h138
-rw-r--r--Source/WebCore/bindings/js/WebCoreJSClientData.cpp117
-rw-r--r--Source/WebCore/bindings/js/WebCoreJSClientData.h66
-rw-r--r--Source/WebCore/bindings/js/WebCoreTypedArrayController.cpp24
-rw-r--r--Source/WebCore/bindings/js/WebCoreTypedArrayController.h21
-rw-r--r--Source/WebCore/bindings/js/WorkerScriptController.cpp127
-rw-r--r--Source/WebCore/bindings/js/WorkerScriptController.h37
-rw-r--r--Source/WebCore/bindings/js/WorkerScriptDebugServer.cpp111
-rw-r--r--Source/WebCore/bindings/js/WorkerScriptDebugServer.h68
301 files changed, 18384 insertions, 12704 deletions
diff --git a/Source/WebCore/bindings/js/ArrayValue.cpp b/Source/WebCore/bindings/js/ArrayValue.cpp
deleted file mode 100644
index e810f435e..000000000
--- a/Source/WebCore/bindings/js/ArrayValue.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "ArrayValue.h"
-
-#include "Dictionary.h"
-#include <runtime/JSArray.h>
-
-using namespace JSC;
-
-namespace WebCore {
-
-ArrayValue::ArrayValue()
- : m_exec(0)
-{
-}
-
-ArrayValue::ArrayValue(JSC::ExecState* exec, JSC::JSValue value)
- : m_exec(exec)
-{
- if (!value.isUndefinedOrNull() && isJSArray(value))
- m_value = value;
-}
-
-ArrayValue& ArrayValue::operator=(const ArrayValue& other)
-{
- m_exec = other.m_exec;
- m_value = other.m_value;
- return *this;
-}
-
-bool ArrayValue::isUndefinedOrNull() const
-{
- return m_value.isEmpty() || m_value.isUndefinedOrNull();
-}
-
-bool ArrayValue::length(size_t& length) const
-{
- if (isUndefinedOrNull())
- return false;
-
- JSArray* array = asArray(m_value);
- length = array->length();
- return true;
-}
-
-bool ArrayValue::get(size_t index, Dictionary& value) const
-{
- if (isUndefinedOrNull())
- return false;
-
- JSValue indexedValue = asArray(m_value)->getIndex(m_exec, index);
- if (indexedValue.isUndefinedOrNull() || !indexedValue.isObject())
- return false;
-
- value = Dictionary(m_exec, indexedValue);
- return true;
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/ArrayValue.h b/Source/WebCore/bindings/js/ArrayValue.h
deleted file mode 100644
index 084f8c3cf..000000000
--- a/Source/WebCore/bindings/js/ArrayValue.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (C) 2012 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef ArrayValue_h
-#define ArrayValue_h
-
-#include <interpreter/CallFrame.h>
-
-namespace WebCore {
-
-class Dictionary;
-
-class ArrayValue {
-public:
- ArrayValue();
- ArrayValue(JSC::ExecState*, JSC::JSValue);
-
- ArrayValue& operator=(const ArrayValue&);
-
- bool isUndefinedOrNull() const;
-
- bool length(size_t&) const;
- bool get(size_t index, Dictionary&) const;
-
-private:
- JSC::ExecState* m_exec;
- JSC::JSValue m_value;
-};
-
-}
-
-#endif // ArrayValue_h
diff --git a/Source/WebCore/bindings/js/BufferSource.h b/Source/WebCore/bindings/js/BufferSource.h
new file mode 100644
index 000000000..01e458418
--- /dev/null
+++ b/Source/WebCore/bindings/js/BufferSource.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <runtime/ArrayBuffer.h>
+#include <runtime/ArrayBufferView.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Variant.h>
+
+namespace WebCore {
+
+class BufferSource {
+public:
+ using VariantType = WTF::Variant<RefPtr<JSC::ArrayBufferView>, RefPtr<JSC::ArrayBuffer>>;
+
+ BufferSource() { }
+ BufferSource(VariantType&& variant)
+ : m_variant(WTFMove(variant))
+ { }
+
+ const VariantType& variant() const { return m_variant; }
+
+ const uint8_t* data() const
+ {
+ return WTF::visit([](auto& buffer) -> const uint8_t* {
+ return static_cast<const uint8_t*>(buffer->data());
+ }, m_variant);
+ }
+
+ size_t length() const
+ {
+ return WTF::visit([](auto& buffer) -> size_t {
+ return buffer->byteLength();
+ }, m_variant);
+ }
+
+private:
+ VariantType m_variant;
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp b/Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp
new file mode 100644
index 000000000..f15a4642e
--- /dev/null
+++ b/Source/WebCore/bindings/js/CachedModuleScriptLoader.cpp
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CachedModuleScriptLoader.h"
+
+#include "CachedScript.h"
+#include "CachedScriptFetcher.h"
+#include "DOMWrapperWorld.h"
+#include "Frame.h"
+#include "JSDOMBinding.h"
+#include "ResourceLoaderOptions.h"
+#include "ScriptController.h"
+#include "ScriptModuleLoader.h"
+#include "ScriptSourceCode.h"
+
+namespace WebCore {
+
+Ref<CachedModuleScriptLoader> CachedModuleScriptLoader::create(CachedModuleScriptLoaderClient& client, DeferredPromise& promise, CachedScriptFetcher& scriptFetcher)
+{
+ return adoptRef(*new CachedModuleScriptLoader(client, promise, scriptFetcher));
+}
+
+CachedModuleScriptLoader::CachedModuleScriptLoader(CachedModuleScriptLoaderClient& client, DeferredPromise& promise, CachedScriptFetcher& scriptFetcher)
+ : m_client(&client)
+ , m_promise(&promise)
+ , m_scriptFetcher(scriptFetcher)
+{
+}
+
+CachedModuleScriptLoader::~CachedModuleScriptLoader()
+{
+ if (m_cachedScript) {
+ m_cachedScript->removeClient(*this);
+ m_cachedScript = nullptr;
+ }
+}
+
+bool CachedModuleScriptLoader::load(Document& document, const URL& sourceURL)
+{
+ ASSERT(!m_cachedScript);
+ m_cachedScript = m_scriptFetcher->requestModuleScript(document, sourceURL);
+ if (!m_cachedScript)
+ return false;
+
+ // If the content is already cached, this immediately calls notifyFinished.
+ m_cachedScript->addClient(*this);
+ return true;
+}
+
+void CachedModuleScriptLoader::notifyFinished(CachedResource& resource)
+{
+ ASSERT_UNUSED(resource, &resource == m_cachedScript);
+ ASSERT(m_cachedScript);
+ ASSERT(m_promise);
+
+ Ref<CachedModuleScriptLoader> protectedThis(*this);
+ if (m_client)
+ m_client->notifyFinished(*this, WTFMove(m_promise));
+
+ // Remove the client after calling notifyFinished to keep the data buffer in
+ // CachedResource alive while notifyFinished processes the resource.
+ m_cachedScript->removeClient(*this);
+ m_cachedScript = nullptr;
+}
+
+}
diff --git a/Source/WebCore/bindings/js/CachedModuleScriptLoader.h b/Source/WebCore/bindings/js/CachedModuleScriptLoader.h
new file mode 100644
index 000000000..04923f4dc
--- /dev/null
+++ b/Source/WebCore/bindings/js/CachedModuleScriptLoader.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015, 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "CachedResourceClient.h"
+#include "CachedResourceHandle.h"
+#include <wtf/Ref.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class CachedModuleScriptLoaderClient;
+class CachedScript;
+class CachedScriptFetcher;
+class DeferredPromise;
+class Document;
+class JSDOMGlobalObject;
+class URL;
+
+class CachedModuleScriptLoader final : public RefCounted<CachedModuleScriptLoader>, private CachedResourceClient {
+public:
+ static Ref<CachedModuleScriptLoader> create(CachedModuleScriptLoaderClient&, DeferredPromise&, CachedScriptFetcher&);
+
+ virtual ~CachedModuleScriptLoader();
+
+ bool load(Document&, const URL& sourceURL);
+
+ CachedScriptFetcher& scriptFetcher() { return m_scriptFetcher.get(); }
+ CachedScript* cachedScript() { return m_cachedScript.get(); }
+
+ void clearClient()
+ {
+ ASSERT(m_client);
+ m_client = nullptr;
+ }
+
+private:
+ CachedModuleScriptLoader(CachedModuleScriptLoaderClient&, DeferredPromise&, CachedScriptFetcher&);
+
+ void notifyFinished(CachedResource&) final;
+
+ CachedModuleScriptLoaderClient* m_client { nullptr };
+ RefPtr<DeferredPromise> m_promise;
+ Ref<CachedScriptFetcher> m_scriptFetcher;
+ CachedResourceHandle<CachedScript> m_cachedScript;
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/CachedModuleScriptLoaderClient.h b/Source/WebCore/bindings/js/CachedModuleScriptLoaderClient.h
new file mode 100644
index 000000000..6ccdbccca
--- /dev/null
+++ b/Source/WebCore/bindings/js/CachedModuleScriptLoaderClient.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2016 Apple, Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "JSDOMPromise.h"
+
+namespace WebCore {
+
+class CachedModuleScriptLoader;
+
+class CachedModuleScriptLoaderClient {
+public:
+ virtual ~CachedModuleScriptLoaderClient() { }
+
+ virtual void notifyFinished(CachedModuleScriptLoader&, RefPtr<DeferredPromise>) = 0;
+};
+
+}
diff --git a/Source/WebCore/bindings/js/CachedScriptFetcher.cpp b/Source/WebCore/bindings/js/CachedScriptFetcher.cpp
new file mode 100644
index 000000000..e54f78513
--- /dev/null
+++ b/Source/WebCore/bindings/js/CachedScriptFetcher.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CachedScriptFetcher.h"
+
+#include "CachedResourceLoader.h"
+#include "CachedScript.h"
+#include "ContentSecurityPolicy.h"
+#include "Document.h"
+#include "Settings.h"
+
+namespace WebCore {
+
+Ref<CachedScriptFetcher> CachedScriptFetcher::create(const String& charset)
+{
+ return adoptRef(*new CachedScriptFetcher(charset));
+}
+
+CachedResourceHandle<CachedScript> CachedScriptFetcher::requestModuleScript(Document& document, const URL& sourceURL) const
+{
+ return requestScriptWithCache(document, sourceURL, String());
+}
+
+CachedResourceHandle<CachedScript> CachedScriptFetcher::requestScriptWithCache(Document& document, const URL& sourceURL, const String& crossOriginMode) const
+{
+ if (!document.settings().isScriptEnabled())
+ return nullptr;
+
+ ASSERT(document.contentSecurityPolicy());
+ bool hasKnownNonce = document.contentSecurityPolicy()->allowScriptWithNonce(m_nonce, m_isInUserAgentShadowTree);
+ ResourceLoaderOptions options = CachedResourceLoader::defaultCachedResourceOptions();
+ options.contentSecurityPolicyImposition = hasKnownNonce ? ContentSecurityPolicyImposition::SkipPolicyCheck : ContentSecurityPolicyImposition::DoPolicyCheck;
+
+ CachedResourceRequest request(ResourceRequest(sourceURL), options);
+ request.setAsPotentiallyCrossOrigin(crossOriginMode, document);
+ request.upgradeInsecureRequestIfNeeded(document);
+
+ request.setCharset(m_charset);
+ if (!m_initiatorName.isNull())
+ request.setInitiator(m_initiatorName);
+
+ return document.cachedResourceLoader().requestScript(WTFMove(request));
+}
+
+}
diff --git a/Source/WebCore/bindings/js/CachedScriptFetcher.h b/Source/WebCore/bindings/js/CachedScriptFetcher.h
new file mode 100644
index 000000000..a1a82ce81
--- /dev/null
+++ b/Source/WebCore/bindings/js/CachedScriptFetcher.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "CachedResourceHandle.h"
+#include <runtime/ScriptFetcher.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class CachedScript;
+class Document;
+class URL;
+
+class CachedScriptFetcher : public JSC::ScriptFetcher {
+public:
+ virtual CachedResourceHandle<CachedScript> requestModuleScript(Document&, const URL& sourceURL) const;
+
+ static Ref<CachedScriptFetcher> create(const String& charset);
+
+protected:
+ CachedScriptFetcher(const String& nonce, const String& charset, const AtomicString& initiatorName, bool isInUserAgentShadowTree)
+ : m_nonce(nonce)
+ , m_charset(charset)
+ , m_initiatorName(initiatorName)
+ , m_isInUserAgentShadowTree(isInUserAgentShadowTree)
+ {
+ }
+
+ CachedScriptFetcher(const String& charset)
+ : m_charset(charset)
+ {
+ }
+
+ CachedResourceHandle<CachedScript> requestScriptWithCache(Document&, const URL& sourceURL, const String& crossOriginMode) const;
+
+private:
+ String m_nonce;
+ String m_charset;
+ AtomicString m_initiatorName;
+ bool m_isInUserAgentShadowTree { false };
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/CachedScriptSourceProvider.h b/Source/WebCore/bindings/js/CachedScriptSourceProvider.h
index b95fdc8ee..47494e7a6 100644
--- a/Source/WebCore/bindings/js/CachedScriptSourceProvider.h
+++ b/Source/WebCore/bindings/js/CachedScriptSourceProvider.h
@@ -23,12 +23,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef CachedScriptSourceProvider_h
-#define CachedScriptSourceProvider_h
+#pragma once
#include "CachedResourceClient.h"
#include "CachedResourceHandle.h"
#include "CachedScript.h"
+#include "CachedScriptFetcher.h"
#include <parser/SourceCode.h>
#include <parser/SourceProvider.h>
@@ -37,31 +37,25 @@ namespace WebCore {
class CachedScriptSourceProvider : public JSC::SourceProvider, public CachedResourceClient {
WTF_MAKE_FAST_ALLOCATED;
public:
- static PassRefPtr<CachedScriptSourceProvider> create(CachedScript* cachedScript) { return adoptRef(new CachedScriptSourceProvider(cachedScript)); }
+ static Ref<CachedScriptSourceProvider> create(CachedScript* cachedScript, JSC::SourceProviderSourceType sourceType, Ref<CachedScriptFetcher>&& scriptFetcher) { return adoptRef(*new CachedScriptSourceProvider(cachedScript, sourceType, WTFMove(scriptFetcher))); }
virtual ~CachedScriptSourceProvider()
{
- m_cachedScript->removeClient(this);
+ m_cachedScript->removeClient(*this);
}
- const String& source() const { return m_cachedScript->script(); }
+ unsigned hash() const override { return m_cachedScript->scriptHash(); }
+ StringView source() const override { return m_cachedScript->script(); }
private:
- CachedScriptSourceProvider(CachedScript* cachedScript)
- : SourceProvider(cachedScript->response().url(), TextPosition::minimumPosition())
+ CachedScriptSourceProvider(CachedScript* cachedScript, JSC::SourceProviderSourceType sourceType, Ref<CachedScriptFetcher>&& scriptFetcher)
+ : SourceProvider(JSC::SourceOrigin { cachedScript->response().url(), WTFMove(scriptFetcher) }, cachedScript->response().url(), TextPosition(), sourceType)
, m_cachedScript(cachedScript)
{
- m_cachedScript->addClient(this);
+ m_cachedScript->addClient(*this);
}
CachedResourceHandle<CachedScript> m_cachedScript;
};
-inline JSC::SourceCode makeSource(CachedScript* cachedScript)
-{
- return JSC::SourceCode(CachedScriptSourceProvider::create(cachedScript));
-}
-
} // namespace WebCore
-
-#endif // CachedScriptSourceProvider_h
diff --git a/Source/WebCore/bindings/js/CallbackFunction.cpp b/Source/WebCore/bindings/js/CallbackFunction.cpp
deleted file mode 100644
index 145d0556b..000000000
--- a/Source/WebCore/bindings/js/CallbackFunction.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "CallbackFunction.h"
-
-#include "ExceptionCode.h"
-#include "JSDOMBinding.h"
-#include <runtime/CallData.h>
-
-namespace WebCore {
-
-bool checkFunctionOnlyCallback(JSC::ExecState* exec, JSC::JSValue value, CallbackAllowedValueFlags acceptedValues)
-{
- if (value.isUndefined() && (acceptedValues & CallbackAllowUndefined))
- return false;
-
- if (value.isNull() && (acceptedValues & CallbackAllowNull))
- return false;
-
- JSC::CallData callData;
- if (getCallData(value, callData) == JSC::CallTypeNone) {
- setDOMException(exec, TYPE_MISMATCH_ERR);
- return false;
- }
-
- return true;
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/CallbackFunction.h b/Source/WebCore/bindings/js/CallbackFunction.h
deleted file mode 100644
index 2562ce97a..000000000
--- a/Source/WebCore/bindings/js/CallbackFunction.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef CallbackFunction_h
-#define CallbackFunction_h
-
-#include <runtime/JSObject.h>
-
-namespace JSC {
-class ExecState;
-}
-
-namespace WebCore {
-
-class JSDOMGlobalObject;
-
-enum CallbackAllowedValueFlag {
- CallbackAllowUndefined = 1,
- CallbackAllowNull = 1 << 1
-};
-
-typedef unsigned CallbackAllowedValueFlags;
-
-bool checkFunctionOnlyCallback(JSC::ExecState*, JSC::JSValue, CallbackAllowedValueFlags);
-
-// Creates callback objects for callbacks marked as FunctionOnly in WebIDL.
-template <typename JSCallbackType>
-PassRefPtr<JSCallbackType> createFunctionOnlyCallback(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, JSC::JSValue value, CallbackAllowedValueFlags acceptedValues = 0)
-{
- if (checkFunctionOnlyCallback(exec, value, acceptedValues))
- return JSCallbackType::create(asObject(value), globalObject);
- return 0;
-}
-
-} // namespace WebCore
-
-#endif // CallbackFunction_h
diff --git a/Source/WebCore/bindings/js/CommonVM.cpp b/Source/WebCore/bindings/js/CommonVM.cpp
new file mode 100644
index 000000000..0187e19c9
--- /dev/null
+++ b/Source/WebCore/bindings/js/CommonVM.cpp
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CommonVM.h"
+
+#include "ScriptController.h"
+#include "Settings.h"
+#include "WebCoreJSClientData.h"
+#include <heap/HeapInlines.h>
+#include "heap/MachineStackMarker.h"
+#include <runtime/VM.h>
+#include <wtf/MainThread.h>
+#include <wtf/text/AtomicString.h>
+
+#if PLATFORM(IOS)
+#include "WebCoreThreadInternal.h"
+#endif
+
+using namespace JSC;
+
+namespace WebCore {
+
+VM* g_commonVMOrNull;
+
+VM& commonVMSlow()
+{
+ ASSERT(isMainThread());
+ ASSERT(!g_commonVMOrNull);
+
+ ScriptController::initializeThreading();
+ g_commonVMOrNull = &VM::createLeaked(LargeHeap).leakRef();
+ g_commonVMOrNull->heap.acquireAccess(); // At any time, we may do things that affect the GC.
+#if !PLATFORM(IOS)
+ g_commonVMOrNull->setExclusiveThread(std::this_thread::get_id());
+#else
+ g_commonVMOrNull->heap.setRunLoop(WebThreadRunLoop());
+ g_commonVMOrNull->heap.machineThreads().addCurrentThread();
+#endif
+
+ g_commonVMOrNull->setGlobalConstRedeclarationShouldThrow(Settings::globalConstRedeclarationShouldThrow());
+
+ JSVMClientData::initNormalWorld(g_commonVMOrNull);
+
+ return *g_commonVMOrNull;
+}
+
+void addImpureProperty(const AtomicString& propertyName)
+{
+ commonVM().addImpureProperty(propertyName);
+}
+
+} // namespace WebCore
+
diff --git a/Source/WebCore/bindings/js/JSTrackEventCustom.cpp b/Source/WebCore/bindings/js/CommonVM.h
index 3142cb1e5..0505168cb 100644
--- a/Source/WebCore/bindings/js/JSTrackEventCustom.cpp
+++ b/Source/WebCore/bindings/js/CommonVM.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -23,28 +23,28 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "config.h"
+#pragma once
-#if ENABLE(VIDEO_TRACK)
+#include <wtf/Forward.h>
-#include "JSTrackEvent.h"
+namespace JSC {
+class VM;
+}
-#include "JSTrackCustom.h"
-#include "TrackBase.h"
+namespace WebCore {
-using namespace JSC;
+WEBCORE_EXPORT extern JSC::VM* g_commonVMOrNull;
-namespace WebCore {
+WEBCORE_EXPORT JSC::VM& commonVMSlow();
-JSValue JSTrackEvent::track(ExecState* exec) const
+inline JSC::VM& commonVM()
{
- TrackBase* track = impl().track();
- if (!track)
- return jsNull();
-
- return toJS(exec, globalObject(), track);
+ if (JSC::VM* result = g_commonVMOrNull)
+ return *result;
+ return commonVMSlow();
}
+void addImpureProperty(const AtomicString&);
+
} // namespace WebCore
-#endif
diff --git a/Source/WebCore/bindings/js/DOMObjectHashTableMap.h b/Source/WebCore/bindings/js/DOMObjectHashTableMap.h
deleted file mode 100644
index 13bf207b0..000000000
--- a/Source/WebCore/bindings/js/DOMObjectHashTableMap.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
- * Copyright (C) 2009 Google, Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef DOMObjectHashTableMap_h
-#define DOMObjectHashTableMap_h
-
-#include <runtime/Lookup.h>
-#include <wtf/HashMap.h>
-
-namespace JSC {
- class VM;
-}
-
-namespace WebCore {
-
-// Map from static HashTable instances to per-GlobalData ones.
-class DOMObjectHashTableMap {
-public:
- static DOMObjectHashTableMap& mapFor(JSC::VM&);
-
- ~DOMObjectHashTableMap()
- {
- for (HashMap<const JSC::HashTable*, JSC::HashTable>::iterator iter = m_map.begin(); iter != m_map.end(); ++iter)
- iter->value.deleteTable();
- }
-
- const JSC::HashTable& get(const JSC::HashTable& staticTable)
- {
- HashMap<const JSC::HashTable*, JSC::HashTable>::iterator iter = m_map.find(&staticTable);
- if (iter != m_map.end())
- return iter->value;
- return m_map.set(&staticTable, staticTable.copy()).iterator->value;
- }
-
-private:
- HashMap<const JSC::HashTable*, JSC::HashTable> m_map;
-};
-
-} // namespace WebCore
-
-#endif // DOMObjectHashTableMap_h
diff --git a/Source/WebCore/bindings/js/DOMRequestState.h b/Source/WebCore/bindings/js/DOMRequestState.h
deleted file mode 100644
index 3453f5b53..000000000
--- a/Source/WebCore/bindings/js/DOMRequestState.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2012 Michael Pruett <michael@68k.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef DOMRequestState_h
-#define DOMRequestState_h
-
-#include "DOMWrapperWorld.h"
-#include "Document.h"
-#include "ScriptState.h"
-#include "WorkerGlobalScope.h"
-
-#include <JavaScriptCore/APIShims.h>
-
-namespace WebCore {
-
-class ScriptExecutionContext;
-
-class DOMRequestState {
-public:
- explicit DOMRequestState(ScriptExecutionContext* scriptExecutionContext)
- : m_scriptExecutionContext(scriptExecutionContext)
- , m_exec(0)
- {
- if (m_scriptExecutionContext->isDocument()) {
- Document* document = toDocument(m_scriptExecutionContext);
- m_exec = execStateFromPage(mainThreadNormalWorld(), document->page());
- } else {
- WorkerGlobalScope* workerGlobalScope = static_cast<WorkerGlobalScope*>(m_scriptExecutionContext);
- m_exec = execStateFromWorkerGlobalScope(workerGlobalScope);
- }
- }
-
- void clear()
- {
- m_scriptExecutionContext = 0;
- m_exec = 0;
- }
-
- class Scope {
- public:
- explicit Scope(DOMRequestState& state)
- : m_entryShim(state.exec())
- {
- }
- private:
- JSC::APIEntryShim m_entryShim;
- };
-
- JSC::ExecState* exec()
- {
- return m_exec;
- }
-
-private:
- ScriptExecutionContext* m_scriptExecutionContext;
- JSC::ExecState* m_exec;
-};
-
-}
-#endif
diff --git a/Source/WebCore/bindings/js/DOMWrapperWorld.cpp b/Source/WebCore/bindings/js/DOMWrapperWorld.cpp
index c25efe24d..1187bc11e 100644
--- a/Source/WebCore/bindings/js/DOMWrapperWorld.cpp
+++ b/Source/WebCore/bindings/js/DOMWrapperWorld.cpp
@@ -21,6 +21,7 @@
#include "config.h"
#include "DOMWrapperWorld.h"
+#include "CommonVM.h"
#include "JSDOMWindow.h"
#include "ScriptController.h"
#include "WebCoreJSClientData.h"
@@ -30,20 +31,20 @@ using namespace JSC;
namespace WebCore {
-DOMWrapperWorld::DOMWrapperWorld(JSC::VM* vm, bool isNormal)
+DOMWrapperWorld::DOMWrapperWorld(JSC::VM& vm, bool isNormal)
: m_vm(vm)
, m_isNormal(isNormal)
{
- VM::ClientData* clientData = m_vm->clientData;
+ VM::ClientData* clientData = m_vm.clientData;
ASSERT(clientData);
- static_cast<WebCoreJSClientData*>(clientData)->rememberWorld(*this);
+ static_cast<JSVMClientData*>(clientData)->rememberWorld(*this);
}
DOMWrapperWorld::~DOMWrapperWorld()
{
- VM::ClientData* clientData = m_vm->clientData;
+ VM::ClientData* clientData = m_vm.clientData;
ASSERT(clientData);
- static_cast<WebCoreJSClientData*>(clientData)->forgetWorld(*this);
+ static_cast<JSVMClientData*>(clientData)->forgetWorld(*this);
// These items are created lazily.
while (!m_scriptControllersWithWindowShells.isEmpty())
@@ -53,7 +54,6 @@ DOMWrapperWorld::~DOMWrapperWorld()
void DOMWrapperWorld::clearWrappers()
{
m_wrappers.clear();
- m_stringCache.clear();
// These items are created lazily.
while (!m_scriptControllersWithWindowShells.isEmpty())
@@ -64,13 +64,13 @@ DOMWrapperWorld& normalWorld(JSC::VM& vm)
{
VM::ClientData* clientData = vm.clientData;
ASSERT(clientData);
- return static_cast<WebCoreJSClientData*>(clientData)->normalWorld();
+ return static_cast<JSVMClientData*>(clientData)->normalWorld();
}
DOMWrapperWorld& mainThreadNormalWorld()
{
ASSERT(isMainThread());
- static DOMWrapperWorld& cachedNormalWorld = normalWorld(*JSDOMWindow::commonVM());
+ static DOMWrapperWorld& cachedNormalWorld = normalWorld(commonVM());
return cachedNormalWorld;
}
diff --git a/Source/WebCore/bindings/js/DOMWrapperWorld.h b/Source/WebCore/bindings/js/DOMWrapperWorld.h
index ac770129a..6eaec1000 100644
--- a/Source/WebCore/bindings/js/DOMWrapperWorld.h
+++ b/Source/WebCore/bindings/js/DOMWrapperWorld.h
@@ -19,56 +19,55 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef DOMWrapperWorld_h
-#define DOMWrapperWorld_h
+#pragma once
#include "JSDOMGlobalObject.h"
-#include <runtime/WeakGCMap.h>
#include <wtf/Forward.h>
namespace WebCore {
-class CSSValue;
-class JSDOMWrapper;
+class DeprecatedCSSOMValue;
class ScriptController;
typedef HashMap<void*, JSC::Weak<JSC::JSObject>> DOMObjectWrapperMap;
-typedef JSC::WeakGCMap<StringImpl*, JSC::JSString, PtrHash<StringImpl*>> JSStringCache;
class DOMWrapperWorld : public RefCounted<DOMWrapperWorld> {
public:
- static PassRefPtr<DOMWrapperWorld> create(JSC::VM* vm, bool isNormal = false)
+ static Ref<DOMWrapperWorld> create(JSC::VM& vm, bool isNormal = false)
{
- return adoptRef(new DOMWrapperWorld(vm, isNormal));
+ return adoptRef(*new DOMWrapperWorld(vm, isNormal));
}
- ~DOMWrapperWorld();
+ WEBCORE_EXPORT ~DOMWrapperWorld();
// Free as much memory held onto by this world as possible.
- void clearWrappers();
+ WEBCORE_EXPORT void clearWrappers();
void didCreateWindowShell(ScriptController* scriptController) { m_scriptControllersWithWindowShells.add(scriptController); }
void didDestroyWindowShell(ScriptController* scriptController) { m_scriptControllersWithWindowShells.remove(scriptController); }
+ void setShadowRootIsAlwaysOpen() { m_shadowRootIsAlwaysOpen = true; }
+ bool shadowRootIsAlwaysOpen() const { return m_shadowRootIsAlwaysOpen; }
+
// FIXME: can we make this private?
DOMObjectWrapperMap m_wrappers;
- JSStringCache m_stringCache;
- HashMap<CSSValue*, void*> m_cssValueRoots;
+ HashMap<DeprecatedCSSOMValue*, void*> m_deprecatedCSSOMValueRoots;
bool isNormal() const { return m_isNormal; }
- JSC::VM* vm() const { return m_vm; }
+ JSC::VM& vm() const { return m_vm; }
protected:
- DOMWrapperWorld(JSC::VM*, bool isNormal);
+ DOMWrapperWorld(JSC::VM&, bool isNormal);
private:
- JSC::VM* m_vm;
+ JSC::VM& m_vm;
HashSet<ScriptController*> m_scriptControllersWithWindowShells;
bool m_isNormal;
+ bool m_shadowRootIsAlwaysOpen { false };
};
DOMWrapperWorld& normalWorld(JSC::VM&);
-DOMWrapperWorld& mainThreadNormalWorld();
+WEBCORE_EXPORT DOMWrapperWorld& mainThreadNormalWorld();
inline DOMWrapperWorld& debuggerWorld() { return mainThreadNormalWorld(); }
inline DOMWrapperWorld& pluginWorld() { return mainThreadNormalWorld(); }
@@ -77,6 +76,9 @@ inline DOMWrapperWorld& currentWorld(JSC::ExecState* exec)
return JSC::jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->world();
}
+inline DOMWrapperWorld& worldForDOMObject(JSC::JSObject* object)
+{
+ return JSC::jsCast<JSDOMGlobalObject*>(object->globalObject())->world();
+}
+
} // namespace WebCore
-
-#endif // DOMWrapperWorld_h
diff --git a/Source/WebCore/bindings/js/Dictionary.cpp b/Source/WebCore/bindings/js/Dictionary.cpp
deleted file mode 100644
index 39ac466fa..000000000
--- a/Source/WebCore/bindings/js/Dictionary.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "Dictionary.h"
-
-#if ENABLE(NOTIFICATIONS)
-#include "JSNotification.h"
-#include "Notification.h"
-#endif
-
-using namespace JSC;
-
-namespace WebCore {
-
-Dictionary::Dictionary()
- : m_dictionary(0, 0)
-{
-}
-
-Dictionary::Dictionary(JSC::ExecState* exec, JSC::JSValue value)
- : m_dictionary(exec, value.isObject() ? value.getObject() : 0)
-{
-}
-
-
-#if ENABLE(NOTIFICATIONS)
-template<>
-JSObject* Dictionary::asJSObject<Notification>(Notification* object) const
-{
- return asObject(toJS(m_dictionary.execState(), jsCast<JSDOMGlobalObject*>(m_dictionary.execState()->lexicalGlobalObject()), object));
-}
-#endif
-
-bool Dictionary::getOwnPropertiesAsStringHashMap(HashMap<String, String>& map) const
-{
- if (!m_dictionary.isValid())
- return false;
-
- JSObject* object = m_dictionary.initializerObject();
- ExecState* exec = m_dictionary.execState();
-
- PropertyNameArray propertyNames(exec);
- JSObject::getOwnPropertyNames(object, exec, propertyNames, ExcludeDontEnumProperties);
- for (PropertyNameArray::const_iterator it = propertyNames.begin(); it != propertyNames.end(); ++it) {
- String stringKey = it->string();
- if (stringKey.isEmpty())
- continue;
- JSValue value = object->get(exec, *it);
- if (exec->hadException())
- continue;
- String stringValue = value.toString(exec)->value(exec);
- if (!exec->hadException())
- map.set(stringKey, stringValue);
- }
-
- return true;
-}
-
-bool Dictionary::getOwnPropertyNames(Vector<String>& names) const
-{
- if (!m_dictionary.isValid())
- return false;
-
- JSObject* object = m_dictionary.initializerObject();
- ExecState* exec = m_dictionary.execState();
-
- PropertyNameArray propertyNames(exec);
- JSObject::getOwnPropertyNames(object, exec, propertyNames, ExcludeDontEnumProperties);
- for (PropertyNameArray::const_iterator it = propertyNames.begin(); it != propertyNames.end(); ++it) {
- String stringKey = it->string();
- if (!stringKey.isEmpty())
- names.append(stringKey);
- }
-
- return true;
-}
-
-bool Dictionary::getWithUndefinedOrNullCheck(const String& propertyName, String& value) const
-{
- return m_dictionary.getWithUndefinedOrNullCheck(propertyName, value);
-}
-
-};
diff --git a/Source/WebCore/bindings/js/Dictionary.h b/Source/WebCore/bindings/js/Dictionary.h
deleted file mode 100644
index fd4bee579..000000000
--- a/Source/WebCore/bindings/js/Dictionary.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- * Copyright (C) 2012 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef Dictionary_h
-#define Dictionary_h
-
-#include "JSDictionary.h"
-#include "JSEventListener.h"
-#include "NotImplemented.h"
-#include <bindings/ScriptValue.h>
-#include <wtf/HashMap.h>
-#include <wtf/text/CString.h>
-#include <wtf/text/WTFString.h>
-
-namespace JSC {
-class JSValue;
-}
-
-namespace WebCore {
-class EventListener;
-
-class Dictionary {
-public:
- Dictionary();
- Dictionary(JSC::ExecState*, JSC::JSValue);
-
- // Returns true if a value was found for the provided property.
- template <typename Result>
- bool get(const char* propertyName, Result&) const;
- template <typename Result>
- bool get(const String& propertyName, Result&) const;
-
- template <typename T>
- PassRefPtr<EventListener> getEventListener(const char* propertyName, T* target) const;
- template <typename T>
- PassRefPtr<EventListener> getEventListener(const String& propertyName, T* target) const;
-
- bool isObject() const { return m_dictionary.isValid(); }
- bool isUndefinedOrNull() const { return !m_dictionary.isValid(); }
- bool getOwnPropertiesAsStringHashMap(HashMap<String, String>&) const;
- bool getOwnPropertyNames(Vector<String>&) const;
- bool getWithUndefinedOrNullCheck(const String& propertyName, String& value) const;
-
-private:
- template <typename T>
- JSC::JSObject* asJSObject(T*) const;
-
- JSDictionary m_dictionary;
-};
-
-template <typename Result>
-bool Dictionary::get(const char* propertyName, Result& result) const
-{
- if (!m_dictionary.isValid())
- return false;
-
- return m_dictionary.get(propertyName, result);
-}
-
-template <typename Result>
-bool Dictionary::get(const String& propertyName, Result& result) const
-{
- return get(propertyName.utf8().data(), result);
-}
-
-template <typename T>
-PassRefPtr<EventListener> Dictionary::getEventListener(const char* propertyName, T* target) const
-{
- if (!m_dictionary.isValid())
- return 0;
-
- Deprecated::ScriptValue eventListener;
- if (!m_dictionary.tryGetProperty(propertyName, eventListener))
- return 0;
- if (eventListener.hasNoValue())
- return 0;
- if (!eventListener.isObject())
- return 0;
-
- return JSEventListener::create(asObject(eventListener.jsValue()), asJSObject(target), true, currentWorld(m_dictionary.execState()));
-}
-
-template <typename T>
-PassRefPtr<EventListener> Dictionary::getEventListener(const String& propertyName, T* target) const
-{
- return getEventListener(propertyName.utf8().data(), target);
-}
-
-}
-
-#endif // Dictionary_h
diff --git a/Source/WebCore/bindings/js/GCController.cpp b/Source/WebCore/bindings/js/GCController.cpp
index ba70d4a06..6f9fca67f 100644
--- a/Source/WebCore/bindings/js/GCController.cpp
+++ b/Source/WebCore/bindings/js/GCController.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2014, 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -26,11 +26,13 @@
#include "config.h"
#include "GCController.h"
-#include "JSDOMWindow.h"
+#include "CommonVM.h"
#include <runtime/VM.h>
#include <runtime/JSLock.h>
#include <heap/Heap.h>
#include <wtf/StdLibExtras.h>
+#include <wtf/FastMalloc.h>
+#include <wtf/NeverDestroyed.h>
using namespace JSC;
@@ -38,57 +40,63 @@ namespace WebCore {
static void collect(void*)
{
- JSLockHolder lock(JSDOMWindow::commonVM());
- JSDOMWindow::commonVM()->heap.collectAllGarbage();
+ JSLockHolder lock(commonVM());
+ commonVM().heap.collectAllGarbage();
}
-GCController& gcController()
+GCController& GCController::singleton()
{
- DEFINE_STATIC_LOCAL(GCController, staticGCController, ());
- return staticGCController;
+ static NeverDestroyed<GCController> controller;
+ return controller;
}
GCController::GCController()
-#if !USE(CF)
- : m_GCTimer(this, &GCController::gcTimerFired)
-#endif
+ : m_GCTimer(*this, &GCController::gcTimerFired)
{
}
void GCController::garbageCollectSoon()
{
- // We only use reportAbandonedObjectGraph on systems with CoreFoundation
- // since it uses a runloop-based timer that is currently only available on
- // systems with CoreFoundation. If and when the notion of a run loop is pushed
- // down into WTF so that more platforms can take advantage of it, we will be
- // able to use reportAbandonedObjectGraph on more platforms.
-#if USE(CF)
- JSLockHolder lock(JSDOMWindow::commonVM());
- JSDOMWindow::commonVM()->heap.reportAbandonedObjectGraph();
+ // We only use reportAbandonedObjectGraph for systems for which there's an implementation
+ // of the garbage collector timers in JavaScriptCore. We wouldn't need this if JavaScriptCore
+ // used a timer implementation from WTF like RunLoop::Timer.
+#if USE(CF) || USE(GLIB)
+ JSLockHolder lock(commonVM());
+ commonVM().heap.reportAbandonedObjectGraph();
#else
+ garbageCollectOnNextRunLoop();
+#endif
+}
+
+void GCController::garbageCollectOnNextRunLoop()
+{
if (!m_GCTimer.isActive())
m_GCTimer.startOneShot(0);
-#endif
}
-#if !USE(CF)
-void GCController::gcTimerFired(Timer<GCController>*)
+void GCController::gcTimerFired()
{
- collect(0);
+ collect(nullptr);
}
-#endif
void GCController::garbageCollectNow()
{
- JSLockHolder lock(JSDOMWindow::commonVM());
-#if PLATFORM(IOS)
- // If JavaScript was never run in this process, there's no need to call GC which will
- // end up creating a VM unnecessarily.
- if (!JSDOMWindow::commonVMExists())
- return;
+ JSLockHolder lock(commonVM());
+ if (!commonVM().heap.isCurrentThreadBusy()) {
+ commonVM().heap.collectAllGarbage();
+ WTF::releaseFastMallocFreeMemory();
+ }
+}
+
+void GCController::garbageCollectNowIfNotDoneRecently()
+{
+#if USE(CF) || USE(GLIB)
+ JSLockHolder lock(commonVM());
+ if (!commonVM().heap.isCurrentThreadBusy())
+ commonVM().heap.collectAllGarbageIfNotDoneRecently();
+#else
+ garbageCollectSoon();
#endif
- if (!JSDOMWindow::commonVM()->heap.isBusy())
- JSDOMWindow::commonVM()->heap.collectAllGarbage();
}
void GCController::garbageCollectOnAlternateThreadForDebugging(bool waitUntilDone)
@@ -103,37 +111,21 @@ void GCController::garbageCollectOnAlternateThreadForDebugging(bool waitUntilDon
detachThread(threadID);
}
-void GCController::releaseExecutableMemory()
+void GCController::setJavaScriptGarbageCollectorTimerEnabled(bool enable)
{
- JSLockHolder lock(JSDOMWindow::commonVM());
-
-#if PLATFORM(IOS)
- // If JavaScript was never run in this process, there's no need to call GC which will
- // end up creating a VM unnecessarily.
- if (!JSDOMWindow::commonVMExists())
- return;
-#endif
-
- // We shouldn't have any javascript running on our stack when this function is called. The
- // following line asserts that.
- ASSERT(!JSDOMWindow::commonVM()->entryScope);
-
- // But be safe in release builds just in case...
- if (JSDOMWindow::commonVM()->entryScope)
- return;
-
- JSDOMWindow::commonVM()->releaseExecutableMemory();
+ commonVM().heap.setGarbageCollectionTimerEnabled(enable);
}
-void GCController::setJavaScriptGarbageCollectorTimerEnabled(bool enable)
+void GCController::deleteAllCode(DeleteAllCodeEffort effort)
{
- JSDOMWindow::commonVM()->heap.setGarbageCollectionTimerEnabled(enable);
+ JSLockHolder lock(commonVM());
+ commonVM().deleteAllCode(effort);
}
-void GCController::discardAllCompiledCode()
+void GCController::deleteAllLinkedCode(DeleteAllCodeEffort effort)
{
- JSLockHolder lock(JSDOMWindow::commonVM());
- JSDOMWindow::commonVM()->discardAllCode();
+ JSLockHolder lock(commonVM());
+ commonVM().deleteAllLinkedCode(effort);
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/GCController.h b/Source/WebCore/bindings/js/GCController.h
index 7db5c3058..b948c3968 100644
--- a/Source/WebCore/bindings/js/GCController.h
+++ b/Source/WebCore/bindings/js/GCController.h
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -23,43 +23,36 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef GCController_h
-#define GCController_h
+#pragma once
-#if USE(CF)
-#include <wtf/FastMalloc.h>
+#include <heap/DeleteAllCodeEffort.h>
+#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
-#else
#include "Timer.h"
-#endif
namespace WebCore {
- class GCController {
- WTF_MAKE_NONCOPYABLE(GCController); WTF_MAKE_FAST_ALLOCATED;
- friend GCController& gcController();
+class GCController {
+ WTF_MAKE_NONCOPYABLE(GCController);
+ friend class WTF::NeverDestroyed<GCController>;
+public:
+ WEBCORE_EXPORT static GCController& singleton();
- public:
- void garbageCollectSoon();
- void garbageCollectNow(); // It's better to call garbageCollectSoon, unless you have a specific reason not to.
+ WEBCORE_EXPORT void garbageCollectSoon();
+ WEBCORE_EXPORT void garbageCollectNow(); // It's better to call garbageCollectSoon, unless you have a specific reason not to.
+ WEBCORE_EXPORT void garbageCollectNowIfNotDoneRecently();
+ void garbageCollectOnNextRunLoop();
- void garbageCollectOnAlternateThreadForDebugging(bool waitUntilDone); // Used for stress testing.
- void releaseExecutableMemory();
- void setJavaScriptGarbageCollectorTimerEnabled(bool);
- void discardAllCompiledCode();
+ WEBCORE_EXPORT void garbageCollectOnAlternateThreadForDebugging(bool waitUntilDone); // Used for stress testing.
+ WEBCORE_EXPORT void setJavaScriptGarbageCollectorTimerEnabled(bool);
+ WEBCORE_EXPORT void deleteAllCode(JSC::DeleteAllCodeEffort);
+ WEBCORE_EXPORT void deleteAllLinkedCode(JSC::DeleteAllCodeEffort);
- private:
- GCController(); // Use gcController() instead
+private:
+ GCController(); // Use singleton() instead.
-#if !USE(CF)
- void gcTimerFired(Timer<GCController>*);
- Timer<GCController> m_GCTimer;
-#endif
- };
-
- // Function to obtain the global GC controller.
- GCController& gcController() PURE_FUNCTION;
+ void gcTimerFired();
+ Timer m_GCTimer;
+};
} // namespace WebCore
-
-#endif // GCController_h
diff --git a/Source/WebCore/bindings/js/IDBBindingUtilities.cpp b/Source/WebCore/bindings/js/IDBBindingUtilities.cpp
index 7a77db444..8fee1e297 100644
--- a/Source/WebCore/bindings/js/IDBBindingUtilities.cpp
+++ b/Source/WebCore/bindings/js/IDBBindingUtilities.cpp
@@ -1,6 +1,7 @@
/*
* Copyright (C) 2010 Google Inc. All rights reserved.
* Copyright (C) 2012 Michael Pruett <michael@68k.org>
+ * Copyright (C) 2014, 2015, 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,14 +28,25 @@
#include "config.h"
#if ENABLE(INDEXED_DATABASE)
+
#include "IDBBindingUtilities.h"
-#include "DOMRequestState.h"
+#include "IDBIndexInfo.h"
#include "IDBKey.h"
+#include "IDBKeyData.h"
#include "IDBKeyPath.h"
+#include "IDBValue.h"
+#include "IndexKey.h"
+#include "JSDOMBinding.h"
+#include "JSDOMConvert.h"
+#include "JSDOMStringList.h"
#include "Logging.h"
+#include "MessagePort.h"
+#include "ScriptExecutionContext.h"
+#include "SerializedScriptValue.h"
#include "SharedBuffer.h"
-
+#include "ThreadSafeDataBuffer.h"
+#include <runtime/ArrayBuffer.h>
#include <runtime/DateInstance.h>
#include <runtime/ObjectConstructor.h>
@@ -42,18 +54,18 @@ using namespace JSC;
namespace WebCore {
-static bool get(ExecState* exec, JSValue object, const String& keyPathElement, JSValue& result)
+static bool get(ExecState& exec, JSValue object, const String& keyPathElement, JSValue& result)
{
if (object.isString() && keyPathElement == "length") {
- result = jsNumber(object.toString(exec)->length());
+ result = jsNumber(asString(object)->length());
return true;
}
if (!object.isObject())
return false;
- Identifier identifier(&exec->vm(), keyPathElement.utf8().data());
- if (!asObject(object)->hasProperty(exec, identifier))
+ Identifier identifier = Identifier::fromString(&exec.vm(), keyPathElement);
+ if (!asObject(object)->hasProperty(&exec, identifier))
return false;
- result = asObject(object)->get(exec, identifier);
+ result = asObject(object)->get(&exec, identifier);
return true;
}
@@ -63,43 +75,64 @@ static bool canSet(JSValue object, const String& keyPathElement)
return object.isObject();
}
-static bool set(ExecState* exec, JSValue& object, const String& keyPathElement, JSValue jsValue)
+static bool set(ExecState& exec, JSValue& object, const String& keyPathElement, JSValue jsValue)
{
if (!canSet(object, keyPathElement))
return false;
- Identifier identifier(&exec->vm(), keyPathElement.utf8().data());
- asObject(object)->putDirect(exec->vm(), identifier, jsValue);
+ Identifier identifier = Identifier::fromString(&exec.vm(), keyPathElement);
+ asObject(object)->putDirect(exec.vm(), identifier, jsValue);
return true;
}
-static JSValue idbKeyToJSValue(ExecState* exec, JSDOMGlobalObject* globalObject, IDBKey* key)
+JSValue toJS(ExecState& state, JSGlobalObject& globalObject, IDBKey* key)
{
if (!key) {
- // This should be undefined, not null.
+ // This must be undefined, not null.
// Spec: http://dvcs.w3.org/hg/IndexedDB/raw-file/tip/Overview.html#idl-def-IDBKeyRange
return jsUndefined();
}
+ VM& vm = state.vm();
+ Locker<JSLock> locker(vm.apiLock());
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
switch (key->type()) {
- case IDBKey::ArrayType:
- {
- const IDBKey::KeyArray& inArray = key->array();
- size_t size = inArray.size();
- JSArray* outArray = constructEmptyArray(exec, 0, globalObject, size);
- for (size_t i = 0; i < size; ++i) {
- IDBKey* arrayKey = inArray.at(i).get();
- outArray->putDirectIndex(exec, i, idbKeyToJSValue(exec, globalObject, arrayKey));
- }
- return JSValue(outArray);
+ case KeyType::Array: {
+ auto& inArray = key->array();
+ unsigned size = inArray.size();
+ auto outArray = constructEmptyArray(&state, 0, &globalObject, size);
+ RETURN_IF_EXCEPTION(scope, JSValue());
+ for (size_t i = 0; i < size; ++i) {
+ outArray->putDirectIndex(&state, i, toJS(state, globalObject, inArray.at(i).get()));
+ RETURN_IF_EXCEPTION(scope, JSValue());
+ }
+ return outArray;
+ }
+ case KeyType::Binary: {
+ auto* data = key->binary().data();
+ if (!data) {
+ ASSERT_NOT_REACHED();
+ return jsNull();
}
- case IDBKey::StringType:
- return jsStringWithCache(exec, key->string());
- case IDBKey::DateType:
- return jsDateOrNull(exec, key->date());
- case IDBKey::NumberType:
+
+ auto arrayBuffer = ArrayBuffer::create(data->data(), data->size());
+ Structure* structure = globalObject.arrayBufferStructure(arrayBuffer->sharingMode());
+ if (!structure)
+ return jsNull();
+
+ return JSArrayBuffer::create(state.vm(), structure, WTFMove(arrayBuffer));
+ }
+ case KeyType::String:
+ return jsStringWithCache(&state, key->string());
+ case KeyType::Date:
+ // FIXME: This should probably be toJS<IDLDate>(...) as per:
+ // http://w3c.github.io/IndexedDB/#request-convert-a-key-to-a-value
+ return toJS<IDLNullable<IDLDate>>(state, key->date());
+ case KeyType::Number:
return jsNumber(key->number());
- case IDBKey::MinType:
- case IDBKey::InvalidType:
+ case KeyType::Min:
+ case KeyType::Max:
+ case KeyType::Invalid:
ASSERT_NOT_REACHED();
return jsUndefined();
}
@@ -110,29 +143,38 @@ static JSValue idbKeyToJSValue(ExecState* exec, JSDOMGlobalObject* globalObject,
static const size_t maximumDepth = 2000;
-static PassRefPtr<IDBKey> createIDBKeyFromValue(ExecState* exec, JSValue value, Vector<JSArray*>& stack)
+static RefPtr<IDBKey> createIDBKeyFromValue(ExecState& exec, JSValue value, Vector<JSArray*>& stack)
{
- if (value.isNumber() && !std::isnan(value.toNumber(exec)))
- return IDBKey::createNumber(value.toNumber(exec));
+ VM& vm = exec.vm();
+ if (value.isNumber() && !std::isnan(value.toNumber(&exec)))
+ return IDBKey::createNumber(value.toNumber(&exec));
+
if (value.isString())
- return IDBKey::createString(value.toString(exec)->value(exec));
- if (value.inherits(DateInstance::info()) && !std::isnan(valueToDate(exec, value)))
- return IDBKey::createDate(valueToDate(exec, value));
+ return IDBKey::createString(asString(value)->value(&exec));
+
+ if (value.inherits(vm, DateInstance::info())) {
+ auto dateValue = valueToDate(exec, value);
+ if (!std::isnan(dateValue))
+ return IDBKey::createDate(dateValue);
+ }
+
if (value.isObject()) {
JSObject* object = asObject(value);
- if (isJSArray(object) || object->inherits(JSArray::info())) {
+ if (isJSArray(object) || object->inherits(vm, JSArray::info())) {
JSArray* array = asArray(object);
size_t length = array->length();
if (stack.contains(array))
- return 0;
+ return nullptr;
+
if (stack.size() >= maximumDepth)
- return 0;
+ return nullptr;
+
stack.append(array);
- IDBKey::KeyArray subkeys;
+ Vector<RefPtr<IDBKey>> subkeys;
for (size_t i = 0; i < length; i++) {
- JSValue item = array->getIndex(exec, i);
+ JSValue item = array->getIndex(&exec, i);
RefPtr<IDBKey> subkey = createIDBKeyFromValue(exec, item, stack);
if (!subkey)
subkeys.append(IDBKey::createInvalid());
@@ -143,30 +185,26 @@ static PassRefPtr<IDBKey> createIDBKeyFromValue(ExecState* exec, JSValue value,
stack.removeLast();
return IDBKey::createArray(subkeys);
}
+
+ if (auto* arrayBuffer = jsDynamicCast<JSArrayBuffer*>(vm, value))
+ return IDBKey::createBinary(*arrayBuffer);
+
+ if (auto* arrayBufferView = jsDynamicCast<JSArrayBufferView*>(vm, value))
+ return IDBKey::createBinary(*arrayBufferView);
}
- return 0;
+ return nullptr;
}
-static PassRefPtr<IDBKey> createIDBKeyFromValue(ExecState* exec, JSValue value)
+static Ref<IDBKey> createIDBKeyFromValue(ExecState& exec, JSValue value)
{
Vector<JSArray*> stack;
RefPtr<IDBKey> key = createIDBKeyFromValue(exec, value, stack);
if (key)
- return key;
+ return *key;
return IDBKey::createInvalid();
}
-IDBKeyPath idbKeyPathFromValue(ExecState* exec, JSValue keyPathValue)
-{
- IDBKeyPath keyPath;
- if (isJSArray(keyPathValue))
- keyPath = IDBKeyPath(toNativeArray<String>(exec, keyPathValue));
- else
- keyPath = IDBKeyPath(keyPathValue.toString(exec)->value(exec));
- return keyPath;
-}
-
-static JSValue getNthValueOnKeyPath(ExecState* exec, JSValue rootValue, const Vector<String>& keyPathElements, size_t index)
+static JSValue getNthValueOnKeyPath(ExecState& exec, JSValue rootValue, const Vector<String>& keyPathElements, size_t index)
{
JSValue currentValue(rootValue);
ASSERT(index <= keyPathElements.size());
@@ -178,21 +216,21 @@ static JSValue getNthValueOnKeyPath(ExecState* exec, JSValue rootValue, const Ve
return currentValue;
}
-static PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(ExecState* exec, const Deprecated::ScriptValue& value, const String& keyPath)
+static RefPtr<IDBKey> internalCreateIDBKeyFromScriptValueAndKeyPath(ExecState& exec, const JSValue& value, const String& keyPath)
{
Vector<String> keyPathElements;
IDBKeyPathParseError error;
IDBParseKeyPath(keyPath, keyPathElements, error);
- ASSERT(error == IDBKeyPathParseErrorNone);
+ ASSERT(error == IDBKeyPathParseError::None);
- JSValue jsValue = value.jsValue();
+ JSValue jsValue = value;
jsValue = getNthValueOnKeyPath(exec, jsValue, keyPathElements, keyPathElements.size());
if (jsValue.isUndefined())
- return 0;
+ return nullptr;
return createIDBKeyFromValue(exec, jsValue);
}
-static JSValue ensureNthValueOnKeyPath(ExecState* exec, JSValue rootValue, const Vector<String>& keyPathElements, size_t index)
+static JSValue ensureNthValueOnKeyPath(ExecState& exec, JSValue rootValue, const Vector<String>& keyPathElements, size_t index)
{
JSValue currentValue(rootValue);
@@ -201,7 +239,7 @@ static JSValue ensureNthValueOnKeyPath(ExecState* exec, JSValue rootValue, const
JSValue parentValue(currentValue);
const String& keyPathElement = keyPathElements[i];
if (!get(exec, parentValue, keyPathElement, currentValue)) {
- JSObject* object = constructEmptyObject(exec);
+ JSObject* object = constructEmptyObject(&exec);
if (!set(exec, parentValue, keyPathElement, JSValue(object)))
return jsUndefined();
currentValue = JSValue(object);
@@ -211,7 +249,7 @@ static JSValue ensureNthValueOnKeyPath(ExecState* exec, JSValue rootValue, const
return currentValue;
}
-static bool canInjectNthValueOnKeyPath(ExecState* exec, JSValue rootValue, const Vector<String>& keyPathElements, size_t index)
+static bool canInjectNthValueOnKeyPath(ExecState& exec, JSValue rootValue, const Vector<String>& keyPathElements, size_t index)
{
if (!rootValue.isObject())
return false;
@@ -228,105 +266,151 @@ static bool canInjectNthValueOnKeyPath(ExecState* exec, JSValue rootValue, const
return true;
}
-bool injectIDBKeyIntoScriptValue(DOMRequestState* requestState, PassRefPtr<IDBKey> key, Deprecated::ScriptValue& value, const IDBKeyPath& keyPath)
+bool injectIDBKeyIntoScriptValue(ExecState& exec, const IDBKeyData& keyData, JSValue value, const IDBKeyPath& keyPath)
{
- LOG(StorageAPI, "injectIDBKeyIntoScriptValue");
+ LOG(IndexedDB, "injectIDBKeyIntoScriptValue");
- ASSERT(keyPath.type() == IDBKeyPath::StringType);
+ ASSERT(WTF::holds_alternative<String>(keyPath));
Vector<String> keyPathElements;
IDBKeyPathParseError error;
- IDBParseKeyPath(keyPath.string(), keyPathElements, error);
- ASSERT(error == IDBKeyPathParseErrorNone);
+ IDBParseKeyPath(WTF::get<String>(keyPath), keyPathElements, error);
+ ASSERT(error == IDBKeyPathParseError::None);
if (keyPathElements.isEmpty())
return false;
- ExecState* exec = requestState->exec();
-
- JSValue parent = ensureNthValueOnKeyPath(exec, value.jsValue(), keyPathElements, keyPathElements.size() - 1);
+ JSValue parent = ensureNthValueOnKeyPath(exec, value, keyPathElements, keyPathElements.size() - 1);
if (parent.isUndefined())
return false;
- if (!set(exec, parent, keyPathElements.last(), idbKeyToJSValue(exec, jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), key.get())))
+ auto key = keyData.maybeCreateIDBKey();
+ if (!key)
+ return false;
+
+ if (!set(exec, parent, keyPathElements.last(), toJS(exec, *exec.lexicalGlobalObject(), key.get())))
return false;
return true;
}
-PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(DOMRequestState* requestState, const Deprecated::ScriptValue& value, const IDBKeyPath& keyPath)
-{
- LOG(StorageAPI, "createIDBKeyFromScriptValueAndKeyPath");
- ASSERT(!keyPath.isNull());
- ExecState* exec = requestState->exec();
-
- if (keyPath.type() == IDBKeyPath::ArrayType) {
- IDBKey::KeyArray result;
- const Vector<String>& array = keyPath.array();
- for (size_t i = 0; i < array.size(); i++) {
- RefPtr<IDBKey> key = createIDBKeyFromScriptValueAndKeyPath(exec, value, array[i]);
+RefPtr<IDBKey> maybeCreateIDBKeyFromScriptValueAndKeyPath(ExecState& exec, const JSValue& value, const IDBKeyPath& keyPath)
+{
+ if (WTF::holds_alternative<Vector<String>>(keyPath)) {
+ auto& array = WTF::get<Vector<String>>(keyPath);
+ Vector<RefPtr<IDBKey>> result;
+ result.reserveInitialCapacity(array.size());
+ for (auto& string : array) {
+ RefPtr<IDBKey> key = internalCreateIDBKeyFromScriptValueAndKeyPath(exec, value, string);
if (!key)
- return 0;
- result.append(key);
+ return nullptr;
+ result.uncheckedAppend(WTFMove(key));
}
- return IDBKey::createArray(result);
+ return IDBKey::createArray(WTFMove(result));
}
- ASSERT(keyPath.type() == IDBKeyPath::StringType);
- return createIDBKeyFromScriptValueAndKeyPath(exec, value, keyPath.string());
+ return internalCreateIDBKeyFromScriptValueAndKeyPath(exec, value, WTF::get<String>(keyPath));
}
-bool canInjectIDBKeyIntoScriptValue(DOMRequestState* requestState, const Deprecated::ScriptValue& scriptValue, const IDBKeyPath& keyPath)
+bool canInjectIDBKeyIntoScriptValue(ExecState& exec, const JSValue& scriptValue, const IDBKeyPath& keyPath)
{
LOG(StorageAPI, "canInjectIDBKeyIntoScriptValue");
- ASSERT(keyPath.type() == IDBKeyPath::StringType);
+ ASSERT(WTF::holds_alternative<String>(keyPath));
Vector<String> keyPathElements;
IDBKeyPathParseError error;
- IDBParseKeyPath(keyPath.string(), keyPathElements, error);
- ASSERT(error == IDBKeyPathParseErrorNone);
+ IDBParseKeyPath(WTF::get<String>(keyPath), keyPathElements, error);
+ ASSERT(error == IDBKeyPathParseError::None);
if (!keyPathElements.size())
return false;
- JSC::ExecState* exec = requestState->exec();
- return canInjectNthValueOnKeyPath(exec, scriptValue.jsValue(), keyPathElements, keyPathElements.size() - 1);
+ return canInjectNthValueOnKeyPath(exec, scriptValue, keyPathElements, keyPathElements.size() - 1);
+}
+
+static JSValue deserializeIDBValueToJSValue(ExecState& state, JSC::JSGlobalObject& globalObject, const IDBValue& value)
+{
+ // FIXME: I think it's peculiar to use undefined to mean "null data" and null to mean "empty data".
+ // But I am not changing this at the moment because at least some callers are specifically checking isUndefined.
+
+ if (!value.data().data())
+ return jsUndefined();
+
+ auto& data = *value.data().data();
+ if (data.isEmpty())
+ return jsNull();
+
+ auto serializedValue = SerializedScriptValue::createFromWireBytes(Vector<uint8_t>(data));
+
+ state.vm().apiLock().lock();
+ Vector<RefPtr<MessagePort>> messagePorts;
+ JSValue result = serializedValue->deserialize(state, &globalObject, messagePorts, value.blobURLs(), value.blobFilePaths(), SerializationErrorMode::NonThrowing);
+ state.vm().apiLock().unlock();
+
+ return result;
}
-Deprecated::ScriptValue deserializeIDBValue(DOMRequestState* requestState, PassRefPtr<SerializedScriptValue> prpValue)
+JSValue deserializeIDBValueToJSValue(ExecState& state, const IDBValue& value)
{
- ExecState* exec = requestState->exec();
- RefPtr<SerializedScriptValue> serializedValue = prpValue;
- if (serializedValue)
- return SerializedScriptValue::deserialize(exec, serializedValue.get(), NonThrowing);
- return Deprecated::ScriptValue(exec->vm(), jsNull());
+ return deserializeIDBValueToJSValue(state, *state.lexicalGlobalObject(), value);
}
-Deprecated::ScriptValue deserializeIDBValueBuffer(DOMRequestState* requestState, PassRefPtr<SharedBuffer> prpBuffer)
+JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, const IDBValue& value)
{
- ExecState* exec = requestState->exec();
- RefPtr<SharedBuffer> buffer = prpBuffer;
- if (buffer) {
- // FIXME: The extra copy here can be eliminated by allowing SerializedScriptValue to take a raw const char* or const uint8_t*.
- Vector<uint8_t> value;
- value.append(buffer->data(), buffer->size());
- RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::createFromWireBytes(value);
- return SerializedScriptValue::deserialize(exec, serializedValue.get(), NonThrowing);
- }
- return Deprecated::ScriptValue(exec->vm(), jsNull());
+ ASSERT(state);
+ return deserializeIDBValueToJSValue(*state, *globalObject, value);
}
-Deprecated::ScriptValue idbKeyToScriptValue(DOMRequestState* requestState, PassRefPtr<IDBKey> key)
+Ref<IDBKey> scriptValueToIDBKey(ExecState& exec, const JSValue& scriptValue)
{
- ExecState* exec = requestState->exec();
- return Deprecated::ScriptValue(exec->vm(), idbKeyToJSValue(exec, jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()), key.get()));
+ return createIDBKeyFromValue(exec, scriptValue);
}
-PassRefPtr<IDBKey> scriptValueToIDBKey(DOMRequestState* requestState, const Deprecated::ScriptValue& scriptValue)
+JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, const IDBKeyData& keyData)
{
- ExecState* exec = requestState->exec();
- return createIDBKeyFromValue(exec, scriptValue.jsValue());
+ ASSERT(state);
+ ASSERT(globalObject);
+
+ return toJS(*state, *globalObject, keyData.maybeCreateIDBKey().get());
+}
+
+static Vector<IDBKeyData> createKeyPathArray(ExecState& exec, JSValue value, const IDBIndexInfo& info)
+{
+ auto visitor = WTF::makeVisitor([&](const String& string) -> Vector<IDBKeyData> {
+ auto idbKey = internalCreateIDBKeyFromScriptValueAndKeyPath(exec, value, string);
+ if (!idbKey)
+ return { };
+
+ Vector<IDBKeyData> keys;
+ if (info.multiEntry() && idbKey->type() == IndexedDB::Array) {
+ for (auto& key : idbKey->array())
+ keys.append(key.get());
+ } else
+ keys.append(idbKey.get());
+ return keys;
+ }, [&](const Vector<String>& vector) -> Vector<IDBKeyData> {
+ Vector<IDBKeyData> keys;
+ for (auto& entry : vector) {
+ auto key = internalCreateIDBKeyFromScriptValueAndKeyPath(exec, value, entry);
+ if (!key || !key->isValid())
+ return { };
+ keys.append(key.get());
+ }
+ return keys;
+ });
+
+ return WTF::visit(visitor, info.keyPath());
+}
+
+void generateIndexKeyForValue(ExecState& exec, const IDBIndexInfo& info, JSValue value, IndexKey& outKey)
+{
+ auto keyDatas = createKeyPathArray(exec, value, info);
+
+ if (keyDatas.isEmpty())
+ return;
+
+ outKey = IndexKey(WTFMove(keyDatas));
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/IDBBindingUtilities.h b/Source/WebCore/bindings/js/IDBBindingUtilities.h
index f012aef2d..c491fee7f 100644
--- a/Source/WebCore/bindings/js/IDBBindingUtilities.h
+++ b/Source/WebCore/bindings/js/IDBBindingUtilities.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2014, 2015, 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,34 +24,41 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef IDBBindingUtilities_h
-#define IDBBindingUtilities_h
+#pragma once
#if ENABLE(INDEXED_DATABASE)
-#include "Dictionary.h"
-#include <bindings/ScriptValue.h>
+#include "IDBKeyPath.h"
#include <wtf/Forward.h>
+namespace JSC {
+class ExecState;
+class JSGlobalObject;
+class JSValue;
+}
+
namespace WebCore {
-class DOMRequestState;
+class IDBIndexInfo;
class IDBKey;
-class IDBKeyPath;
-class SharedBuffer;
+class IDBKeyData;
+class IDBValue;
+class IndexKey;
+class JSDOMGlobalObject;
+
+RefPtr<IDBKey> maybeCreateIDBKeyFromScriptValueAndKeyPath(JSC::ExecState&, const JSC::JSValue&, const IDBKeyPath&);
+bool canInjectIDBKeyIntoScriptValue(JSC::ExecState&, const JSC::JSValue&, const IDBKeyPath&);
+bool injectIDBKeyIntoScriptValue(JSC::ExecState&, const IDBKeyData&, JSC::JSValue, const IDBKeyPath&);
-IDBKeyPath idbKeyPathFromValue(JSC::ExecState*, JSC::JSValue);
+void generateIndexKeyForValue(JSC::ExecState&, const IDBIndexInfo&, JSC::JSValue, IndexKey& outKey);
-bool injectIDBKeyIntoScriptValue(DOMRequestState*, PassRefPtr<IDBKey>, Deprecated::ScriptValue&, const IDBKeyPath&);
-PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(DOMRequestState*, const Deprecated::ScriptValue&, const IDBKeyPath&);
-bool canInjectIDBKeyIntoScriptValue(DOMRequestState*, const Deprecated::ScriptValue&, const IDBKeyPath&);
-Deprecated::ScriptValue deserializeIDBValue(DOMRequestState*, PassRefPtr<SerializedScriptValue>);
-Deprecated::ScriptValue deserializeIDBValueBuffer(DOMRequestState*, PassRefPtr<SharedBuffer>);
-Deprecated::ScriptValue idbKeyToScriptValue(DOMRequestState*, PassRefPtr<IDBKey>);
-PassRefPtr<IDBKey> scriptValueToIDBKey(DOMRequestState*, const Deprecated::ScriptValue&);
+Ref<IDBKey> scriptValueToIDBKey(JSC::ExecState&, const JSC::JSValue&);
+
+JSC::JSValue deserializeIDBValueToJSValue(JSC::ExecState&, const IDBValue&);
+JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, const IDBValue&);
+JSC::JSValue toJS(JSC::ExecState&, JSC::JSGlobalObject&, IDBKey*);
+JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, const IDBKeyData&);
}
#endif // ENABLE(INDEXED_DATABASE)
-
-#endif // IDBBindingUtilities_h
diff --git a/Source/WebCore/bindings/js/JSAnimationTimelineCustom.cpp b/Source/WebCore/bindings/js/JSAnimationTimelineCustom.cpp
new file mode 100644
index 000000000..47df4e7e7
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSAnimationTimelineCustom.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) Canon Inc. 2016
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted, provided that the following conditions
+ * are required to be met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Canon Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(WEB_ANIMATIONS)
+#include "JSAnimationTimeline.h"
+
+#include "DocumentTimeline.h"
+#include "JSDOMBinding.h"
+#include "JSDocumentTimeline.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<AnimationTimeline>&& value)
+{
+ if (value->isDocumentTimeline())
+ return createWrapper<DocumentTimeline>(globalObject, WTFMove(value));
+ return createWrapper<AnimationTimeline>(globalObject, WTFMove(value));
+}
+
+JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, AnimationTimeline& value)
+{
+ return wrap(state, globalObject, value);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEB_ANIMATIONS)
diff --git a/Source/WebCore/bindings/js/JSAttrCustom.cpp b/Source/WebCore/bindings/js/JSAttrCustom.cpp
index 07e1689a2..d45cf6d2c 100644
--- a/Source/WebCore/bindings/js/JSAttrCustom.cpp
+++ b/Source/WebCore/bindings/js/JSAttrCustom.cpp
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -29,28 +29,14 @@
#include "config.h"
#include "JSAttr.h"
-#include "Document.h"
#include "Element.h"
-#include "HTMLNames.h"
-
-using namespace JSC;
namespace WebCore {
-using namespace HTMLNames;
-
-void JSAttr::visitChildren(JSCell* cell, SlotVisitor& visitor)
+void JSAttr::visitAdditionalChildren(JSC::SlotVisitor& visitor)
{
- JSAttr* thisObject = jsCast<JSAttr*>(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
-
- Base::visitChildren(thisObject, visitor);
- Element* element = thisObject->impl().ownerElement();
- if (!element)
- return;
- visitor.addOpaqueRoot(root(element));
+ if (Element* element = wrapped().ownerElement())
+ visitor.addOpaqueRoot(root(element));
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSAudioBufferSourceNodeCustom.cpp b/Source/WebCore/bindings/js/JSAudioBufferSourceNodeCustom.cpp
deleted file mode 100644
index 853576ab7..000000000
--- a/Source/WebCore/bindings/js/JSAudioBufferSourceNodeCustom.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2010, Google Inc. All rights reserved.
- * Copyright (C) 2012 Samsung Electronics
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(WEB_AUDIO)
-
-#include "JSAudioBufferSourceNode.h"
-
-#include "AudioBuffer.h"
-#include "AudioBufferSourceNode.h"
-#include "JSAudioBuffer.h"
-#include <runtime/Error.h>
-
-using namespace JSC;
-
-namespace WebCore {
-
-void JSAudioBufferSourceNode::setBuffer(ExecState* exec, JSValue value)
-{
- AudioBuffer* buffer = toAudioBuffer(value);
- if (!buffer) {
- exec->vm().throwException(exec, createTypeError(exec, "Value is not of type AudioBuffer"));
- return;
- }
-
- if (!impl().setBuffer(buffer))
- exec->vm().throwException(exec, createTypeError(exec, "AudioBuffer unsupported number of channels"));
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/bindings/js/JSAudioContextCustom.cpp b/Source/WebCore/bindings/js/JSAudioContextCustom.cpp
deleted file mode 100644
index e195ddf11..000000000
--- a/Source/WebCore/bindings/js/JSAudioContextCustom.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2010, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(WEB_AUDIO)
-
-#include "AudioContext.h"
-
-#include "AudioBuffer.h"
-#include "Document.h"
-#include "JSAudioBuffer.h"
-#include "JSAudioContext.h"
-#include "JSOfflineAudioContext.h"
-#include "OfflineAudioContext.h"
-#include <runtime/ArrayBuffer.h>
-#include <runtime/Error.h>
-#include <runtime/JSArrayBuffer.h>
-
-using namespace JSC;
-
-namespace WebCore {
-
-EncodedJSValue JSC_HOST_CALL JSAudioContextConstructor::constructJSAudioContext(ExecState* exec)
-{
- JSAudioContextConstructor* jsConstructor = jsCast<JSAudioContextConstructor*>(exec->callee());
- if (!jsConstructor)
- return throwVMError(exec, createReferenceError(exec, "AudioContext constructor callee is unavailable"));
-
- ScriptExecutionContext* scriptExecutionContext = jsConstructor->scriptExecutionContext();
- if (!scriptExecutionContext)
- return throwVMError(exec, createReferenceError(exec, "AudioContext constructor script execution context is unavailable"));
-
- if (!scriptExecutionContext->isDocument())
- return throwVMError(exec, createReferenceError(exec, "AudioContext constructor called in a script execution context which is not a document"));
-
- Document& document = toDocument(*scriptExecutionContext);
-
- RefPtr<AudioContext> audioContext;
-
- if (!exec->argumentCount()) {
- // Constructor for default AudioContext which talks to audio hardware.
- ExceptionCode ec = 0;
- audioContext = AudioContext::create(document, ec);
- if (ec) {
- setDOMException(exec, ec);
- return JSValue::encode(JSValue());
- }
- if (!audioContext.get())
- return throwVMError(exec, createSyntaxError(exec, "audio resources unavailable for AudioContext construction"));
- } else {
-#if ENABLE(LEGACY_WEB_AUDIO)
- // Constructor for offline (render-target) AudioContext which renders into an AudioBuffer.
- // new AudioContext(in unsigned long numberOfChannels, in unsigned long numberOfFrames, in float sampleRate);
- document.addConsoleMessage(JSMessageSource, WarningMessageLevel,
- "Deprecated AudioContext constructor: use OfflineAudioContext instead");
-
- if (exec->argumentCount() < 3)
- return throwVMError(exec, createNotEnoughArgumentsError(exec));
-
- int32_t numberOfChannels = exec->argument(0).toInt32(exec);
- int32_t numberOfFrames = exec->argument(1).toInt32(exec);
- float sampleRate = exec->argument(2).toFloat(exec);
-
- if (numberOfChannels <= 0 || numberOfChannels > 10)
- return throwVMError(exec, createSyntaxError(exec, "Invalid number of channels"));
-
- if (numberOfFrames <= 0)
- return throwVMError(exec, createSyntaxError(exec, "Invalid number of frames"));
-
- if (sampleRate <= 0)
- return throwVMError(exec, createSyntaxError(exec, "Invalid sample rate"));
-
-
- ExceptionCode ec = 0;
- audioContext = OfflineAudioContext::create(document, numberOfChannels, numberOfFrames, sampleRate, ec);
- if (ec) {
- setDOMException(exec, ec);
- return throwVMError(exec, createSyntaxError(exec, "Error creating OfflineAudioContext"));
- }
-#else
- return throwVMError(exec, createSyntaxError(exec, "Illegal AudioContext constructor"));
-#endif
- }
-
- if (!audioContext.get())
- return throwVMError(exec, createReferenceError(exec, "Error creating AudioContext"));
-
- return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), AudioContext, audioContext.get()));
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/bindings/js/JSAudioTrackCustom.cpp b/Source/WebCore/bindings/js/JSAudioTrackCustom.cpp
index ebbd46b5e..732341e50 100644
--- a/Source/WebCore/bindings/js/JSAudioTrackCustom.cpp
+++ b/Source/WebCore/bindings/js/JSAudioTrackCustom.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -35,43 +35,38 @@ using namespace JSC;
namespace WebCore {
-void JSAudioTrack::visitChildren(JSCell* cell, SlotVisitor& visitor)
+void JSAudioTrack::visitAdditionalChildren(SlotVisitor& visitor)
{
- JSAudioTrack* jsAudioTrack = jsCast<JSAudioTrack*>(cell);
- ASSERT_GC_OBJECT_INHERITS(jsAudioTrack, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(jsAudioTrack->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(jsAudioTrack, visitor);
-
- AudioTrack& audioTrack = jsAudioTrack->impl();
- visitor.addOpaqueRoot(root(&audioTrack));
+ visitor.addOpaqueRoot(root(&wrapped()));
}
-void JSAudioTrack::setKind(ExecState* exec, JSValue value)
+void JSAudioTrack::setKind(ExecState& state, JSValue value)
{
- UNUSED_PARAM(exec);
#if ENABLE(MEDIA_SOURCE)
- const String& nativeValue(value.isEmpty() ? String() : value.toString(exec)->value(exec));
- if (exec->hadException())
- return;
- impl().setKind(nativeValue);
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto string = value.toWTFString(&state);
+ RETURN_IF_EXCEPTION(scope, void());
+ wrapped().setKind(string);
#else
+ UNUSED_PARAM(state);
UNUSED_PARAM(value);
- return;
#endif
}
-void JSAudioTrack::setLanguage(ExecState* exec, JSValue value)
+void JSAudioTrack::setLanguage(ExecState& state, JSValue value)
{
- UNUSED_PARAM(exec);
#if ENABLE(MEDIA_SOURCE)
- const String& nativeValue(value.isEmpty() ? String() : value.toString(exec)->value(exec));
- if (exec->hadException())
- return;
- impl().setLanguage(nativeValue);
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto string = value.toWTFString(&state);
+ RETURN_IF_EXCEPTION(scope, void());
+ wrapped().setLanguage(string);
#else
+ UNUSED_PARAM(state);
UNUSED_PARAM(value);
- return;
#endif
}
diff --git a/Source/WebCore/bindings/js/JSAudioTrackListCustom.cpp b/Source/WebCore/bindings/js/JSAudioTrackListCustom.cpp
index 23fd0b916..6fd1a5040 100644
--- a/Source/WebCore/bindings/js/JSAudioTrackListCustom.cpp
+++ b/Source/WebCore/bindings/js/JSAudioTrackListCustom.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -26,6 +26,7 @@
#include "config.h"
#if ENABLE(VIDEO_TRACK)
+
#include "JSAudioTrackList.h"
#include "Element.h"
@@ -35,17 +36,9 @@ using namespace JSC;
namespace WebCore {
-void JSAudioTrackList::visitChildren(JSCell* cell, SlotVisitor& visitor)
+void JSAudioTrackList::visitAdditionalChildren(SlotVisitor& visitor)
{
- JSAudioTrackList* jsAudioTrackList = jsCast<JSAudioTrackList*>(cell);
- ASSERT_GC_OBJECT_INHERITS(jsAudioTrackList, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(jsAudioTrackList->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(jsAudioTrackList, visitor);
-
- AudioTrackList& audioTrackList = jsAudioTrackList->impl();
- visitor.addOpaqueRoot(root(audioTrackList.element()));
- audioTrackList.visitJSEventListeners(visitor);
+ visitor.addOpaqueRoot(root(wrapped().element()));
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp b/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp
new file mode 100644
index 000000000..4d379309a
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSBindingsAllInOne.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2009, 2010 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+// This all-in-one cpp file cuts down on template bloat to allow us to build our Windows release build.
+
+#include "CachedModuleScriptLoader.cpp"
+#include "DOMWrapperWorld.cpp"
+#include "GCController.cpp"
+#include "JSAnimationTimelineCustom.cpp"
+#include "JSAttrCustom.cpp"
+#include "JSAudioTrackCustom.cpp"
+#include "JSAudioTrackListCustom.cpp"
+#include "JSBlobCustom.cpp"
+#include "JSCSSRuleCustom.cpp"
+#include "JSCSSRuleListCustom.cpp"
+#include "JSCSSStyleDeclarationCustom.cpp"
+#include "JSCSSValueCustom.cpp"
+#include "JSCallbackData.cpp"
+#include "JSCanvasRenderingContext2DCustom.cpp"
+#include "JSCommandLineAPIHostCustom.cpp"
+#include "JSCryptoCustom.cpp"
+#include "JSCustomEventCustom.cpp"
+#include "JSSQLStatementErrorCallbackCustom.cpp"
+#include "JSCustomXPathNSResolver.cpp"
+#include "JSDOMBindingSecurity.cpp"
+#include "JSDOMBuiltinConstructorBase.cpp"
+#include "JSDOMConstructorBase.cpp"
+#include "JSDOMConstructorWithDocument.cpp"
+#include "JSDOMExceptionHandling.cpp"
+#include "JSDOMGlobalObject.cpp"
+#include "JSDOMGlobalObjectTask.cpp"
+#include "JSDOMPromise.cpp"
+#include "JSDOMStringMapCustom.cpp"
+#include "JSDOMWindowBase.cpp"
+#include "JSDOMWindowCustom.cpp"
+#include "JSDOMWindowProperties.cpp"
+#include "JSDOMWindowShell.cpp"
+#include "JSDOMWrapper.cpp"
+#include "JSDOMWrapperCache.cpp"
+#include "JSDocumentCustom.cpp"
+#include "JSDocumentFragmentCustom.cpp"
+#include "JSElementCustom.cpp"
+#include "JSErrorHandler.cpp"
+#include "JSEventCustom.cpp"
+#include "JSEventListener.cpp"
+#include "JSEventTargetCustom.cpp"
+#include "JSExceptionBase.cpp"
+#include "JSHTMLAllCollectionCustom.cpp"
+#include "JSHTMLAppletElementCustom.cpp"
+#include "JSHTMLCanvasElementCustom.cpp"
+#include "JSHTMLCollectionCustom.cpp"
+#include "JSHTMLDocumentCustom.cpp"
+#include "JSHTMLElementCustom.cpp"
+#include "JSHTMLEmbedElementCustom.cpp"
+#include "JSHTMLFormControlsCollectionCustom.cpp"
+#include "JSHTMLFrameSetElementCustom.cpp"
+#include "JSHTMLObjectElementCustom.cpp"
+#include "JSHTMLOptionsCollectionCustom.cpp"
+#include "JSHTMLSelectElementCustom.cpp"
+#include "JSHTMLTemplateElementCustom.cpp"
+#include "JSHistoryCustom.cpp"
+#include "JSImageDataCustom.cpp"
+#include "JSInspectorFrontendHostCustom.cpp"
+#include "JSLazyEventListener.cpp"
+#include "JSLocationCustom.cpp"
+#include "JSMainThreadExecState.cpp"
+#include "JSMessageChannelCustom.cpp"
+#include "JSMessageEventCustom.cpp"
+#include "JSMessagePortCustom.cpp"
+#include "JSMutationCallback.cpp"
+#include "JSMutationObserverCustom.cpp"
+#include "JSNodeCustom.cpp"
+#include "JSNodeFilterCustom.cpp"
+#include "JSNodeIteratorCustom.cpp"
+#include "JSNodeListCustom.cpp"
+#include "JSPluginElementFunctions.cpp"
+#include "JSPopStateEventCustom.cpp"
+#include "JSReadableStreamPrivateConstructors.cpp"
+#include "JSSVGPathSegCustom.cpp"
+#include "JSStorageCustom.cpp"
+#include "JSStyleSheetCustom.cpp"
+#include "JSTextCustom.cpp"
+#include "JSTextTrackCueCustom.cpp"
+#include "JSTextTrackCustom.cpp"
+#include "JSTextTrackListCustom.cpp"
+#include "JSTrackCustom.cpp"
+#include "JSTreeWalkerCustom.cpp"
+#include "JSVideoTrackCustom.cpp"
+#include "JSVideoTrackListCustom.cpp"
+#include "JSWorkerCustom.cpp"
+#include "JSWorkerGlobalScopeBase.cpp"
+#include "JSWorkerGlobalScopeCustom.cpp"
+#include "JSXMLDocumentCustom.cpp"
+#include "JSXMLHttpRequestCustom.cpp"
+#include "JSXPathNSResolverCustom.cpp"
+#include "JSXPathResultCustom.cpp"
+#include "ScheduledAction.cpp"
+#include "ScriptCachedFrameData.cpp"
+#include "ScriptController.cpp"
+#include "ScriptGlobalObject.cpp"
+#include "ScriptModuleLoader.cpp"
+#include "ScriptState.cpp"
+#include "SerializedScriptValue.cpp"
+#include "WebCoreTypedArrayController.cpp"
+#include "WorkerScriptController.cpp"
diff --git a/Source/WebCore/bindings/js/JSBiquadFilterNodeCustom.cpp b/Source/WebCore/bindings/js/JSBiquadFilterNodeCustom.cpp
deleted file mode 100644
index fe342b81b..000000000
--- a/Source/WebCore/bindings/js/JSBiquadFilterNodeCustom.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright (C) 2012, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(WEB_AUDIO)
-
-#include "JSBiquadFilterNode.h"
-
-#include "BiquadFilterNode.h"
-#include "ExceptionCode.h"
-#include <runtime/Error.h>
-
-using namespace JSC;
-
-namespace WebCore {
-
-void JSBiquadFilterNode::setType(ExecState* exec, JSValue value)
-{
-#if ENABLE(LEGACY_WEB_AUDIO)
- if (value.isNumber()) {
- uint32_t type = value.toUInt32(exec);
- if (!impl().setType(type))
- exec->vm().throwException(exec, createTypeError(exec, "Illegal BiquadFilterNode type"));
- return;
- }
-#endif
-
- if (value.isString()) {
- String type = value.toString(exec)->value(exec);
- if (type == "lowpass" || type == "highpass" || type == "bandpass" || type == "lowshelf" || type == "highshelf" || type == "peaking" || type == "notch" || type == "allpass") {
- impl().setType(type);
- return;
- }
- }
-
- exec->vm().throwException(exec, createTypeError(exec, "Illegal BiquadFilterNode type"));
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/bindings/js/JSBlobCustom.cpp b/Source/WebCore/bindings/js/JSBlobCustom.cpp
index bfcd4d192..649594010 100644
--- a/Source/WebCore/bindings/js/JSBlobCustom.cpp
+++ b/Source/WebCore/bindings/js/JSBlobCustom.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2012 Google Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -31,111 +32,23 @@
#include "config.h"
#include "JSBlob.h"
-#include "Blob.h"
-#include "ExceptionCode.h"
-#include "ExceptionCodePlaceholder.h"
#include "JSDOMBinding.h"
-#include "JSDictionary.h"
#include "JSFile.h"
-#include "WebKitBlobBuilder.h"
-#include <runtime/Error.h>
-#include <runtime/JSArray.h>
-#include <runtime/JSArrayBuffer.h>
-#include <runtime/JSArrayBufferView.h>
-#include <wtf/Assertions.h>
using namespace JSC;
namespace WebCore {
-JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Blob* blob)
+JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<Blob>&& blob)
{
- if (!blob)
- return jsNull();
-
- if (blob->isFile())
- return wrap<JSFile>(exec, globalObject, static_cast<File*>(blob));
-
- return wrap<JSBlob>(exec, globalObject, blob);
+ if (is<File>(blob))
+ return createWrapper<File>(globalObject, WTFMove(blob));
+ return createWrapper<Blob>(globalObject, WTFMove(blob));
}
-EncodedJSValue JSC_HOST_CALL JSBlobConstructor::constructJSBlob(ExecState* exec)
+JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, Blob& blob)
{
- JSBlobConstructor* jsConstructor = jsCast<JSBlobConstructor*>(exec->callee());
- ScriptExecutionContext* context = jsConstructor->scriptExecutionContext();
- if (!context)
- return throwVMError(exec, createReferenceError(exec, "Blob constructor associated document is unavailable"));
-
- if (!exec->argumentCount()) {
- RefPtr<Blob> blob = Blob::create();
- return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), Blob, blob.get()));
- }
-
- unsigned blobPartsLength = 0;
- JSObject* blobParts = toJSSequence(exec, exec->argument(0), blobPartsLength);
- if (exec->hadException())
- return JSValue::encode(jsUndefined());
- ASSERT(blobParts);
-
- String type;
- String endings = ASCIILiteral("transparent");
-
- if (exec->argumentCount() > 1) {
- JSValue blobPropertyBagValue = exec->argument(1);
-
- if (!blobPropertyBagValue.isObject())
- return throwVMError(exec, createTypeError(exec, "Second argument of the constructor is not of type Object"));
-
- // Given the above test, this will always yield an object.
- JSObject* blobPropertyBagObject = blobPropertyBagValue.toObject(exec);
-
- // Create the dictionary wrapper from the initializer object.
- JSDictionary dictionary(exec, blobPropertyBagObject);
-
- // Attempt to get the endings property and validate it.
- bool containsEndings = dictionary.get("endings", endings);
- if (exec->hadException())
- return JSValue::encode(jsUndefined());
-
- if (containsEndings) {
- if (endings != "transparent" && endings != "native")
- return throwVMError(exec, createTypeError(exec, "The endings property must be either \"transparent\" or \"native\""));
- }
-
- // Attempt to get the type property.
- dictionary.get("type", type);
- if (exec->hadException())
- return JSValue::encode(jsUndefined());
- }
-
- ASSERT(endings == "transparent" || endings == "native");
-
- BlobBuilder blobBuilder;
-
- for (unsigned i = 0; i < blobPartsLength; ++i) {
- JSValue item = blobParts->get(exec, i);
- if (exec->hadException())
- return JSValue::encode(jsUndefined());
-
-#if ENABLE(BLOB)
- if (ArrayBuffer* arrayBuffer = toArrayBuffer(item))
- blobBuilder.append(arrayBuffer);
- else if (RefPtr<ArrayBufferView> arrayBufferView = toArrayBufferView(item))
- blobBuilder.append(arrayBufferView.release());
- else
-#endif
- if (Blob* blob = toBlob(item))
- blobBuilder.append(blob);
- else {
- String string = item.toString(exec)->value(exec);
- if (exec->hadException())
- return JSValue::encode(jsUndefined());
- blobBuilder.append(string, endings);
- }
- }
-
- RefPtr<Blob> blob = blobBuilder.getBlob(type);
- return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), Blob, blob.get()));
+ return wrap(state, globalObject, blob);
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSCSSRuleCustom.cpp b/Source/WebCore/bindings/js/JSCSSRuleCustom.cpp
index 3003a70eb..666757bf7 100644
--- a/Source/WebCore/bindings/js/JSCSSRuleCustom.cpp
+++ b/Source/WebCore/bindings/js/JSCSSRuleCustom.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -26,29 +26,28 @@
#include "config.h"
#include "JSCSSRule.h"
-#include "CSSCharsetRule.h"
#include "CSSFontFaceRule.h"
#include "CSSImportRule.h"
+#include "CSSKeyframeRule.h"
+#include "CSSKeyframesRule.h"
#include "CSSMediaRule.h"
+#include "CSSNamespaceRule.h"
#include "CSSPageRule.h"
#include "CSSStyleRule.h"
#include "CSSSupportsRule.h"
-#include "JSCSSCharsetRule.h"
#include "JSCSSFontFaceRule.h"
-#include "JSCSSHostRule.h"
#include "JSCSSImportRule.h"
+#include "JSCSSKeyframeRule.h"
+#include "JSCSSKeyframesRule.h"
#include "JSCSSMediaRule.h"
+#include "JSCSSNamespaceRule.h"
#include "JSCSSPageRule.h"
#include "JSCSSStyleRule.h"
#include "JSCSSSupportsRule.h"
#include "JSNode.h"
#include "JSStyleSheetCustom.h"
-#include "JSWebKitCSSKeyframeRule.h"
-#include "JSWebKitCSSKeyframesRule.h"
#include "JSWebKitCSSRegionRule.h"
#include "JSWebKitCSSViewportRule.h"
-#include "WebKitCSSKeyframeRule.h"
-#include "WebKitCSSKeyframesRule.h"
#include "WebKitCSSRegionRule.h"
#include "WebKitCSSViewportRule.h"
@@ -56,75 +55,48 @@ using namespace JSC;
namespace WebCore {
-void JSCSSRule::visitChildren(JSCell* cell, SlotVisitor& visitor)
+void JSCSSRule::visitAdditionalChildren(SlotVisitor& visitor)
{
- JSCSSRule* thisObject = jsCast<JSCSSRule*>(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(thisObject, visitor);
- visitor.addOpaqueRoot(root(&thisObject->impl()));
+ visitor.addOpaqueRoot(root(&wrapped()));
}
-JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, CSSRule* rule)
+JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<CSSRule>&& rule)
{
- if (!rule)
- return jsNull();
-
- JSObject* wrapper = getCachedWrapper(currentWorld(exec), rule);
- if (wrapper)
- return wrapper;
-
switch (rule->type()) {
- case CSSRule::STYLE_RULE:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSStyleRule, rule);
- break;
- case CSSRule::MEDIA_RULE:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSMediaRule, rule);
- break;
- case CSSRule::FONT_FACE_RULE:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSFontFaceRule, rule);
- break;
- case CSSRule::PAGE_RULE:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSPageRule, rule);
- break;
- case CSSRule::IMPORT_RULE:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSImportRule, rule);
- break;
- case CSSRule::CHARSET_RULE:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSCharsetRule, rule);
- break;
- case CSSRule::WEBKIT_KEYFRAME_RULE:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, WebKitCSSKeyframeRule, rule);
- break;
- case CSSRule::WEBKIT_KEYFRAMES_RULE:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, WebKitCSSKeyframesRule, rule);
- break;
-#if ENABLE(CSS3_CONDITIONAL_RULES)
- case CSSRule::SUPPORTS_RULE:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSSupportsRule, rule);
- break;
-#endif
+ case CSSRule::STYLE_RULE:
+ return createWrapper<CSSStyleRule>(globalObject, WTFMove(rule));
+ case CSSRule::MEDIA_RULE:
+ return createWrapper<CSSMediaRule>(globalObject, WTFMove(rule));
+ case CSSRule::FONT_FACE_RULE:
+ return createWrapper<CSSFontFaceRule>(globalObject, WTFMove(rule));
+ case CSSRule::PAGE_RULE:
+ return createWrapper<CSSPageRule>(globalObject, WTFMove(rule));
+ case CSSRule::IMPORT_RULE:
+ return createWrapper<CSSImportRule>(globalObject, WTFMove(rule));
+ case CSSRule::NAMESPACE_RULE:
+ return createWrapper<CSSNamespaceRule>(globalObject, WTFMove(rule));
+ case CSSRule::KEYFRAME_RULE:
+ return createWrapper<CSSKeyframeRule>(globalObject, WTFMove(rule));
+ case CSSRule::KEYFRAMES_RULE:
+ return createWrapper<CSSKeyframesRule>(globalObject, WTFMove(rule));
+ case CSSRule::SUPPORTS_RULE:
+ return createWrapper<CSSSupportsRule>(globalObject, WTFMove(rule));
#if ENABLE(CSS_DEVICE_ADAPTATION)
- case CSSRule::WEBKIT_VIEWPORT_RULE:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, WebKitCSSViewportRule, rule);
- break;
+ case CSSRule::WEBKIT_VIEWPORT_RULE:
+ return createWrapper<WebKitCSSViewportRule>(globalObject, WTFMove(rule));
#endif
#if ENABLE(CSS_REGIONS)
- case CSSRule::WEBKIT_REGION_RULE:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, WebKitCSSRegionRule, rule);
- break;
+ case CSSRule::WEBKIT_REGION_RULE:
+ return createWrapper<WebKitCSSRegionRule>(globalObject, WTFMove(rule));
#endif
-#if ENABLE(SHADOW_DOM)
- case CSSRule::HOST_RULE:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSHostRule, rule);
- break;
-#endif
- default:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSRule, rule);
+ default:
+ return createWrapper<CSSRule>(globalObject, WTFMove(rule));
}
+}
- return wrapper;
+JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, CSSRule& object)
+{
+ return wrap(state, globalObject, object);
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSCSSRuleCustom.h b/Source/WebCore/bindings/js/JSCSSRuleCustom.h
index 720565840..e99a19e02 100644
--- a/Source/WebCore/bindings/js/JSCSSRuleCustom.h
+++ b/Source/WebCore/bindings/js/JSCSSRuleCustom.h
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -23,8 +23,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSCSSRuleCustom_h
-#define JSCSSRuleCustom_h
+#pragma once
#include "CSSRule.h"
#include "CSSStyleSheet.h"
@@ -43,5 +42,3 @@ inline void* root(CSSRule* rule)
}
} // namespace WebCore
-
-#endif // JSCSSRuleCustom_h
diff --git a/Source/WebCore/bindings/js/JSCSSRuleListCustom.cpp b/Source/WebCore/bindings/js/JSCSSRuleListCustom.cpp
index d4c22a855..028444fe3 100644
--- a/Source/WebCore/bindings/js/JSCSSRuleListCustom.cpp
+++ b/Source/WebCore/bindings/js/JSCSSRuleListCustom.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -38,12 +38,12 @@ namespace WebCore {
bool JSCSSRuleListOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
{
- JSCSSRuleList* jsCSSRuleList = jsCast<JSCSSRuleList*>(handle.get().asCell());
+ JSCSSRuleList* jsCSSRuleList = jsCast<JSCSSRuleList*>(handle.slot()->asCell());
if (!jsCSSRuleList->hasCustomProperties())
return false;
- if (CSSStyleSheet* styleSheet = jsCSSRuleList->impl().styleSheet())
+ if (CSSStyleSheet* styleSheet = jsCSSRuleList->wrapped().styleSheet())
return visitor.containsOpaqueRoot(root(styleSheet));
- if (CSSRule* cssRule = jsCSSRuleList->impl().item(0))
+ if (CSSRule* cssRule = jsCSSRuleList->wrapped().item(0))
return visitor.containsOpaqueRoot(root(cssRule));
return false;
}
diff --git a/Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp b/Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp
index e8190f2f1..4104a8952 100644
--- a/Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp
+++ b/Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008, 2009, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2007-2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -26,58 +26,54 @@
#include "config.h"
#include "JSCSSStyleDeclarationCustom.h"
-#include "CSSParser.h"
-#include "CSSPrimitiveValue.h"
#include "CSSPropertyNames.h"
-#include "CSSValue.h"
+#include "CSSPropertyParser.h"
+#include "CSSRule.h"
+#include "CSSStyleDeclaration.h"
+#include "CSSStyleSheet.h"
+#include "CustomElementReactionQueue.h"
+#include "DeprecatedCSSOMPrimitiveValue.h"
#include "HashTools.h"
-#include "JSCSSValue.h"
+#include "JSCSSStyleDeclaration.h"
+#include "JSDeprecatedCSSOMValue.h"
#include "JSNode.h"
+#include "JSStyleSheetCustom.h"
#include "RuntimeEnabledFeatures.h"
#include "Settings.h"
#include "StyleProperties.h"
+#include "StyledElement.h"
+#include <runtime/IdentifierInlines.h>
#include <runtime/StringPrototype.h>
#include <wtf/ASCIICType.h>
#include <wtf/text/AtomicString.h>
-#include <wtf/text/StringBuilder.h>
#include <wtf/text/StringConcatenate.h>
-#include <wtf/text/WTFString.h>
using namespace JSC;
-using namespace WTF;
namespace WebCore {
-void JSCSSStyleDeclaration::visitChildren(JSCell* cell, SlotVisitor& visitor)
+void* root(CSSStyleDeclaration* style)
{
- JSCSSStyleDeclaration* thisObject = jsCast<JSCSSStyleDeclaration*>(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(thisObject, visitor);
- visitor.addOpaqueRoot(root(&thisObject->impl()));
+ ASSERT(style);
+ if (auto* parentRule = style->parentRule())
+ return root(parentRule);
+ if (auto* styleSheet = style->parentStyleSheet())
+ return root(styleSheet);
+ if (auto* parentElement = style->parentElement())
+ return root(parentElement);
+ return style;
}
-class CSSPropertyInfo {
-public:
- CSSPropertyID propertyID;
- bool hadPixelOrPosPrefix;
-};
-
-enum PropertyNamePrefix
+void JSCSSStyleDeclaration::visitAdditionalChildren(SlotVisitor& visitor)
{
- PropertyNamePrefixNone,
- PropertyNamePrefixCSS,
- PropertyNamePrefixPixel,
- PropertyNamePrefixPos,
-#if ENABLE(LEGACY_CSS_VENDOR_PREFIXES)
- PropertyNamePrefixApple,
-#endif
- PropertyNamePrefixEpub,
+ visitor.addOpaqueRoot(root(&wrapped()));
+}
+
+enum class PropertyNamePrefix {
+ None, Epub, CSS, Pixel, Pos, WebKit,
#if ENABLE(LEGACY_CSS_VENDOR_PREFIXES)
- PropertyNamePrefixKHTML,
+ Apple, KHTML,
#endif
- PropertyNamePrefixWebKit
};
template<size_t prefixCStringLength>
@@ -97,7 +93,7 @@ static inline bool matchesCSSPropertyNamePrefix(const StringImpl& propertyName,
// The prefix within the property name must be followed by a capital letter.
// Other characters in the prefix within the property name must be lowercase.
- if (propertyName.length() < (prefixLength + 1))
+ if (propertyName.length() < prefixLength + 1)
return false;
for (size_t i = offset; i < prefixLength; ++i) {
@@ -107,10 +103,11 @@ static inline bool matchesCSSPropertyNamePrefix(const StringImpl& propertyName,
if (!isASCIIUpper(propertyName[prefixLength]))
return false;
+
return true;
}
-static PropertyNamePrefix getCSSPropertyNamePrefix(const StringImpl& propertyName)
+static PropertyNamePrefix propertyNamePrefix(const StringImpl& propertyName)
{
ASSERT(propertyName.length());
@@ -120,37 +117,37 @@ static PropertyNamePrefix getCSSPropertyNamePrefix(const StringImpl& propertyNam
#if ENABLE(LEGACY_CSS_VENDOR_PREFIXES)
case 'a':
if (RuntimeEnabledFeatures::sharedFeatures().legacyCSSVendorPrefixesEnabled() && matchesCSSPropertyNamePrefix(propertyName, "apple"))
- return PropertyNamePrefixApple;
+ return PropertyNamePrefix::Apple;
break;
#endif
case 'c':
if (matchesCSSPropertyNamePrefix(propertyName, "css"))
- return PropertyNamePrefixCSS;
+ return PropertyNamePrefix::CSS;
break;
#if ENABLE(LEGACY_CSS_VENDOR_PREFIXES)
case 'k':
if (RuntimeEnabledFeatures::sharedFeatures().legacyCSSVendorPrefixesEnabled() && matchesCSSPropertyNamePrefix(propertyName, "khtml"))
- return PropertyNamePrefixKHTML;
+ return PropertyNamePrefix::KHTML;
break;
#endif
case 'e':
if (matchesCSSPropertyNamePrefix(propertyName, "epub"))
- return PropertyNamePrefixEpub;
+ return PropertyNamePrefix::Epub;
break;
case 'p':
if (matchesCSSPropertyNamePrefix(propertyName, "pos"))
- return PropertyNamePrefixPos;
+ return PropertyNamePrefix::Pos;
if (matchesCSSPropertyNamePrefix(propertyName, "pixel"))
- return PropertyNamePrefixPixel;
+ return PropertyNamePrefix::Pixel;
break;
case 'w':
if (matchesCSSPropertyNamePrefix(propertyName, "webkit"))
- return PropertyNamePrefixWebKit;
+ return PropertyNamePrefix::WebKit;
break;
default:
break;
}
- return PropertyNamePrefixNone;
+ return PropertyNamePrefix::None;
}
static inline void writeWebKitPrefix(char*& buffer)
@@ -175,7 +172,12 @@ static inline void writeEpubPrefix(char*& buffer)
*buffer++ = '-';
}
-static CSSPropertyInfo cssPropertyIDForJSCSSPropertyName(PropertyName propertyName)
+struct CSSPropertyInfo {
+ CSSPropertyID propertyID;
+ bool hadPixelOrPosPrefix;
+};
+
+static CSSPropertyInfo parseJavaScriptCSSPropertyName(PropertyName propertyName)
{
CSSPropertyInfo propertyInfo = {CSSPropertyInvalid, false};
bool hadPixelOrPosPrefix = false;
@@ -188,9 +190,9 @@ static CSSPropertyInfo cssPropertyIDForJSCSSPropertyName(PropertyName propertyNa
return propertyInfo;
String stringForCache = String(propertyNameString);
- typedef HashMap<String, CSSPropertyInfo> CSSPropertyInfoMap;
- DEFINE_STATIC_LOCAL(CSSPropertyInfoMap, propertyInfoCache, ());
- propertyInfo = propertyInfoCache.get(stringForCache);
+ using CSSPropertyInfoMap = HashMap<String, CSSPropertyInfo>;
+ static NeverDestroyed<CSSPropertyInfoMap> propertyInfoCache;
+ propertyInfo = propertyInfoCache.get().get(stringForCache);
if (propertyInfo.propertyID)
return propertyInfo;
@@ -203,35 +205,35 @@ static CSSPropertyInfo cssPropertyIDForJSCSSPropertyName(PropertyName propertyNa
// Prefixes CSS, Pixel, Pos are ignored.
// Prefixes Apple, KHTML and Webkit are transposed to "-webkit-".
// The prefix "Epub" becomes "-epub-".
- switch (getCSSPropertyNamePrefix(*propertyNameString)) {
- case PropertyNamePrefixNone:
+ switch (propertyNamePrefix(*propertyNameString)) {
+ case PropertyNamePrefix::None:
if (isASCIIUpper((*propertyNameString)[0]))
return propertyInfo;
break;
- case PropertyNamePrefixCSS:
+ case PropertyNamePrefix::CSS:
i += 3;
break;
- case PropertyNamePrefixPixel:
+ case PropertyNamePrefix::Pixel:
i += 5;
hadPixelOrPosPrefix = true;
break;
- case PropertyNamePrefixPos:
+ case PropertyNamePrefix::Pos:
i += 3;
hadPixelOrPosPrefix = true;
break;
#if ENABLE(LEGACY_CSS_VENDOR_PREFIXES)
- case PropertyNamePrefixApple:
- case PropertyNamePrefixKHTML:
+ case PropertyNamePrefix::Apple:
+ case PropertyNamePrefix::KHTML:
ASSERT(RuntimeEnabledFeatures::sharedFeatures().legacyCSSVendorPrefixesEnabled());
writeWebKitPrefix(bufferPtr);
i += 5;
break;
#endif
- case PropertyNamePrefixEpub:
+ case PropertyNamePrefix::Epub:
writeEpubPrefix(bufferPtr);
i += 4;
break;
- case PropertyNamePrefixWebKit:
+ case PropertyNamePrefix::WebKit:
writeWebKitPrefix(bufferPtr);
i += 6;
break;
@@ -248,7 +250,7 @@ static CSSPropertyInfo cssPropertyIDForJSCSSPropertyName(PropertyName propertyNa
for (; i < length; ++i) {
UChar c = (*propertyNameString)[i];
- if (!c || c >= 0x7F)
+ if (!c || !isASCII(c))
return propertyInfo; // illegal character
if (isASCIIUpper(c)) {
size_t bufferSizeLeft = stringEnd - bufferPtr;
@@ -256,7 +258,7 @@ static CSSPropertyInfo cssPropertyIDForJSCSSPropertyName(PropertyName propertyNa
if (propertySizeLeft > bufferSizeLeft)
return propertyInfo;
*bufferPtr++ = '-';
- *bufferPtr++ = toASCIILower(c);
+ *bufferPtr++ = toASCIILowerUnchecked(c);
} else
*bufferPtr++ = c;
ASSERT_WITH_SECURITY_IMPLICATION(bufferPtr < bufferEnd);
@@ -269,142 +271,125 @@ static CSSPropertyInfo cssPropertyIDForJSCSSPropertyName(PropertyName propertyNa
cssPropertyNameIOSAliasing(buffer, name, outputLength);
#endif
- const Property* hashTableEntry = findProperty(name, outputLength);
- int propertyID = hashTableEntry ? hashTableEntry->id : 0;
- if (propertyID) {
+ auto* hashTableEntry = findProperty(name, outputLength);
+ if (auto propertyID = hashTableEntry ? hashTableEntry->id : 0) {
propertyInfo.hadPixelOrPosPrefix = hadPixelOrPosPrefix;
propertyInfo.propertyID = static_cast<CSSPropertyID>(propertyID);
- propertyInfoCache.add(stringForCache, propertyInfo);
+ propertyInfoCache.get().add(stringForCache, propertyInfo);
}
return propertyInfo;
}
-static inline JSValue getPropertyValueFallback(ExecState* exec, JSCSSStyleDeclaration* thisObj, unsigned index)
-{
- // If the property is a shorthand property (such as "padding"),
- // it can only be accessed using getPropertyValue.
- return jsStringWithCache(exec, thisObj->impl().getPropertyValueInternal(static_cast<CSSPropertyID>(index)));
-}
-
-static inline JSValue cssPropertyGetterPixelOrPosPrefix(ExecState* exec, JSCSSStyleDeclaration* thisObj, unsigned propertyID)
+static inline JSValue stylePropertyGetter(ExecState& state, JSCSSStyleDeclaration& thisObject, CSSPropertyID propertyID, const RefPtr<CSSValue>& value)
{
- // Set up pixelOrPos boolean to handle the fact that
- // pixelTop returns "CSS Top" as number value in unit pixels
- // posTop returns "CSS top" as number value in unit pixels _if_ its a
- // positioned element. if it is not a positioned element, return 0
- // from MSIE documentation FIXME: IMPLEMENT THAT (Dirk)
- RefPtr<CSSValue> v = thisObj->impl().getPropertyCSSValueInternal(static_cast<CSSPropertyID>(propertyID));
- if (v) {
- if (v->isPrimitiveValue())
- return jsNumber(static_pointer_cast<CSSPrimitiveValue>(v)->getFloatValue(CSSPrimitiveValue::CSS_PX));
- return jsStringOrNull(exec, v->cssText());
- }
-
- return getPropertyValueFallback(exec, thisObj, propertyID);
+ if (value)
+ return toJS<IDLNullable<IDLDOMString>>(state, value->cssText());
+ // If the property is a shorthand property (such as "padding"), it can only be accessed using getPropertyValue.
+ return toJS<IDLDOMString>(state, thisObject.wrapped().getPropertyValueInternal(propertyID));
}
-static EncodedJSValue cssPropertyGetterPixelOrPosPrefixCallback(ExecState* exec, EncodedJSValue, EncodedJSValue thisValue, unsigned propertyID)
+static inline JSValue stylePropertyGetter(ExecState& state, JSCSSStyleDeclaration& thisObject, CSSPropertyID propertyID)
{
- JSCSSStyleDeclaration* thisObject = jsDynamicCast<JSCSSStyleDeclaration*>(JSValue::decode(thisValue));
- if (!thisObject)
- return throwVMTypeError(exec);
- return JSValue::encode(cssPropertyGetterPixelOrPosPrefix(exec, thisObject, propertyID));
+ return stylePropertyGetter(state, thisObject, propertyID, thisObject.wrapped().getPropertyCSSValueInternal(propertyID));
}
-static inline JSValue cssPropertyGetter(ExecState* exec, JSCSSStyleDeclaration* thisObj, unsigned propertyID)
+static inline JSValue stylePropertyGetterPixelOrPosPrefix(ExecState& state, JSCSSStyleDeclaration& thisObject, CSSPropertyID propertyID)
{
- RefPtr<CSSValue> v = thisObj->impl().getPropertyCSSValueInternal(static_cast<CSSPropertyID>(propertyID));
- if (v)
- return jsStringOrNull(exec, v->cssText());
-
- return getPropertyValueFallback(exec, thisObj, propertyID);
+ // Call this version of the getter so that, e.g., pixelTop returns top as a number
+ // in pixel units and posTop should does the same _if_ this is a positioned element.
+ // FIXME: If not a positioned element, MSIE documentation says posTop should return 0; this rule is not implemented.
+ auto value = thisObject.wrapped().getPropertyCSSValueInternal(propertyID);
+ if (is<CSSPrimitiveValue>(value.get()))
+ return jsNumber(downcast<CSSPrimitiveValue>(*value).floatValue(CSSPrimitiveValue::CSS_PX));
+ return stylePropertyGetter(state, thisObject, propertyID, value);
}
-static EncodedJSValue cssPropertyGetterCallback(ExecState* exec, EncodedJSValue, EncodedJSValue thisValue, unsigned propertyID)
+static inline JSValue stylePropertyGetter(ExecState& state, JSCSSStyleDeclaration& thisObject, const CSSPropertyInfo& propertyInfo)
{
- JSCSSStyleDeclaration* thisObject = jsDynamicCast<JSCSSStyleDeclaration*>(JSValue::decode(thisValue));
- if (!thisObject)
- return throwVMTypeError(exec);
- return JSValue::encode(cssPropertyGetter(exec, thisObject, propertyID));
+ if (propertyInfo.hadPixelOrPosPrefix)
+ return stylePropertyGetterPixelOrPosPrefix(state, thisObject, propertyInfo.propertyID);
+ return stylePropertyGetter(state, thisObject, propertyInfo.propertyID);
}
-bool JSCSSStyleDeclaration::getOwnPropertySlotDelegate(ExecState*, PropertyName propertyIdentifier, PropertySlot& slot)
+bool JSCSSStyleDeclaration::getOwnPropertySlotDelegate(ExecState* state, PropertyName propertyName, PropertySlot& slot)
{
- CSSPropertyInfo propertyInfo = cssPropertyIDForJSCSSPropertyName(propertyIdentifier);
+ auto propertyInfo = parseJavaScriptCSSPropertyName(propertyName);
if (!propertyInfo.propertyID)
return false;
-
- if (propertyInfo.hadPixelOrPosPrefix)
- slot.setCustomIndex(this, ReadOnly | DontDelete | DontEnum, static_cast<unsigned>(propertyInfo.propertyID), cssPropertyGetterPixelOrPosPrefixCallback);
- else
- slot.setCustomIndex(this, ReadOnly | DontDelete | DontEnum, static_cast<unsigned>(propertyInfo.propertyID), cssPropertyGetterCallback);
+ slot.setValue(this, DontDelete, stylePropertyGetter(*state, *this, propertyInfo));
return true;
}
-bool JSCSSStyleDeclaration::putDelegate(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot&)
+bool JSCSSStyleDeclaration::putDelegate(ExecState* state, PropertyName propertyName, JSValue value, PutPropertySlot&, bool& putResult)
{
- CSSPropertyInfo propertyInfo = cssPropertyIDForJSCSSPropertyName(propertyName);
+ CustomElementReactionStack customElementReactionStack;
+ auto propertyInfo = parseJavaScriptCSSPropertyName(propertyName);
if (!propertyInfo.propertyID)
return false;
- String propValue = valueToStringWithNullCheck(exec, value);
+ auto propertyValue = convert<IDLDOMString>(*state, value, StringConversionConfiguration::TreatNullAsEmptyString);
if (propertyInfo.hadPixelOrPosPrefix)
- propValue.append("px");
+ propertyValue.append("px");
bool important = false;
if (Settings::shouldRespectPriorityInCSSAttributeSetters()) {
- size_t importantIndex = propValue.find("!important", 0, false);
- if (importantIndex != notFound) {
+ auto importantIndex = propertyValue.findIgnoringASCIICase("!important");
+ if (importantIndex && importantIndex != notFound) {
important = true;
- propValue = propValue.left(importantIndex - 1);
+ propertyValue = propertyValue.left(importantIndex - 1);
}
}
- ExceptionCode ec = 0;
- impl().setPropertyInternal(static_cast<CSSPropertyID>(propertyInfo.propertyID), propValue, important, ec);
- setDOMException(exec, ec);
+ auto setPropertyInternalResult = wrapped().setPropertyInternal(propertyInfo.propertyID, propertyValue, important);
+ if (setPropertyInternalResult.hasException()) {
+ auto& vm = state->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ propagateException(*state, scope, setPropertyInternalResult.releaseException());
+ return true;
+ }
+ putResult = setPropertyInternalResult.releaseReturnValue();
return true;
}
-JSValue JSCSSStyleDeclaration::getPropertyCSSValue(ExecState* exec)
+JSValue JSCSSStyleDeclaration::getPropertyCSSValue(ExecState& state)
{
- const String& propertyName = exec->argument(0).toString(exec)->value(exec);
- if (exec->hadException())
- return jsUndefined();
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (UNLIKELY(state.argumentCount() < 1))
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
- RefPtr<CSSValue> cssValue = impl().getPropertyCSSValue(propertyName);
- if (!cssValue)
+ auto propertyName = state.uncheckedArgument(0).toWTFString(&state);
+ RETURN_IF_EXCEPTION(scope, JSValue());
+
+ auto value = wrapped().getPropertyCSSValue(propertyName);
+ if (!value)
return jsNull();
- currentWorld(exec).m_cssValueRoots.add(cssValue.get(), root(&impl())); // Balanced by JSCSSValueOwner::finalize().
- return toJS(exec, globalObject(), WTF::getPtr(cssValue));
+ globalObject()->world().m_deprecatedCSSOMValueRoots.add(value.get(), root(&wrapped())); // Balanced by JSDeprecatedCSSOMValueOwner::finalize().
+ return toJS(&state, globalObject(), *value);
}
-void JSCSSStyleDeclaration::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+void JSCSSStyleDeclaration::getOwnPropertyNames(JSObject* object, ExecState* state, PropertyNameArray& propertyNames, EnumerationMode mode)
{
- JSCSSStyleDeclaration* thisObject = jsCast<JSCSSStyleDeclaration*>(object);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
-
- unsigned length = thisObject->impl().length();
- for (unsigned i = 0; i < length; ++i)
- propertyNames.add(Identifier::from(exec, i));
-
- static Identifier* propertyIdentifiers = 0;
- if (!propertyIdentifiers) {
- Vector<String, numCSSProperties> jsPropertyNames;
- for (int id = firstCSSProperty; id < firstCSSProperty + numCSSProperties; ++id)
- jsPropertyNames.append(getJSPropertyName(static_cast<CSSPropertyID>(id)));
- std::sort(jsPropertyNames.begin(), jsPropertyNames.end(), WTF::codePointCompareLessThan);
-
- propertyIdentifiers = new Identifier[numCSSProperties];
+ static const Identifier* const cssPropertyNames = [state] {
+ String names[numCSSProperties];
for (int i = 0; i < numCSSProperties; ++i)
- propertyIdentifiers[i] = Identifier(exec, jsPropertyNames[i].impl());
- }
+ names[i] = getJSPropertyName(static_cast<CSSPropertyID>(firstCSSProperty + i));
+ std::sort(&names[0], &names[numCSSProperties], WTF::codePointCompareLessThan);
+ auto* identifiers = new Identifier[numCSSProperties];
+ for (int i = 0; i < numCSSProperties; ++i)
+ identifiers[i] = Identifier::fromString(state, names[i]);
+ return identifiers;
+ }();
+ unsigned length = jsCast<JSCSSStyleDeclaration*>(object)->wrapped().length();
+ for (unsigned i = 0; i < length; ++i)
+ propertyNames.add(Identifier::from(state, i));
for (int i = 0; i < numCSSProperties; ++i)
- propertyNames.add(propertyIdentifiers[i]);
+ propertyNames.add(cssPropertyNames[i]);
- Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
+ Base::getOwnPropertyNames(object, state, propertyNames, mode);
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.h b/Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.h
index 6ed1fec30..af2a9dce5 100644
--- a/Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.h
+++ b/Source/WebCore/bindings/js/JSCSSStyleDeclarationCustom.h
@@ -23,26 +23,12 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSCSSStyleDeclarationCustom_h
-#define JSCSSStyleDeclarationCustom_h
-
-#include "CSSRule.h"
-#include "CSSStyleDeclaration.h"
-#include "CSSStyleSheet.h"
-#include "JSCSSStyleDeclaration.h"
-#include "JSStyleSheetCustom.h"
+#pragma once
namespace WebCore {
-inline void* root(CSSStyleDeclaration* style)
-{
- if (CSSRule* parentRule = style->parentRule())
- return root(parentRule);
- if (CSSStyleSheet* styleSheet = style->parentStyleSheet())
- return root(styleSheet);
- return style;
-}
+class CSSStyleDeclaration;
-}
+void* root(CSSStyleDeclaration*);
-#endif // JSCSSStyleDeclarationCustom_h
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSCSSValueCustom.cpp b/Source/WebCore/bindings/js/JSCSSValueCustom.cpp
index 050e4b8e3..13e23701d 100644
--- a/Source/WebCore/bindings/js/JSCSSValueCustom.cpp
+++ b/Source/WebCore/bindings/js/JSCSSValueCustom.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -24,90 +24,50 @@
*/
#include "config.h"
-#include "JSCSSValue.h"
-#include "CSSPrimitiveValue.h"
-#include "CSSValueList.h"
-#include "JSCSSPrimitiveValue.h"
-#include "JSCSSValueList.h"
+#include "DeprecatedCSSOMPrimitiveValue.h"
+#include "DeprecatedCSSOMValueList.h"
+#include "JSDeprecatedCSSOMPrimitiveValue.h"
+#include "JSDeprecatedCSSOMValue.h"
+#include "JSDeprecatedCSSOMValueList.h"
#include "JSNode.h"
-#include "JSWebKitCSSTransformValue.h"
-#include "WebKitCSSTransformValue.h"
-
-#if ENABLE(CSS_FILTERS)
-#include "JSWebKitCSSFilterValue.h"
-#include "WebKitCSSFilterValue.h"
-#endif
-
-#if ENABLE(SVG)
-#include "JSSVGColor.h"
-#include "JSSVGPaint.h"
-#include "SVGColor.h"
-#include "SVGPaint.h"
-#endif
using namespace JSC;
namespace WebCore {
-bool JSCSSValueOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, SlotVisitor& visitor)
+bool JSDeprecatedCSSOMValueOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void* context, SlotVisitor& visitor)
{
- JSCSSValue* jsCSSValue = jsCast<JSCSSValue*>(handle.get().asCell());
+ JSDeprecatedCSSOMValue* jsCSSValue = jsCast<JSDeprecatedCSSOMValue*>(handle.slot()->asCell());
if (!jsCSSValue->hasCustomProperties())
return false;
DOMWrapperWorld* world = static_cast<DOMWrapperWorld*>(context);
- void* root = world->m_cssValueRoots.get(&jsCSSValue->impl());
+ void* root = world->m_deprecatedCSSOMValueRoots.get(&jsCSSValue->wrapped());
if (!root)
return false;
return visitor.containsOpaqueRoot(root);
}
-void JSCSSValueOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context)
+void JSDeprecatedCSSOMValueOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context)
{
- JSCSSValue* jsCSSValue = jsCast<JSCSSValue*>(handle.get().asCell());
+ JSDeprecatedCSSOMValue* jsCSSValue = static_cast<JSDeprecatedCSSOMValue*>(handle.slot()->asCell());
DOMWrapperWorld& world = *static_cast<DOMWrapperWorld*>(context);
- world.m_cssValueRoots.remove(&jsCSSValue->impl());
- uncacheWrapper(world, &jsCSSValue->impl(), jsCSSValue);
- jsCSSValue->releaseImpl();
+ world.m_deprecatedCSSOMValueRoots.remove(&jsCSSValue->wrapped());
+ uncacheWrapper(world, &jsCSSValue->wrapped(), jsCSSValue);
}
-JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, CSSValue* value)
+JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<DeprecatedCSSOMValue>&& value)
{
- if (!value)
- return jsNull();
-
- // Scripts should only ever see cloned CSSValues, never the internal ones.
- ASSERT(value->isCSSOMSafe());
-
- // If we're here under erroneous circumstances, prefer returning null over a potentially insecure value.
- if (!value->isCSSOMSafe())
- return jsNull();
-
- JSObject* wrapper = getCachedWrapper(currentWorld(exec), value);
-
- if (wrapper)
- return wrapper;
-
- if (value->isWebKitCSSTransformValue())
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, WebKitCSSTransformValue, value);
-#if ENABLE(CSS_FILTERS)
- else if (value->isWebKitCSSFilterValue())
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, WebKitCSSFilterValue, value);
-#endif
- else if (value->isValueList())
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSValueList, value);
-#if ENABLE(SVG)
- else if (value->isSVGPaint())
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, SVGPaint, value);
- else if (value->isSVGColor())
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, SVGColor, value);
-#endif
- else if (value->isPrimitiveValue())
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSPrimitiveValue, value);
- else
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSValue, value);
+ if (value->isValueList())
+ return createWrapper<DeprecatedCSSOMValueList>(globalObject, WTFMove(value));
+ if (value->isPrimitiveValue())
+ return createWrapper<DeprecatedCSSOMPrimitiveValue>(globalObject, WTFMove(value));
+ return createWrapper<DeprecatedCSSOMValue>(globalObject, WTFMove(value));
+}
- return wrapper;
+JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, DeprecatedCSSOMValue& value)
+{
+ return wrap(state, globalObject, value);
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSCallbackData.cpp b/Source/WebCore/bindings/js/JSCallbackData.cpp
index f53d4404f..655eaf44c 100644
--- a/Source/WebCore/bindings/js/JSCallbackData.cpp
+++ b/Source/WebCore/bindings/js/JSCallbackData.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2007-2009, 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -33,60 +33,63 @@
#include "JSDOMBinding.h"
#include "JSMainThreadExecState.h"
#include "JSMainThreadExecStateInstrumentation.h"
+#include <runtime/Exception.h>
using namespace JSC;
namespace WebCore {
-void JSCallbackData::deleteData(void* context)
+JSValue JSCallbackData::invokeCallback(JSDOMGlobalObject& globalObject, JSObject* callback, MarkedArgumentBuffer& args, CallbackType method, PropertyName functionName, NakedPtr<JSC::Exception>& returnedException)
{
- delete static_cast<JSCallbackData*>(context);
-}
-
-JSValue JSCallbackData::invokeCallback(MarkedArgumentBuffer& args, bool* raisedException)
-{
- ASSERT(callback());
- return invokeCallback(callback(), args, raisedException);
-}
+ ASSERT(callback);
-JSValue JSCallbackData::invokeCallback(JSValue thisValue, MarkedArgumentBuffer& args, bool* raisedException)
-{
- ASSERT(callback());
- ASSERT(globalObject());
+ ExecState* exec = globalObject.globalExec();
+ JSValue function;
+ CallData callData;
+ CallType callType = CallType::None;
- ExecState* exec = globalObject()->globalExec();
- JSValue function = callback();
+ if (method != CallbackType::Object) {
+ function = callback;
+ callType = callback->methodTable()->getCallData(callback, callData);
+ }
+ if (callType == CallType::None) {
+ if (method == CallbackType::Function) {
+ returnedException = JSC::Exception::create(exec->vm(), createTypeError(exec));
+ return JSValue();
+ }
- CallData callData;
- CallType callType = callback()->methodTable()->getCallData(callback(), callData);
- if (callType == CallTypeNone) {
- function = callback()->get(exec, Identifier(exec, "handleEvent"));
+ ASSERT(!functionName.isNull());
+ function = callback->get(exec, functionName);
callType = getCallData(function, callData);
- if (callType == CallTypeNone)
+ if (callType == CallType::None) {
+ returnedException = JSC::Exception::create(exec->vm(), createTypeError(exec));
return JSValue();
+ }
}
- ScriptExecutionContext* context = globalObject()->scriptExecutionContext();
+ ASSERT(!function.isEmpty());
+ ASSERT(callType != CallType::None);
+
+ ScriptExecutionContext* context = globalObject.scriptExecutionContext();
// We will fail to get the context if the frame has been detached.
if (!context)
return JSValue();
InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(context, callType, callData);
+ returnedException = nullptr;
JSValue result = context->isDocument()
- ? JSMainThreadExecState::call(exec, function, callType, callData, thisValue, args)
- : JSC::call(exec, function, callType, callData, thisValue, args);
+ ? JSMainThreadExecState::profiledCall(exec, JSC::ProfilingReason::Other, function, callType, callData, callback, args, returnedException)
+ : JSC::profiledCall(exec, JSC::ProfilingReason::Other, function, callType, callData, callback, args, returnedException);
- InspectorInstrumentation::didCallFunction(cookie);
-
- if (exec->hadException()) {
- reportCurrentException(exec);
- if (raisedException)
- *raisedException = true;
- return result;
- }
+ InspectorInstrumentation::didCallFunction(cookie, context);
return result;
}
+bool JSCallbackDataWeak::WeakOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, SlotVisitor& visitor)
+{
+ return visitor.containsOpaqueRoot(context);
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSCallbackData.h b/Source/WebCore/bindings/js/JSCallbackData.h
index ff76a9e85..3ea990e56 100644
--- a/Source/WebCore/bindings/js/JSCallbackData.h
+++ b/Source/WebCore/bindings/js/JSCallbackData.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2007-2009, 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -26,8 +26,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSCallbackData_h
-#define JSCallbackData_h
+#pragma once
#include "JSDOMBinding.h"
#include "JSDOMGlobalObject.h"
@@ -45,11 +44,13 @@ namespace WebCore {
class JSCallbackData {
public:
- static void deleteData(void*);
+ enum class CallbackType { Function, Object, FunctionOrObject };
- JSCallbackData(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)
- : m_callback(globalObject->vm(), callback)
- , m_globalObject(globalObject->vm(), globalObject)
+ JSDOMGlobalObject* globalObject() { return m_globalObject.get(); }
+
+protected:
+ explicit JSCallbackData(JSDOMGlobalObject* globalObject)
+ : m_globalObject(globalObject)
#ifndef NDEBUG
, m_thread(currentThread())
#endif
@@ -62,40 +63,74 @@ public:
ASSERT(m_thread == currentThread());
#endif
}
-
- JSC::JSObject* callback() { return m_callback.get(); }
- JSDOMGlobalObject* globalObject() { return m_globalObject.get(); }
- JSC::JSValue invokeCallback(JSC::MarkedArgumentBuffer&, bool* raisedException = 0);
- JSC::JSValue invokeCallback(JSC::JSValue thisValue, JSC::MarkedArgumentBuffer&, bool* raisedException = 0);
+ static JSC::JSValue invokeCallback(JSDOMGlobalObject&, JSC::JSObject* callback, JSC::MarkedArgumentBuffer&, CallbackType, JSC::PropertyName functionName, NakedPtr<JSC::Exception>& returnedException);
private:
- JSC::Strong<JSC::JSObject> m_callback;
- JSC::Strong<JSDOMGlobalObject> m_globalObject;
+ JSC::Weak<JSDOMGlobalObject> m_globalObject;
#ifndef NDEBUG
ThreadIdentifier m_thread;
#endif
};
-class DeleteCallbackDataTask : public ScriptExecutionContext::Task {
+class JSCallbackDataStrong : public JSCallbackData {
public:
- static PassOwnPtr<DeleteCallbackDataTask> create(JSCallbackData* data)
+ JSCallbackDataStrong(JSC::JSObject* callback, JSDOMGlobalObject* globalObject, void*)
+ : JSCallbackData(globalObject)
+ , m_callback(globalObject->vm(), callback)
{
- return adoptPtr(new DeleteCallbackDataTask(data));
}
- virtual void performTask(ScriptExecutionContext*)
+ JSC::JSObject* callback() { return m_callback.get(); }
+
+ JSC::JSValue invokeCallback(JSC::MarkedArgumentBuffer& args, CallbackType callbackType, JSC::PropertyName functionName, NakedPtr<JSC::Exception>& returnedException)
{
- delete m_data;
+ auto* globalObject = this->globalObject();
+ if (!globalObject)
+ return { };
+
+ return JSCallbackData::invokeCallback(*globalObject, callback(), args, callbackType, functionName, returnedException);
}
- virtual bool isCleanupTask() const { return true; }
+
private:
+ JSC::Strong<JSC::JSObject> m_callback;
+};
+
+class JSCallbackDataWeak : public JSCallbackData {
+public:
+ JSCallbackDataWeak(JSC::JSObject* callback, JSDOMGlobalObject* globalObject, void* owner)
+ : JSCallbackData(globalObject)
+ , m_callback(callback, &m_weakOwner, owner)
+ {
+ }
+
+ JSC::JSObject* callback() { return m_callback.get(); }
- DeleteCallbackDataTask(JSCallbackData* data) : m_data(data) {}
+ JSC::JSValue invokeCallback(JSC::MarkedArgumentBuffer& args, CallbackType callbackType, JSC::PropertyName functionName, NakedPtr<JSC::Exception>& returnedException)
+ {
+ auto* globalObject = this->globalObject();
+ if (!globalObject)
+ return { };
+
+ return JSCallbackData::invokeCallback(*globalObject, callback(), args, callbackType, functionName, returnedException);
+ }
- JSCallbackData* m_data;
+private:
+ class WeakOwner : public JSC::WeakHandleOwner {
+ bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::SlotVisitor&) override;
+ };
+ WeakOwner m_weakOwner;
+ JSC::Weak<JSC::JSObject> m_callback;
};
-} // namespace WebCore
+class DeleteCallbackDataTask : public ScriptExecutionContext::Task {
+public:
+ template <typename CallbackDataType>
+ explicit DeleteCallbackDataTask(CallbackDataType* data)
+ : ScriptExecutionContext::Task(ScriptExecutionContext::Task::CleanupTask, [data = std::unique_ptr<CallbackDataType>(data)] (ScriptExecutionContext&) {
+ })
+ {
+ }
+};
-#endif // JSCallbackData_h
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp b/Source/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp
index efa539fb5..b347e3bec 100644
--- a/Source/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp
+++ b/Source/WebCore/bindings/js/JSCanvasRenderingContext2DCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2006-2017 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -38,84 +38,16 @@ using namespace JSC;
namespace WebCore {
-static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, const CanvasStyle& style)
+bool JSCanvasRenderingContext2DOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
{
- if (style.canvasGradient())
- return toJS(exec, globalObject, style.canvasGradient());
- if (style.canvasPattern())
- return toJS(exec, globalObject, style.canvasPattern());
- return jsStringWithCache(exec, style.color());
+ JSCanvasRenderingContext2D* jsCanvasRenderingContext = jsCast<JSCanvasRenderingContext2D*>(handle.slot()->asCell());
+ void* root = WebCore::root(jsCanvasRenderingContext->wrapped().canvas());
+ return visitor.containsOpaqueRoot(root);
}
-static CanvasStyle toHTMLCanvasStyle(ExecState*, JSValue value)
+void JSCanvasRenderingContext2D::visitAdditionalChildren(SlotVisitor& visitor)
{
- if (!value.isObject())
- return CanvasStyle();
- JSObject* object = asObject(value);
- if (object->inherits(JSCanvasGradient::info()))
- return CanvasStyle(&jsCast<JSCanvasGradient*>(object)->impl());
- if (object->inherits(JSCanvasPattern::info()))
- return CanvasStyle(&jsCast<JSCanvasPattern*>(object)->impl());
- return CanvasStyle();
-}
-
-JSValue JSCanvasRenderingContext2D::strokeStyle(ExecState* exec) const
-{
- return toJS(exec, globalObject(), impl().strokeStyle());
-}
-
-void JSCanvasRenderingContext2D::setStrokeStyle(ExecState* exec, JSValue value)
-{
- CanvasRenderingContext2D& context = impl();
- if (value.isString()) {
- context.setStrokeColor(asString(value)->value(exec));
- return;
- }
- context.setStrokeStyle(toHTMLCanvasStyle(exec, value));
-}
-
-JSValue JSCanvasRenderingContext2D::fillStyle(ExecState* exec) const
-{
- return toJS(exec, globalObject(), impl().fillStyle());
-}
-
-void JSCanvasRenderingContext2D::setFillStyle(ExecState* exec, JSValue value)
-{
- CanvasRenderingContext2D& context = impl();
- if (value.isString()) {
- context.setFillColor(asString(value)->value(exec));
- return;
- }
- context.setFillStyle(toHTMLCanvasStyle(exec, value));
-}
-
-JSValue JSCanvasRenderingContext2D::webkitLineDash(ExecState* exec) const
-{
- const Vector<float>& dash = impl().getLineDash();
-
- MarkedArgumentBuffer list;
- Vector<float>::const_iterator end = dash.end();
- for (Vector<float>::const_iterator it = dash.begin(); it != end; ++it)
- list.append(JSValue(*it));
- return constructArray(exec, 0, globalObject(), list);
-}
-
-void JSCanvasRenderingContext2D::setWebkitLineDash(ExecState* exec, JSValue value)
-{
- if (!isJSArray(value))
- return;
-
- Vector<float> dash;
- JSArray* valueArray = asArray(value);
- for (unsigned i = 0; i < valueArray->length(); ++i) {
- float elem = valueArray->getIndex(exec, i).toFloat(exec);
- if (elem <= 0 || !std::isfinite(elem))
- return;
-
- dash.append(elem);
- }
-
- impl().setWebkitLineDash(dash);
+ visitor.addOpaqueRoot(root(wrapped().canvas()));
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSCanvasRenderingContextCustom.cpp b/Source/WebCore/bindings/js/JSCanvasRenderingContextCustom.cpp
deleted file mode 100644
index 0314bd205..000000000
--- a/Source/WebCore/bindings/js/JSCanvasRenderingContextCustom.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "JSCanvasRenderingContext.h"
-
-#include "CanvasRenderingContext2D.h"
-#include "HTMLCanvasElement.h"
-#include "JSCanvasRenderingContext2D.h"
-#include "JSNode.h"
-#if ENABLE(WEBGL)
-#include "WebGLRenderingContext.h"
-#include "JSWebGLRenderingContext.h"
-#endif
-
-using namespace JSC;
-
-namespace WebCore {
-
-void JSCanvasRenderingContext::visitChildren(JSCell* cell, SlotVisitor& visitor)
-{
- JSCanvasRenderingContext* thisObject = jsCast<JSCanvasRenderingContext*>(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(thisObject, visitor);
-
- visitor.addOpaqueRoot(root(thisObject->impl().canvas()));
-}
-
-JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, CanvasRenderingContext* object)
-{
- if (!object)
- return jsNull();
-
-#if ENABLE(WEBGL)
- if (object->is3d())
- return wrap<JSWebGLRenderingContext>(exec, globalObject, static_cast<WebGLRenderingContext*>(object));
-#endif
- ASSERT_WITH_SECURITY_IMPLICATION(object->is2d());
- return wrap<JSCanvasRenderingContext2D>(exec, globalObject, static_cast<CanvasRenderingContext2D*>(object));
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSClipboardCustom.cpp b/Source/WebCore/bindings/js/JSClipboardCustom.cpp
deleted file mode 100644
index 47314441c..000000000
--- a/Source/WebCore/bindings/js/JSClipboardCustom.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2008, 2013 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "JSClipboard.h"
-
-#include "Clipboard.h"
-
-using namespace JSC;
-
-namespace WebCore {
-
-JSValue JSClipboard::types(ExecState* exec) const
-{
- Vector<String> types = impl().types();
- return types.isEmpty() ? jsNull() : jsArray(exec, globalObject(), types);
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSCommandLineAPIHostCustom.cpp b/Source/WebCore/bindings/js/JSCommandLineAPIHostCustom.cpp
index be0ae27f3..d89b305be 100644
--- a/Source/WebCore/bindings/js/JSCommandLineAPIHostCustom.cpp
+++ b/Source/WebCore/bindings/js/JSCommandLineAPIHostCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007-2008, 2016 Apple Inc. All rights reserved.
* Copyright (C) 2008 Matt Lilek <webkit@mattlilek.com>
* Copyright (C) 2010-2011 Google Inc. All rights reserved.
*
@@ -31,13 +31,12 @@
*/
#include "config.h"
-
-#if ENABLE(INSPECTOR)
-
#include "JSCommandLineAPIHost.h"
#include "CommandLineAPIHost.h"
+#include "Database.h"
#include "InspectorDOMAgent.h"
+#include "JSDatabase.h"
#include "JSEventListener.h"
#include "JSNode.h"
#include "JSStorage.h"
@@ -45,129 +44,120 @@
#include <bindings/ScriptValue.h>
#include <inspector/InspectorValues.h>
#include <parser/SourceCode.h>
+#include <runtime/IdentifierInlines.h>
#include <runtime/JSArray.h>
#include <runtime/JSFunction.h>
#include <runtime/JSLock.h>
#include <runtime/ObjectConstructor.h>
-#if ENABLE(SQL_DATABASE)
-#include "Database.h"
-#include "JSDatabase.h"
-#endif
-
using namespace JSC;
namespace WebCore {
-JSValue JSCommandLineAPIHost::inspectedObject(ExecState* exec)
+JSValue JSCommandLineAPIHost::inspectedObject(ExecState& state)
{
- if (exec->argumentCount() < 1)
- return jsUndefined();
-
- CommandLineAPIHost::InspectableObject* object = impl().inspectedObject(exec->uncheckedArgument(0).toInt32(exec));
+ CommandLineAPIHost::InspectableObject* object = wrapped().inspectedObject();
if (!object)
return jsUndefined();
- JSLockHolder lock(exec);
- Deprecated::ScriptValue scriptValue = object->get(exec);
- if (scriptValue.hasNoValue())
- return jsUndefined();
-
- return scriptValue.jsValue();
+ JSLockHolder lock(&state);
+ auto scriptValue = object->get(state);
+ return scriptValue ? scriptValue : jsUndefined();
}
-static JSArray* getJSListenerFunctions(ExecState* exec, Document* document, const EventListenerInfo& listenerInfo)
+static JSArray* getJSListenerFunctions(ExecState& state, Document* document, const EventListenerInfo& listenerInfo)
{
- JSArray* result = constructEmptyArray(exec, nullptr);
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ JSArray* result = constructEmptyArray(&state, nullptr);
+ RETURN_IF_EXCEPTION(scope, nullptr);
size_t handlersCount = listenerInfo.eventListenerVector.size();
for (size_t i = 0, outputIndex = 0; i < handlersCount; ++i) {
- const JSEventListener* jsListener = JSEventListener::cast(listenerInfo.eventListenerVector[i].listener.get());
+ const JSEventListener* jsListener = JSEventListener::cast(&listenerInfo.eventListenerVector[i]->callback());
if (!jsListener) {
ASSERT_NOT_REACHED();
continue;
}
// Hide listeners from other contexts.
- if (&jsListener->isolatedWorld() != &currentWorld(exec))
+ if (&jsListener->isolatedWorld() != &currentWorld(&state))
continue;
JSObject* function = jsListener->jsFunction(document);
if (!function)
continue;
- JSObject* listenerEntry = constructEmptyObject(exec);
- listenerEntry->putDirect(exec->vm(), Identifier(exec, "listener"), function);
- listenerEntry->putDirect(exec->vm(), Identifier(exec, "useCapture"), jsBoolean(listenerInfo.eventListenerVector[i].useCapture));
- result->putDirectIndex(exec, outputIndex++, JSValue(listenerEntry));
+ JSObject* listenerEntry = constructEmptyObject(&state);
+ listenerEntry->putDirect(vm, Identifier::fromString(&state, "listener"), function);
+ listenerEntry->putDirect(vm, Identifier::fromString(&state, "useCapture"), jsBoolean(listenerInfo.eventListenerVector[i]->useCapture()));
+ result->putDirectIndex(&state, outputIndex++, JSValue(listenerEntry));
+ RETURN_IF_EXCEPTION(scope, nullptr);
}
return result;
}
-JSValue JSCommandLineAPIHost::getEventListeners(ExecState* exec)
+JSValue JSCommandLineAPIHost::getEventListeners(ExecState& state)
{
- if (exec->argumentCount() < 1)
+ if (state.argumentCount() < 1)
return jsUndefined();
- JSValue value = exec->uncheckedArgument(0);
+ VM& vm = state.vm();
+ JSValue value = state.uncheckedArgument(0);
if (!value.isObject() || value.isNull())
return jsUndefined();
- Node* node = toNode(value);
+ Node* node = JSNode::toWrapped(vm, value);
if (!node)
return jsUndefined();
Vector<EventListenerInfo> listenersArray;
- impl().getEventListenersImpl(node, listenersArray);
+ wrapped().getEventListenersImpl(node, listenersArray);
- JSObject* result = constructEmptyObject(exec);
+ JSObject* result = constructEmptyObject(&state);
for (size_t i = 0; i < listenersArray.size(); ++i) {
- JSArray* listeners = getJSListenerFunctions(exec, &node->document(), listenersArray[i]);
+ JSArray* listeners = getJSListenerFunctions(state, &node->document(), listenersArray[i]);
if (!listeners->length())
continue;
AtomicString eventType = listenersArray[i].eventType;
- result->putDirect(exec->vm(), Identifier(exec, eventType.impl()), JSValue(listeners));
+ result->putDirect(state.vm(), Identifier::fromString(&state, eventType.impl()), JSValue(listeners));
}
return result;
}
-JSValue JSCommandLineAPIHost::inspect(ExecState* exec)
+JSValue JSCommandLineAPIHost::inspect(ExecState& state)
{
- if (exec->argumentCount() >= 2) {
- Deprecated::ScriptValue object(exec->vm(), exec->uncheckedArgument(0));
- Deprecated::ScriptValue hints(exec->vm(), exec->uncheckedArgument(1));
- impl().inspectImpl(object.toInspectorValue(exec), hints.toInspectorValue(exec));
- }
-
+ if (state.argumentCount() < 2)
+ return jsUndefined();
+ wrapped().inspectImpl(Inspector::toInspectorValue(state, state.uncheckedArgument(0)),
+ Inspector::toInspectorValue(state, state.uncheckedArgument(1)));
return jsUndefined();
}
-JSValue JSCommandLineAPIHost::databaseId(ExecState* exec)
+JSValue JSCommandLineAPIHost::databaseId(ExecState& state)
{
- if (exec->argumentCount() < 1)
+ if (state.argumentCount() < 1)
return jsUndefined();
-#if ENABLE(SQL_DATABASE)
- Database* database = toDatabase(exec->uncheckedArgument(0));
+ VM& vm = state.vm();
+ Database* database = JSDatabase::toWrapped(vm, state.uncheckedArgument(0));
if (database)
- return jsStringWithCache(exec, impl().databaseIdImpl(database));
-#endif
+ return jsStringWithCache(&state, wrapped().databaseIdImpl(database));
return jsUndefined();
}
-JSValue JSCommandLineAPIHost::storageId(ExecState* exec)
+JSValue JSCommandLineAPIHost::storageId(ExecState& state)
{
- if (exec->argumentCount() < 1)
+ if (state.argumentCount() < 1)
return jsUndefined();
- Storage* storage = toStorage(exec->uncheckedArgument(0));
+ VM& vm = state.vm();
+ Storage* storage = JSStorage::toWrapped(vm, state.uncheckedArgument(0));
if (storage)
- return jsStringWithCache(exec, impl().storageIdImpl(storage));
+ return jsStringWithCache(&state, wrapped().storageIdImpl(storage));
return jsUndefined();
}
} // namespace WebCore
-
-#endif // ENABLE(INSPECTOR)
diff --git a/Source/WebCore/bindings/js/JSCryptoAlgorithmBuilder.cpp b/Source/WebCore/bindings/js/JSCryptoAlgorithmBuilder.cpp
new file mode 100644
index 000000000..d99c27abd
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSCryptoAlgorithmBuilder.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSCryptoAlgorithmBuilder.h"
+
+#if ENABLE(SUBTLE_CRYPTO)
+
+#include <runtime/JSCInlines.h>
+#include <runtime/ObjectConstructor.h>
+#include <runtime/TypedArrays.h>
+#include <runtime/TypedArrayInlines.h>
+#include <runtime/VMEntryScope.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSCryptoAlgorithmBuilder::JSCryptoAlgorithmBuilder(ExecState* exec)
+ : m_exec(exec)
+ , m_dictionary(constructEmptyObject(exec))
+{
+}
+
+JSCryptoAlgorithmBuilder::~JSCryptoAlgorithmBuilder()
+{
+}
+
+void JSCryptoAlgorithmBuilder::add(const char* key, unsigned value)
+{
+ VM& vm = m_exec->vm();
+ Identifier identifier = Identifier::fromString(&vm, key);
+ m_dictionary->putDirect(vm, identifier, jsNumber(value));
+}
+
+void JSCryptoAlgorithmBuilder::add(const char* key, const String& value)
+{
+ VM& vm = m_exec->vm();
+ Identifier identifier = Identifier::fromString(&vm, key);
+ m_dictionary->putDirect(vm, identifier, jsString(m_exec, value));
+}
+
+void JSCryptoAlgorithmBuilder::add(const char* key, const Vector<uint8_t>& buffer)
+{
+ VM& vm = m_exec->vm();
+ Identifier identifier = Identifier::fromString(&vm, key);
+ RefPtr<Uint8Array> arrayView = Uint8Array::create(buffer.data(), buffer.size());
+ m_dictionary->putDirect(vm, identifier, arrayView->wrap(m_exec, vm.entryScope->globalObject()));
+}
+
+void JSCryptoAlgorithmBuilder::add(const char* key, const JSCryptoAlgorithmBuilder& nestedBuilder)
+{
+ VM& vm = m_exec->vm();
+ Identifier identifier = Identifier::fromString(&vm, key);
+ m_dictionary->putDirect(vm, identifier, nestedBuilder.result());
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SUBTLE_CRYPTO)
diff --git a/Source/WebCore/bindings/js/JSCryptoAlgorithmBuilder.h b/Source/WebCore/bindings/js/JSCryptoAlgorithmBuilder.h
new file mode 100644
index 000000000..ce696aef2
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSCryptoAlgorithmBuilder.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(SUBTLE_CRYPTO)
+
+#include <wtf/Forward.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace JSC {
+class ExecState;
+class JSObject;
+}
+
+namespace WebCore {
+
+class JSCryptoAlgorithmBuilder {
+ WTF_MAKE_NONCOPYABLE(JSCryptoAlgorithmBuilder);
+public:
+ JSCryptoAlgorithmBuilder(JSC::ExecState*);
+ virtual ~JSCryptoAlgorithmBuilder();
+
+ JSC::JSObject* result() const { return m_dictionary; }
+
+ void add(const char*, unsigned);
+ void add(const char*, const String&);
+ void add(const char*, const Vector<uint8_t>&);
+ void add(const char*, const JSCryptoAlgorithmBuilder&);
+
+private:
+ JSC::ExecState* m_exec;
+ JSC::JSObject* m_dictionary;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SUBTLE_CRYPTO)
diff --git a/Source/WebCore/bindings/js/JSCryptoAlgorithmDictionary.cpp b/Source/WebCore/bindings/js/JSCryptoAlgorithmDictionary.cpp
new file mode 100644
index 000000000..10e1230ed
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSCryptoAlgorithmDictionary.cpp
@@ -0,0 +1,668 @@
+/*
+ * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSCryptoAlgorithmDictionary.h"
+
+#if ENABLE(SUBTLE_CRYPTO)
+
+#include "CryptoAlgorithmAesCbcParamsDeprecated.h"
+#include "CryptoAlgorithmAesKeyGenParamsDeprecated.h"
+#include "CryptoAlgorithmHmacKeyParamsDeprecated.h"
+#include "CryptoAlgorithmHmacParamsDeprecated.h"
+#include "CryptoAlgorithmParameters.h"
+#include "CryptoAlgorithmRegistry.h"
+#include "CryptoAlgorithmRsaKeyGenParamsDeprecated.h"
+#include "CryptoAlgorithmRsaKeyParamsWithHashDeprecated.h"
+#include "CryptoAlgorithmRsaOaepParamsDeprecated.h"
+#include "CryptoAlgorithmRsaSsaParamsDeprecated.h"
+#include "ExceptionCode.h"
+#include "JSCryptoOperationData.h"
+#include "JSDOMBinding.h"
+#include "JSDOMConvert.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+static inline JSValue getProperty(ExecState& state, JSObject* object, const char* name)
+{
+ return object->get(&state, Identifier::fromString(&state, name));
+}
+
+CryptoAlgorithmIdentifier JSCryptoAlgorithmDictionary::parseAlgorithmIdentifier(ExecState& state, ThrowScope& scope, JSValue value)
+{
+ // typedef (Algorithm or DOMString) AlgorithmIdentifier;
+
+ String algorithmName;
+ VM& vm = state.vm();
+
+ if (value.isString()) {
+ algorithmName = asString(value)->value(&state);
+ RETURN_IF_EXCEPTION(scope, { });
+ } else if (value.isObject()) {
+ if (asObject(value)->inherits(vm, StringObject::info())) {
+ algorithmName = asStringObject(value)->internalValue()->value(&state);
+ RETURN_IF_EXCEPTION(scope, { });
+ } else {
+ // FIXME: This doesn't perform some checks mandated by WebIDL for dictionaries:
+ // - null and undefined input should be treated as if all elements in the dictionary were undefined;
+ // - undefined elements should be treated as having a default value, or as not present if there isn't such;
+ // - RegExp and Date objects cannot be converted to dictionaries.
+ //
+ // This is partially because we don't implement it elsewhere in WebCore yet, and partially because
+ // WebCrypto doesn't yet clearly specify what to do with non-present values in most cases anyway.
+
+ auto nameValue = getProperty(state, asObject(value), "name");
+ RETURN_IF_EXCEPTION(scope, { });
+
+ algorithmName = convert<IDLDOMString>(state, nameValue);
+ RETURN_IF_EXCEPTION(scope, { });
+ }
+ }
+
+ if (!algorithmName.containsOnlyASCII()) {
+ throwSyntaxError(&state, scope);
+ return { };
+ }
+
+ auto identifier = CryptoAlgorithmRegistry::singleton().identifier(algorithmName);
+ if (!identifier) {
+ throwNotSupportedError(state, scope);
+ return { };
+ }
+
+ return identifier.value();
+}
+
+static std::optional<CryptoAlgorithmIdentifier> optionalHashAlgorithm(ExecState& state, ThrowScope& scope, JSObject* object)
+{
+ auto hash = getProperty(state, object, "hash");
+ RETURN_IF_EXCEPTION(scope, { });
+
+ if (hash.isUndefinedOrNull())
+ return std::nullopt;
+
+ return JSCryptoAlgorithmDictionary::parseAlgorithmIdentifier(state, scope, hash);
+}
+
+static CryptoAlgorithmIdentifier requiredHashAlgorithm(ExecState& state, ThrowScope& scope, JSObject* object)
+{
+ auto result = optionalHashAlgorithm(state, scope, object);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ if (!result) {
+ throwNotSupportedError(state, scope);
+ return { };
+ }
+
+ return result.value();
+}
+
+static RefPtr<CryptoAlgorithmParametersDeprecated> createAesCbcParams(ExecState& state, JSValue value)
+{
+ auto scope = DECLARE_THROW_SCOPE(state.vm());
+
+ if (!value.isObject()) {
+ throwTypeError(&state, scope);
+ return nullptr;
+ }
+
+ auto iv = getProperty(state, asObject(value), "iv");
+ RETURN_IF_EXCEPTION(scope, { });
+
+ auto result = adoptRef(*new CryptoAlgorithmAesCbcParamsDeprecated);
+
+ auto ivData = cryptoOperationDataFromJSValue(state, scope, iv);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ if (ivData.second != 16) {
+ throwException(&state, scope, createError(&state, "AES-CBC initialization data must be 16 bytes"));
+ return nullptr;
+ }
+
+ memcpy(result->iv.data(), ivData.first, ivData.second);
+
+ return WTFMove(result);
+}
+
+static RefPtr<CryptoAlgorithmParametersDeprecated> createAesKeyGenParams(ExecState& state, JSValue value)
+{
+ auto scope = DECLARE_THROW_SCOPE(state.vm());
+
+ if (!value.isObject()) {
+ throwTypeError(&state, scope);
+ return nullptr;
+ }
+
+ auto result = adoptRef(*new CryptoAlgorithmAesKeyGenParamsDeprecated);
+
+ auto lengthValue = getProperty(state, asObject(value), "length");
+ RETURN_IF_EXCEPTION(scope, nullptr);
+
+ result->length = convert<IDLUnsignedShort>(state, lengthValue, IntegerConversionConfiguration::EnforceRange);
+
+ return WTFMove(result);
+}
+
+static RefPtr<CryptoAlgorithmParametersDeprecated> createHmacParams(ExecState& state, JSValue value)
+{
+ auto scope = DECLARE_THROW_SCOPE(state.vm());
+
+ if (!value.isObject()) {
+ throwTypeError(&state, scope);
+ return nullptr;
+ }
+
+ auto result = adoptRef(*new CryptoAlgorithmHmacParamsDeprecated);
+
+ result->hash = requiredHashAlgorithm(state, scope, asObject(value));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ return WTFMove(result);
+}
+
+static RefPtr<CryptoAlgorithmParametersDeprecated> createHmacKeyParams(ExecState& state, JSValue value)
+{
+ auto scope = DECLARE_THROW_SCOPE(state.vm());
+
+ if (!value.isObject()) {
+ throwTypeError(&state, scope);
+ return nullptr;
+ }
+
+ auto result = adoptRef(*new CryptoAlgorithmHmacKeyParamsDeprecated);
+
+ result->hash = requiredHashAlgorithm(state, scope, asObject(value));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ auto lengthValue = getProperty(state, asObject(value), "length");
+ RETURN_IF_EXCEPTION(scope, nullptr);
+
+ result->length = convert<IDLUnsignedShort>(state, lengthValue, IntegerConversionConfiguration::Normal);
+ RETURN_IF_EXCEPTION(scope, nullptr);
+
+ result->hasLength = true;
+
+ return WTFMove(result);
+}
+
+static RefPtr<CryptoAlgorithmParametersDeprecated> createRsaKeyGenParams(ExecState& state, JSValue value)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (!value.isObject()) {
+ throwTypeError(&state, scope);
+ return nullptr;
+ }
+
+ auto result = adoptRef(*new CryptoAlgorithmRsaKeyGenParamsDeprecated);
+
+ auto modulusLengthValue = getProperty(state, asObject(value), "modulusLength");
+ RETURN_IF_EXCEPTION(scope, nullptr);
+
+ // FIXME: Why no EnforceRange? Filed as <https://www.w3.org/Bugs/Public/show_bug.cgi?id=23779>.
+ result->modulusLength = convert<IDLUnsignedLong>(state, modulusLengthValue, IntegerConversionConfiguration::Normal);
+ RETURN_IF_EXCEPTION(scope, nullptr);
+
+ auto publicExponentValue = getProperty(state, asObject(value), "publicExponent");
+ RETURN_IF_EXCEPTION(scope, nullptr);
+
+ auto publicExponentArray = toUnsharedUint8Array(vm, publicExponentValue);
+ if (!publicExponentArray) {
+ throwTypeError(&state, scope, ASCIILiteral("Expected a Uint8Array in publicExponent"));
+ return nullptr;
+ }
+ result->publicExponent.append(publicExponentArray->data(), publicExponentArray->byteLength());
+
+ if (auto optionalHash = optionalHashAlgorithm(state, scope, asObject(value))) {
+ result->hasHash = true;
+ result->hash = optionalHash.value();
+ }
+
+ return WTFMove(result);
+}
+
+static RefPtr<CryptoAlgorithmParametersDeprecated> createRsaKeyParamsWithHash(ExecState&, JSValue)
+{
+ // WebCrypto RSA algorithms currently do not take any parameters to importKey.
+ return adoptRef(*new CryptoAlgorithmRsaKeyParamsWithHashDeprecated);
+}
+
+static RefPtr<CryptoAlgorithmParametersDeprecated> createRsaOaepParams(ExecState& state, JSValue value)
+{
+ auto scope = DECLARE_THROW_SCOPE(state.vm());
+
+ if (!value.isObject()) {
+ throwTypeError(&state, scope);
+ return nullptr;
+ }
+
+ auto result = adoptRef(*new CryptoAlgorithmRsaOaepParamsDeprecated);
+
+ result->hash = requiredHashAlgorithm(state, scope, asObject(value));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ auto labelValue = getProperty(state, asObject(value), "label");
+ RETURN_IF_EXCEPTION(scope, { });
+
+ result->hasLabel = !labelValue.isUndefinedOrNull();
+ if (!result->hasLabel)
+ return WTFMove(result);
+
+ auto labelData = cryptoOperationDataFromJSValue(state, scope, labelValue);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ result->label.append(labelData.first, labelData.second);
+
+ return WTFMove(result);
+}
+
+static RefPtr<CryptoAlgorithmParametersDeprecated> createRsaSsaParams(ExecState& state, JSValue value)
+{
+ auto scope = DECLARE_THROW_SCOPE(state.vm());
+
+ if (!value.isObject()) {
+ throwTypeError(&state, scope);
+ return nullptr;
+ }
+
+ auto result = adoptRef(*new CryptoAlgorithmRsaSsaParamsDeprecated);
+
+ result->hash = requiredHashAlgorithm(state, scope, asObject(value));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ return WTFMove(result);
+}
+
+RefPtr<CryptoAlgorithmParametersDeprecated> JSCryptoAlgorithmDictionary::createParametersForEncrypt(ExecState& state, ThrowScope& scope, CryptoAlgorithmIdentifier algorithm, JSValue value)
+{
+ switch (algorithm) {
+ case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
+ return adoptRef(*new CryptoAlgorithmParametersDeprecated);
+ case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
+ case CryptoAlgorithmIdentifier::RSA_PSS:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ case CryptoAlgorithmIdentifier::RSA_OAEP:
+ return createRsaOaepParams(state, value);
+ case CryptoAlgorithmIdentifier::ECDSA:
+ case CryptoAlgorithmIdentifier::ECDH:
+ case CryptoAlgorithmIdentifier::AES_CTR:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ case CryptoAlgorithmIdentifier::AES_CBC:
+ return createAesCbcParams(state, value);
+ case CryptoAlgorithmIdentifier::AES_CMAC:
+ case CryptoAlgorithmIdentifier::AES_GCM:
+ case CryptoAlgorithmIdentifier::AES_CFB:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ case CryptoAlgorithmIdentifier::AES_KW:
+ return adoptRef(*new CryptoAlgorithmParametersDeprecated);
+ case CryptoAlgorithmIdentifier::HMAC:
+ case CryptoAlgorithmIdentifier::DH:
+ case CryptoAlgorithmIdentifier::SHA_1:
+ case CryptoAlgorithmIdentifier::SHA_224:
+ case CryptoAlgorithmIdentifier::SHA_256:
+ case CryptoAlgorithmIdentifier::SHA_384:
+ case CryptoAlgorithmIdentifier::SHA_512:
+ case CryptoAlgorithmIdentifier::CONCAT:
+ case CryptoAlgorithmIdentifier::HKDF_CTR:
+ case CryptoAlgorithmIdentifier::PBKDF2:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+ return nullptr;
+}
+
+RefPtr<CryptoAlgorithmParametersDeprecated> JSCryptoAlgorithmDictionary::createParametersForDecrypt(ExecState& state, ThrowScope& scope, CryptoAlgorithmIdentifier algorithm, JSValue value)
+{
+ switch (algorithm) {
+ case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
+ return adoptRef(*new CryptoAlgorithmParametersDeprecated);
+ case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
+ case CryptoAlgorithmIdentifier::RSA_PSS:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ case CryptoAlgorithmIdentifier::RSA_OAEP:
+ return createRsaOaepParams(state, value);
+ case CryptoAlgorithmIdentifier::ECDSA:
+ case CryptoAlgorithmIdentifier::ECDH:
+ case CryptoAlgorithmIdentifier::AES_CTR:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ case CryptoAlgorithmIdentifier::AES_CBC:
+ return createAesCbcParams(state, value);
+ case CryptoAlgorithmIdentifier::AES_CMAC:
+ case CryptoAlgorithmIdentifier::AES_GCM:
+ case CryptoAlgorithmIdentifier::AES_CFB:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ case CryptoAlgorithmIdentifier::AES_KW:
+ return adoptRef(*new CryptoAlgorithmParametersDeprecated);
+ case CryptoAlgorithmIdentifier::HMAC:
+ case CryptoAlgorithmIdentifier::DH:
+ case CryptoAlgorithmIdentifier::SHA_1:
+ case CryptoAlgorithmIdentifier::SHA_224:
+ case CryptoAlgorithmIdentifier::SHA_256:
+ case CryptoAlgorithmIdentifier::SHA_384:
+ case CryptoAlgorithmIdentifier::SHA_512:
+ case CryptoAlgorithmIdentifier::CONCAT:
+ case CryptoAlgorithmIdentifier::HKDF_CTR:
+ case CryptoAlgorithmIdentifier::PBKDF2:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+ return nullptr;
+}
+
+RefPtr<CryptoAlgorithmParametersDeprecated> JSCryptoAlgorithmDictionary::createParametersForSign(ExecState& state, ThrowScope& scope, CryptoAlgorithmIdentifier algorithm, JSValue value)
+{
+ switch (algorithm) {
+ case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
+ return createRsaSsaParams(state, value);
+ case CryptoAlgorithmIdentifier::RSA_PSS:
+ case CryptoAlgorithmIdentifier::RSA_OAEP:
+ case CryptoAlgorithmIdentifier::ECDSA:
+ case CryptoAlgorithmIdentifier::ECDH:
+ case CryptoAlgorithmIdentifier::AES_CTR:
+ case CryptoAlgorithmIdentifier::AES_CBC:
+ case CryptoAlgorithmIdentifier::AES_CMAC:
+ case CryptoAlgorithmIdentifier::AES_GCM:
+ case CryptoAlgorithmIdentifier::AES_CFB:
+ case CryptoAlgorithmIdentifier::AES_KW:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ case CryptoAlgorithmIdentifier::HMAC:
+ return createHmacParams(state, value);
+ case CryptoAlgorithmIdentifier::DH:
+ case CryptoAlgorithmIdentifier::SHA_1:
+ case CryptoAlgorithmIdentifier::SHA_224:
+ case CryptoAlgorithmIdentifier::SHA_256:
+ case CryptoAlgorithmIdentifier::SHA_384:
+ case CryptoAlgorithmIdentifier::SHA_512:
+ case CryptoAlgorithmIdentifier::CONCAT:
+ case CryptoAlgorithmIdentifier::HKDF_CTR:
+ case CryptoAlgorithmIdentifier::PBKDF2:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+ return nullptr;
+}
+
+RefPtr<CryptoAlgorithmParametersDeprecated> JSCryptoAlgorithmDictionary::createParametersForVerify(ExecState& state, ThrowScope& scope, CryptoAlgorithmIdentifier algorithm, JSValue value)
+{
+ switch (algorithm) {
+ case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
+ return createRsaSsaParams(state, value);
+ case CryptoAlgorithmIdentifier::RSA_PSS:
+ case CryptoAlgorithmIdentifier::RSA_OAEP:
+ case CryptoAlgorithmIdentifier::ECDSA:
+ case CryptoAlgorithmIdentifier::ECDH:
+ case CryptoAlgorithmIdentifier::AES_CTR:
+ case CryptoAlgorithmIdentifier::AES_CBC:
+ case CryptoAlgorithmIdentifier::AES_CMAC:
+ case CryptoAlgorithmIdentifier::AES_GCM:
+ case CryptoAlgorithmIdentifier::AES_CFB:
+ case CryptoAlgorithmIdentifier::AES_KW:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ case CryptoAlgorithmIdentifier::HMAC:
+ return createHmacParams(state, value);
+ case CryptoAlgorithmIdentifier::DH:
+ case CryptoAlgorithmIdentifier::SHA_1:
+ case CryptoAlgorithmIdentifier::SHA_224:
+ case CryptoAlgorithmIdentifier::SHA_256:
+ case CryptoAlgorithmIdentifier::SHA_384:
+ case CryptoAlgorithmIdentifier::SHA_512:
+ case CryptoAlgorithmIdentifier::CONCAT:
+ case CryptoAlgorithmIdentifier::HKDF_CTR:
+ case CryptoAlgorithmIdentifier::PBKDF2:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+ return nullptr;
+}
+
+RefPtr<CryptoAlgorithmParametersDeprecated> JSCryptoAlgorithmDictionary::createParametersForDigest(ExecState& state, ThrowScope& scope, CryptoAlgorithmIdentifier algorithm, JSValue)
+{
+ switch (algorithm) {
+ case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
+ case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
+ case CryptoAlgorithmIdentifier::RSA_PSS:
+ case CryptoAlgorithmIdentifier::RSA_OAEP:
+ case CryptoAlgorithmIdentifier::ECDSA:
+ case CryptoAlgorithmIdentifier::ECDH:
+ case CryptoAlgorithmIdentifier::AES_CTR:
+ case CryptoAlgorithmIdentifier::AES_CBC:
+ case CryptoAlgorithmIdentifier::AES_CMAC:
+ case CryptoAlgorithmIdentifier::AES_GCM:
+ case CryptoAlgorithmIdentifier::AES_CFB:
+ case CryptoAlgorithmIdentifier::AES_KW:
+ case CryptoAlgorithmIdentifier::HMAC:
+ case CryptoAlgorithmIdentifier::DH:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ case CryptoAlgorithmIdentifier::SHA_1:
+ case CryptoAlgorithmIdentifier::SHA_224:
+ case CryptoAlgorithmIdentifier::SHA_256:
+ case CryptoAlgorithmIdentifier::SHA_384:
+ case CryptoAlgorithmIdentifier::SHA_512:
+ return adoptRef(*new CryptoAlgorithmParametersDeprecated);
+ case CryptoAlgorithmIdentifier::CONCAT:
+ case CryptoAlgorithmIdentifier::HKDF_CTR:
+ case CryptoAlgorithmIdentifier::PBKDF2:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+ return nullptr;
+}
+
+RefPtr<CryptoAlgorithmParametersDeprecated> JSCryptoAlgorithmDictionary::createParametersForGenerateKey(ExecState& state, ThrowScope& scope, CryptoAlgorithmIdentifier algorithm, JSValue value)
+{
+ switch (algorithm) {
+ case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
+ case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
+ case CryptoAlgorithmIdentifier::RSA_PSS:
+ case CryptoAlgorithmIdentifier::RSA_OAEP:
+ return createRsaKeyGenParams(state, value);
+ case CryptoAlgorithmIdentifier::ECDSA:
+ case CryptoAlgorithmIdentifier::ECDH:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ case CryptoAlgorithmIdentifier::AES_CTR:
+ case CryptoAlgorithmIdentifier::AES_CBC:
+ case CryptoAlgorithmIdentifier::AES_CMAC:
+ case CryptoAlgorithmIdentifier::AES_GCM:
+ case CryptoAlgorithmIdentifier::AES_CFB:
+ case CryptoAlgorithmIdentifier::AES_KW:
+ return createAesKeyGenParams(state, value);
+ case CryptoAlgorithmIdentifier::HMAC:
+ return createHmacKeyParams(state, value);
+ case CryptoAlgorithmIdentifier::DH:
+ case CryptoAlgorithmIdentifier::SHA_1:
+ case CryptoAlgorithmIdentifier::SHA_224:
+ case CryptoAlgorithmIdentifier::SHA_256:
+ case CryptoAlgorithmIdentifier::SHA_384:
+ case CryptoAlgorithmIdentifier::SHA_512:
+ case CryptoAlgorithmIdentifier::CONCAT:
+ case CryptoAlgorithmIdentifier::HKDF_CTR:
+ case CryptoAlgorithmIdentifier::PBKDF2:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+ return nullptr;
+}
+
+RefPtr<CryptoAlgorithmParametersDeprecated> JSCryptoAlgorithmDictionary::createParametersForDeriveKey(ExecState& state, ThrowScope& scope, CryptoAlgorithmIdentifier algorithm, JSValue)
+{
+ switch (algorithm) {
+ case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
+ case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
+ case CryptoAlgorithmIdentifier::RSA_PSS:
+ case CryptoAlgorithmIdentifier::RSA_OAEP:
+ case CryptoAlgorithmIdentifier::ECDSA:
+ case CryptoAlgorithmIdentifier::ECDH:
+ case CryptoAlgorithmIdentifier::AES_CTR:
+ case CryptoAlgorithmIdentifier::AES_CBC:
+ case CryptoAlgorithmIdentifier::AES_CMAC:
+ case CryptoAlgorithmIdentifier::AES_GCM:
+ case CryptoAlgorithmIdentifier::AES_CFB:
+ case CryptoAlgorithmIdentifier::AES_KW:
+ case CryptoAlgorithmIdentifier::HMAC:
+ case CryptoAlgorithmIdentifier::DH:
+ case CryptoAlgorithmIdentifier::SHA_1:
+ case CryptoAlgorithmIdentifier::SHA_224:
+ case CryptoAlgorithmIdentifier::SHA_256:
+ case CryptoAlgorithmIdentifier::SHA_384:
+ case CryptoAlgorithmIdentifier::SHA_512:
+ case CryptoAlgorithmIdentifier::CONCAT:
+ case CryptoAlgorithmIdentifier::HKDF_CTR:
+ case CryptoAlgorithmIdentifier::PBKDF2:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+ return nullptr;
+}
+
+RefPtr<CryptoAlgorithmParametersDeprecated> JSCryptoAlgorithmDictionary::createParametersForDeriveBits(ExecState& state, ThrowScope& scope, CryptoAlgorithmIdentifier algorithm, JSValue)
+{
+ switch (algorithm) {
+ case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
+ case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
+ case CryptoAlgorithmIdentifier::RSA_PSS:
+ case CryptoAlgorithmIdentifier::RSA_OAEP:
+ case CryptoAlgorithmIdentifier::ECDSA:
+ case CryptoAlgorithmIdentifier::ECDH:
+ case CryptoAlgorithmIdentifier::AES_CTR:
+ case CryptoAlgorithmIdentifier::AES_CBC:
+ case CryptoAlgorithmIdentifier::AES_CMAC:
+ case CryptoAlgorithmIdentifier::AES_GCM:
+ case CryptoAlgorithmIdentifier::AES_CFB:
+ case CryptoAlgorithmIdentifier::AES_KW:
+ case CryptoAlgorithmIdentifier::HMAC:
+ case CryptoAlgorithmIdentifier::DH:
+ case CryptoAlgorithmIdentifier::SHA_1:
+ case CryptoAlgorithmIdentifier::SHA_224:
+ case CryptoAlgorithmIdentifier::SHA_256:
+ case CryptoAlgorithmIdentifier::SHA_384:
+ case CryptoAlgorithmIdentifier::SHA_512:
+ case CryptoAlgorithmIdentifier::CONCAT:
+ case CryptoAlgorithmIdentifier::HKDF_CTR:
+ case CryptoAlgorithmIdentifier::PBKDF2:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+ return nullptr;
+}
+
+RefPtr<CryptoAlgorithmParametersDeprecated> JSCryptoAlgorithmDictionary::createParametersForImportKey(ExecState& state, ThrowScope& scope, CryptoAlgorithmIdentifier algorithm, JSValue value)
+{
+ switch (algorithm) {
+ case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
+ case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
+ case CryptoAlgorithmIdentifier::RSA_PSS:
+ case CryptoAlgorithmIdentifier::RSA_OAEP:
+ return createRsaKeyParamsWithHash(state, value);
+ case CryptoAlgorithmIdentifier::ECDSA:
+ case CryptoAlgorithmIdentifier::ECDH:
+ case CryptoAlgorithmIdentifier::AES_CTR:
+ case CryptoAlgorithmIdentifier::AES_CBC:
+ case CryptoAlgorithmIdentifier::AES_CMAC:
+ case CryptoAlgorithmIdentifier::AES_GCM:
+ case CryptoAlgorithmIdentifier::AES_CFB:
+ case CryptoAlgorithmIdentifier::AES_KW:
+ return adoptRef(*new CryptoAlgorithmParametersDeprecated);
+ case CryptoAlgorithmIdentifier::HMAC:
+ return createHmacParams(state, value);
+ case CryptoAlgorithmIdentifier::DH:
+ return adoptRef(*new CryptoAlgorithmParametersDeprecated);
+ case CryptoAlgorithmIdentifier::SHA_1:
+ case CryptoAlgorithmIdentifier::SHA_224:
+ case CryptoAlgorithmIdentifier::SHA_256:
+ case CryptoAlgorithmIdentifier::SHA_384:
+ case CryptoAlgorithmIdentifier::SHA_512:
+ case CryptoAlgorithmIdentifier::CONCAT:
+ case CryptoAlgorithmIdentifier::HKDF_CTR:
+ case CryptoAlgorithmIdentifier::PBKDF2:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+ return nullptr;
+}
+
+RefPtr<CryptoAlgorithmParametersDeprecated> JSCryptoAlgorithmDictionary::createParametersForExportKey(ExecState& state, ThrowScope& scope, CryptoAlgorithmIdentifier algorithm, JSValue)
+{
+ switch (algorithm) {
+ case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
+ case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
+ case CryptoAlgorithmIdentifier::RSA_PSS:
+ case CryptoAlgorithmIdentifier::RSA_OAEP:
+ case CryptoAlgorithmIdentifier::ECDSA:
+ case CryptoAlgorithmIdentifier::ECDH:
+ case CryptoAlgorithmIdentifier::AES_CTR:
+ case CryptoAlgorithmIdentifier::AES_CBC:
+ case CryptoAlgorithmIdentifier::AES_CMAC:
+ case CryptoAlgorithmIdentifier::AES_GCM:
+ case CryptoAlgorithmIdentifier::AES_CFB:
+ case CryptoAlgorithmIdentifier::AES_KW:
+ case CryptoAlgorithmIdentifier::HMAC:
+ case CryptoAlgorithmIdentifier::DH:
+ return adoptRef(*new CryptoAlgorithmParametersDeprecated);
+ case CryptoAlgorithmIdentifier::SHA_1:
+ case CryptoAlgorithmIdentifier::SHA_224:
+ case CryptoAlgorithmIdentifier::SHA_256:
+ case CryptoAlgorithmIdentifier::SHA_384:
+ case CryptoAlgorithmIdentifier::SHA_512:
+ case CryptoAlgorithmIdentifier::CONCAT:
+ case CryptoAlgorithmIdentifier::HKDF_CTR:
+ case CryptoAlgorithmIdentifier::PBKDF2:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ }
+ RELEASE_ASSERT_NOT_REACHED();
+ return nullptr;
+}
+
+}
+
+#endif // ENABLE(SUBTLE_CRYPTO)
diff --git a/Source/WebCore/bindings/js/JSCryptoAlgorithmDictionary.h b/Source/WebCore/bindings/js/JSCryptoAlgorithmDictionary.h
new file mode 100644
index 000000000..64ce3db75
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSCryptoAlgorithmDictionary.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(SUBTLE_CRYPTO)
+
+#include "CryptoAlgorithmIdentifier.h"
+#include <wtf/Forward.h>
+
+namespace JSC {
+class ExecState;
+class JSValue;
+class ThrowScope;
+}
+
+namespace WebCore {
+
+class CryptoAlgorithmParametersDeprecated;
+
+class JSCryptoAlgorithmDictionary {
+public:
+ static CryptoAlgorithmIdentifier parseAlgorithmIdentifier(JSC::ExecState&, JSC::ThrowScope&, JSC::JSValue);
+
+ static RefPtr<CryptoAlgorithmParametersDeprecated> createParametersForEncrypt(JSC::ExecState&, JSC::ThrowScope&, CryptoAlgorithmIdentifier, JSC::JSValue);
+ static RefPtr<CryptoAlgorithmParametersDeprecated> createParametersForDecrypt(JSC::ExecState&, JSC::ThrowScope&, CryptoAlgorithmIdentifier, JSC::JSValue);
+ static RefPtr<CryptoAlgorithmParametersDeprecated> createParametersForSign(JSC::ExecState&, JSC::ThrowScope&, CryptoAlgorithmIdentifier, JSC::JSValue);
+ static RefPtr<CryptoAlgorithmParametersDeprecated> createParametersForVerify(JSC::ExecState&, JSC::ThrowScope&, CryptoAlgorithmIdentifier, JSC::JSValue);
+ static RefPtr<CryptoAlgorithmParametersDeprecated> createParametersForDigest(JSC::ExecState&, JSC::ThrowScope&, CryptoAlgorithmIdentifier, JSC::JSValue);
+ static RefPtr<CryptoAlgorithmParametersDeprecated> createParametersForGenerateKey(JSC::ExecState&, JSC::ThrowScope&, CryptoAlgorithmIdentifier, JSC::JSValue);
+ static RefPtr<CryptoAlgorithmParametersDeprecated> createParametersForDeriveKey(JSC::ExecState&, JSC::ThrowScope&, CryptoAlgorithmIdentifier, JSC::JSValue);
+ static RefPtr<CryptoAlgorithmParametersDeprecated> createParametersForDeriveBits(JSC::ExecState&, JSC::ThrowScope&, CryptoAlgorithmIdentifier, JSC::JSValue);
+ static RefPtr<CryptoAlgorithmParametersDeprecated> createParametersForImportKey(JSC::ExecState&, JSC::ThrowScope&, CryptoAlgorithmIdentifier, JSC::JSValue);
+ static RefPtr<CryptoAlgorithmParametersDeprecated> createParametersForExportKey(JSC::ExecState&, JSC::ThrowScope&, CryptoAlgorithmIdentifier, JSC::JSValue);
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SUBTLE_CRYPTO)
diff --git a/Source/WebCore/bindings/js/JSCryptoCustom.cpp b/Source/WebCore/bindings/js/JSCryptoCustom.cpp
index 9d1177146..a71b71aeb 100644
--- a/Source/WebCore/bindings/js/JSCryptoCustom.cpp
+++ b/Source/WebCore/bindings/js/JSCryptoCustom.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2012 Google Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -25,8 +26,9 @@
#include "config.h"
#include "JSCrypto.h"
-#include "ExceptionCode.h"
-
+#include "JSDOMConvertBufferSource.h"
+#include "JSDOMExceptionHandling.h"
+#include <heap/HeapInlines.h>
#include <runtime/ArrayBufferView.h>
#include <runtime/Error.h>
#include <runtime/JSArrayBufferView.h>
@@ -35,23 +37,20 @@ using namespace JSC;
namespace WebCore {
-JSValue JSCrypto::getRandomValues(ExecState* exec)
+JSValue JSCrypto::getRandomValues(ExecState& state)
{
- if (exec->argumentCount() < 1)
- return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
- JSValue buffer = exec->argument(0);
- RefPtr<ArrayBufferView> arrayBufferView = toArrayBufferView(buffer);
- if (!arrayBufferView)
- return throwTypeError(exec);
+ if (state.argumentCount() < 1)
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
- ExceptionCode ec = 0;
- impl().getRandomValues(arrayBufferView.get(), ec);
+ JSValue buffer = state.argument(0);
+ auto arrayBufferView = toUnsharedArrayBufferView(vm, buffer);
+ if (!arrayBufferView)
+ return throwTypeError(&state, scope);
- if (ec) {
- setDOMException(exec, ec);
- return jsUndefined();
- }
+ propagateException(state, scope, wrapped().getRandomValues(*arrayBufferView));
return buffer;
}
diff --git a/Source/WebCore/bindings/js/JSCryptoKeyCustom.cpp b/Source/WebCore/bindings/js/JSCryptoKeyCustom.cpp
new file mode 100644
index 000000000..e975400db
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSCryptoKeyCustom.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSCryptoKey.h"
+
+#if ENABLE(SUBTLE_CRYPTO)
+
+#include "CryptoKeyAES.h"
+#include "CryptoKeyHMAC.h"
+#include "CryptoKeyRSA.h"
+#include "JSCryptoAlgorithmBuilder.h"
+#include <heap/HeapInlines.h>
+#include <runtime/JSCJSValueInlines.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSValue JSCryptoKey::algorithm(JSC::ExecState& state) const
+{
+ if (m_algorithm)
+ return m_algorithm.get();
+
+ JSCryptoAlgorithmBuilder builder(&state);
+
+ std::unique_ptr<KeyAlgorithm> algorithm = wrapped().buildAlgorithm();
+ switch (algorithm->keyAlgorithmClass()) {
+ case KeyAlgorithmClass::AES: {
+ auto& aesAlgorithm = downcast<AesKeyAlgorithm>(*algorithm);
+ builder.add("name", aesAlgorithm.name());
+ builder.add("length", aesAlgorithm.length());
+ break;
+ }
+ case KeyAlgorithmClass::HMAC: {
+ auto& hmacAlgorithm = downcast<HmacKeyAlgorithm>(*algorithm);
+ builder.add("name", hmacAlgorithm.name());
+ JSCryptoAlgorithmBuilder hmacHash(&state);
+ hmacHash.add("name", hmacAlgorithm.hash());
+ builder.add("hash", hmacHash);
+ builder.add("length", hmacAlgorithm.length());
+ break;
+ }
+ case KeyAlgorithmClass::HRSA: {
+ auto& rsaAlgorithm = downcast<RsaHashedKeyAlgorithm>(*algorithm);
+ builder.add("name", rsaAlgorithm.name());
+ builder.add("modulusLength", rsaAlgorithm.modulusLength());
+ builder.add("publicExponent", rsaAlgorithm.publicExponent());
+ JSCryptoAlgorithmBuilder rsaHash(&state);
+ rsaHash.add("name", rsaAlgorithm.hash());
+ builder.add("hash", rsaHash);
+ break;
+ }
+ case KeyAlgorithmClass::RSA: {
+ auto& rsaAlgorithm = downcast<RsaKeyAlgorithm>(*algorithm);
+ builder.add("name", rsaAlgorithm.name());
+ builder.add("modulusLength", rsaAlgorithm.modulusLength());
+ builder.add("publicExponent", rsaAlgorithm.publicExponent());
+ break;
+ }
+ }
+
+ m_algorithm.set(state.vm(), this, builder.result());
+ return m_algorithm.get();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SUBTLE_CRYPTO)
diff --git a/Source/WebCore/bindings/js/JSCryptoKeySerializationJWK.cpp b/Source/WebCore/bindings/js/JSCryptoKeySerializationJWK.cpp
new file mode 100644
index 000000000..92317c20d
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSCryptoKeySerializationJWK.cpp
@@ -0,0 +1,771 @@
+/*
+ * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSCryptoKeySerializationJWK.h"
+
+#if ENABLE(SUBTLE_CRYPTO)
+
+#include "CryptoAlgorithm.h"
+#include "CryptoAlgorithmHmacParamsDeprecated.h"
+#include "CryptoAlgorithmRegistry.h"
+#include "CryptoAlgorithmRsaKeyParamsWithHashDeprecated.h"
+#include "CryptoKey.h"
+#include "CryptoKeyAES.h"
+#include "CryptoKeyDataOctetSequence.h"
+#include "CryptoKeyDataRSAComponents.h"
+#include "CryptoKeyHMAC.h"
+#include "CryptoKeyRSA.h"
+#include "ExceptionCode.h"
+#include "JSDOMBinding.h"
+#include <heap/StrongInlines.h>
+#include <runtime/JSCInlines.h>
+#include <runtime/JSONObject.h>
+#include <runtime/ObjectConstructor.h>
+#include <wtf/text/Base64.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+static bool getJSArrayFromJSON(ExecState* exec, JSObject* json, const char* key, JSArray*& result)
+{
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ Identifier identifier = Identifier::fromString(exec, key);
+ PropertySlot slot(json, PropertySlot::InternalMethodType::Get);
+
+ if (!json->getPropertySlot(exec, identifier, slot))
+ return false;
+
+ JSValue value = slot.getValue(exec, identifier);
+ ASSERT(!scope.exception());
+ if (!isJSArray(value)) {
+ throwTypeError(exec, scope, String::format("Expected an array for \"%s\" JSON key", key));
+ return false;
+ }
+
+ result = asArray(value);
+
+ return true;
+}
+
+static bool getStringFromJSON(ExecState* exec, JSObject* json, const char* key, String& result)
+{
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ Identifier identifier = Identifier::fromString(exec, key);
+ PropertySlot slot(json, PropertySlot::InternalMethodType::Get);
+
+ if (!json->getPropertySlot(exec, identifier, slot))
+ return false;
+
+ JSValue jsValue = slot.getValue(exec, identifier);
+ ASSERT(!scope.exception());
+ if (!jsValue.getString(exec, result)) {
+ // Can get an out of memory exception.
+ RETURN_IF_EXCEPTION(scope, false);
+ throwTypeError(exec, scope, String::format("Expected a string value for \"%s\" JSON key", key));
+ return false;
+ }
+
+ return true;
+}
+
+static bool getBooleanFromJSON(ExecState* exec, JSObject* json, const char* key, bool& result)
+{
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ Identifier identifier = Identifier::fromString(exec, key);
+ PropertySlot slot(json, PropertySlot::InternalMethodType::Get);
+
+ if (!json->getPropertySlot(exec, identifier, slot))
+ return false;
+
+ JSValue jsValue = slot.getValue(exec, identifier);
+ ASSERT(!scope.exception());
+ if (!jsValue.isBoolean()) {
+ throwTypeError(exec, scope, String::format("Expected a boolean value for \"%s\" JSON key", key));
+ return false;
+ }
+
+ result = jsValue.asBoolean();
+ return true;
+}
+
+static bool getBigIntegerVectorFromJSON(ExecState* exec, JSObject* json, const char* key, Vector<uint8_t>& result)
+{
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ String base64urlEncodedNumber;
+ if (!getStringFromJSON(exec, json, key, base64urlEncodedNumber))
+ return false;
+
+ if (!base64URLDecode(base64urlEncodedNumber, result)) {
+ throwTypeError(exec, scope, ASCIILiteral("Cannot decode base64url key data in JWK"));
+ return false;
+ }
+
+ if (result[0] == 0) {
+ throwTypeError(exec, scope, ASCIILiteral("JWK BigInteger must utilize the minimum number of octets to represent the value"));
+ return false;
+ }
+
+ return true;
+}
+
+JSCryptoKeySerializationJWK::JSCryptoKeySerializationJWK(ExecState* exec, const String& jsonString)
+ : m_exec(exec)
+{
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ JSValue jsonValue = JSONParse(exec, jsonString);
+ if (UNLIKELY(scope.exception()))
+ return;
+
+ if (!jsonValue || !jsonValue.isObject()) {
+ throwTypeError(exec, scope, ASCIILiteral("Invalid JWK serialization"));
+ return;
+ }
+
+ m_json.set(vm, asObject(jsonValue));
+}
+
+JSCryptoKeySerializationJWK::~JSCryptoKeySerializationJWK()
+{
+}
+
+static Ref<CryptoAlgorithmParametersDeprecated> createHMACParameters(CryptoAlgorithmIdentifier hashFunction)
+{
+ auto hmacParameters = adoptRef(*new CryptoAlgorithmHmacParamsDeprecated);
+ hmacParameters->hash = hashFunction;
+ return WTFMove(hmacParameters);
+}
+
+static Ref<CryptoAlgorithmParametersDeprecated> createRSAKeyParametersWithHash(CryptoAlgorithmIdentifier hashFunction)
+{
+ auto rsaKeyParameters = adoptRef(*new CryptoAlgorithmRsaKeyParamsWithHashDeprecated);
+ rsaKeyParameters->hasHash = true;
+ rsaKeyParameters->hash = hashFunction;
+ return WTFMove(rsaKeyParameters);
+}
+
+std::optional<CryptoAlgorithmPair> JSCryptoKeySerializationJWK::reconcileAlgorithm(CryptoAlgorithm* suggestedAlgorithm, CryptoAlgorithmParametersDeprecated* suggestedParameters) const
+{
+ VM& vm = m_exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (!getStringFromJSON(m_exec, m_json.get(), "alg", m_jwkAlgorithmName)) {
+ // Algorithm is optional in JWK.
+ return CryptoAlgorithmPair { suggestedAlgorithm, suggestedParameters };
+ }
+
+ auto& algorithmRegisty = CryptoAlgorithmRegistry::singleton();
+ RefPtr<CryptoAlgorithm> algorithm;
+ RefPtr<CryptoAlgorithmParametersDeprecated> parameters;
+ if (m_jwkAlgorithmName == "HS256") {
+ algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::HMAC);
+ parameters = createHMACParameters(CryptoAlgorithmIdentifier::SHA_256);
+ } else if (m_jwkAlgorithmName == "HS384") {
+ algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::HMAC);
+ parameters = createHMACParameters(CryptoAlgorithmIdentifier::SHA_384);
+ } else if (m_jwkAlgorithmName == "HS512") {
+ algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::HMAC);
+ parameters = createHMACParameters(CryptoAlgorithmIdentifier::SHA_512);
+ } else if (m_jwkAlgorithmName == "RS256") {
+ algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5);
+ parameters = createRSAKeyParametersWithHash(CryptoAlgorithmIdentifier::SHA_256);
+ } else if (m_jwkAlgorithmName == "RS384") {
+ algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5);
+ parameters = createRSAKeyParametersWithHash(CryptoAlgorithmIdentifier::SHA_384);
+ } else if (m_jwkAlgorithmName == "RS512") {
+ algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5);
+ parameters = createRSAKeyParametersWithHash(CryptoAlgorithmIdentifier::SHA_512);
+ } else if (m_jwkAlgorithmName == "RSA1_5") {
+ algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5);
+ parameters = adoptRef(*new CryptoAlgorithmRsaKeyParamsWithHashDeprecated);
+ } else if (m_jwkAlgorithmName == "RSA-OAEP") {
+ algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::RSA_OAEP);
+ parameters = createRSAKeyParametersWithHash(CryptoAlgorithmIdentifier::SHA_1);
+ } else if (m_jwkAlgorithmName == "A128CBC") {
+ algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::AES_CBC);
+ parameters = adoptRef(*new CryptoAlgorithmParametersDeprecated);
+ } else if (m_jwkAlgorithmName == "A192CBC") {
+ algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::AES_CBC);
+ parameters = adoptRef(*new CryptoAlgorithmParametersDeprecated);
+ } else if (m_jwkAlgorithmName == "A256CBC") {
+ algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::AES_CBC);
+ parameters = adoptRef(*new CryptoAlgorithmParametersDeprecated);
+ } else if (m_jwkAlgorithmName == "A128KW") {
+ algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::AES_KW);
+ parameters = adoptRef(*new CryptoAlgorithmParametersDeprecated);
+ } else if (m_jwkAlgorithmName == "A192KW") {
+ algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::AES_KW);
+ parameters = adoptRef(*new CryptoAlgorithmParametersDeprecated);
+ } else if (m_jwkAlgorithmName == "A256KW") {
+ algorithm = algorithmRegisty.create(CryptoAlgorithmIdentifier::AES_KW);
+ parameters = adoptRef(*new CryptoAlgorithmParametersDeprecated);
+ } else {
+ throwTypeError(m_exec, scope, "Unsupported JWK algorithm " + m_jwkAlgorithmName);
+ return std::nullopt;
+ }
+
+ if (!suggestedAlgorithm)
+ return CryptoAlgorithmPair { algorithm, parameters };
+
+ if (!algorithm)
+ return CryptoAlgorithmPair { suggestedAlgorithm, suggestedParameters };
+
+ if (algorithm->identifier() != suggestedAlgorithm->identifier())
+ return std::nullopt;
+
+ if (algorithm->identifier() == CryptoAlgorithmIdentifier::HMAC) {
+ if (downcast<CryptoAlgorithmHmacParamsDeprecated>(*parameters).hash != downcast<CryptoAlgorithmHmacParamsDeprecated>(*suggestedParameters).hash)
+ return std::nullopt;
+ return CryptoAlgorithmPair { suggestedAlgorithm, suggestedParameters };
+ }
+ if (algorithm->identifier() == CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5
+ || algorithm->identifier() == CryptoAlgorithmIdentifier::RSA_OAEP) {
+ CryptoAlgorithmRsaKeyParamsWithHashDeprecated& rsaKeyParameters = downcast<CryptoAlgorithmRsaKeyParamsWithHashDeprecated>(*parameters);
+ CryptoAlgorithmRsaKeyParamsWithHashDeprecated& suggestedRSAKeyParameters = downcast<CryptoAlgorithmRsaKeyParamsWithHashDeprecated>(*suggestedParameters);
+ ASSERT(rsaKeyParameters.hasHash);
+ if (suggestedRSAKeyParameters.hasHash) {
+ if (suggestedRSAKeyParameters.hash != rsaKeyParameters.hash)
+ return std::nullopt;
+ return CryptoAlgorithmPair { suggestedAlgorithm, suggestedParameters };
+ }
+ suggestedRSAKeyParameters.hasHash = true;
+ suggestedRSAKeyParameters.hash = rsaKeyParameters.hash;
+ }
+
+ // Other algorithms don't have parameters.
+ return CryptoAlgorithmPair { suggestedAlgorithm, suggestedParameters };
+}
+
+static bool tryJWKKeyOpsValue(ExecState* exec, CryptoKeyUsageBitmap& usages, const String& operation, const String& tryOperation, CryptoKeyUsageBitmap tryUsage)
+{
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (operation == tryOperation) {
+ if (usages & tryUsage) {
+ throwTypeError(exec, scope, ASCIILiteral("JWK key_ops contains a duplicate operation"));
+ return false;
+ }
+ usages |= tryUsage;
+ }
+ return true;
+}
+
+void JSCryptoKeySerializationJWK::reconcileUsages(CryptoKeyUsageBitmap& suggestedUsages) const
+{
+ VM& vm = m_exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ CryptoKeyUsageBitmap jwkUsages = 0;
+
+ JSArray* keyOps;
+ if (getJSArrayFromJSON(m_exec, m_json.get(), "key_ops", keyOps)) {
+ for (size_t i = 0; i < keyOps->length(); ++i) {
+ JSValue jsValue = keyOps->getIndex(m_exec, i);
+ String operation;
+ if (!jsValue.getString(m_exec, operation)) {
+ if (!scope.exception())
+ throwTypeError(m_exec, scope, ASCIILiteral("JWK key_ops attribute could not be processed"));
+ return;
+ }
+ if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("sign"), CryptoKeyUsageSign))
+ return;
+ if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("verify"), CryptoKeyUsageVerify))
+ return;
+ if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("encrypt"), CryptoKeyUsageEncrypt))
+ return;
+ if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("decrypt"), CryptoKeyUsageDecrypt))
+ return;
+ if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("wrapKey"), CryptoKeyUsageWrapKey))
+ return;
+ if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("unwrapKey"), CryptoKeyUsageUnwrapKey))
+ return;
+ if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("deriveKey"), CryptoKeyUsageDeriveKey))
+ return;
+ if (!tryJWKKeyOpsValue(m_exec, jwkUsages, operation, ASCIILiteral("deriveBits"), CryptoKeyUsageDeriveBits))
+ return;
+ }
+ } else {
+ RETURN_IF_EXCEPTION(scope, void());
+
+ String jwkUseString;
+ if (!getStringFromJSON(m_exec, m_json.get(), "use", jwkUseString)) {
+ // We have neither key_ops nor use.
+ return;
+ }
+
+ if (jwkUseString == "enc")
+ jwkUsages |= (CryptoKeyUsageEncrypt | CryptoKeyUsageDecrypt | CryptoKeyUsageWrapKey | CryptoKeyUsageUnwrapKey);
+ else if (jwkUseString == "sig")
+ jwkUsages |= (CryptoKeyUsageSign | CryptoKeyUsageVerify);
+ else {
+ throwTypeError(m_exec, scope, "Unsupported JWK key use value \"" + jwkUseString + "\"");
+ return;
+ }
+ }
+
+ suggestedUsages = suggestedUsages & jwkUsages;
+}
+
+void JSCryptoKeySerializationJWK::reconcileExtractable(bool& suggestedExtractable) const
+{
+ bool jwkExtractable;
+ if (!getBooleanFromJSON(m_exec, m_json.get(), "ext", jwkExtractable))
+ return;
+
+ suggestedExtractable = suggestedExtractable && jwkExtractable;
+}
+
+bool JSCryptoKeySerializationJWK::keySizeIsValid(size_t sizeInBits) const
+{
+ if (m_jwkAlgorithmName == "HS256")
+ return sizeInBits >= 256;
+ if (m_jwkAlgorithmName == "HS384")
+ return sizeInBits >= 384;
+ if (m_jwkAlgorithmName == "HS512")
+ return sizeInBits >= 512;
+ if (m_jwkAlgorithmName == "A128CBC")
+ return sizeInBits == 128;
+ if (m_jwkAlgorithmName == "A192CBC")
+ return sizeInBits == 192;
+ if (m_jwkAlgorithmName == "A256CBC")
+ return sizeInBits == 256;
+ if (m_jwkAlgorithmName == "A128KW")
+ return sizeInBits == 128;
+ if (m_jwkAlgorithmName == "A192KW")
+ return sizeInBits == 192;
+ if (m_jwkAlgorithmName == "A256KW")
+ return sizeInBits == 256;
+ if (m_jwkAlgorithmName == "RS256")
+ return sizeInBits >= 2048;
+ if (m_jwkAlgorithmName == "RS384")
+ return sizeInBits >= 2048;
+ if (m_jwkAlgorithmName == "RS512")
+ return sizeInBits >= 2048;
+ if (m_jwkAlgorithmName == "RSA1_5")
+ return sizeInBits >= 2048;
+ if (m_jwkAlgorithmName == "RSA_OAEP")
+ return sizeInBits >= 2048;
+ return true;
+}
+
+std::unique_ptr<CryptoKeyData> JSCryptoKeySerializationJWK::keyDataOctetSequence() const
+{
+ VM& vm = m_exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ String keyBase64URL;
+ if (!getStringFromJSON(m_exec, m_json.get(), "k", keyBase64URL)) {
+ if (!scope.exception())
+ throwTypeError(m_exec, scope, ASCIILiteral("Secret key data is not present is JWK"));
+ return nullptr;
+ }
+
+ Vector<uint8_t> octetSequence;
+ if (!base64URLDecode(keyBase64URL, octetSequence)) {
+ throwTypeError(m_exec, scope, ASCIILiteral("Cannot decode base64url key data in JWK"));
+ return nullptr;
+ }
+
+ if (!keySizeIsValid(octetSequence.size() * 8)) {
+ throwTypeError(m_exec, scope, "Key size is not valid for " + m_jwkAlgorithmName);
+ return nullptr;
+ }
+
+ return std::make_unique<CryptoKeyDataOctetSequence>(octetSequence);
+}
+
+std::unique_ptr<CryptoKeyData> JSCryptoKeySerializationJWK::keyDataRSAComponents() const
+{
+ VM& vm = m_exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ Vector<uint8_t> modulus;
+ Vector<uint8_t> exponent;
+ Vector<uint8_t> privateExponent;
+
+ if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "n", modulus)) {
+ if (!scope.exception())
+ throwTypeError(m_exec, scope, ASCIILiteral("Required JWK \"n\" member is missing"));
+ return nullptr;
+ }
+
+ if (!keySizeIsValid(modulus.size() * 8)) {
+ throwTypeError(m_exec, scope, "Key size is not valid for " + m_jwkAlgorithmName);
+ return nullptr;
+ }
+
+ if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "e", exponent)) {
+ if (!scope.exception())
+ throwTypeError(m_exec, scope, ASCIILiteral("Required JWK \"e\" member is missing"));
+ return nullptr;
+ }
+
+ if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "d", modulus)) {
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ return CryptoKeyDataRSAComponents::createPublic(modulus, exponent);
+ }
+
+ CryptoKeyDataRSAComponents::PrimeInfo firstPrimeInfo;
+ CryptoKeyDataRSAComponents::PrimeInfo secondPrimeInfo;
+ Vector<CryptoKeyDataRSAComponents::PrimeInfo> otherPrimeInfos;
+ if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "p", firstPrimeInfo.primeFactor)) {
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ return CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent);
+ }
+
+ if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "dp", firstPrimeInfo.factorCRTExponent)) {
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ return CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent);
+ }
+
+ if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "q", secondPrimeInfo.primeFactor)) {
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ return CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent);
+ }
+
+ if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "dq", secondPrimeInfo.factorCRTExponent)) {
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ return CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent);
+ }
+
+ if (!getBigIntegerVectorFromJSON(m_exec, m_json.get(), "qi", secondPrimeInfo.factorCRTCoefficient)) {
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ return CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent);
+ }
+
+ JSArray* otherPrimeInfoJSArray;
+ if (!getJSArrayFromJSON(m_exec, m_json.get(), "oth", otherPrimeInfoJSArray)) {
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ return CryptoKeyDataRSAComponents::createPrivateWithAdditionalData(modulus, exponent, privateExponent, firstPrimeInfo, secondPrimeInfo, otherPrimeInfos);
+ }
+
+ for (size_t i = 0; i < otherPrimeInfoJSArray->length(); ++i) {
+ CryptoKeyDataRSAComponents::PrimeInfo info;
+ JSValue element = otherPrimeInfoJSArray->getIndex(m_exec, i);
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ if (!element.isObject()) {
+ throwTypeError(m_exec, scope, ASCIILiteral("JWK \"oth\" array member is not an object"));
+ return nullptr;
+ }
+ if (!getBigIntegerVectorFromJSON(m_exec, asObject(element), "r", info.primeFactor)) {
+ if (!scope.exception())
+ throwTypeError(m_exec, scope, ASCIILiteral("Cannot get prime factor for a prime in \"oth\" dictionary"));
+ return nullptr;
+ }
+ if (!getBigIntegerVectorFromJSON(m_exec, asObject(element), "d", info.factorCRTExponent)) {
+ if (!scope.exception())
+ throwTypeError(m_exec, scope, ASCIILiteral("Cannot get factor CRT exponent for a prime in \"oth\" dictionary"));
+ return nullptr;
+ }
+ if (!getBigIntegerVectorFromJSON(m_exec, asObject(element), "t", info.factorCRTCoefficient)) {
+ if (!scope.exception())
+ throwTypeError(m_exec, scope, ASCIILiteral("Cannot get factor CRT coefficient for a prime in \"oth\" dictionary"));
+ return nullptr;
+ }
+ otherPrimeInfos.append(info);
+ }
+
+ return CryptoKeyDataRSAComponents::createPrivateWithAdditionalData(modulus, exponent, privateExponent, firstPrimeInfo, secondPrimeInfo, otherPrimeInfos);
+}
+
+std::unique_ptr<CryptoKeyData> JSCryptoKeySerializationJWK::keyData() const
+{
+ VM& vm = m_exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ String jwkKeyType;
+ if (!getStringFromJSON(m_exec, m_json.get(), "kty", jwkKeyType)) {
+ if (!scope.exception())
+ throwTypeError(m_exec, scope, ASCIILiteral("Required JWK \"kty\" member is missing"));
+ return nullptr;
+ }
+
+ if (jwkKeyType == "oct")
+ return keyDataOctetSequence();
+
+ if (jwkKeyType == "RSA")
+ return keyDataRSAComponents();
+
+ throwTypeError(m_exec, scope, "Unsupported JWK key type " + jwkKeyType);
+ return nullptr;
+}
+
+static void addToJSON(ExecState* exec, JSObject* json, const char* key, const String& value)
+{
+ VM& vm = exec->vm();
+ Identifier identifier = Identifier::fromString(&vm, key);
+ json->putDirect(vm, identifier, jsString(exec, value));
+}
+
+static void buildJSONForOctetSequence(ExecState* exec, const Vector<uint8_t>& keyData, JSObject* result)
+{
+ addToJSON(exec, result, "kty", "oct");
+ addToJSON(exec, result, "k", base64URLEncode(keyData));
+}
+
+static void buildJSONForRSAComponents(JSC::ExecState* exec, const CryptoKeyDataRSAComponents& data, JSC::JSObject* result)
+{
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ addToJSON(exec, result, "kty", "RSA");
+ addToJSON(exec, result, "n", base64URLEncode(data.modulus()));
+ addToJSON(exec, result, "e", base64URLEncode(data.exponent()));
+
+ if (data.type() == CryptoKeyDataRSAComponents::Type::Public)
+ return;
+
+ addToJSON(exec, result, "d", base64URLEncode(data.privateExponent()));
+
+ if (!data.hasAdditionalPrivateKeyParameters())
+ return;
+
+ addToJSON(exec, result, "p", base64URLEncode(data.firstPrimeInfo().primeFactor));
+ addToJSON(exec, result, "q", base64URLEncode(data.secondPrimeInfo().primeFactor));
+ addToJSON(exec, result, "dp", base64URLEncode(data.firstPrimeInfo().factorCRTExponent));
+ addToJSON(exec, result, "dq", base64URLEncode(data.secondPrimeInfo().factorCRTExponent));
+ addToJSON(exec, result, "qi", base64URLEncode(data.secondPrimeInfo().factorCRTCoefficient));
+
+ if (data.otherPrimeInfos().isEmpty())
+ return;
+
+ JSArray* oth = constructEmptyArray(exec, 0, exec->lexicalGlobalObject(), data.otherPrimeInfos().size());
+ RETURN_IF_EXCEPTION(scope, void());
+ for (size_t i = 0, size = data.otherPrimeInfos().size(); i < size; ++i) {
+ JSObject* jsPrimeInfo = constructEmptyObject(exec);
+ addToJSON(exec, jsPrimeInfo, "r", base64URLEncode(data.otherPrimeInfos()[i].primeFactor));
+ addToJSON(exec, jsPrimeInfo, "d", base64URLEncode(data.otherPrimeInfos()[i].factorCRTExponent));
+ addToJSON(exec, jsPrimeInfo, "t", base64URLEncode(data.otherPrimeInfos()[i].factorCRTCoefficient));
+ oth->putDirectIndex(exec, i, jsPrimeInfo);
+ RETURN_IF_EXCEPTION(scope, void());
+ }
+ result->putDirect(vm, Identifier::fromString(exec, "oth"), oth);
+}
+
+static void addBoolToJSON(ExecState* exec, JSObject* json, const char* key, bool value)
+{
+ VM& vm = exec->vm();
+ Identifier identifier = Identifier::fromString(&vm, key);
+ json->putDirect(vm, identifier, jsBoolean(value));
+}
+
+static void addJWKAlgorithmToJSON(ExecState* exec, JSObject* json, const CryptoKey& key)
+{
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ String jwkAlgorithm;
+ switch (key.algorithmIdentifier()) {
+ case CryptoAlgorithmIdentifier::HMAC:
+ switch (downcast<CryptoKeyHMAC>(key).hashAlgorithmIdentifier()) {
+ case CryptoAlgorithmIdentifier::SHA_256:
+ if (downcast<CryptoKeyHMAC>(key).key().size() * 8 >= 256)
+ jwkAlgorithm = "HS256";
+ break;
+ case CryptoAlgorithmIdentifier::SHA_384:
+ if (downcast<CryptoKeyHMAC>(key).key().size() * 8 >= 384)
+ jwkAlgorithm = "HS384";
+ break;
+ case CryptoAlgorithmIdentifier::SHA_512:
+ if (downcast<CryptoKeyHMAC>(key).key().size() * 8 >= 512)
+ jwkAlgorithm = "HS512";
+ break;
+ default:
+ break;
+ }
+ break;
+ case CryptoAlgorithmIdentifier::AES_CBC:
+ switch (downcast<CryptoKeyAES>(key).key().size() * 8) {
+ case 128:
+ jwkAlgorithm = "A128CBC";
+ break;
+ case 192:
+ jwkAlgorithm = "A192CBC";
+ break;
+ case 256:
+ jwkAlgorithm = "A256CBC";
+ break;
+ }
+ break;
+ case CryptoAlgorithmIdentifier::AES_KW:
+ switch (downcast<CryptoKeyAES>(key).key().size() * 8) {
+ case 128:
+ jwkAlgorithm = "A128KW";
+ break;
+ case 192:
+ jwkAlgorithm = "A192KW";
+ break;
+ case 256:
+ jwkAlgorithm = "A256KW";
+ break;
+ }
+ break;
+ case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5: {
+ const CryptoKeyRSA& rsaKey = downcast<CryptoKeyRSA>(key);
+ CryptoAlgorithmIdentifier hash;
+ if (!rsaKey.isRestrictedToHash(hash))
+ break;
+ if (rsaKey.keySizeInBits() < 2048)
+ break;
+ switch (hash) {
+ case CryptoAlgorithmIdentifier::SHA_256:
+ jwkAlgorithm = "RS256";
+ break;
+ case CryptoAlgorithmIdentifier::SHA_384:
+ jwkAlgorithm = "RS384";
+ break;
+ case CryptoAlgorithmIdentifier::SHA_512:
+ jwkAlgorithm = "RS512";
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: {
+ const CryptoKeyRSA& rsaKey = downcast<CryptoKeyRSA>(key);
+ if (rsaKey.keySizeInBits() < 2048)
+ break;
+ jwkAlgorithm = "RSA1_5";
+ break;
+ }
+ case CryptoAlgorithmIdentifier::RSA_OAEP: {
+ const CryptoKeyRSA& rsaKey = downcast<CryptoKeyRSA>(key);
+ CryptoAlgorithmIdentifier hash;
+ // WebCrypto RSA-OAEP keys are not tied to any particular hash, unless previously imported from JWK, which only supports SHA-1.
+ if (rsaKey.isRestrictedToHash(hash) && hash != CryptoAlgorithmIdentifier::SHA_1)
+ break;
+ if (rsaKey.keySizeInBits() < 2048)
+ break;
+ jwkAlgorithm = "RSA-OAEP";
+ break;
+ }
+ default:
+ break;
+ }
+
+ if (jwkAlgorithm.isNull()) {
+ // The spec doesn't currently tell whether export should fail, or just skip "alg" (which is an optional key in JWK).
+ throwTypeError(exec, scope, ASCIILiteral("Key algorithm and size do not map to any JWK algorithm identifier"));
+ return;
+ }
+
+ addToJSON(exec, json, "alg", jwkAlgorithm);
+}
+
+static void addUsagesToJSON(ExecState* exec, JSObject* json, CryptoKeyUsageBitmap usages)
+{
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ JSArray* keyOps = constructEmptyArray(exec, 0, exec->lexicalGlobalObject(), 0);
+ RETURN_IF_EXCEPTION(scope, void());
+
+ unsigned index = 0;
+ if (usages & CryptoKeyUsageSign) {
+ keyOps->putDirectIndex(exec, index++, jsNontrivialString(exec, ASCIILiteral("sign")));
+ RETURN_IF_EXCEPTION(scope, void());
+ }
+ if (usages & CryptoKeyUsageVerify) {
+ keyOps->putDirectIndex(exec, index++, jsNontrivialString(exec, ASCIILiteral("verify")));
+ RETURN_IF_EXCEPTION(scope, void());
+ }
+ if (usages & CryptoKeyUsageEncrypt) {
+ keyOps->putDirectIndex(exec, index++, jsNontrivialString(exec, ASCIILiteral("encrypt")));
+ RETURN_IF_EXCEPTION(scope, void());
+ }
+ if (usages & CryptoKeyUsageDecrypt) {
+ keyOps->putDirectIndex(exec, index++, jsNontrivialString(exec, ASCIILiteral("decrypt")));
+ RETURN_IF_EXCEPTION(scope, void());
+ }
+ if (usages & CryptoKeyUsageWrapKey) {
+ keyOps->putDirectIndex(exec, index++, jsNontrivialString(exec, ASCIILiteral("wrapKey")));
+ RETURN_IF_EXCEPTION(scope, void());
+ }
+ if (usages & CryptoKeyUsageUnwrapKey) {
+ keyOps->putDirectIndex(exec, index++, jsNontrivialString(exec, ASCIILiteral("unwrapKey")));
+ RETURN_IF_EXCEPTION(scope, void());
+ }
+ if (usages & CryptoKeyUsageDeriveKey) {
+ keyOps->putDirectIndex(exec, index++, jsNontrivialString(exec, ASCIILiteral("deriveKey")));
+ RETURN_IF_EXCEPTION(scope, void());
+ }
+ if (usages & CryptoKeyUsageDeriveBits) {
+ keyOps->putDirectIndex(exec, index++, jsNontrivialString(exec, ASCIILiteral("deriveBits")));
+ RETURN_IF_EXCEPTION(scope, void());
+ }
+
+ json->putDirect(vm, Identifier::fromString(exec, "key_ops"), keyOps);
+}
+
+String JSCryptoKeySerializationJWK::serialize(ExecState* exec, const CryptoKey& key)
+{
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ std::unique_ptr<CryptoKeyData> keyData = key.exportData();
+ if (!keyData) {
+ // This generally shouldn't happen as long as all key types implement exportData(), but as underlying libraries return errors, there may be some rare failure conditions.
+ throwTypeError(exec, scope, ASCIILiteral("Couldn't export key material"));
+ return String();
+ }
+
+ JSObject* result = constructEmptyObject(exec);
+
+ addJWKAlgorithmToJSON(exec, result, key);
+ RETURN_IF_EXCEPTION(scope, String());
+
+ addBoolToJSON(exec, result, "ext", key.extractable());
+
+ addUsagesToJSON(exec, result, key.usagesBitmap());
+ RETURN_IF_EXCEPTION(scope, String());
+
+ if (is<CryptoKeyDataOctetSequence>(*keyData))
+ buildJSONForOctetSequence(exec, downcast<CryptoKeyDataOctetSequence>(*keyData).octetSequence(), result);
+ else if (is<CryptoKeyDataRSAComponents>(*keyData))
+ buildJSONForRSAComponents(exec, downcast<CryptoKeyDataRSAComponents>(*keyData), result);
+ else {
+ throwTypeError(exec, scope, ASCIILiteral("Key doesn't support exportKey"));
+ return String();
+ }
+ RETURN_IF_EXCEPTION(scope, String());
+
+ return JSONStringify(exec, result, 0);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SUBTLE_CRYPTO)
diff --git a/Source/WebCore/bindings/js/JSCryptoKeySerializationJWK.h b/Source/WebCore/bindings/js/JSCryptoKeySerializationJWK.h
new file mode 100644
index 000000000..47a5a03be
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSCryptoKeySerializationJWK.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(SUBTLE_CRYPTO)
+
+#include "CryptoKeySerialization.h"
+#include <heap/Strong.h>
+#include <wtf/text/WTFString.h>
+
+namespace JSC {
+class ExecState;
+class JSObject;
+}
+
+namespace WebCore {
+
+class CryptoAlgorithmParametersDeprecated;
+class CryptoKey;
+class CryptoKeyDataRSAComponents;
+
+class JSCryptoKeySerializationJWK final : public CryptoKeySerialization {
+WTF_MAKE_NONCOPYABLE(JSCryptoKeySerializationJWK);
+public:
+ JSCryptoKeySerializationJWK(JSC::ExecState*, const String&);
+ virtual ~JSCryptoKeySerializationJWK();
+
+ static String serialize(JSC::ExecState* exec, const CryptoKey&);
+
+private:
+ std::optional<CryptoAlgorithmPair> reconcileAlgorithm(CryptoAlgorithm*, CryptoAlgorithmParametersDeprecated*) const override;
+
+ void reconcileUsages(CryptoKeyUsageBitmap&) const override;
+ void reconcileExtractable(bool&) const override;
+
+ std::unique_ptr<CryptoKeyData> keyData() const override;
+
+ bool keySizeIsValid(size_t sizeInBits) const;
+ std::unique_ptr<CryptoKeyData> keyDataOctetSequence() const;
+ std::unique_ptr<CryptoKeyData> keyDataRSAComponents() const;
+
+ JSC::ExecState* m_exec;
+ JSC::Strong<JSC::JSObject> m_json;
+
+ mutable String m_jwkAlgorithmName; // Stored when reconcileAlgorithm is called, and used later.
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SUBTLE_CRYPTO)
diff --git a/Source/WebCore/bindings/js/JSCryptoOperationData.cpp b/Source/WebCore/bindings/js/JSCryptoOperationData.cpp
new file mode 100644
index 000000000..2e35f2e14
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSCryptoOperationData.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSCryptoOperationData.h"
+
+#if ENABLE(SUBTLE_CRYPTO)
+
+#include "JSDOMConvertBufferSource.h"
+#include <heap/HeapInlines.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+CryptoOperationData cryptoOperationDataFromJSValue(ExecState& state, ThrowScope& scope, JSValue value)
+{
+ VM& vm = state.vm();
+ if (auto* buffer = toUnsharedArrayBuffer(vm, value))
+ return { static_cast<uint8_t*>(buffer->data()), buffer->byteLength() };
+
+ if (auto bufferView = toUnsharedArrayBufferView(vm, value))
+ return { static_cast<uint8_t*>(bufferView->baseAddress()), bufferView->byteLength() };
+
+ throwTypeError(&state, scope, ASCIILiteral("Only ArrayBuffer and ArrayBufferView objects can be passed as CryptoOperationData"));
+ return { };
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SUBTLE_CRYPTO)
diff --git a/Source/WebCore/bindings/js/JSCryptoOperationData.h b/Source/WebCore/bindings/js/JSCryptoOperationData.h
new file mode 100644
index 000000000..909e13242
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSCryptoOperationData.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(SUBTLE_CRYPTO)
+
+namespace JSC {
+class ExecState;
+class JSValue;
+class ThrowScope;
+}
+
+namespace WebCore {
+
+using CryptoOperationData = std::pair<const uint8_t*, size_t>;
+
+CryptoOperationData cryptoOperationDataFromJSValue(JSC::ExecState&, JSC::ThrowScope&, JSC::JSValue);
+
+} // namespace WebCore
+
+#endif // ENABLE(SUBTLE_CRYPTO)
diff --git a/Source/WebCore/bindings/js/JSCustomElementInterface.cpp b/Source/WebCore/bindings/js/JSCustomElementInterface.cpp
new file mode 100644
index 000000000..793ecb842
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSCustomElementInterface.cpp
@@ -0,0 +1,315 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "config.h"
+#include "JSCustomElementInterface.h"
+
+#include "DOMWrapperWorld.h"
+#include "HTMLUnknownElement.h"
+#include "JSDOMBinding.h"
+#include "JSDOMGlobalObject.h"
+#include "JSElement.h"
+#include "JSHTMLElement.h"
+#include "JSMainThreadExecState.h"
+#include "JSMainThreadExecStateInstrumentation.h"
+#include "ScriptExecutionContext.h"
+#include <heap/WeakInlines.h>
+#include <runtime/JSLock.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSCustomElementInterface::JSCustomElementInterface(const QualifiedName& name, JSObject* constructor, JSDOMGlobalObject* globalObject)
+ : ActiveDOMCallback(globalObject->scriptExecutionContext())
+ , m_name(name)
+ , m_constructor(constructor)
+ , m_isolatedWorld(&globalObject->world())
+{
+}
+
+JSCustomElementInterface::~JSCustomElementInterface()
+{
+}
+
+static RefPtr<Element> constructCustomElementSynchronously(Document&, VM&, ExecState&, JSObject* constructor, const AtomicString& localName);
+
+Ref<Element> JSCustomElementInterface::constructElementWithFallback(Document& document, const AtomicString& localName)
+{
+ if (auto element = tryToConstructCustomElement(document, localName))
+ return element.releaseNonNull();
+
+ auto element = HTMLUnknownElement::create(QualifiedName(nullAtom, localName, HTMLNames::xhtmlNamespaceURI), document);
+ element->setIsCustomElementUpgradeCandidate();
+ element->setIsFailedCustomElement(*this);
+
+ return WTFMove(element);
+}
+
+Ref<Element> JSCustomElementInterface::constructElementWithFallback(Document& document, const QualifiedName& name)
+{
+ if (auto element = tryToConstructCustomElement(document, name.localName())) {
+ if (name.prefix() != nullAtom)
+ element->setPrefix(name.prefix());
+ return element.releaseNonNull();
+ }
+
+ auto element = HTMLUnknownElement::create(name, document);
+ element->setIsCustomElementUpgradeCandidate();
+ element->setIsFailedCustomElement(*this);
+
+ return WTFMove(element);
+}
+
+RefPtr<Element> JSCustomElementInterface::tryToConstructCustomElement(Document& document, const AtomicString& localName)
+{
+ if (!canInvokeCallback())
+ return nullptr;
+
+ Ref<JSCustomElementInterface> protectedThis(*this);
+
+ VM& vm = m_isolatedWorld->vm();
+ JSLockHolder lock(vm);
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+
+ if (!m_constructor)
+ return nullptr;
+
+ ASSERT(&document == scriptExecutionContext());
+ auto& state = *document.execState();
+ auto element = constructCustomElementSynchronously(document, vm, state, m_constructor.get(), localName);
+ ASSERT(!!scope.exception() == !element);
+ if (!element) {
+ auto* exception = scope.exception();
+ scope.clearException();
+ reportException(&state, exception);
+ return nullptr;
+ }
+
+ return element;
+}
+
+// https://dom.spec.whatwg.org/#concept-create-element
+// 6. 1. If the synchronous custom elements flag is set
+static RefPtr<Element> constructCustomElementSynchronously(Document& document, VM& vm, ExecState& state, JSObject* constructor, const AtomicString& localName)
+{
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ ConstructData constructData;
+ ConstructType constructType = constructor->methodTable()->getConstructData(constructor, constructData);
+ if (constructType == ConstructType::None) {
+ ASSERT_NOT_REACHED();
+ return nullptr;
+ }
+
+ InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionConstruct(&document, constructType, constructData);
+ MarkedArgumentBuffer args;
+ JSValue newElement = construct(&state, constructor, constructType, constructData, args);
+ InspectorInstrumentation::didCallFunction(cookie, &document);
+ RETURN_IF_EXCEPTION(scope, nullptr);
+
+ ASSERT(!newElement.isEmpty());
+ HTMLElement* wrappedElement = JSHTMLElement::toWrapped(vm, newElement);
+ if (!wrappedElement) {
+ throwTypeError(&state, scope, ASCIILiteral("The result of constructing a custom element must be a HTMLElement"));
+ return nullptr;
+ }
+
+ if (wrappedElement->hasAttributes()) {
+ throwNotSupportedError(state, scope, ASCIILiteral("A newly constructed custom element must not have attributes"));
+ return nullptr;
+ }
+ if (wrappedElement->hasChildNodes()) {
+ throwNotSupportedError(state, scope, ASCIILiteral("A newly constructed custom element must not have child nodes"));
+ return nullptr;
+ }
+ if (wrappedElement->parentNode()) {
+ throwNotSupportedError(state, scope, ASCIILiteral("A newly constructed custom element must not have a parent node"));
+ return nullptr;
+ }
+ if (&wrappedElement->document() != &document) {
+ throwNotSupportedError(state, scope, ASCIILiteral("A newly constructed custom element belongs to a wrong docuemnt"));
+ return nullptr;
+ }
+ ASSERT(wrappedElement->namespaceURI() == HTMLNames::xhtmlNamespaceURI);
+ if (wrappedElement->localName() != localName) {
+ throwNotSupportedError(state, scope, ASCIILiteral("A newly constructed custom element belongs to a wrong docuemnt"));
+ return nullptr;
+ }
+
+ return wrappedElement;
+}
+
+void JSCustomElementInterface::upgradeElement(Element& element)
+{
+ ASSERT(element.tagQName() == name());
+ ASSERT(element.isCustomElementUpgradeCandidate());
+ if (!canInvokeCallback())
+ return;
+
+ Ref<JSCustomElementInterface> protectedThis(*this);
+ VM& vm = m_isolatedWorld->vm();
+ JSLockHolder lock(vm);
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (!m_constructor)
+ return;
+
+ ScriptExecutionContext* context = scriptExecutionContext();
+ if (!context)
+ return;
+ ASSERT(context->isDocument());
+ JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, *m_isolatedWorld);
+ ExecState* state = globalObject->globalExec();
+ RETURN_IF_EXCEPTION(scope, void());
+
+ ConstructData constructData;
+ ConstructType constructType = m_constructor->methodTable()->getConstructData(m_constructor.get(), constructData);
+ if (constructType == ConstructType::None) {
+ ASSERT_NOT_REACHED();
+ return;
+ }
+
+ CustomElementReactionQueue::enqueuePostUpgradeReactions(element);
+
+ m_constructionStack.append(&element);
+
+ MarkedArgumentBuffer args;
+ InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionConstruct(context, constructType, constructData);
+ JSValue returnedElement = construct(state, m_constructor.get(), constructType, constructData, args);
+ InspectorInstrumentation::didCallFunction(cookie, context);
+
+ m_constructionStack.removeLast();
+
+ if (UNLIKELY(scope.exception())) {
+ element.setIsFailedCustomElement(*this);
+ reportException(state, scope.exception());
+ return;
+ }
+
+ Element* wrappedElement = JSElement::toWrapped(vm, returnedElement);
+ if (!wrappedElement || wrappedElement != &element) {
+ element.setIsFailedCustomElement(*this);
+ reportException(state, createDOMException(state, INVALID_STATE_ERR, "Custom element constructor failed to upgrade an element"));
+ return;
+ }
+ element.setIsDefinedCustomElement(*this);
+}
+
+void JSCustomElementInterface::invokeCallback(Element& element, JSObject* callback, const WTF::Function<void(ExecState*, JSDOMGlobalObject*, MarkedArgumentBuffer&)>& addArguments)
+{
+ if (!canInvokeCallback())
+ return;
+
+ auto* context = scriptExecutionContext();
+ if (!context)
+ return;
+
+ Ref<JSCustomElementInterface> protectedThis(*this);
+ JSLockHolder lock(m_isolatedWorld->vm());
+
+ ASSERT(context);
+ ASSERT(context->isDocument());
+ JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(context, *m_isolatedWorld);
+ ExecState* state = globalObject->globalExec();
+
+ JSObject* jsElement = asObject(toJS(state, globalObject, element));
+
+ CallData callData;
+ CallType callType = callback->methodTable()->getCallData(callback, callData);
+ ASSERT(callType != CallType::None);
+
+ MarkedArgumentBuffer args;
+ addArguments(state, globalObject, args);
+
+ InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(context, callType, callData);
+
+ NakedPtr<JSC::Exception> exception;
+ JSMainThreadExecState::call(state, callback, callType, callData, jsElement, args, exception);
+
+ InspectorInstrumentation::didCallFunction(cookie, context);
+
+ if (exception)
+ reportException(state, exception);
+}
+
+void JSCustomElementInterface::setConnectedCallback(JSC::JSObject* callback)
+{
+ m_connectedCallback = callback;
+}
+
+void JSCustomElementInterface::invokeConnectedCallback(Element& element)
+{
+ invokeCallback(element, m_connectedCallback.get());
+}
+
+void JSCustomElementInterface::setDisconnectedCallback(JSC::JSObject* callback)
+{
+ m_disconnectedCallback = callback;
+}
+
+void JSCustomElementInterface::invokeDisconnectedCallback(Element& element)
+{
+ invokeCallback(element, m_disconnectedCallback.get());
+}
+
+void JSCustomElementInterface::setAdoptedCallback(JSC::JSObject* callback)
+{
+ m_adoptedCallback = callback;
+}
+
+void JSCustomElementInterface::invokeAdoptedCallback(Element& element, Document& oldDocument, Document& newDocument)
+{
+ invokeCallback(element, m_adoptedCallback.get(), [&](ExecState* state, JSDOMGlobalObject* globalObject, MarkedArgumentBuffer& args) {
+ args.append(toJS(state, globalObject, oldDocument));
+ args.append(toJS(state, globalObject, newDocument));
+ });
+}
+
+void JSCustomElementInterface::setAttributeChangedCallback(JSC::JSObject* callback, const Vector<String>& observedAttributes)
+{
+ m_attributeChangedCallback = callback;
+ m_observedAttributes.clear();
+ for (auto& name : observedAttributes)
+ m_observedAttributes.add(name);
+}
+
+void JSCustomElementInterface::invokeAttributeChangedCallback(Element& element, const QualifiedName& attributeName, const AtomicString& oldValue, const AtomicString& newValue)
+{
+ invokeCallback(element, m_attributeChangedCallback.get(), [&](ExecState* state, JSDOMGlobalObject*, MarkedArgumentBuffer& args) {
+ args.append(toJS<IDLDOMString>(*state, attributeName.localName()));
+ args.append(toJS<IDLNullable<IDLDOMString>>(*state, oldValue));
+ args.append(toJS<IDLNullable<IDLDOMString>>(*state, newValue));
+ args.append(toJS<IDLNullable<IDLDOMString>>(*state, attributeName.namespaceURI()));
+ });
+}
+
+void JSCustomElementInterface::didUpgradeLastElementInConstructionStack()
+{
+ m_constructionStack.last() = nullptr;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSCustomElementInterface.h b/Source/WebCore/bindings/js/JSCustomElementInterface.h
new file mode 100644
index 000000000..8a3f656ee
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSCustomElementInterface.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2013 Google Inc. All rights reserved.
+ * Copyright (C) 2015, 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "ActiveDOMCallback.h"
+#include "QualifiedName.h"
+#include <heap/Weak.h>
+#include <heap/WeakInlines.h>
+#include <runtime/JSObject.h>
+#include <wtf/Forward.h>
+#include <wtf/Function.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/AtomicStringHash.h>
+
+namespace JSC {
+class JSObject;
+class PrivateName;
+}
+
+namespace WebCore {
+
+class DOMWrapperWorld;
+class Document;
+class Element;
+class JSDOMGlobalObject;
+class MathMLElement;
+class SVGElement;
+
+class JSCustomElementInterface : public RefCounted<JSCustomElementInterface>, public ActiveDOMCallback {
+public:
+ static Ref<JSCustomElementInterface> create(const QualifiedName& name, JSC::JSObject* callback, JSDOMGlobalObject* globalObject)
+ {
+ return adoptRef(*new JSCustomElementInterface(name, callback, globalObject));
+ }
+
+ Ref<Element> constructElementWithFallback(Document&, const AtomicString&);
+ Ref<Element> constructElementWithFallback(Document&, const QualifiedName&);
+
+ void upgradeElement(Element&);
+
+ void setConnectedCallback(JSC::JSObject*);
+ bool hasConnectedCallback() const { return !!m_connectedCallback; }
+ void invokeConnectedCallback(Element&);
+
+ void setDisconnectedCallback(JSC::JSObject*);
+ bool hasDisconnectedCallback() const { return !!m_disconnectedCallback; }
+ void invokeDisconnectedCallback(Element&);
+
+ void setAdoptedCallback(JSC::JSObject*);
+ bool hasAdoptedCallback() const { return !!m_adoptedCallback; }
+ void invokeAdoptedCallback(Element&, Document& oldDocument, Document& newDocument);
+
+ void setAttributeChangedCallback(JSC::JSObject* callback, const Vector<String>& observedAttributes);
+ bool observesAttribute(const AtomicString& name) const { return m_observedAttributes.contains(name); }
+ void invokeAttributeChangedCallback(Element&, const QualifiedName&, const AtomicString& oldValue, const AtomicString& newValue);
+
+ ScriptExecutionContext* scriptExecutionContext() const { return ContextDestructionObserver::scriptExecutionContext(); }
+ JSC::JSObject* constructor() { return m_constructor.get(); }
+
+ const QualifiedName& name() const { return m_name; }
+
+ bool isUpgradingElement() const { return !m_constructionStack.isEmpty(); }
+ Element* lastElementInConstructionStack() const { return m_constructionStack.last().get(); }
+ void didUpgradeLastElementInConstructionStack();
+
+ virtual ~JSCustomElementInterface();
+
+private:
+ JSCustomElementInterface(const QualifiedName&, JSC::JSObject* callback, JSDOMGlobalObject*);
+
+ RefPtr<Element> tryToConstructCustomElement(Document&, const AtomicString&);
+
+ void invokeCallback(Element&, JSC::JSObject* callback, const WTF::Function<void(JSC::ExecState*, JSDOMGlobalObject*, JSC::MarkedArgumentBuffer&)>& addArguments = { });
+
+ QualifiedName m_name;
+ JSC::Weak<JSC::JSObject> m_constructor;
+ JSC::Weak<JSC::JSObject> m_connectedCallback;
+ JSC::Weak<JSC::JSObject> m_disconnectedCallback;
+ JSC::Weak<JSC::JSObject> m_adoptedCallback;
+ JSC::Weak<JSC::JSObject> m_attributeChangedCallback;
+ RefPtr<DOMWrapperWorld> m_isolatedWorld;
+ Vector<RefPtr<Element>, 1> m_constructionStack;
+ HashSet<AtomicString> m_observedAttributes;
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSCustomElementRegistryCustom.cpp b/Source/WebCore/bindings/js/JSCustomElementRegistryCustom.cpp
new file mode 100644
index 000000000..cf9e96d27
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSCustomElementRegistryCustom.cpp
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2015, 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSCustomElementRegistry.h"
+
+#include "CustomElementRegistry.h"
+#include "Document.h"
+#include "HTMLNames.h"
+#include "JSCustomElementInterface.h"
+#include "JSDOMBinding.h"
+#include "JSDOMConvert.h"
+#include "JSDOMPromise.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+static JSObject* getCustomElementCallback(ExecState& state, JSObject& prototype, const Identifier& id)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ JSValue callback = prototype.get(&state, id);
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ if (callback.isUndefined())
+ return nullptr;
+ if (!callback.isFunction()) {
+ throwTypeError(&state, scope, ASCIILiteral("A custom element callback must be a function"));
+ return nullptr;
+ }
+ return callback.getObject();
+}
+
+static bool validateCustomElementNameAndThrowIfNeeded(ExecState& state, const AtomicString& name)
+{
+ auto scope = DECLARE_THROW_SCOPE(state.vm());
+
+ switch (Document::validateCustomElementName(name)) {
+ case CustomElementNameValidationStatus::Valid:
+ return true;
+ case CustomElementNameValidationStatus::ConflictsWithBuiltinNames:
+ throwSyntaxError(&state, scope, ASCIILiteral("Custom element name cannot be same as one of the builtin elements"));
+ return false;
+ case CustomElementNameValidationStatus::NoHyphen:
+ throwSyntaxError(&state, scope, ASCIILiteral("Custom element name must contain a hyphen"));
+ return false;
+ case CustomElementNameValidationStatus::ContainsUpperCase:
+ throwSyntaxError(&state, scope, ASCIILiteral("Custom element name cannot contain an upper case letter"));
+ return false;
+ }
+ ASSERT_NOT_REACHED();
+ return false;
+}
+
+// https://html.spec.whatwg.org/#dom-customelementregistry-define
+JSValue JSCustomElementRegistry::define(ExecState& state)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (UNLIKELY(state.argumentCount() < 2))
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+
+ AtomicString localName(state.uncheckedArgument(0).toString(&state)->toAtomicString(&state));
+ RETURN_IF_EXCEPTION(scope, JSValue());
+
+ JSValue constructorValue = state.uncheckedArgument(1);
+ if (!constructorValue.isConstructor())
+ return throwTypeError(&state, scope, ASCIILiteral("The second argument must be a constructor"));
+ JSObject* constructor = constructorValue.getObject();
+
+ if (!validateCustomElementNameAndThrowIfNeeded(state, localName))
+ return jsUndefined();
+
+ CustomElementRegistry& registry = wrapped();
+
+ if (registry.elementDefinitionIsRunning()) {
+ throwNotSupportedError(state, scope, ASCIILiteral("Cannot define a custom element while defining another custom element"));
+ return jsUndefined();
+ }
+ SetForScope<bool> change(registry.elementDefinitionIsRunning(), true);
+
+ if (registry.findInterface(localName)) {
+ throwNotSupportedError(state, scope, ASCIILiteral("Cannot define multiple custom elements with the same tag name"));
+ return jsUndefined();
+ }
+
+ if (registry.containsConstructor(constructor)) {
+ throwNotSupportedError(state, scope, ASCIILiteral("Cannot define multiple custom elements with the same class"));
+ return jsUndefined();
+ }
+
+ JSValue prototypeValue = constructor->get(&state, vm.propertyNames->prototype);
+ RETURN_IF_EXCEPTION(scope, JSValue());
+ if (!prototypeValue.isObject())
+ return throwTypeError(&state, scope, ASCIILiteral("Custom element constructor's prototype must be an object"));
+ JSObject& prototypeObject = *asObject(prototypeValue);
+
+ QualifiedName name(nullAtom, localName, HTMLNames::xhtmlNamespaceURI);
+ auto elementInterface = JSCustomElementInterface::create(name, constructor, globalObject());
+
+ auto* connectedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "connectedCallback"));
+ if (connectedCallback)
+ elementInterface->setConnectedCallback(connectedCallback);
+ RETURN_IF_EXCEPTION(scope, JSValue());
+
+ auto* disconnectedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "disconnectedCallback"));
+ if (disconnectedCallback)
+ elementInterface->setDisconnectedCallback(disconnectedCallback);
+ RETURN_IF_EXCEPTION(scope, JSValue());
+
+ auto* adoptedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "adoptedCallback"));
+ if (adoptedCallback)
+ elementInterface->setAdoptedCallback(adoptedCallback);
+ RETURN_IF_EXCEPTION(scope, JSValue());
+
+ auto* attributeChangedCallback = getCustomElementCallback(state, prototypeObject, Identifier::fromString(&vm, "attributeChangedCallback"));
+ RETURN_IF_EXCEPTION(scope, JSValue());
+ if (attributeChangedCallback) {
+ auto observedAttributesValue = constructor->get(&state, Identifier::fromString(&state, "observedAttributes"));
+ RETURN_IF_EXCEPTION(scope, JSValue());
+ if (!observedAttributesValue.isUndefined()) {
+ auto observedAttributes = convert<IDLSequence<IDLDOMString>>(state, observedAttributesValue);
+ RETURN_IF_EXCEPTION(scope, JSValue());
+ elementInterface->setAttributeChangedCallback(attributeChangedCallback, observedAttributes);
+ }
+ }
+
+ auto addToGlobalObjectWithPrivateName = [&] (JSObject* objectToAdd) {
+ if (objectToAdd) {
+ PrivateName uniquePrivateName;
+ globalObject()->putDirect(vm, uniquePrivateName, objectToAdd);
+ }
+ };
+
+ addToGlobalObjectWithPrivateName(constructor);
+ addToGlobalObjectWithPrivateName(connectedCallback);
+ addToGlobalObjectWithPrivateName(disconnectedCallback);
+ addToGlobalObjectWithPrivateName(adoptedCallback);
+ addToGlobalObjectWithPrivateName(attributeChangedCallback);
+
+ registry.addElementDefinition(WTFMove(elementInterface));
+
+ return jsUndefined();
+}
+
+// https://html.spec.whatwg.org/#dom-customelementregistry-whendefined
+static JSValue whenDefinedPromise(ExecState& state, JSDOMGlobalObject& globalObject, CustomElementRegistry& registry, JSPromiseDeferred& promiseDeferred)
+{
+ auto scope = DECLARE_THROW_SCOPE(state.vm());
+
+ if (UNLIKELY(state.argumentCount() < 1))
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+
+ AtomicString localName(state.uncheckedArgument(0).toString(&state)->toAtomicString(&state));
+ RETURN_IF_EXCEPTION(scope, JSValue());
+
+ if (!validateCustomElementNameAndThrowIfNeeded(state, localName)) {
+ ASSERT(scope.exception());
+ return jsUndefined();
+ }
+
+ if (registry.findInterface(localName)) {
+ DeferredPromise::create(globalObject, promiseDeferred)->resolve();
+ return promiseDeferred.promise();
+ }
+
+ auto result = registry.promiseMap().ensure(localName, [&] {
+ return DeferredPromise::create(globalObject, promiseDeferred);
+ });
+
+ return result.iterator->value->promise();
+}
+
+JSValue JSCustomElementRegistry::whenDefined(ExecState& state)
+{
+ auto scope = DECLARE_CATCH_SCOPE(state.vm());
+
+ ASSERT(globalObject());
+ auto promiseDeferred = JSPromiseDeferred::create(&state, globalObject());
+ ASSERT(promiseDeferred);
+ JSValue promise = whenDefinedPromise(state, *globalObject(), wrapped(), *promiseDeferred);
+
+ if (UNLIKELY(scope.exception())) {
+ rejectPromiseWithExceptionIfAny(state, *globalObject(), *promiseDeferred);
+ ASSERT(!scope.exception());
+ return promiseDeferred->promise();
+ }
+
+ return promise;
+}
+
+}
diff --git a/Source/WebCore/bindings/js/JSRTCStatsResponseCustom.cpp b/Source/WebCore/bindings/js/JSCustomEventCustom.cpp
index 821dc1b1f..8cfb769f4 100644
--- a/Source/WebCore/bindings/js/JSRTCStatsResponseCustom.cpp
+++ b/Source/WebCore/bindings/js/JSCustomEventCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) Research In Motion Limited 2013. All rights reserved.
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -24,28 +24,37 @@
*/
#include "config.h"
+#include "JSCustomEvent.h"
-#if ENABLE(MEDIA_STREAM)
-#include "JSRTCStatsResponse.h"
-
-#include "JSRTCStatsReport.h"
-#include <wtf/text/AtomicString.h>
+#include "CustomEvent.h"
+#include "DOMWrapperWorld.h"
+#include <runtime/JSCInlines.h>
+#include <runtime/JSCJSValue.h>
+#include <runtime/Structure.h>
using namespace JSC;
namespace WebCore {
-
-bool JSRTCStatsResponse::canGetItemsForName(ExecState*, RTCStatsResponse* response, PropertyName propertyName)
-{
- return response->canGetItemsForName(propertyNameToAtomicString(propertyName));
-}
-
-EncodedJSValue JSRTCStatsResponse::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName)
+
+JSValue JSCustomEvent::detail(ExecState& state) const
{
- JSRTCStatsResponse* thisObj = jsCast<JSRTCStatsResponse*>(JSValue::decode(slotBase));
- return JSValue::encode(toJS(exec, thisObj->globalObject(), thisObj->impl().namedItem(propertyNameToAtomicString(propertyName))));
+ auto& event = wrapped();
+
+ auto detail = event.detail();
+ if (!detail)
+ return jsNull();
+
+ if (detail.isObject() && &worldForDOMObject(detail.getObject()) != &currentWorld(&state)) {
+ // We need to make sure CustomEvents do not leak their detail property across isolated DOM worlds.
+ // Ideally, we would check that the worlds have different privileges but that's not possible yet.
+ auto serializedDetail = event.trySerializeDetail(state);
+ if (!serializedDetail)
+ return jsNull();
+ return serializedDetail->deserialize(state, globalObject());
+ }
+
+ return detail;
}
} // namespace WebCore
-#endif // ENABLE(MEDIA_STREAM)
diff --git a/Source/WebCore/bindings/js/JSCustomXPathNSResolver.cpp b/Source/WebCore/bindings/js/JSCustomXPathNSResolver.cpp
index f1b63f85a..2f14dff6b 100644
--- a/Source/WebCore/bindings/js/JSCustomXPathNSResolver.cpp
+++ b/Source/WebCore/bindings/js/JSCustomXPathNSResolver.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -26,14 +26,14 @@
#include "config.h"
#include "JSCustomXPathNSResolver.h"
+#include "CommonVM.h"
#include "Document.h"
-#include "ExceptionCode.h"
#include "Frame.h"
+#include "JSDOMExceptionHandling.h"
#include "JSDOMWindowCustom.h"
#include "JSMainThreadExecState.h"
#include "Page.h"
-#include "PageConsole.h"
-#include "SecurityOrigin.h"
+#include "PageConsoleClient.h"
#include <runtime/JSLock.h>
#include <wtf/Ref.h>
@@ -41,23 +41,21 @@ namespace WebCore {
using namespace JSC;
-PassRefPtr<JSCustomXPathNSResolver> JSCustomXPathNSResolver::create(ExecState* exec, JSValue value)
+ExceptionOr<Ref<JSCustomXPathNSResolver>> JSCustomXPathNSResolver::create(ExecState& state, JSValue value)
{
if (value.isUndefinedOrNull())
- return 0;
+ return Exception { TypeError };
- JSObject* resolverObject = value.getObject();
- if (!resolverObject) {
- setDOMException(exec, TYPE_MISMATCH_ERR);
- return 0;
- }
+ auto* resolverObject = value.getObject();
+ if (!resolverObject)
+ return Exception { TYPE_MISMATCH_ERR };
- return adoptRef(new JSCustomXPathNSResolver(exec, resolverObject, asJSDOMWindow(exec->vmEntryGlobalObject())));
+ return adoptRef(*new JSCustomXPathNSResolver(state.vm(), resolverObject, asJSDOMWindow(state.vmEntryGlobalObject())));
}
-JSCustomXPathNSResolver::JSCustomXPathNSResolver(ExecState* exec, JSObject* customResolver, JSDOMWindow* globalObject)
- : m_customResolver(exec->vm(), customResolver)
- , m_globalObject(exec->vm(), globalObject)
+JSCustomXPathNSResolver::JSCustomXPathNSResolver(VM& vm, JSObject* customResolver, JSDOMWindow* globalObject)
+ : m_customResolver(vm, customResolver)
+ , m_globalObject(vm, globalObject)
{
}
@@ -69,37 +67,37 @@ String JSCustomXPathNSResolver::lookupNamespaceURI(const String& prefix)
{
ASSERT(m_customResolver);
- JSLockHolder lock(JSDOMWindowBase::commonVM());
+ JSLockHolder lock(commonVM());
ExecState* exec = m_globalObject->globalExec();
- JSValue function = m_customResolver->get(exec, Identifier(exec, "lookupNamespaceURI"));
+ JSValue function = m_customResolver->get(exec, Identifier::fromString(exec, "lookupNamespaceURI"));
CallData callData;
CallType callType = getCallData(function, callData);
- if (callType == CallTypeNone) {
+ if (callType == CallType::None) {
callType = m_customResolver->methodTable()->getCallData(m_customResolver.get(), callData);
- if (callType == CallTypeNone) {
- // FIXME: <http://webkit.org/b/114312> JSCustomXPathNSResolver::lookupNamespaceURI Console Message should include Line, Column, and SourceURL
- if (PageConsole* console = m_globalObject->impl().pageConsole())
- console->addMessage(JSMessageSource, ErrorMessageLevel, "XPathNSResolver does not have a lookupNamespaceURI method.");
+ if (callType == CallType::None) {
+ if (PageConsoleClient* console = m_globalObject->wrapped().console())
+ console->addMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("XPathNSResolver does not have a lookupNamespaceURI method."));
return String();
}
function = m_customResolver.get();
}
- Ref<JSCustomXPathNSResolver> selfProtector(*this);
+ Ref<JSCustomXPathNSResolver> protectedThis(*this);
MarkedArgumentBuffer args;
args.append(jsStringWithCache(exec, prefix));
- JSValue retval = JSMainThreadExecState::call(exec, function, callType, callData, m_customResolver.get(), args);
+ NakedPtr<JSC::Exception> exception;
+ JSValue retval = JSMainThreadExecState::call(exec, function, callType, callData, m_customResolver.get(), args, exception);
String result;
- if (exec->hadException())
- reportCurrentException(exec);
+ if (exception)
+ reportException(exec, exception);
else {
if (!retval.isUndefinedOrNull())
- result = retval.toString(exec)->value(exec);
+ result = retval.toWTFString(exec);
}
return result;
diff --git a/Source/WebCore/bindings/js/JSCustomXPathNSResolver.h b/Source/WebCore/bindings/js/JSCustomXPathNSResolver.h
index 7e218e8b7..4cee8d316 100644
--- a/Source/WebCore/bindings/js/JSCustomXPathNSResolver.h
+++ b/Source/WebCore/bindings/js/JSCustomXPathNSResolver.h
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -23,43 +23,32 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSCustomXPathNSResolver_h
-#define JSCustomXPathNSResolver_h
+#pragma once
+#include "ExceptionOr.h"
#include "XPathNSResolver.h"
#include <heap/Strong.h>
#include <heap/StrongInlines.h>
+#include <runtime/JSCInlines.h>
#include <runtime/JSCJSValue.h>
-#include <runtime/Operations.h>
-#include <wtf/Forward.h>
-#include <wtf/RefPtr.h>
-
-namespace JSC {
- class ExecState;
- class JSObject;
-}
namespace WebCore {
- class Frame;
- class JSDOMWindow;
+class JSDOMWindow;
- class JSCustomXPathNSResolver : public XPathNSResolver {
- public:
- static PassRefPtr<JSCustomXPathNSResolver> create(JSC::ExecState*, JSC::JSValue);
-
- virtual ~JSCustomXPathNSResolver();
+class JSCustomXPathNSResolver final : public XPathNSResolver {
+public:
+ static ExceptionOr<Ref<JSCustomXPathNSResolver>> create(JSC::ExecState&, JSC::JSValue);
+ virtual ~JSCustomXPathNSResolver();
- virtual String lookupNamespaceURI(const String& prefix);
+private:
+ JSCustomXPathNSResolver(JSC::VM&, JSC::JSObject*, JSDOMWindow*);
- private:
- JSCustomXPathNSResolver(JSC::ExecState*, JSC::JSObject*, JSDOMWindow*);
+ String lookupNamespaceURI(const String& prefix) final;
- // JSCustomXPathNSResolvers are always temporary so using a Strong reference is safe here.
- JSC::Strong<JSC::JSObject> m_customResolver;
- JSC::Strong<JSDOMWindow> m_globalObject;
- };
+ // JSCustomXPathNSResolvers are always temporary so using a Strong reference is safe here.
+ JSC::Strong<JSC::JSObject> m_customResolver;
+ JSC::Strong<JSDOMWindow> m_globalObject;
+};
} // namespace WebCore
-
-#endif // JSCustomXPathNSResolver_h
diff --git a/Source/WebCore/bindings/js/JSDOMBinding.cpp b/Source/WebCore/bindings/js/JSDOMBinding.cpp
deleted file mode 100644
index a32d332ad..000000000
--- a/Source/WebCore/bindings/js/JSDOMBinding.cpp
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
- * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013 Apple Inc. All rights reserved.
- * Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
- * Copyright (C) 2013 Michael Pruett <michael@68k.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "config.h"
-#include "JSDOMBinding.h"
-
-#include "CachedScript.h"
-#include "DOMConstructorWithDocument.h"
-#include "DOMObjectHashTableMap.h"
-#include "DOMStringList.h"
-#include "ExceptionCode.h"
-#include "ExceptionHeaders.h"
-#include "ExceptionInterfaces.h"
-#include "Frame.h"
-#include "HTMLParserIdioms.h"
-#include "JSDOMWindowCustom.h"
-#include "JSExceptionBase.h"
-#include "SecurityOrigin.h"
-#include "ScriptCallStack.h"
-#include "ScriptCallStackFactory.h"
-#include <interpreter/Interpreter.h>
-#include <runtime/DateInstance.h>
-#include <runtime/Error.h>
-#include <runtime/ExceptionHelpers.h>
-#include <runtime/JSFunction.h>
-#include <wtf/MathExtras.h>
-
-using namespace JSC;
-
-namespace WebCore {
-
-STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(DOMConstructorObject);
-STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(DOMConstructorWithDocument);
-
-void addImpureProperty(const AtomicString& propertyName)
-{
- JSDOMWindow::commonVM()->addImpureProperty(propertyName);
-}
-
-const JSC::HashTable& getHashTableForGlobalData(VM& vm, const JSC::HashTable& staticTable)
-{
- return DOMObjectHashTableMap::mapFor(vm).get(staticTable);
-}
-
-JSValue jsStringOrNull(ExecState* exec, const String& s)
-{
- if (s.isNull())
- return jsNull();
- return jsStringWithCache(exec, s);
-}
-
-JSValue jsOwnedStringOrNull(ExecState* exec, const String& s)
-{
- if (s.isNull())
- return jsNull();
- return jsOwnedString(exec, s);
-}
-
-JSValue jsStringOrUndefined(ExecState* exec, const String& s)
-{
- if (s.isNull())
- return jsUndefined();
- return jsStringWithCache(exec, s);
-}
-
-JSValue jsString(ExecState* exec, const URL& url)
-{
- return jsStringWithCache(exec, url.string());
-}
-
-JSValue jsStringOrNull(ExecState* exec, const URL& url)
-{
- if (url.isNull())
- return jsNull();
- return jsStringWithCache(exec, url.string());
-}
-
-JSValue jsStringOrUndefined(ExecState* exec, const URL& url)
-{
- if (url.isNull())
- return jsUndefined();
- return jsStringWithCache(exec, url.string());
-}
-
-AtomicStringImpl* findAtomicString(PropertyName propertyName)
-{
- StringImpl* impl = propertyName.publicName();
- if (!impl)
- return 0;
- ASSERT(impl->existingHash());
- return AtomicString::find(impl);
-}
-
-String valueToStringWithNullCheck(ExecState* exec, JSValue value)
-{
- if (value.isNull())
- return String();
- return value.toString(exec)->value(exec);
-}
-
-String valueToStringWithUndefinedOrNullCheck(ExecState* exec, JSValue value)
-{
- if (value.isUndefinedOrNull())
- return String();
- return value.toString(exec)->value(exec);
-}
-
-JSValue jsDateOrNull(ExecState* exec, double value)
-{
- if (!std::isfinite(value))
- return jsNull();
- return DateInstance::create(exec->vm(), exec->lexicalGlobalObject()->dateStructure(), value);
-}
-
-double valueToDate(ExecState* exec, JSValue value)
-{
- if (value.isNumber())
- return value.asNumber();
- if (!value.inherits(DateInstance::info()))
- return std::numeric_limits<double>::quiet_NaN();
- return static_cast<DateInstance*>(value.toObject(exec))->internalNumber();
-}
-
-JSC::JSValue jsArray(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<DOMStringList> stringList)
-{
- JSC::MarkedArgumentBuffer list;
- if (stringList) {
- for (unsigned i = 0; i < stringList->length(); ++i)
- list.append(jsStringWithCache(exec, stringList->item(i)));
- }
- return JSC::constructArray(exec, 0, globalObject, list);
-}
-
-void reportException(ExecState* exec, JSValue exception, CachedScript* cachedScript)
-{
- if (isTerminatedExecutionException(exception))
- return;
-
- Interpreter::ErrorHandlingMode mode(exec);
-
- RefPtr<ScriptCallStack> callStack(createScriptCallStackFromException(exec, exception, ScriptCallStack::maxCallStackSizeToCapture));
- exec->clearException();
- exec->clearSupplementaryExceptionInfo();
-
- JSDOMGlobalObject* globalObject = jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject());
- if (JSDOMWindow* window = jsDynamicCast<JSDOMWindow*>(globalObject)) {
- if (!window->impl().isCurrentlyDisplayedInFrame())
- return;
- }
-
- int lineNumber = 0;
- int columnNumber = 0;
- String exceptionSourceURL;
- if (callStack->size()) {
- const ScriptCallFrame& frame = callStack->at(0);
- lineNumber = frame.lineNumber();
- columnNumber = frame.columnNumber();
- exceptionSourceURL = frame.sourceURL();
- } else {
- // There may not be an exceptionStack for a <script> SyntaxError. Fallback to getting at least the line and sourceURL from the exception.
- JSObject* exceptionObject = exception.toObject(exec);
- JSValue lineValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "line"));
- lineNumber = lineValue && lineValue.isNumber() ? int(lineValue.toNumber(exec)) : 0;
- JSValue columnValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "column"));
- columnNumber = columnValue && columnValue.isNumber() ? int(columnValue.toNumber(exec)) : 0;
- JSValue sourceURLValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "sourceURL"));
- exceptionSourceURL = sourceURLValue && sourceURLValue.isString() ? sourceURLValue.toString(exec)->value(exec) : ASCIILiteral("undefined");
- }
-
- String errorMessage;
- if (ExceptionBase* exceptionBase = toExceptionBase(exception))
- errorMessage = exceptionBase->message() + ": " + exceptionBase->description();
- else {
- // FIXME: <http://webkit.org/b/115087> Web Inspector: WebCore::reportException should not evaluate JavaScript handling exceptions
- // If this is a custon exception object, call toString on it to try and get a nice string representation for the exception.
- errorMessage = exception.toString(exec)->value(exec);
- exec->clearException();
- exec->clearSupplementaryExceptionInfo();
- }
-
- ScriptExecutionContext* scriptExecutionContext = globalObject->scriptExecutionContext();
- scriptExecutionContext->reportException(errorMessage, lineNumber, columnNumber, exceptionSourceURL, callStack->size() ? callStack : 0, cachedScript);
-}
-
-void reportCurrentException(ExecState* exec)
-{
- JSValue exception = exec->exception();
- exec->clearException();
- reportException(exec, exception);
-}
-
-#define TRY_TO_CREATE_EXCEPTION(interfaceName) \
- case interfaceName##Type: \
- errorObject = toJS(exec, globalObject, interfaceName::create(description)); \
- break;
-
-void setDOMException(ExecState* exec, ExceptionCode ec)
-{
- if (!ec || exec->hadException())
- return;
-
- // FIXME: Handle other WebIDL exception types.
- if (ec == TypeError) {
- throwTypeError(exec);
- return;
- }
-
- // FIXME: All callers to setDOMException need to pass in the right global object
- // for now, we're going to assume the lexicalGlobalObject. Which is wrong in cases like this:
- // frames[0].document.createElement(null, null); // throws an exception which should have the subframes prototypes.
- JSDOMGlobalObject* globalObject = deprecatedGlobalObjectForPrototype(exec);
-
- ExceptionCodeDescription description(ec);
-
- JSValue errorObject;
- switch (description.type) {
- DOM_EXCEPTION_INTERFACES_FOR_EACH(TRY_TO_CREATE_EXCEPTION)
- }
-
- ASSERT(errorObject);
- exec->vm().throwException(exec, errorObject);
-}
-
-#undef TRY_TO_CREATE_EXCEPTION
-
-bool shouldAllowAccessToNode(ExecState* exec, Node* node)
-{
- return BindingSecurity::shouldAllowAccessToNode(exec, node);
-}
-
-bool shouldAllowAccessToFrame(ExecState* exec, Frame* target)
-{
- return BindingSecurity::shouldAllowAccessToFrame(exec, target);
-}
-
-bool shouldAllowAccessToFrame(ExecState* exec, Frame* frame, String& message)
-{
- if (!frame)
- return false;
- if (BindingSecurity::shouldAllowAccessToFrame(exec, frame, DoNotReportSecurityError))
- return true;
- message = frame->document()->domWindow()->crossDomainAccessErrorMessage(activeDOMWindow(exec));
- return false;
-}
-
-bool shouldAllowAccessToDOMWindow(ExecState* exec, DOMWindow& target, String& message)
-{
- if (BindingSecurity::shouldAllowAccessToDOMWindow(exec, target, DoNotReportSecurityError))
- return true;
- message = target.crossDomainAccessErrorMessage(activeDOMWindow(exec));
- return false;
-}
-
-void printErrorMessageForFrame(Frame* frame, const String& message)
-{
- if (!frame)
- return;
- frame->document()->domWindow()->printErrorMessage(message);
-}
-
-EncodedJSValue objectToStringFunctionGetter(ExecState* exec, EncodedJSValue, EncodedJSValue, PropertyName propertyName)
-{
- return JSValue::encode(JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), 0, propertyName.publicName(), objectProtoFuncToString));
-}
-
-Structure* getCachedDOMStructure(JSDOMGlobalObject* globalObject, const ClassInfo* classInfo)
-{
- JSDOMStructureMap& structures = globalObject->structures();
- return structures.get(classInfo).get();
-}
-
-Structure* cacheDOMStructure(JSDOMGlobalObject* globalObject, Structure* structure, const ClassInfo* classInfo)
-{
- JSDOMStructureMap& structures = globalObject->structures();
- ASSERT(!structures.contains(classInfo));
- return structures.set(classInfo, WriteBarrier<Structure>(globalObject->vm(), globalObject, structure)).iterator->value.get();
-}
-
-static const int32_t kMaxInt32 = 0x7fffffff;
-static const int32_t kMinInt32 = -kMaxInt32 - 1;
-static const uint32_t kMaxUInt32 = 0xffffffffU;
-static const int64_t kJSMaxInteger = 0x20000000000000LL - 1; // 2^53 - 1, largest integer exactly representable in ECMAScript.
-
-static double enforceRange(ExecState* exec, double x, double minimum, double maximum)
-{
- if (std::isnan(x) || std::isinf(x)) {
- throwTypeError(exec);
- return 0;
- }
- x = trunc(x);
- if (x < minimum || x > maximum) {
- throwTypeError(exec);
- return 0;
- }
- return x;
-}
-
-template <typename T>
-struct IntTypeLimits {
-};
-
-template <>
-struct IntTypeLimits<int8_t> {
- static const int8_t minValue = -128;
- static const int8_t maxValue = 127;
- static const unsigned numberOfValues = 256; // 2^8
-};
-
-template <>
-struct IntTypeLimits<uint8_t> {
- static const uint8_t maxValue = 255;
- static const unsigned numberOfValues = 256; // 2^8
-};
-
-template <>
-struct IntTypeLimits<int16_t> {
- static const short minValue = -32768;
- static const short maxValue = 32767;
- static const unsigned numberOfValues = 65536; // 2^16
-};
-
-template <>
-struct IntTypeLimits<uint16_t> {
- static const unsigned short maxValue = 65535;
- static const unsigned numberOfValues = 65536; // 2^16
-};
-
-template <typename T>
-static inline T toSmallerInt(ExecState* exec, JSValue value, IntegerConversionConfiguration configuration)
-{
- typedef IntTypeLimits<T> LimitsTrait;
- // Fast path if the value is already a 32-bit signed integer in the right range.
- if (value.isInt32()) {
- int32_t d = value.asInt32();
- if (d >= LimitsTrait::minValue && d <= LimitsTrait::maxValue)
- return static_cast<T>(d);
- if (configuration == EnforceRange) {
- throwTypeError(exec);
- return 0;
- }
- d %= LimitsTrait::numberOfValues;
- return static_cast<T>(d > LimitsTrait::maxValue ? d - LimitsTrait::numberOfValues : d);
- }
-
- double x = value.toNumber(exec);
- if (exec->hadException())
- return 0;
-
- if (configuration == EnforceRange)
- return enforceRange(exec, x, LimitsTrait::minValue, LimitsTrait::maxValue);
-
- if (std::isnan(x) || std::isinf(x) || !x)
- return 0;
-
- x = x < 0 ? -floor(fabs(x)) : floor(fabs(x));
- x = fmod(x, LimitsTrait::numberOfValues);
-
- return static_cast<T>(x > LimitsTrait::maxValue ? x - LimitsTrait::numberOfValues : x);
-}
-
-template <typename T>
-static inline T toSmallerUInt(ExecState* exec, JSValue value, IntegerConversionConfiguration configuration)
-{
- typedef IntTypeLimits<T> LimitsTrait;
- // Fast path if the value is already a 32-bit unsigned integer in the right range.
- if (value.isUInt32()) {
- uint32_t d = value.asUInt32();
- if (d <= LimitsTrait::maxValue)
- return static_cast<T>(d);
- if (configuration == EnforceRange) {
- throwTypeError(exec);
- return 0;
- }
- return static_cast<T>(d);
- }
-
- double x = value.toNumber(exec);
- if (exec->hadException())
- return 0;
-
- if (configuration == EnforceRange)
- return enforceRange(exec, x, 0, LimitsTrait::maxValue);
-
- if (std::isnan(x) || std::isinf(x) || !x)
- return 0;
-
- x = x < 0 ? -floor(fabs(x)) : floor(fabs(x));
- return static_cast<T>(fmod(x, LimitsTrait::numberOfValues));
-}
-
-// http://www.w3.org/TR/WebIDL/#es-byte
-int8_t toInt8(ExecState* exec, JSValue value, IntegerConversionConfiguration configuration)
-{
- return toSmallerInt<int8_t>(exec, value, configuration);
-}
-
-// http://www.w3.org/TR/WebIDL/#es-octet
-uint8_t toUInt8(ExecState* exec, JSValue value, IntegerConversionConfiguration configuration)
-{
- return toSmallerUInt<uint8_t>(exec, value, configuration);
-}
-
-// http://www.w3.org/TR/WebIDL/#es-short
-int16_t toInt16(ExecState* exec, JSValue value, IntegerConversionConfiguration configuration)
-{
- return toSmallerInt<int16_t>(exec, value, configuration);
-}
-
-// http://www.w3.org/TR/WebIDL/#es-unsigned-short
-uint16_t toUInt16(ExecState* exec, JSValue value, IntegerConversionConfiguration configuration)
-{
- return toSmallerUInt<uint16_t>(exec, value, configuration);
-}
-
-// http://www.w3.org/TR/WebIDL/#es-long
-int32_t toInt32EnforceRange(ExecState* exec, JSValue value)
-{
- if (value.isInt32())
- return value.asInt32();
-
- double x = value.toNumber(exec);
- if (exec->hadException())
- return 0;
- return enforceRange(exec, x, kMinInt32, kMaxInt32);
-}
-
-// http://www.w3.org/TR/WebIDL/#es-unsigned-long
-uint32_t toUInt32EnforceRange(ExecState* exec, JSValue value)
-{
- if (value.isUInt32())
- return value.asUInt32();
-
- double x = value.toNumber(exec);
- if (exec->hadException())
- return 0;
- return enforceRange(exec, x, 0, kMaxUInt32);
-}
-
-// http://www.w3.org/TR/WebIDL/#es-long-long
-int64_t toInt64(ExecState* exec, JSValue value, IntegerConversionConfiguration configuration)
-{
- if (value.isInt32())
- return value.asInt32();
-
- double x = value.toNumber(exec);
- if (exec->hadException())
- return 0;
-
- if (configuration == EnforceRange)
- return enforceRange(exec, x, -kJSMaxInteger, kJSMaxInteger);
-
- // Map NaNs and +/-Infinity to 0; convert finite values modulo 2^64.
- unsigned long long n;
- doubleToInteger(x, n);
- return n;
-}
-
-// http://www.w3.org/TR/WebIDL/#es-unsigned-long-long
-uint64_t toUInt64(ExecState* exec, JSValue value, IntegerConversionConfiguration configuration)
-{
- if (value.isUInt32())
- return value.asUInt32();
-
- double x = value.toNumber(exec);
- if (exec->hadException())
- return 0;
-
- if (configuration == EnforceRange)
- return enforceRange(exec, x, 0, kJSMaxInteger);
-
- // Map NaNs and +/-Infinity to 0; convert finite values modulo 2^64.
- unsigned long long n;
- doubleToInteger(x, n);
- return n;
-}
-
-DOMWindow& activeDOMWindow(ExecState* exec)
-{
- return asJSDOMWindow(exec->lexicalGlobalObject())->impl();
-}
-
-DOMWindow& firstDOMWindow(ExecState* exec)
-{
- return asJSDOMWindow(exec->vmEntryGlobalObject())->impl();
-}
-
-static inline bool canAccessDocument(JSC::ExecState* state, Document* targetDocument, SecurityReportingOption reportingOption = ReportSecurityError)
-{
- if (!targetDocument)
- return false;
-
- DOMWindow& active = activeDOMWindow(state);
-
- if (active.document()->securityOrigin()->canAccess(targetDocument->securityOrigin()))
- return true;
-
- if (reportingOption == ReportSecurityError)
- printErrorMessageForFrame(targetDocument->frame(), targetDocument->domWindow()->crossDomainAccessErrorMessage(active));
-
- return false;
-}
-
-bool BindingSecurity::shouldAllowAccessToDOMWindow(JSC::ExecState* state, DOMWindow& target, SecurityReportingOption reportingOption)
-{
- return canAccessDocument(state, target.document(), reportingOption);
-}
-
-bool BindingSecurity::shouldAllowAccessToFrame(JSC::ExecState* state, Frame* target, SecurityReportingOption reportingOption)
-{
- return target && canAccessDocument(state, target->document(), reportingOption);
-}
-
-bool BindingSecurity::shouldAllowAccessToNode(JSC::ExecState* state, Node* target)
-{
- return target && canAccessDocument(state, &target->document());
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMBinding.h b/Source/WebCore/bindings/js/JSDOMBinding.h
index 097ce6b26..34890157c 100644
--- a/Source/WebCore/bindings/js/JSDOMBinding.h
+++ b/Source/WebCore/bindings/js/JSDOMBinding.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2003-2006, 2008-2009, 2013, 2016 Apple Inc. All rights reserved.
* Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
* Copyright (C) 2009 Google, Inc. All rights reserved.
* Copyright (C) 2012 Ericsson AB. All rights reserved.
@@ -21,653 +21,24 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef JSDOMBinding_h
-#define JSDOMBinding_h
+#pragma once
-#include "JSDOMGlobalObject.h"
-#include "JSDOMWrapper.h"
-#include "DOMWrapperWorld.h"
-#include "ScriptWrappable.h"
-#include "ScriptWrappableInlines.h"
-#include "WebCoreTypedArrayController.h"
+// FIXME: Remove this header.
+
+#include "ExceptionOr.h"
+#include "JSDOMWrapperCache.h"
#include <cstddef>
-#include <heap/Weak.h>
-#include <heap/WeakInlines.h>
-#include <runtime/Error.h>
-#include <runtime/FunctionPrototype.h>
+#include <heap/HeapInlines.h>
+#include <heap/SlotVisitorInlines.h>
+#include <runtime/AuxiliaryBarrierInlines.h>
#include <runtime/JSArray.h>
-#include <runtime/JSArrayBuffer.h>
-#include <runtime/JSDataView.h>
-#include <runtime/JSTypedArrays.h>
+#include <runtime/JSCJSValueInlines.h>
+#include <runtime/JSCellInlines.h>
+#include <runtime/JSObjectInlines.h>
#include <runtime/Lookup.h>
-#include <runtime/ObjectPrototype.h>
-#include <runtime/Operations.h>
-#include <runtime/TypedArrayInlines.h>
-#include <runtime/TypedArrays.h>
+#include <runtime/ObjectConstructor.h>
+#include <runtime/StructureInlines.h>
+#include <runtime/WriteBarrier.h>
#include <wtf/Forward.h>
-#include <wtf/Noncopyable.h>
+#include <wtf/GetPtr.h>
#include <wtf/Vector.h>
-
-namespace JSC {
-class HashEntry;
-}
-
-namespace WebCore {
-
-class DOMStringList;
-
-class CachedScript;
-class Document;
-class DOMWindow;
-class Frame;
-class HTMLDocument;
-class URL;
-class Node;
-
-typedef int ExceptionCode;
-
-DOMWindow& activeDOMWindow(JSC::ExecState*);
-DOMWindow& firstDOMWindow(JSC::ExecState*);
-
-// Base class for all constructor objects in the JSC bindings.
-class DOMConstructorObject : public JSDOMWrapper {
- typedef JSDOMWrapper Base;
-public:
- static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
- {
- return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
- }
-
-protected:
- static const unsigned StructureFlags = JSC::ImplementsHasInstance | JSC::OverridesVisitChildren | JSDOMWrapper::StructureFlags;
- DOMConstructorObject(JSC::Structure* structure, JSDOMGlobalObject* globalObject)
- : JSDOMWrapper(structure, globalObject)
- {
- }
-};
-
-JSC::Structure* getCachedDOMStructure(JSDOMGlobalObject*, const JSC::ClassInfo*);
-JSC::Structure* cacheDOMStructure(JSDOMGlobalObject*, JSC::Structure*, const JSC::ClassInfo*);
-
-inline JSDOMGlobalObject* deprecatedGlobalObjectForPrototype(JSC::ExecState* exec)
-{
- // FIXME: Callers to this function should be using the global object
- // from which the object is being created, instead of assuming the lexical one.
- // e.g. subframe.document.body should use the subframe's global object, not the lexical one.
- return JSC::jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject());
-}
-
-template<class WrapperClass> inline JSC::Structure* getDOMStructure(JSC::VM& vm, JSDOMGlobalObject* globalObject)
-{
- if (JSC::Structure* structure = getCachedDOMStructure(globalObject, WrapperClass::info()))
- return structure;
- return cacheDOMStructure(globalObject, WrapperClass::createStructure(vm, globalObject, WrapperClass::createPrototype(vm, globalObject)), WrapperClass::info());
-}
-
-template<class WrapperClass> inline JSC::Structure* deprecatedGetDOMStructure(JSC::ExecState* exec)
-{
- // FIXME: This function is wrong. It uses the wrong global object for creating the prototype structure.
- return getDOMStructure<WrapperClass>(exec->vm(), deprecatedGlobalObjectForPrototype(exec));
-}
-
-template<class WrapperClass> inline JSC::JSObject* getDOMPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
-{
- return JSC::jsCast<JSC::JSObject*>(asObject(getDOMStructure<WrapperClass>(vm, JSC::jsCast<JSDOMGlobalObject*>(globalObject))->storedPrototype()));
-}
-
-inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld& world, JSC::ArrayBuffer*)
-{
- return static_cast<WebCoreTypedArrayController*>(world.vm()->m_typedArrayController.get())->wrapperOwner();
-}
-
-inline void* wrapperContext(DOMWrapperWorld& world, JSC::ArrayBuffer*)
-{
- return &world;
-}
-
-inline JSDOMWrapper* getInlineCachedWrapper(DOMWrapperWorld&, void*) { return 0; }
-inline bool setInlineCachedWrapper(DOMWrapperWorld&, void*, JSDOMWrapper*, JSC::WeakHandleOwner*, void*) { return false; }
-inline bool clearInlineCachedWrapper(DOMWrapperWorld&, void*, JSDOMWrapper*) { return false; }
-
-inline JSDOMWrapper* getInlineCachedWrapper(DOMWrapperWorld& world, ScriptWrappable* domObject)
-{
- if (!world.isNormal())
- return 0;
- return domObject->wrapper();
-}
-
-inline JSC::JSArrayBuffer* getInlineCachedWrapper(DOMWrapperWorld& world, JSC::ArrayBuffer* buffer)
-{
- if (!world.isNormal())
- return 0;
- return buffer->m_wrapper.get();
-}
-
-inline bool setInlineCachedWrapper(DOMWrapperWorld& world, ScriptWrappable* domObject, JSDOMWrapper* wrapper, JSC::WeakHandleOwner* wrapperOwner, void* context)
-{
- if (!world.isNormal())
- return false;
- domObject->setWrapper(wrapper, wrapperOwner, context);
- return true;
-}
-
-inline bool setInlineCachedWrapper(DOMWrapperWorld& world, JSC::ArrayBuffer* domObject, JSC::JSArrayBuffer* wrapper, JSC::WeakHandleOwner* wrapperOwner, void* context)
-{
- if (!world.isNormal())
- return false;
- domObject->m_wrapper = JSC::Weak<JSC::JSArrayBuffer>(wrapper, wrapperOwner, context);
- return true;
-}
-
-inline bool clearInlineCachedWrapper(DOMWrapperWorld& world, ScriptWrappable* domObject, JSDOMWrapper* wrapper)
-{
- if (!world.isNormal())
- return false;
- domObject->clearWrapper(wrapper);
- return true;
-}
-
-inline bool clearInlineCachedWrapper(DOMWrapperWorld& world, JSC::ArrayBuffer* domObject, JSC::JSArrayBuffer* wrapper)
-{
- if (!world.isNormal())
- return false;
- weakClear(domObject->m_wrapper, wrapper);
- return true;
-}
-
-template <typename DOMClass> inline JSC::JSObject* getCachedWrapper(DOMWrapperWorld& world, DOMClass* domObject)
-{
- if (JSC::JSObject* wrapper = getInlineCachedWrapper(world, domObject))
- return wrapper;
- return world.m_wrappers.get(domObject);
-}
-
-template <typename DOMClass, typename WrapperClass> inline void cacheWrapper(DOMWrapperWorld& world, DOMClass* domObject, WrapperClass* wrapper)
-{
- JSC::WeakHandleOwner* owner = wrapperOwner(world, domObject);
- void* context = wrapperContext(world, domObject);
- if (setInlineCachedWrapper(world, domObject, wrapper, owner, context))
- return;
- weakAdd(world.m_wrappers, (void*)domObject, JSC::Weak<JSC::JSObject>(wrapper, owner, context));
-}
-
-template <typename DOMClass, typename WrapperClass> inline void uncacheWrapper(DOMWrapperWorld& world, DOMClass* domObject, WrapperClass* wrapper)
-{
- if (clearInlineCachedWrapper(world, domObject, wrapper))
- return;
- weakRemove(world.m_wrappers, (void*)domObject, wrapper);
-}
-
-#define CREATE_DOM_WRAPPER(exec, globalObject, className, object) createWrapper<JS##className>(exec, globalObject, static_cast<className*>(object))
-template<class WrapperClass, class DOMClass> inline JSDOMWrapper* createWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* node)
-{
- ASSERT(node);
- ASSERT(!getCachedWrapper(currentWorld(exec), node));
- WrapperClass* wrapper = WrapperClass::create(getDOMStructure<WrapperClass>(exec->vm(), globalObject), globalObject, node);
- // FIXME: The entire function can be removed, once we fix caching.
- // This function is a one-off hack to make Nodes cache in the right global object.
- cacheWrapper(currentWorld(exec), node, wrapper);
- return wrapper;
-}
-
-template<class WrapperClass, class DOMClass> inline JSC::JSValue wrap(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* domObject)
-{
- if (!domObject)
- return JSC::jsNull();
- if (JSC::JSObject* wrapper = getCachedWrapper(currentWorld(exec), domObject))
- return wrapper;
- return createWrapper<WrapperClass>(exec, globalObject, domObject);
-}
-
-template<class WrapperClass, class DOMClass> inline JSC::JSValue getExistingWrapper(JSC::ExecState* exec, DOMClass* domObject)
-{
- ASSERT(domObject);
- return getCachedWrapper(currentWorld(exec), domObject);
-}
-
-template<class WrapperClass, class DOMClass> inline JSC::JSValue createNewWrapper(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMClass* domObject)
-{
- ASSERT(domObject);
- ASSERT(!getCachedWrapper(currentWorld(exec), domObject));
- return createWrapper<WrapperClass>(exec, globalObject, domObject);
-}
-
-inline JSC::JSValue argumentOrNull(JSC::ExecState* exec, unsigned index)
-{
- return index >= exec->argumentCount() ? JSC::JSValue() : exec->argument(index);
-}
-
-void addImpureProperty(const AtomicString&);
-
-const JSC::HashTable& getHashTableForGlobalData(JSC::VM&, const JSC::HashTable& staticTable);
-
-void reportException(JSC::ExecState*, JSC::JSValue exception, CachedScript* = 0);
-void reportCurrentException(JSC::ExecState*);
-
-// Convert a DOM implementation exception code into a JavaScript exception in the execution state.
-void setDOMException(JSC::ExecState*, ExceptionCode);
-
-JSC::JSValue jsStringWithCache(JSC::ExecState*, const String&);
-JSC::JSValue jsString(JSC::ExecState*, const URL&); // empty if the URL is null
-inline JSC::JSValue jsStringWithCache(JSC::ExecState* exec, const AtomicString& s)
-{
- return jsStringWithCache(exec, s.string());
-}
-
-JSC::JSValue jsStringOrNull(JSC::ExecState*, const String&); // null if the string is null
-JSC::JSValue jsStringOrNull(JSC::ExecState*, const URL&); // null if the URL is null
-
-JSC::JSValue jsStringOrUndefined(JSC::ExecState*, const String&); // undefined if the string is null
-JSC::JSValue jsStringOrUndefined(JSC::ExecState*, const URL&); // undefined if the URL is null
-
-// See JavaScriptCore for explanation: Should be used for any string that is already owned by another
-// object, to let the engine know that collecting the JSString wrapper is unlikely to save memory.
-JSC::JSValue jsOwnedStringOrNull(JSC::ExecState*, const String&);
-
-String propertyNameToString(JSC::PropertyName);
-
-AtomicString propertyNameToAtomicString(JSC::PropertyName);
-AtomicStringImpl* findAtomicString(JSC::PropertyName);
-
-String valueToStringWithNullCheck(JSC::ExecState*, JSC::JSValue); // null if the value is null
-String valueToStringWithUndefinedOrNullCheck(JSC::ExecState*, JSC::JSValue); // null if the value is null or undefined
-
-inline int32_t finiteInt32Value(JSC::JSValue value, JSC::ExecState* exec, bool& okay)
-{
- double number = value.toNumber(exec);
- okay = std::isfinite(number);
- return JSC::toInt32(number);
-}
-
-enum IntegerConversionConfiguration {
- NormalConversion,
- EnforceRange,
- // FIXME: Implement Clamp
-};
-
-int32_t toInt32EnforceRange(JSC::ExecState*, JSC::JSValue);
-uint32_t toUInt32EnforceRange(JSC::ExecState*, JSC::JSValue);
-
-int8_t toInt8(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration);
-uint8_t toUInt8(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration);
-
-int16_t toInt16(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration);
-uint16_t toUInt16(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration);
-
-/*
- Convert a value to an integer as per <http://www.w3.org/TR/WebIDL/>.
- The conversion fails if the value cannot be converted to a number or,
- if EnforceRange is specified, the value is outside the range of the
- destination integer type.
-*/
-inline int32_t toInt32(JSC::ExecState* exec, JSC::JSValue value, IntegerConversionConfiguration configuration)
-{
- if (configuration == EnforceRange)
- return toInt32EnforceRange(exec, value);
- return value.toInt32(exec);
-}
-
-inline uint32_t toUInt32(JSC::ExecState* exec, JSC::JSValue value, IntegerConversionConfiguration configuration)
-{
- if (configuration == EnforceRange)
- return toUInt32EnforceRange(exec, value);
- return value.toUInt32(exec);
-}
-
-int64_t toInt64(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration);
-uint64_t toUInt64(JSC::ExecState*, JSC::JSValue, IntegerConversionConfiguration);
-
-// Returns a Date instance for the specified value, or null if the value is NaN or infinity.
-JSC::JSValue jsDateOrNull(JSC::ExecState*, double);
-// NaN if the value can't be converted to a date.
-double valueToDate(JSC::ExecState*, JSC::JSValue);
-
-// Validates that the passed object is a sequence type per section 4.1.13 of the WebIDL spec.
-inline JSC::JSObject* toJSSequence(JSC::ExecState* exec, JSC::JSValue value, unsigned& length)
-{
- JSC::JSObject* object = value.getObject();
- if (!object) {
- throwVMError(exec, createTypeError(exec, "Value is not a sequence"));
- return 0;
- }
-
- JSC::JSValue lengthValue = object->get(exec, exec->propertyNames().length);
- if (exec->hadException())
- return 0;
-
- if (lengthValue.isUndefinedOrNull()) {
- throwVMError(exec, createTypeError(exec, "Value is not a sequence"));
- return 0;
- }
-
- length = lengthValue.toUInt32(exec);
- if (exec->hadException())
- return 0;
-
- return object;
-}
-
-inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, JSC::ArrayBuffer* buffer)
-{
- if (!buffer)
- return JSC::jsNull();
- if (JSC::JSValue result = getExistingWrapper<JSC::JSArrayBuffer>(exec, buffer))
- return result;
- buffer->ref();
- JSC::JSArrayBuffer* wrapper = JSC::JSArrayBuffer::create(exec->vm(), globalObject->arrayBufferStructure(), buffer);
- cacheWrapper(currentWorld(exec), buffer, wrapper);
- return wrapper;
-}
-
-inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, JSC::ArrayBufferView* view)
-{
- if (!view)
- return JSC::jsNull();
- return view->wrap(exec, globalObject);
-}
-
-template <typename T>
-inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, PassRefPtr<T> ptr)
-{
- return toJS(exec, globalObject, ptr.get());
-}
-
-template <typename T>
-inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<T>& vector)
-{
- JSC::JSArray* array = constructEmptyArray(exec, 0, vector.size());
-
- for (size_t i = 0; i < vector.size(); ++i)
- array->putDirectIndex(exec, i, toJS(exec, globalObject, vector[i]));
-
- return array;
-}
-
-template <typename T>
-inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<RefPtr<T>>& vector)
-{
- JSC::JSArray* array = constructEmptyArray(exec, 0, vector.size());
-
- for (size_t i = 0; i < vector.size(); ++i)
- array->putDirectIndex(exec, i, toJS(exec, globalObject, vector[i].get()));
-
- return array;
-}
-
-inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject*, const String& value)
-{
- return jsStringOrNull(exec, value);
-}
-
-template <class T>
-struct JSValueTraits {
- static inline JSC::JSValue arrayJSValue(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const T& value)
- {
- return toJS(exec, globalObject, WTF::getPtr(value));
- }
-};
-
-template<>
-struct JSValueTraits<String> {
- static inline JSC::JSValue arrayJSValue(JSC::ExecState* exec, JSDOMGlobalObject*, const String& value)
- {
- return jsStringWithCache(exec, value);
- }
-};
-
-template<>
-struct JSValueTraits<float> {
- static inline JSC::JSValue arrayJSValue(JSC::ExecState*, JSDOMGlobalObject*, const float& value)
- {
- return JSC::jsNumber(value);
- }
-};
-
-template<>
-struct JSValueTraits<unsigned long> {
- static inline JSC::JSValue arrayJSValue(JSC::ExecState*, JSDOMGlobalObject*, const unsigned long& value)
- {
- return JSC::jsNumber(value);
- }
-};
-
-template <typename T, size_t inlineCapacity>
-JSC::JSValue jsArray(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, const Vector<T, inlineCapacity>& iterator)
-{
- JSC::MarkedArgumentBuffer list;
- typename Vector<T, inlineCapacity>::const_iterator end = iterator.end();
- typedef JSValueTraits<T> TraitsType;
-
- for (typename Vector<T, inlineCapacity>::const_iterator iter = iterator.begin(); iter != end; ++iter)
- list.append(TraitsType::arrayJSValue(exec, globalObject, *iter));
-
- return JSC::constructArray(exec, 0, globalObject, list);
-}
-
-JSC::JSValue jsArray(JSC::ExecState*, JSDOMGlobalObject*, PassRefPtr<DOMStringList>);
-
-inline PassRefPtr<JSC::ArrayBufferView> toArrayBufferView(JSC::JSValue value)
-{
- JSC::JSArrayBufferView* wrapper = JSC::jsDynamicCast<JSC::JSArrayBufferView*>(value);
- if (!wrapper)
- return 0;
- return wrapper->impl();
-}
-
-inline PassRefPtr<JSC::Int8Array> toInt8Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Int8Adaptor>(value); }
-inline PassRefPtr<JSC::Int16Array> toInt16Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Int16Adaptor>(value); }
-inline PassRefPtr<JSC::Int32Array> toInt32Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Int32Adaptor>(value); }
-inline PassRefPtr<JSC::Uint8Array> toUint8Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Uint8Adaptor>(value); }
-inline PassRefPtr<JSC::Uint8ClampedArray> toUint8ClampedArray(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Uint8ClampedAdaptor>(value); }
-inline PassRefPtr<JSC::Uint16Array> toUint16Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Uint16Adaptor>(value); }
-inline PassRefPtr<JSC::Uint32Array> toUint32Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Uint32Adaptor>(value); }
-inline PassRefPtr<JSC::Float32Array> toFloat32Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Float32Adaptor>(value); }
-inline PassRefPtr<JSC::Float64Array> toFloat64Array(JSC::JSValue value) { return JSC::toNativeTypedView<JSC::Float64Adaptor>(value); }
-
-inline PassRefPtr<JSC::DataView> toDataView(JSC::JSValue value)
-{
- JSC::JSDataView* wrapper = JSC::jsDynamicCast<JSC::JSDataView*>(value);
- if (!wrapper)
- return 0;
- return wrapper->typedImpl();
-}
-
-template<class T> struct NativeValueTraits;
-
-template<>
-struct NativeValueTraits<String> {
- static inline bool nativeValue(JSC::ExecState* exec, JSC::JSValue jsValue, String& indexedValue)
- {
- indexedValue = jsValue.toString(exec)->value(exec);
- return true;
- }
-};
-
-template<>
-struct NativeValueTraits<unsigned> {
- static inline bool nativeValue(JSC::ExecState* exec, JSC::JSValue jsValue, unsigned& indexedValue)
- {
- if (!jsValue.isNumber())
- return false;
-
- indexedValue = jsValue.toUInt32(exec);
- if (exec->hadException())
- return false;
-
- return true;
- }
-};
-
-template<>
-struct NativeValueTraits<float> {
- static inline bool nativeValue(JSC::ExecState* exec, JSC::JSValue jsValue, float& indexedValue)
- {
- indexedValue = jsValue.toFloat(exec);
- return !exec->hadException();
- }
-};
-
-template <class T, class JST>
-Vector<RefPtr<T>> toRefPtrNativeArray(JSC::ExecState* exec, JSC::JSValue value, T* (*toT)(JSC::JSValue value))
-{
- if (!isJSArray(value))
- return Vector<RefPtr<T>>();
-
- Vector<RefPtr<T>> result;
- JSC::JSArray* array = asArray(value);
- size_t size = array->length();
- result.reserveInitialCapacity(size);
- for (size_t i = 0; i < size; ++i) {
- JSC::JSValue element = array->getIndex(exec, i);
- if (element.inherits(JST::info()))
- result.uncheckedAppend((*toT)(element));
- else {
- throwVMError(exec, createTypeError(exec, "Invalid Array element type"));
- return Vector<RefPtr<T>>();
- }
- }
- return result;
-}
-
-template <class T>
-Vector<T> toNativeArray(JSC::ExecState* exec, JSC::JSValue value)
-{
- unsigned length = 0;
- if (isJSArray(value)) {
- JSC::JSArray* array = asArray(value);
- length = array->length();
- } else
- toJSSequence(exec, value, length);
-
- JSC::JSObject* object = value.getObject();
- Vector<T> result;
- result.reserveInitialCapacity(length);
- typedef NativeValueTraits<T> TraitsType;
-
- for (unsigned i = 0; i < length; ++i) {
- T indexValue;
- if (!TraitsType::nativeValue(exec, object->get(exec, i), indexValue))
- return Vector<T>();
- result.uncheckedAppend(indexValue);
- }
- return result;
-}
-
-template <class T>
-Vector<T> toNativeArguments(JSC::ExecState* exec, size_t startIndex = 0)
-{
- size_t length = exec->argumentCount();
- ASSERT(startIndex <= length);
-
- Vector<T> result;
- result.reserveInitialCapacity(length);
- typedef NativeValueTraits<T> TraitsType;
-
- for (size_t i = startIndex; i < length; ++i) {
- T indexValue;
- if (!TraitsType::nativeValue(exec, exec->argument(i), indexValue))
- return Vector<T>();
- result.uncheckedAppend(indexValue);
- }
- return result;
-}
-
-bool shouldAllowAccessToNode(JSC::ExecState*, Node*);
-bool shouldAllowAccessToFrame(JSC::ExecState*, Frame*);
-bool shouldAllowAccessToFrame(JSC::ExecState*, Frame*, String& message);
-bool shouldAllowAccessToDOMWindow(JSC::ExecState*, DOMWindow&, String& message);
-
-void printErrorMessageForFrame(Frame*, const String& message);
-JSC::EncodedJSValue objectToStringFunctionGetter(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue, JSC::PropertyName);
-
-inline JSC::JSValue jsStringWithCache(JSC::ExecState* exec, const String& s)
-{
- StringImpl* stringImpl = s.impl();
- if (!stringImpl || !stringImpl->length())
- return jsEmptyString(exec);
-
- if (stringImpl->length() == 1) {
- UChar singleCharacter = (*stringImpl)[0u];
- if (singleCharacter <= JSC::maxSingleCharacterString) {
- JSC::VM* vm = &exec->vm();
- return vm->smallStrings.singleCharacterString(static_cast<unsigned char>(singleCharacter));
- }
- }
-
- JSStringCache& stringCache = currentWorld(exec).m_stringCache;
- JSStringCache::AddResult addResult = stringCache.add(stringImpl, nullptr);
- if (addResult.isNewEntry)
- addResult.iterator->value = JSC::jsString(exec, String(stringImpl));
- return JSC::JSValue(addResult.iterator->value.get());
-}
-
-inline String propertyNameToString(JSC::PropertyName propertyName)
-{
- return propertyName.publicName();
-}
-
-inline AtomicString propertyNameToAtomicString(JSC::PropertyName propertyName)
-{
- return AtomicString(propertyName.publicName());
-}
-
-template <class ThisImp>
-inline const JSC::HashEntry* getStaticValueSlotEntryWithoutCaching(JSC::ExecState* exec, JSC::PropertyName propertyName)
-{
- const JSC::HashEntry* entry = ThisImp::info()->propHashTable(exec)->entry(exec, propertyName);
- if (!entry) // not found, forward to parent
- return getStaticValueSlotEntryWithoutCaching<typename ThisImp::Base>(exec, propertyName);
- return entry;
-}
-
-template <>
-inline const JSC::HashEntry* getStaticValueSlotEntryWithoutCaching<JSDOMWrapper>(JSC::ExecState*, JSC::PropertyName)
-{
- return 0;
-}
-
-template<typename T>
-class HasMemoryCostMemberFunction {
- typedef char YesType;
- struct NoType {
- char padding[8];
- };
-
- template<typename U>
- static decltype(static_cast<U*>(nullptr)->memoryCost(), YesType()) test(int);
-
- template<typename U>
- static NoType test(...);
-
-public:
- static const bool value = sizeof(test<T>(0)) == sizeof(YesType);
-};
-
-template <typename T, bool hasReportCostFunction = HasMemoryCostMemberFunction<T>::value > struct ReportMemoryCost;
-template <typename T> struct ReportMemoryCost<T, true> {
- static void reportMemoryCost(JSC::ExecState* exec, T* impl)
- {
- exec->heap()->reportExtraMemoryCost(impl->memoryCost());
- }
-};
-template <typename T> struct ReportMemoryCost<T, false> {
- static void reportMemoryCost(JSC::ExecState*, T*)
- {
- }
-};
-
-enum SecurityReportingOption {
- DoNotReportSecurityError,
- ReportSecurityError,
-};
-
-class BindingSecurity {
-public:
- static bool shouldAllowAccessToNode(JSC::ExecState*, Node*);
- static bool shouldAllowAccessToDOMWindow(JSC::ExecState*, DOMWindow&, SecurityReportingOption = ReportSecurityError);
- static bool shouldAllowAccessToFrame(JSC::ExecState*, Frame*, SecurityReportingOption = ReportSecurityError);
-};
-
-} // namespace WebCore
-
-#endif // JSDOMBinding_h
diff --git a/Source/WebCore/bindings/js/JSDOMBindingCaller.h b/Source/WebCore/bindings/js/JSDOMBindingCaller.h
new file mode 100644
index 000000000..715c6713d
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMBindingCaller.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003-2006, 2008-2009, 2013, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
+ * Copyright (C) 2009 Google, Inc. All rights reserved.
+ * Copyright (C) 2012 Ericsson AB. All rights reserved.
+ * Copyright (C) 2013 Michael Pruett <michael@68k.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include "JSDOMExceptionHandling.h"
+
+namespace WebCore {
+
+enum class CastedThisErrorBehavior { Throw, ReturnEarly, RejectPromise, Assert };
+
+template<typename JSClass>
+struct BindingCaller {
+ using AttributeSetterFunction = bool(JSC::ExecState&, JSClass&, JSC::JSValue, JSC::ThrowScope&);
+ using AttributeGetterFunction = JSC::JSValue(JSC::ExecState&, JSClass&, JSC::ThrowScope&);
+ using OperationCallerFunction = JSC::EncodedJSValue(JSC::ExecState*, JSClass*, JSC::ThrowScope&);
+ using PromiseOperationCallerFunction = JSC::EncodedJSValue(JSC::ExecState*, JSClass*, Ref<DeferredPromise>&&, JSC::ThrowScope&);
+
+ static JSClass* castForAttribute(JSC::ExecState&, JSC::EncodedJSValue);
+ static JSClass* castForOperation(JSC::ExecState&);
+
+ template<PromiseOperationCallerFunction operationCaller, CastedThisErrorBehavior shouldThrow = CastedThisErrorBehavior::RejectPromise>
+ static JSC::EncodedJSValue callPromiseOperation(JSC::ExecState* state, Ref<DeferredPromise>&& promise, const char* operationName)
+ {
+ ASSERT(state);
+ auto throwScope = DECLARE_THROW_SCOPE(state->vm());
+ auto* thisObject = castForOperation(*state);
+ if (shouldThrow != CastedThisErrorBehavior::Assert && UNLIKELY(!thisObject))
+ return rejectPromiseWithThisTypeError(promise.get(), JSClass::info()->className, operationName);
+ ASSERT(thisObject);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, JSClass::info());
+ // FIXME: We should refactor the binding generated code to use references for state and thisObject.
+ return operationCaller(state, thisObject, WTFMove(promise), throwScope);
+ }
+
+ template<OperationCallerFunction operationCaller, CastedThisErrorBehavior shouldThrow = CastedThisErrorBehavior::Throw>
+ static JSC::EncodedJSValue callOperation(JSC::ExecState* state, const char* operationName)
+ {
+ ASSERT(state);
+ auto throwScope = DECLARE_THROW_SCOPE(state->vm());
+ auto* thisObject = castForOperation(*state);
+ if (shouldThrow != CastedThisErrorBehavior::Assert && UNLIKELY(!thisObject)) {
+ if (shouldThrow == CastedThisErrorBehavior::Throw)
+ return throwThisTypeError(*state, throwScope, JSClass::info()->className, operationName);
+ // For custom promise-returning operations
+ return rejectPromiseWithThisTypeError(*state, JSClass::info()->className, operationName);
+ }
+ ASSERT(thisObject);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, JSClass::info());
+ // FIXME: We should refactor the binding generated code to use references for state and thisObject.
+ return operationCaller(state, thisObject, throwScope);
+ }
+
+ template<AttributeSetterFunction setter, CastedThisErrorBehavior shouldThrow = CastedThisErrorBehavior::Throw>
+ static bool setAttribute(JSC::ExecState* state, JSC::EncodedJSValue thisValue, JSC::EncodedJSValue encodedValue, const char* attributeName)
+ {
+ ASSERT(state);
+ auto throwScope = DECLARE_THROW_SCOPE(state->vm());
+ auto* thisObject = castForAttribute(*state, thisValue);
+ if (UNLIKELY(!thisObject))
+ return (shouldThrow == CastedThisErrorBehavior::Throw) ? throwSetterTypeError(*state, throwScope, JSClass::info()->className, attributeName) : false;
+ return setter(*state, *thisObject, JSC::JSValue::decode(encodedValue), throwScope);
+ }
+
+ template<AttributeGetterFunction getter, CastedThisErrorBehavior shouldThrow = CastedThisErrorBehavior::Throw>
+ static JSC::EncodedJSValue attribute(JSC::ExecState* state, JSC::EncodedJSValue thisValue, const char* attributeName)
+ {
+ ASSERT(state);
+ auto throwScope = DECLARE_THROW_SCOPE(state->vm());
+ auto* thisObject = castForAttribute(*state, thisValue);
+ if (UNLIKELY(!thisObject)) {
+ if (shouldThrow == CastedThisErrorBehavior::Throw)
+ return throwGetterTypeError(*state, throwScope, JSClass::info()->className, attributeName);
+ if (shouldThrow == CastedThisErrorBehavior::RejectPromise)
+ return rejectPromiseWithGetterTypeError(*state, JSClass::info()->className, attributeName);
+ return JSC::JSValue::encode(JSC::jsUndefined());
+ }
+ return JSC::JSValue::encode(getter(*state, *thisObject, throwScope));
+ }
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMBindingSecurity.cpp b/Source/WebCore/bindings/js/JSDOMBindingSecurity.cpp
new file mode 100644
index 000000000..4eefc8691
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMBindingSecurity.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004-2011, 2013, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
+ * Copyright (C) 2013 Michael Pruett <michael@68k.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "JSDOMBindingSecurity.h"
+
+#include "DOMWindow.h"
+#include "Document.h"
+#include "Frame.h"
+#include "JSDOMExceptionHandling.h"
+#include "JSDOMWindowBase.h"
+#include "SecurityOrigin.h"
+#include <wtf/text/WTFString.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+void printErrorMessageForFrame(Frame* frame, const String& message)
+{
+ if (!frame)
+ return;
+ frame->document()->domWindow()->printErrorMessage(message);
+}
+
+static inline bool canAccessDocument(JSC::ExecState* state, Document* targetDocument, SecurityReportingOption reportingOption)
+{
+ VM& vm = state->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (!targetDocument)
+ return false;
+
+ DOMWindow& active = activeDOMWindow(state);
+
+ if (active.document()->securityOrigin().canAccess(targetDocument->securityOrigin()))
+ return true;
+
+ switch (reportingOption) {
+ case ThrowSecurityError:
+ throwSecurityError(*state, scope, targetDocument->domWindow()->crossDomainAccessErrorMessage(active));
+ break;
+ case LogSecurityError:
+ printErrorMessageForFrame(targetDocument->frame(), targetDocument->domWindow()->crossDomainAccessErrorMessage(active));
+ break;
+ case DoNotReportSecurityError:
+ break;
+ }
+
+ return false;
+}
+
+bool BindingSecurity::shouldAllowAccessToFrame(ExecState& state, Frame& frame, String& message)
+{
+ if (BindingSecurity::shouldAllowAccessToFrame(&state, &frame, DoNotReportSecurityError))
+ return true;
+ message = frame.document()->domWindow()->crossDomainAccessErrorMessage(activeDOMWindow(&state));
+ return false;
+}
+
+bool BindingSecurity::shouldAllowAccessToDOMWindow(ExecState& state, DOMWindow& globalObject, String& message)
+{
+ if (BindingSecurity::shouldAllowAccessToDOMWindow(&state, globalObject, DoNotReportSecurityError))
+ return true;
+ message = globalObject.crossDomainAccessErrorMessage(activeDOMWindow(&state));
+ return false;
+}
+
+bool BindingSecurity::shouldAllowAccessToDOMWindow(JSC::ExecState* state, DOMWindow& target, SecurityReportingOption reportingOption)
+{
+ return canAccessDocument(state, target.document(), reportingOption);
+}
+
+bool BindingSecurity::shouldAllowAccessToFrame(JSC::ExecState* state, Frame* target, SecurityReportingOption reportingOption)
+{
+ return target && canAccessDocument(state, target->document(), reportingOption);
+}
+
+bool BindingSecurity::shouldAllowAccessToNode(JSC::ExecState& state, Node* target)
+{
+ return !target || canAccessDocument(&state, &target->document(), LogSecurityError);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMBindingSecurity.h b/Source/WebCore/bindings/js/JSDOMBindingSecurity.h
new file mode 100644
index 000000000..7b4085a51
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMBindingSecurity.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003-2006, 2008-2009, 2013, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
+ * Copyright (C) 2009 Google, Inc. All rights reserved.
+ * Copyright (C) 2012 Ericsson AB. All rights reserved.
+ * Copyright (C) 2013 Michael Pruett <michael@68k.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include "ExceptionOr.h"
+#include <wtf/Forward.h>
+
+namespace JSC {
+class ExecState;
+}
+
+namespace WebCore {
+
+class DOMWindow;
+class Frame;
+class Node;
+
+void printErrorMessageForFrame(Frame*, const String& message);
+
+enum SecurityReportingOption { DoNotReportSecurityError, LogSecurityError, ThrowSecurityError };
+
+namespace BindingSecurity {
+
+template<typename T> T* checkSecurityForNode(JSC::ExecState&, T&);
+template<typename T> T* checkSecurityForNode(JSC::ExecState&, T*);
+template<typename T> ExceptionOr<T*> checkSecurityForNode(JSC::ExecState&, ExceptionOr<T*>&&);
+template<typename T> ExceptionOr<T*> checkSecurityForNode(JSC::ExecState&, ExceptionOr<T&>&&);
+
+bool shouldAllowAccessToDOMWindow(JSC::ExecState*, DOMWindow&, SecurityReportingOption = LogSecurityError);
+bool shouldAllowAccessToDOMWindow(JSC::ExecState&, DOMWindow&, String& message);
+bool shouldAllowAccessToFrame(JSC::ExecState*, Frame*, SecurityReportingOption = LogSecurityError);
+bool shouldAllowAccessToFrame(JSC::ExecState&, Frame&, String& message);
+bool shouldAllowAccessToNode(JSC::ExecState&, Node*);
+
+};
+
+template<typename T> inline T* BindingSecurity::checkSecurityForNode(JSC::ExecState& state, T& node)
+{
+ return shouldAllowAccessToNode(state, &node) ? &node : nullptr;
+}
+
+template<typename T> inline T* BindingSecurity::checkSecurityForNode(JSC::ExecState& state, T* node)
+{
+ return shouldAllowAccessToNode(state, node) ? node : nullptr;
+}
+
+template<typename T> inline ExceptionOr<T*> BindingSecurity::checkSecurityForNode(JSC::ExecState& state, ExceptionOr<T*>&& value)
+{
+ if (value.hasException())
+ return value.releaseException();
+ return checkSecurityForNode(state, value.releaseReturnValue());
+}
+
+template<typename T> inline ExceptionOr<T*> BindingSecurity::checkSecurityForNode(JSC::ExecState& state, ExceptionOr<T&>&& value)
+{
+ if (value.hasException())
+ return value.releaseException();
+ return checkSecurityForNode(state, value.releaseReturnValue());
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMBuiltinConstructor.h b/Source/WebCore/bindings/js/JSDOMBuiltinConstructor.h
new file mode 100644
index 000000000..74ee3a5ca
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMBuiltinConstructor.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2015, 2016 Canon Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include "JSDOMBuiltinConstructorBase.h"
+#include "JSDOMExceptionHandling.h"
+#include "JSDOMWrapperCache.h"
+
+namespace WebCore {
+
+template<typename JSClass> class JSDOMBuiltinConstructor : public JSDOMBuiltinConstructorBase {
+public:
+ using Base = JSDOMBuiltinConstructorBase;
+
+ static JSDOMBuiltinConstructor* create(JSC::VM&, JSC::Structure*, JSDOMGlobalObject&);
+ static JSC::Structure* createStructure(JSC::VM&, JSC::JSGlobalObject&, JSC::JSValue prototype);
+
+ DECLARE_INFO;
+
+ // Usually defined for each specialization class.
+ static JSC::JSValue prototypeForStructure(JSC::VM&, const JSDOMGlobalObject&);
+
+private:
+ JSDOMBuiltinConstructor(JSC::Structure* structure, JSDOMGlobalObject& globalObject)
+ : Base(structure, globalObject)
+ {
+ }
+
+ void finishCreation(JSC::VM&, JSDOMGlobalObject&);
+ static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&);
+ static JSC::EncodedJSValue JSC_HOST_CALL construct(JSC::ExecState*);
+
+ JSC::EncodedJSValue callConstructor(JSC::ExecState&, JSC::JSObject&);
+ JSC::EncodedJSValue callConstructor(JSC::ExecState&, JSC::JSObject*);
+
+ // Usually defined for each specialization class.
+ void initializeProperties(JSC::VM&, JSDOMGlobalObject&) { }
+ // Must be defined for each specialization class.
+ JSC::FunctionExecutable* initializeExecutable(JSC::VM&);
+};
+
+template<typename JSClass> inline JSDOMBuiltinConstructor<JSClass>* JSDOMBuiltinConstructor<JSClass>::create(JSC::VM& vm, JSC::Structure* structure, JSDOMGlobalObject& globalObject)
+{
+ JSDOMBuiltinConstructor* constructor = new (NotNull, JSC::allocateCell<JSDOMBuiltinConstructor>(vm.heap)) JSDOMBuiltinConstructor(structure, globalObject);
+ constructor->finishCreation(vm, globalObject);
+ return constructor;
+}
+
+template<typename JSClass> inline JSC::Structure* JSDOMBuiltinConstructor<JSClass>::createStructure(JSC::VM& vm, JSC::JSGlobalObject& globalObject, JSC::JSValue prototype)
+{
+ return JSC::Structure::create(vm, &globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+}
+
+template<typename JSClass> inline void JSDOMBuiltinConstructor<JSClass>::finishCreation(JSC::VM& vm, JSDOMGlobalObject& globalObject)
+{
+ Base::finishCreation(vm);
+ ASSERT(inherits(vm, info()));
+ setInitializeFunction(vm, *JSC::JSFunction::createBuiltinFunction(vm, initializeExecutable(vm), &globalObject));
+ initializeProperties(vm, globalObject);
+}
+
+template<typename JSClass> inline JSC::EncodedJSValue JSDOMBuiltinConstructor<JSClass>::callConstructor(JSC::ExecState& state, JSC::JSObject& object)
+{
+ Base::callFunctionWithCurrentArguments(state, object, *initializeFunction());
+ return JSC::JSValue::encode(&object);
+}
+
+template<typename JSClass> inline JSC::EncodedJSValue JSDOMBuiltinConstructor<JSClass>::callConstructor(JSC::ExecState& state, JSC::JSObject* object)
+{
+ JSC::VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ if (!object)
+ return throwConstructorScriptExecutionContextUnavailableError(state, scope, info()->className);
+ return callConstructor(state, *object);
+}
+
+template<typename JSClass> inline
+typename std::enable_if<JSDOMObjectInspector<JSClass>::isSimpleWrapper, JSC::JSObject&>::type createJSObject(JSDOMBuiltinConstructor<JSClass>& constructor)
+{
+ auto& globalObject = *constructor.globalObject();
+ return *JSClass::create(getDOMStructure<JSClass>(globalObject.vm(), globalObject), &globalObject, JSClass::DOMWrapped::create());
+}
+
+template<typename JSClass> inline
+typename std::enable_if<JSDOMObjectInspector<JSClass>::isBuiltin, JSC::JSObject&>::type createJSObject(JSDOMBuiltinConstructor<JSClass>& constructor)
+{
+ auto& globalObject = *constructor.globalObject();
+ return *JSClass::create(getDOMStructure<JSClass>(globalObject.vm(), globalObject), &globalObject);
+}
+
+template<typename JSClass> inline
+typename std::enable_if<JSDOMObjectInspector<JSClass>::isComplexWrapper, JSC::JSObject*>::type createJSObject(JSDOMBuiltinConstructor<JSClass>& constructor)
+{
+ ScriptExecutionContext* context = constructor.scriptExecutionContext();
+ if (!context)
+ return nullptr;
+ auto& globalObject = *constructor.globalObject();
+ return JSClass::create(getDOMStructure<JSClass>(globalObject.vm(), globalObject), &globalObject, JSClass::DOMWrapped::create(*context));
+}
+
+template<typename JSClass> inline JSC::EncodedJSValue JSC_HOST_CALL JSDOMBuiltinConstructor<JSClass>::construct(JSC::ExecState* state)
+{
+ ASSERT(state);
+ auto* castedThis = JSC::jsCast<JSDOMBuiltinConstructor*>(state->jsCallee());
+ return castedThis->callConstructor(*state, createJSObject(*castedThis));
+}
+
+template<typename JSClass> inline JSC::ConstructType JSDOMBuiltinConstructor<JSClass>::getConstructData(JSC::JSCell*, JSC::ConstructData& constructData)
+{
+ constructData.native.function = construct;
+ return JSC::ConstructType::Host;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMBuiltinConstructorBase.cpp b/Source/WebCore/bindings/js/JSDOMBuiltinConstructorBase.cpp
new file mode 100644
index 000000000..42ea13278
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMBuiltinConstructorBase.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004-2011, 2013, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
+ * Copyright (C) 2013 Michael Pruett <michael@68k.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "JSDOMBuiltinConstructorBase.h"
+
+#include <runtime/JSCInlines.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+void JSDOMBuiltinConstructorBase::callFunctionWithCurrentArguments(JSC::ExecState& state, JSC::JSObject& thisObject, JSC::JSFunction& function)
+{
+ JSC::CallData callData;
+ JSC::CallType callType = JSC::getCallData(&function, callData);
+ ASSERT(callType != CallType::None);
+
+ JSC::MarkedArgumentBuffer arguments;
+ for (unsigned i = 0; i < state.argumentCount(); ++i)
+ arguments.append(state.uncheckedArgument(i));
+ JSC::call(&state, &function, callType, callData, &thisObject, arguments);
+}
+
+void JSDOMBuiltinConstructorBase::visitChildren(JSC::JSCell* cell, JSC::SlotVisitor& visitor)
+{
+ auto* thisObject = jsCast<JSDOMBuiltinConstructorBase*>(cell);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+ Base::visitChildren(thisObject, visitor);
+ visitor.append(thisObject->m_initializeFunction);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMBuiltinConstructorBase.h b/Source/WebCore/bindings/js/JSDOMBuiltinConstructorBase.h
new file mode 100644
index 000000000..c6cf294f1
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMBuiltinConstructorBase.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015, 2016 Canon Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include "JSDOMConstructorBase.h"
+
+namespace WebCore {
+
+class JSDOMBuiltinConstructorBase : public JSDOMConstructorBase {
+public:
+ using Base = JSDOMConstructorBase;
+
+protected:
+ JSDOMBuiltinConstructorBase(JSC::Structure* structure, JSDOMGlobalObject& globalObject)
+ : JSDOMConstructorBase(structure, globalObject)
+ {
+ }
+
+ static void visitChildren(JSC::JSCell*, JSC::SlotVisitor&);
+
+ JSC::JSFunction* initializeFunction();
+ void setInitializeFunction(JSC::VM&, JSC::JSFunction&);
+
+ static void callFunctionWithCurrentArguments(JSC::ExecState&, JSC::JSObject& thisObject, JSC::JSFunction&);
+
+private:
+ JSC::WriteBarrier<JSC::JSFunction> m_initializeFunction;
+};
+
+inline JSC::JSFunction* JSDOMBuiltinConstructorBase::initializeFunction()
+{
+ return m_initializeFunction.get();
+}
+
+inline void JSDOMBuiltinConstructorBase::setInitializeFunction(JSC::VM& vm, JSC::JSFunction& function)
+{
+ m_initializeFunction.set(vm, this, &function);
+}
+
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConstructor.h b/Source/WebCore/bindings/js/JSDOMConstructor.h
new file mode 100644
index 000000000..01767a940
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConstructor.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2015, 2016 Canon Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include "JSDOMConstructorBase.h"
+
+namespace WebCore {
+
+template<typename JSClass> class JSDOMConstructor : public JSDOMConstructorBase {
+public:
+ using Base = JSDOMConstructorBase;
+
+ static JSDOMConstructor* create(JSC::VM&, JSC::Structure*, JSDOMGlobalObject&);
+ static JSC::Structure* createStructure(JSC::VM&, JSC::JSGlobalObject&, JSC::JSValue prototype);
+
+ DECLARE_INFO;
+
+ // Must be defined for each specialization class.
+ static JSC::JSValue prototypeForStructure(JSC::VM&, const JSDOMGlobalObject&);
+
+private:
+ JSDOMConstructor(JSC::Structure* structure, JSDOMGlobalObject& globalObject)
+ : Base(structure, globalObject)
+ {
+ }
+
+ void finishCreation(JSC::VM&, JSDOMGlobalObject&);
+ static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&);
+
+ // Usually defined for each specialization class.
+ void initializeProperties(JSC::VM&, JSDOMGlobalObject&) { }
+ // Must be defined for each specialization class.
+ static JSC::EncodedJSValue JSC_HOST_CALL construct(JSC::ExecState*);
+};
+
+template<typename JSClass> inline JSDOMConstructor<JSClass>* JSDOMConstructor<JSClass>::create(JSC::VM& vm, JSC::Structure* structure, JSDOMGlobalObject& globalObject)
+{
+ JSDOMConstructor* constructor = new (NotNull, JSC::allocateCell<JSDOMConstructor>(vm.heap)) JSDOMConstructor(structure, globalObject);
+ constructor->finishCreation(vm, globalObject);
+ return constructor;
+}
+
+template<typename JSClass> inline JSC::Structure* JSDOMConstructor<JSClass>::createStructure(JSC::VM& vm, JSC::JSGlobalObject& globalObject, JSC::JSValue prototype)
+{
+ return JSC::Structure::create(vm, &globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+}
+
+template<typename JSClass> inline void JSDOMConstructor<JSClass>::finishCreation(JSC::VM& vm, JSDOMGlobalObject& globalObject)
+{
+ Base::finishCreation(vm);
+ ASSERT(inherits(vm, info()));
+ initializeProperties(vm, globalObject);
+}
+
+template<typename JSClass> inline JSC::ConstructType JSDOMConstructor<JSClass>::getConstructData(JSC::JSCell*, JSC::ConstructData& constructData)
+{
+ constructData.native.function = construct;
+ return JSC::ConstructType::Host;
+}
+
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMPluginCustom.cpp b/Source/WebCore/bindings/js/JSDOMConstructorBase.cpp
index e23e60f76..3c04c5408 100644
--- a/Source/WebCore/bindings/js/JSDOMPluginCustom.cpp
+++ b/Source/WebCore/bindings/js/JSDOMConstructorBase.cpp
@@ -1,5 +1,8 @@
/*
- * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004-2011, 2013, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
+ * Copyright (C) 2013 Michael Pruett <michael@68k.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -17,25 +20,28 @@
*/
#include "config.h"
-#include "JSDOMPlugin.h"
+#include "JSDOMConstructor.h"
-#include "DOMPlugin.h"
-#include "JSDOMMimeType.h"
-#include <wtf/text/AtomicString.h>
+#include <runtime/JSCInlines.h>
+
+using namespace JSC;
namespace WebCore {
-using namespace JSC;
+STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSDOMConstructorBase);
-bool JSDOMPlugin::canGetItemsForName(ExecState*, DOMPlugin* plugin, PropertyName propertyName)
+static EncodedJSValue JSC_HOST_CALL callThrowTypeError(ExecState* exec)
{
- return plugin->canGetItemsForName(propertyNameToAtomicString(propertyName));
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ throwTypeError(exec, scope, ASCIILiteral("Constructor requires 'new' operator"));
+ return JSValue::encode(jsNull());
}
-EncodedJSValue JSDOMPlugin::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName)
+CallType JSDOMConstructorBase::getCallData(JSCell*, CallData& callData)
{
- JSDOMPlugin* thisObj = jsCast<JSDOMPlugin*>(JSValue::decode(slotBase));
- return JSValue::encode(toJS(exec, thisObj->globalObject(), thisObj->impl().namedItem(propertyNameToAtomicString(propertyName))));
+ callData.native.function = callThrowTypeError;
+ return CallType::Host;
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConstructorBase.h b/Source/WebCore/bindings/js/JSDOMConstructorBase.h
new file mode 100644
index 000000000..a142e5ad6
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConstructorBase.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2015, 2016 Canon Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include "JSDOMWrapper.h"
+
+namespace WebCore {
+
+// Base class for all constructor objects in the JSC bindings.
+class JSDOMConstructorBase : public JSDOMObject {
+public:
+ using Base = JSDOMObject;
+
+ static const unsigned StructureFlags = Base::StructureFlags | JSC::ImplementsHasInstance | JSC::ImplementsDefaultHasInstance | JSC::TypeOfShouldCallGetCallData;
+ static JSC::Structure* createStructure(JSC::VM&, JSC::JSGlobalObject*, JSC::JSValue);
+
+protected:
+ JSDOMConstructorBase(JSC::Structure* structure, JSDOMGlobalObject& globalObject)
+ : JSDOMObject(structure, globalObject)
+ {
+ }
+
+ static String className(const JSObject*);
+ static JSC::CallType getCallData(JSCell*, JSC::CallData&);
+};
+
+inline JSC::Structure* JSDOMConstructorBase::createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+{
+ return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+}
+
+inline String JSDOMConstructorBase::className(const JSObject*)
+{
+ return ASCIILiteral("Function");
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConstructorNotConstructable.h b/Source/WebCore/bindings/js/JSDOMConstructorNotConstructable.h
new file mode 100644
index 000000000..399742b38
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConstructorNotConstructable.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2015, 2016 Canon Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include "JSDOMConstructorBase.h"
+#include "JSDOMExceptionHandling.h"
+
+namespace WebCore {
+
+template<typename JSClass> class JSDOMConstructorNotConstructable : public JSDOMConstructorBase {
+public:
+ using Base = JSDOMConstructorBase;
+
+ static JSDOMConstructorNotConstructable* create(JSC::VM&, JSC::Structure*, JSDOMGlobalObject&);
+ static JSC::Structure* createStructure(JSC::VM&, JSC::JSGlobalObject&, JSC::JSValue prototype);
+
+ DECLARE_INFO;
+
+ // Must be defined for each specialization class.
+ static JSC::JSValue prototypeForStructure(JSC::VM&, const JSDOMGlobalObject&);
+
+private:
+ JSDOMConstructorNotConstructable(JSC::Structure* structure, JSDOMGlobalObject& globalObject)
+ : Base(structure, globalObject)
+ {
+ }
+
+ void finishCreation(JSC::VM&, JSDOMGlobalObject&);
+
+ // Usually defined for each specialization class.
+ void initializeProperties(JSC::VM&, JSDOMGlobalObject&) { }
+
+ static JSC::EncodedJSValue JSC_HOST_CALL callThrowTypeError(JSC::ExecState* exec)
+ {
+ JSC::VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ JSC::throwTypeError(exec, scope, ASCIILiteral("Illegal constructor"));
+ return JSC::JSValue::encode(JSC::jsNull());
+ }
+
+ static JSC::CallType getCallData(JSC::JSCell*, JSC::CallData& callData)
+ {
+ callData.native.function = callThrowTypeError;
+ return JSC::CallType::Host;
+ }
+};
+
+template<typename JSClass> inline JSDOMConstructorNotConstructable<JSClass>* JSDOMConstructorNotConstructable<JSClass>::create(JSC::VM& vm, JSC::Structure* structure, JSDOMGlobalObject& globalObject)
+{
+ JSDOMConstructorNotConstructable* constructor = new (NotNull, JSC::allocateCell<JSDOMConstructorNotConstructable>(vm.heap)) JSDOMConstructorNotConstructable(structure, globalObject);
+ constructor->finishCreation(vm, globalObject);
+ return constructor;
+}
+
+template<typename JSClass> inline JSC::Structure* JSDOMConstructorNotConstructable<JSClass>::createStructure(JSC::VM& vm, JSC::JSGlobalObject& globalObject, JSC::JSValue prototype)
+{
+ return JSC::Structure::create(vm, &globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+}
+
+template<typename JSClass> inline void JSDOMConstructorNotConstructable<JSClass>::finishCreation(JSC::VM& vm, JSDOMGlobalObject& globalObject)
+{
+ Base::finishCreation(vm);
+ ASSERT(inherits(vm, info()));
+ initializeProperties(vm, globalObject);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/DOMObjectHashTableMap.cpp b/Source/WebCore/bindings/js/JSDOMConstructorWithDocument.cpp
index 4d6b916bc..c23acffd0 100644
--- a/Source/WebCore/bindings/js/DOMObjectHashTableMap.cpp
+++ b/Source/WebCore/bindings/js/JSDOMConstructorWithDocument.cpp
@@ -1,7 +1,8 @@
/*
* Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2011, 2013, 2016 Apple Inc. All rights reserved.
* Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
+ * Copyright (C) 2013 Michael Pruett <michael@68k.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -19,19 +20,12 @@
*/
#include "config.h"
-#include "DOMObjectHashTableMap.h"
-
-#include "WebCoreJSClientData.h"
+#include "JSDOMConstructorWithDocument.h"
using namespace JSC;
-namespace WebCore{
+namespace WebCore {
-DOMObjectHashTableMap& DOMObjectHashTableMap::mapFor(VM& vm)
-{
- VM::ClientData* clientData = vm.clientData;
- ASSERT(clientData);
- return static_cast<WebCoreJSClientData*>(clientData)->hashTableMap;
-}
+STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSDOMConstructorWithDocument);
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/DOMConstructorWithDocument.h b/Source/WebCore/bindings/js/JSDOMConstructorWithDocument.h
index 5c98f6116..1a9a95964 100644
--- a/Source/WebCore/bindings/js/DOMConstructorWithDocument.h
+++ b/Source/WebCore/bindings/js/JSDOMConstructorWithDocument.h
@@ -1,5 +1,6 @@
/*
- * Copyright (C) 2009 Google, Inc. All rights reserved.
+ * Copyright (C) 2015, 2016 Canon Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -16,38 +17,35 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-
-#ifndef DOMConstructorWithDocument_h
-#define DOMConstructorWithDocument_h
+#pragma once
#include "Document.h"
-#include "JSDOMBinding.h"
+#include "JSDOMConstructorBase.h"
namespace WebCore {
// Constructors using this base class depend on being in a Document and
// can never be used from a WorkerGlobalScope.
-class DOMConstructorWithDocument : public DOMConstructorObject {
- typedef DOMConstructorObject Base;
+class JSDOMConstructorWithDocument : public JSDOMConstructorBase {
public:
+ using Base = JSDOMConstructorBase;
+
Document* document() const
{
- return toDocument(scriptExecutionContext());
+ return downcast<Document>(scriptExecutionContext());
}
protected:
- DOMConstructorWithDocument(JSC::Structure* structure, JSDOMGlobalObject* globalObject)
- : DOMConstructorObject(structure, globalObject)
+ JSDOMConstructorWithDocument(JSC::Structure* structure, JSDOMGlobalObject& globalObject)
+ : JSDOMConstructorBase(structure, globalObject)
{
}
- void finishCreation(JSDOMGlobalObject* globalObject)
+ void finishCreation(JSDOMGlobalObject& globalObject)
{
- Base::finishCreation(globalObject->vm());
- ASSERT(globalObject->scriptExecutionContext()->isDocument());
+ Base::finishCreation(globalObject.vm());
+ ASSERT(globalObject.scriptExecutionContext()->isDocument());
}
};
} // namespace WebCore
-
-#endif // DOMConstructorWithDocument_h
diff --git a/Source/WebCore/bindings/js/JSDOMConvert.h b/Source/WebCore/bindings/js/JSDOMConvert.h
new file mode 100644
index 000000000..44afd4d3e
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvert.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "JSDOMConvertAny.h"
+#include "JSDOMConvertBoolean.h"
+#include "JSDOMConvertBufferSource.h"
+#include "JSDOMConvertCallbacks.h"
+#include "JSDOMConvertDate.h"
+#include "JSDOMConvertDictionary.h"
+#include "JSDOMConvertEnumeration.h"
+#include "JSDOMConvertEventListener.h"
+#include "JSDOMConvertIndexedDB.h"
+#include "JSDOMConvertInterface.h"
+#include "JSDOMConvertJSON.h"
+#include "JSDOMConvertNull.h"
+#include "JSDOMConvertNullable.h"
+#include "JSDOMConvertNumbers.h"
+#include "JSDOMConvertObject.h"
+#include "JSDOMConvertRecord.h"
+#include "JSDOMConvertSequences.h"
+#include "JSDOMConvertSerializedScriptValue.h"
+#include "JSDOMConvertStrings.h"
+#include "JSDOMConvertUnion.h"
+#include "JSDOMConvertWebGL.h"
+#include "JSDOMConvertXPathNSResolver.h"
diff --git a/Source/WebCore/bindings/js/JSDOMConvertAny.h b/Source/WebCore/bindings/js/JSDOMConvertAny.h
new file mode 100644
index 000000000..b27ab7ca6
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertAny.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+#include "JSDOMConvertBase.h"
+
+namespace WebCore {
+
+template<> struct Converter<IDLAny> : DefaultConverter<IDLAny> {
+ using ReturnType = JSC::JSValue;
+
+ static JSC::JSValue convert(JSC::ExecState&, JSC::JSValue value)
+ {
+ return value;
+ }
+
+ static JSC::JSValue convert(const JSC::Strong<JSC::Unknown>& value)
+ {
+ return value.get();
+ }
+};
+
+template<> struct JSConverter<IDLAny> {
+ static constexpr bool needsState = false;
+ static constexpr bool needsGlobalObject = false;
+
+ static JSC::JSValue convert(const JSC::JSValue& value)
+ {
+ return value;
+ }
+
+ static JSC::JSValue convert(const JSC::Strong<JSC::Unknown>& value)
+ {
+ return value.get();
+ }
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertBase.h b/Source/WebCore/bindings/js/JSDOMConvertBase.h
new file mode 100644
index 000000000..bd23abe52
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertBase.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "JSDOMExceptionHandling.h"
+
+namespace WebCore {
+
+// Conversion from JSValue -> Implementation
+template<typename T> struct Converter;
+
+
+struct DefaultExceptionThrower {
+ void operator()(JSC::ExecState& state, JSC::ThrowScope& scope)
+ {
+ throwTypeError(&state, scope);
+ }
+};
+
+template<typename T> typename Converter<T>::ReturnType convert(JSC::ExecState&, JSC::JSValue);
+template<typename T> typename Converter<T>::ReturnType convert(JSC::ExecState&, JSC::JSValue, JSC::JSObject&);
+template<typename T> typename Converter<T>::ReturnType convert(JSC::ExecState&, JSC::JSValue, JSDOMGlobalObject&);
+template<typename T, typename ExceptionThrower> typename Converter<T>::ReturnType convert(JSC::ExecState&, JSC::JSValue, ExceptionThrower&&);
+template<typename T, typename ExceptionThrower> typename Converter<T>::ReturnType convert(JSC::ExecState&, JSC::JSValue, JSC::JSObject&, ExceptionThrower&&);
+template<typename T, typename ExceptionThrower> typename Converter<T>::ReturnType convert(JSC::ExecState&, JSC::JSValue, JSDOMGlobalObject&, ExceptionThrower&&);
+
+template<typename T> inline typename Converter<T>::ReturnType convert(JSC::ExecState& state, JSC::JSValue value)
+{
+ return Converter<T>::convert(state, value);
+}
+
+template<typename T> inline typename Converter<T>::ReturnType convert(JSC::ExecState& state, JSC::JSValue value, JSC::JSObject& thisObject)
+{
+ return Converter<T>::convert(state, value, thisObject);
+}
+
+template<typename T> inline typename Converter<T>::ReturnType convert(JSC::ExecState& state, JSC::JSValue value, JSDOMGlobalObject& globalObject)
+{
+ return Converter<T>::convert(state, value, globalObject);
+}
+
+template<typename T, typename ExceptionThrower> inline typename Converter<T>::ReturnType convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower)
+{
+ return Converter<T>::convert(state, value, std::forward<ExceptionThrower>(exceptionThrower));
+}
+
+template<typename T, typename ExceptionThrower> inline typename Converter<T>::ReturnType convert(JSC::ExecState& state, JSC::JSValue value, JSC::JSObject& thisObject, ExceptionThrower&& exceptionThrower)
+{
+ return Converter<T>::convert(state, value, thisObject, std::forward<ExceptionThrower>(exceptionThrower));
+}
+
+template<typename T, typename ExceptionThrower> inline typename Converter<T>::ReturnType convert(JSC::ExecState& state, JSC::JSValue value, JSDOMGlobalObject& globalObject, ExceptionThrower&& exceptionThrower)
+{
+ return Converter<T>::convert(state, value, globalObject, std::forward<ExceptionThrower>(exceptionThrower));
+}
+
+// Conversion from Implementation -> JSValue
+template<typename T> struct JSConverter;
+
+template<typename T, typename U> inline JSC::JSValue toJS(U&&);
+template<typename T, typename U> inline JSC::JSValue toJS(JSC::ExecState&, U&&);
+template<typename T, typename U> inline JSC::JSValue toJS(JSC::ExecState&, JSDOMGlobalObject&, U&&);
+template<typename T, typename U> inline JSC::JSValue toJS(JSC::ExecState&, JSC::ThrowScope&, ExceptionOr<U>&&);
+template<typename T, typename U> inline JSC::JSValue toJS(JSC::ExecState&, JSDOMGlobalObject&, JSC::ThrowScope&, ExceptionOr<U>&&);
+template<typename T, typename U> inline JSC::JSValue toJSNewlyCreated(JSC::ExecState&, JSDOMGlobalObject&, U&&);
+template<typename T, typename U> inline JSC::JSValue toJSNewlyCreated(JSC::ExecState&, JSDOMGlobalObject&, JSC::ThrowScope&, ExceptionOr<U>&&);
+
+template<typename T, bool needsState = JSConverter<T>::needsState, bool needsGlobalObject = JSConverter<T>::needsGlobalObject>
+struct JSConverterOverloader;
+
+template<typename T>
+struct JSConverterOverloader<T, true, true> {
+ template<typename U> static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value)
+ {
+ return JSConverter<T>::convert(state, globalObject, std::forward<U>(value));
+ }
+};
+
+template<typename T>
+struct JSConverterOverloader<T, true, false> {
+ template<typename U> static JSC::JSValue convert(JSC::ExecState& state, U&& value)
+ {
+ return JSConverter<T>::convert(state, std::forward<U>(value));
+ }
+
+ template<typename U> static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject&, U&& value)
+ {
+ return JSConverter<T>::convert(state, std::forward<U>(value));
+ }
+};
+
+template<typename T>
+struct JSConverterOverloader<T, false, false> {
+ template<typename U> static JSC::JSValue convert(JSC::ExecState&, U&& value)
+ {
+ return JSConverter<T>::convert(std::forward<U>(value));
+ }
+
+ template<typename U> static JSC::JSValue convert(JSC::ExecState&, JSDOMGlobalObject&, U&& value)
+ {
+ return JSConverter<T>::convert(std::forward<U>(value));
+ }
+};
+
+template<typename T, typename U> inline JSC::JSValue toJS(U&& value)
+{
+ return JSConverter<T>::convert(std::forward<U>(value));
+}
+
+template<typename T, typename U> inline JSC::JSValue toJS(JSC::ExecState& state, U&& value)
+{
+ return JSConverterOverloader<T>::convert(state, std::forward<U>(value));
+}
+
+template<typename T, typename U> inline JSC::JSValue toJS(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value)
+{
+ return JSConverterOverloader<T>::convert(state, globalObject, std::forward<U>(value));
+}
+
+template<typename T, typename U> inline JSC::JSValue toJS(JSC::ExecState& state, JSC::ThrowScope& throwScope, ExceptionOr<U>&& value)
+{
+ if (UNLIKELY(value.hasException())) {
+ propagateException(state, throwScope, value.releaseException());
+ return { };
+ }
+
+ return toJS<T>(state, value.releaseReturnValue());
+}
+
+template<typename T, typename U> inline JSC::JSValue toJS(JSC::ExecState& state, JSDOMGlobalObject& globalObject, JSC::ThrowScope& throwScope, ExceptionOr<U>&& value)
+{
+ if (UNLIKELY(value.hasException())) {
+ propagateException(state, throwScope, value.releaseException());
+ return { };
+ }
+
+ return toJS<T>(state, globalObject, value.releaseReturnValue());
+}
+
+template<typename T, typename U> inline JSC::JSValue toJSNewlyCreated(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value)
+{
+ return JSConverter<T>::convertNewlyCreated(state, globalObject, std::forward<U>(value));
+}
+
+template<typename T, typename U> inline JSC::JSValue toJSNewlyCreated(JSC::ExecState& state, JSDOMGlobalObject& globalObject, JSC::ThrowScope& throwScope, ExceptionOr<U>&& value)
+{
+ if (UNLIKELY(value.hasException())) {
+ propagateException(state, throwScope, value.releaseException());
+ return { };
+ }
+
+ return toJSNewlyCreated<T>(state, globalObject, value.releaseReturnValue());
+}
+
+
+template<typename T> struct DefaultConverter {
+ using ReturnType = typename T::ImplementationType;
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertBoolean.h b/Source/WebCore/bindings/js/JSDOMConvertBoolean.h
new file mode 100644
index 000000000..853be0c7e
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertBoolean.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+#include "JSDOMConvertBase.h"
+
+namespace WebCore {
+
+template<> struct Converter<IDLBoolean> : DefaultConverter<IDLBoolean> {
+ static bool convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ return value.toBoolean(&state);
+ }
+};
+
+template<> struct JSConverter<IDLBoolean> {
+ static constexpr bool needsState = false;
+ static constexpr bool needsGlobalObject = false;
+
+ static JSC::JSValue convert(bool value)
+ {
+ return JSC::jsBoolean(value);
+ }
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertBufferSource.h b/Source/WebCore/bindings/js/JSDOMConvertBufferSource.h
new file mode 100644
index 000000000..dc45fc129
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertBufferSource.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "BufferSource.h"
+#include "JSDOMConvertInterface.h"
+#include "JSDOMWrapperCache.h"
+#include "JSDynamicDowncast.h"
+#include <runtime/JSTypedArrays.h>
+
+namespace WebCore {
+
+// FIXME: It is wrong that we treat buffer related types as interfaces, they should be their own IDL type.
+
+// Add adaptors to make ArrayBuffer / ArrayBufferView / typed arrays act like normal interfaces.
+
+template<typename ImplementationClass> struct JSDOMWrapperConverterTraits;
+
+template<> struct JSDOMWrapperConverterTraits<JSC::ArrayBuffer> {
+ using WrapperClass = JSC::JSArrayBuffer;
+ using ToWrappedReturnType = JSC::ArrayBuffer*;
+};
+
+template<> struct JSDOMWrapperConverterTraits<JSC::ArrayBufferView> {
+ using WrapperClass = JSC::JSArrayBufferView;
+ using ToWrappedReturnType = RefPtr<ArrayBufferView>;
+};
+
+template<typename Adaptor> struct JSDOMWrapperConverterTraits<JSC::GenericTypedArrayView<Adaptor>> {
+ using WrapperClass = JSC::JSGenericTypedArrayView<Adaptor>;
+ using ToWrappedReturnType = RefPtr<JSC::GenericTypedArrayView<Adaptor>>;
+};
+
+
+inline RefPtr<JSC::Int8Array> toPossiblySharedInt8Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Int8Adaptor>(vm, value); }
+inline RefPtr<JSC::Int16Array> toPossiblySharedInt16Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Int16Adaptor>(vm, value); }
+inline RefPtr<JSC::Int32Array> toPossiblySharedInt32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Int32Adaptor>(vm, value); }
+inline RefPtr<JSC::Uint8Array> toPossiblySharedUint8Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Uint8Adaptor>(vm, value); }
+inline RefPtr<JSC::Uint8ClampedArray> toPossiblySharedUint8ClampedArray(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Uint8ClampedAdaptor>(vm, value); }
+inline RefPtr<JSC::Uint16Array> toPossiblySharedUint16Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Uint16Adaptor>(vm, value); }
+inline RefPtr<JSC::Uint32Array> toPossiblySharedUint32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Uint32Adaptor>(vm, value); }
+inline RefPtr<JSC::Float32Array> toPossiblySharedFloat32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Float32Adaptor>(vm, value); }
+inline RefPtr<JSC::Float64Array> toPossiblySharedFloat64Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toPossiblySharedNativeTypedView<JSC::Float64Adaptor>(vm, value); }
+
+inline RefPtr<JSC::Int8Array> toUnsharedInt8Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Int8Adaptor>(vm, value); }
+inline RefPtr<JSC::Int16Array> toUnsharedInt16Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Int16Adaptor>(vm, value); }
+inline RefPtr<JSC::Int32Array> toUnsharedInt32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Int32Adaptor>(vm, value); }
+inline RefPtr<JSC::Uint8Array> toUnsharedUint8Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Uint8Adaptor>(vm, value); }
+inline RefPtr<JSC::Uint8ClampedArray> toUnsharedUint8ClampedArray(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Uint8ClampedAdaptor>(vm, value); }
+inline RefPtr<JSC::Uint16Array> toUnsharedUint16Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Uint16Adaptor>(vm, value); }
+inline RefPtr<JSC::Uint32Array> toUnsharedUint32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Uint32Adaptor>(vm, value); }
+inline RefPtr<JSC::Float32Array> toUnsharedFloat32Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Float32Adaptor>(vm, value); }
+inline RefPtr<JSC::Float64Array> toUnsharedFloat64Array(JSC::VM& vm, JSC::JSValue value) { return JSC::toUnsharedNativeTypedView<JSC::Float64Adaptor>(vm, value); }
+
+inline JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, JSC::ArrayBuffer& buffer)
+{
+ if (auto result = getCachedWrapper(globalObject->world(), buffer))
+ return result;
+
+ // The JSArrayBuffer::create function will register the wrapper in finishCreation.
+ return JSC::JSArrayBuffer::create(state->vm(), globalObject->arrayBufferStructure(buffer.sharingMode()), &buffer);
+}
+
+inline JSC::JSValue toJS(JSC::ExecState* state, JSC::JSGlobalObject* globalObject, JSC::ArrayBufferView& view)
+{
+ return view.wrap(state, globalObject);
+}
+
+inline JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, JSC::ArrayBuffer* buffer)
+{
+ if (!buffer)
+ return JSC::jsNull();
+ return toJS(state, globalObject, *buffer);
+}
+
+inline JSC::JSValue toJS(JSC::ExecState* state, JSC::JSGlobalObject* globalObject, JSC::ArrayBufferView* view)
+{
+ if (!view)
+ return JSC::jsNull();
+ return toJS(state, globalObject, *view);
+}
+
+inline RefPtr<JSC::ArrayBufferView> toPossiblySharedArrayBufferView(JSC::VM& vm, JSC::JSValue value)
+{
+ auto* wrapper = jsDynamicDowncast<JSC::JSArrayBufferView*>(vm, value);
+ if (!wrapper)
+ return nullptr;
+ return wrapper->possiblySharedImpl();
+}
+
+inline RefPtr<JSC::ArrayBufferView> toUnsharedArrayBufferView(JSC::VM& vm, JSC::JSValue value)
+{
+ auto result = toPossiblySharedArrayBufferView(vm, value);
+ if (!result || result->isShared())
+ return nullptr;
+ return result;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertCallbacks.h b/Source/WebCore/bindings/js/JSDOMConvertCallbacks.h
new file mode 100644
index 000000000..3c1397aeb
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertCallbacks.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+#include "JSDOMConvertBase.h"
+
+namespace WebCore {
+
+template<typename T> struct Converter<IDLCallbackFunction<T>> : DefaultConverter<IDLCallbackFunction<T>> {
+ template<typename ExceptionThrower = DefaultExceptionThrower>
+ static RefPtr<T> convert(JSC::ExecState& state, JSC::JSValue value, JSDOMGlobalObject& globalObject, ExceptionThrower&& exceptionThrower = ExceptionThrower())
+ {
+ JSC::VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (!value.isFunction()) {
+ exceptionThrower(state, scope);
+ return nullptr;
+ }
+
+ return T::create(JSC::asObject(value), &globalObject);
+ }
+};
+
+template<typename T> struct JSConverter<IDLCallbackFunction<T>> {
+ static constexpr bool needsState = false;
+ static constexpr bool needsGlobalObject = false;
+
+ template <typename U>
+ static JSC::JSValue convert(const U& value)
+ {
+ return toJS(Detail::getPtrOrRef(value));
+ }
+
+ template<typename U>
+ static JSC::JSValue convertNewlyCreated(U&& value)
+ {
+ return toJSNewlyCreated(std::forward<U>(value));
+ }
+};
+
+
+template<typename T> struct Converter<IDLCallbackInterface<T>> : DefaultConverter<IDLCallbackInterface<T>> {
+ template<typename ExceptionThrower = DefaultExceptionThrower>
+ static RefPtr<T> convert(JSC::ExecState& state, JSC::JSValue value, JSDOMGlobalObject& globalObject, ExceptionThrower&& exceptionThrower = ExceptionThrower())
+ {
+ JSC::VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (!value.isObject()) {
+ exceptionThrower(state, scope);
+ return nullptr;
+ }
+
+ return T::create(JSC::asObject(value), &globalObject);
+ }
+};
+
+template<typename T> struct JSConverter<IDLCallbackInterface<T>> {
+ static constexpr bool needsState = false;
+ static constexpr bool needsGlobalObject = false;
+
+ template <typename U>
+ static JSC::JSValue convert(const U& value)
+ {
+ return toJS(Detail::getPtrOrRef(value));
+ }
+
+ template<typename U>
+ static JSC::JSValue convertNewlyCreated(U&& value)
+ {
+ return toJSNewlyCreated(std::forward<U>(value));
+ }
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertDate.cpp b/Source/WebCore/bindings/js/JSDOMConvertDate.cpp
new file mode 100644
index 000000000..c019a6e5b
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertDate.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004-2011, 2013, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
+ * Copyright (C) 2013 Michael Pruett <michael@68k.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "JSDOMConvertDate.h"
+
+#include <heap/HeapInlines.h>
+#include <runtime/DateInstance.h>
+#include <runtime/JSCJSValueInlines.h>
+#include <runtime/JSGlobalObject.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+// FIXME: This should get passed a global object rather than getting it out of the ExecState.
+JSValue jsDate(ExecState& state, double value)
+{
+ return DateInstance::create(state.vm(), state.lexicalGlobalObject()->dateStructure(), value);
+}
+
+double valueToDate(ExecState& state, JSValue value)
+{
+ if (value.isNumber())
+ return value.asNumber();
+ if (!value.inherits(state.vm(), DateInstance::info()))
+ return std::numeric_limits<double>::quiet_NaN();
+ return static_cast<DateInstance*>(value.toObject(&state))->internalNumber();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertDate.h b/Source/WebCore/bindings/js/JSDOMConvertDate.h
new file mode 100644
index 000000000..4314de6e4
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertDate.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+#include "JSDOMConvertBase.h"
+
+namespace WebCore {
+
+JSC::JSValue jsDate(JSC::ExecState&, double value);
+double valueToDate(JSC::ExecState&, JSC::JSValue); // NaN if the value can't be converted to a date.
+
+template<> struct Converter<IDLDate> : DefaultConverter<IDLDate> {
+ static double convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ return valueToDate(state, value);
+ }
+};
+
+template<> struct JSConverter<IDLDate> {
+ static constexpr bool needsState = true;
+ static constexpr bool needsGlobalObject = false;
+
+ // FIXME: This should be taking a JSDOMGlobalObject and passing it to jsDate.
+ static JSC::JSValue convert(JSC::ExecState& state, double value)
+ {
+ return jsDate(state, value);
+ }
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertDictionary.h b/Source/WebCore/bindings/js/JSDOMConvertDictionary.h
new file mode 100644
index 000000000..19fceff83
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertDictionary.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+#include "JSDOMConvertBase.h"
+
+namespace WebCore {
+
+// Specialized by generated code for IDL dictionary conversion.
+template<typename T> T convertDictionary(JSC::ExecState&, JSC::JSValue);
+
+
+template<typename T> struct Converter<IDLDictionary<T>> : DefaultConverter<IDLDictionary<T>> {
+ using ReturnType = T;
+
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ return convertDictionary<T>(state, value);
+ }
+};
+
+template<typename T> struct JSConverter<IDLDictionary<T>> {
+ static constexpr bool needsState = true;
+ static constexpr bool needsGlobalObject = true;
+
+ static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const T& dictionary)
+ {
+ return convertDictionaryToJS(state, globalObject, dictionary);
+ }
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertEnumeration.h b/Source/WebCore/bindings/js/JSDOMConvertEnumeration.h
new file mode 100644
index 000000000..ec43133c2
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertEnumeration.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+#include "JSDOMConvertBase.h"
+
+namespace WebCore {
+
+// Specialized by generated code for IDL enumeration conversion.
+template<typename T> std::optional<T> parseEnumeration(JSC::ExecState&, JSC::JSValue);
+template<typename T> T convertEnumeration(JSC::ExecState&, JSC::JSValue);
+template<typename T> const char* expectedEnumerationValues();
+
+// Specialized by generated code for IDL enumeration conversion.
+template<typename T> JSC::JSString* convertEnumerationToJS(JSC::ExecState&, T);
+
+
+template<typename T> struct Converter<IDLEnumeration<T>> : DefaultConverter<IDLEnumeration<T>> {
+ static T convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ return convertEnumeration<T>(state, value);
+ }
+};
+
+template<typename T> struct JSConverter<IDLEnumeration<T>> {
+ static constexpr bool needsState = true;
+ static constexpr bool needsGlobalObject = false;
+
+ static JSC::JSValue convert(JSC::ExecState& exec, T value)
+ {
+ return convertEnumerationToJS(exec, value);
+ }
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertEventListener.h b/Source/WebCore/bindings/js/JSDOMConvertEventListener.h
new file mode 100644
index 000000000..e55f32c3c
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertEventListener.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+#include "JSDOMConvertBase.h"
+
+namespace WebCore {
+
+template<typename T> struct Converter<IDLEventListener<T>> : DefaultConverter<IDLEventListener<T>> {
+ using ReturnType = RefPtr<T>;
+
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, JSC::JSObject& thisObject)
+ {
+ auto scope = DECLARE_THROW_SCOPE(state.vm());
+
+ auto listener = T::create(value, thisObject, false, currentWorld(&state));
+ if (!listener)
+ throwTypeError(&state, scope);
+
+ return listener;
+ }
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertIndexedDB.h b/Source/WebCore/bindings/js/JSDOMConvertIndexedDB.h
new file mode 100644
index 000000000..78d7e3763
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertIndexedDB.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include "IDBBindingUtilities.h"
+#include "IDLTypes.h"
+#include "JSDOMConvertBase.h"
+
+namespace WebCore {
+
+template<> struct JSConverter<IDLIDBKey> {
+ static constexpr bool needsState = true;
+ static constexpr bool needsGlobalObject = true;
+
+ template <typename U>
+ static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value)
+ {
+ return toJS(state, globalObject, std::forward<U>(value));
+ }
+};
+
+template<> struct JSConverter<IDLIDBKeyData> {
+ static constexpr bool needsState = true;
+ static constexpr bool needsGlobalObject = true;
+
+ template <typename U>
+ static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value)
+ {
+ return toJS(&state, &globalObject, std::forward<U>(value));
+ }
+};
+
+template<> struct JSConverter<IDLIDBValue> {
+ static constexpr bool needsState = true;
+ static constexpr bool needsGlobalObject = true;
+
+ template <typename U>
+ static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value)
+ {
+ return toJS(&state, &globalObject, std::forward<U>(value));
+ }
+};
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/bindings/js/JSDOMConvertInterface.h b/Source/WebCore/bindings/js/JSDOMConvertInterface.h
new file mode 100644
index 000000000..6c0b5eefe
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertInterface.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+#include "JSDOMConvertBase.h"
+#include "JSDOMExceptionHandling.h"
+
+namespace WebCore {
+
+template<typename ImplementationClass> struct JSDOMWrapperConverterTraits;
+
+template<typename T> struct Converter<IDLInterface<T>> : DefaultConverter<IDLInterface<T>> {
+ using ReturnType = typename JSDOMWrapperConverterTraits<T>::ToWrappedReturnType;
+ using WrapperType = typename JSDOMWrapperConverterTraits<T>::WrapperClass;
+
+ template<typename ExceptionThrower = DefaultExceptionThrower>
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower())
+ {
+ auto& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ ReturnType object = WrapperType::toWrapped(vm, value);
+ if (UNLIKELY(!object))
+ exceptionThrower(state, scope);
+ return object;
+ }
+};
+
+namespace Detail {
+
+template <typename T> inline T* getPtrOrRef(const T* p) { return const_cast<T*>(p); }
+template <typename T> inline T& getPtrOrRef(const T& p) { return const_cast<T&>(p); }
+template <typename T> inline T* getPtrOrRef(const RefPtr<T>& p) { return p.get(); }
+template <typename T> inline T& getPtrOrRef(const Ref<T>& p) { return p.get(); }
+
+}
+
+template<typename T> struct JSConverter<IDLInterface<T>> {
+ static constexpr bool needsState = true;
+ static constexpr bool needsGlobalObject = true;
+
+ template <typename U>
+ static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const U& value)
+ {
+ return toJS(&state, &globalObject, Detail::getPtrOrRef(value));
+ }
+
+ template<typename U>
+ static JSC::JSValue convertNewlyCreated(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value)
+ {
+ return toJSNewlyCreated(&state, &globalObject, std::forward<U>(value));
+ }
+};
+
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertJSON.h b/Source/WebCore/bindings/js/JSDOMConvertJSON.h
new file mode 100644
index 000000000..2f1b4d2b4
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertJSON.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+#include "JSDOMConvertBase.h"
+#include <runtime/JSONObject.h>
+
+namespace WebCore {
+
+template<> struct Converter<IDLJSON> : DefaultConverter<IDLJSON> {
+ static String convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ return JSC::JSONStringify(&state, value, 0);
+ }
+};
+
+template<> struct JSConverter<IDLJSON> {
+ static constexpr bool needsState = true;
+ static constexpr bool needsGlobalObject = false;
+
+ static JSC::JSValue convert(JSC::ExecState& state, const String& value)
+ {
+ return JSC::JSONParse(&state, value);
+ }
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertNull.h b/Source/WebCore/bindings/js/JSDOMConvertNull.h
new file mode 100644
index 000000000..262d75106
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertNull.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+#include "JSDOMConvertBase.h"
+
+namespace WebCore {
+
+template<> struct Converter<IDLNull> : DefaultConverter<IDLNull> {
+ static std::nullptr_t convert(JSC::ExecState&, JSC::JSValue)
+ {
+ return nullptr;
+ }
+};
+
+template<> struct JSConverter<IDLNull> {
+ static constexpr bool needsState = false;
+ static constexpr bool needsGlobalObject = false;
+
+ static JSC::JSValue convert(std::nullptr_t)
+ {
+ return JSC::jsNull();
+ }
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertNullable.h b/Source/WebCore/bindings/js/JSDOMConvertNullable.h
new file mode 100644
index 000000000..c42c83150
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertNullable.h
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+#include "JSDOMConvertAny.h"
+#include "JSDOMConvertInterface.h"
+#include "JSDOMConvertNumbers.h"
+#include "JSDOMConvertStrings.h"
+
+namespace WebCore {
+
+namespace Detail {
+
+template<typename IDLType>
+struct NullableConversionType;
+
+template<typename IDLType>
+struct NullableConversionType {
+ using Type = typename IDLNullable<IDLType>::ImplementationType;
+};
+
+template<typename T>
+struct NullableConversionType<IDLInterface<T>> {
+ using Type = typename Converter<IDLInterface<T>>::ReturnType;
+};
+
+template<>
+struct NullableConversionType<IDLAny> {
+ using Type = typename Converter<IDLAny>::ReturnType;
+};
+
+}
+
+template<typename T> struct Converter<IDLNullable<T>> : DefaultConverter<IDLNullable<T>> {
+ using ReturnType = typename Detail::NullableConversionType<T>::Type;
+
+ // 1. If Type(V) is not Object, and the conversion to an IDL value is being performed
+ // due to V being assigned to an attribute whose type is a nullable callback function
+ // that is annotated with [TreatNonObjectAsNull], then return the IDL nullable type T?
+ // value null.
+ //
+ // NOTE: Handled elsewhere.
+ //
+ // 2. Otherwise, if V is null or undefined, then return the IDL nullable type T? value null.
+ // 3. Otherwise, return the result of converting V using the rules for the inner IDL type T.
+
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ if (value.isUndefinedOrNull())
+ return T::nullValue();
+ return Converter<T>::convert(state, value);
+ }
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, JSC::JSObject& thisObject)
+ {
+ if (value.isUndefinedOrNull())
+ return T::nullValue();
+ return Converter<T>::convert(state, value, thisObject);
+ }
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, JSDOMGlobalObject& globalObject)
+ {
+ if (value.isUndefinedOrNull())
+ return T::nullValue();
+ return Converter<T>::convert(state, value, globalObject);
+ }
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, IntegerConversionConfiguration configuration)
+ {
+ if (value.isUndefinedOrNull())
+ return T::nullValue();
+ return Converter<T>::convert(state, value, configuration);
+ }
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, StringConversionConfiguration configuration)
+ {
+ if (value.isUndefinedOrNull())
+ return T::nullValue();
+ return Converter<T>::convert(state, value, configuration);
+ }
+ template<typename ExceptionThrower = DefaultExceptionThrower>
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower)
+ {
+ if (value.isUndefinedOrNull())
+ return T::nullValue();
+ return Converter<T>::convert(state, value, std::forward<ExceptionThrower>(exceptionThrower));
+ }
+ template<typename ExceptionThrower = DefaultExceptionThrower>
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, JSC::JSObject& thisObject, ExceptionThrower&& exceptionThrower)
+ {
+ if (value.isUndefinedOrNull())
+ return T::nullValue();
+ return Converter<T>::convert(state, value, thisObject, std::forward<ExceptionThrower>(exceptionThrower));
+ }
+ template<typename ExceptionThrower = DefaultExceptionThrower>
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, JSDOMGlobalObject& globalObject, ExceptionThrower&& exceptionThrower)
+ {
+ if (value.isUndefinedOrNull())
+ return T::nullValue();
+ return Converter<T>::convert(state, value, globalObject, std::forward<ExceptionThrower>(exceptionThrower));
+ }
+};
+
+template<typename T> struct JSConverter<IDLNullable<T>> {
+ using ImplementationType = typename IDLNullable<T>::ImplementationType;
+
+ static constexpr bool needsState = JSConverter<T>::needsState;
+ static constexpr bool needsGlobalObject = JSConverter<T>::needsGlobalObject;
+
+ template<typename U>
+ static JSC::JSValue convert(U&& value)
+ {
+ if (T::isNullValue(value))
+ return JSC::jsNull();
+ return JSConverter<T>::convert(T::extractValueFromNullable(value));
+ }
+ template<typename U>
+ static JSC::JSValue convert(JSC::ExecState& state, U&& value)
+ {
+ if (T::isNullValue(value))
+ return JSC::jsNull();
+ return JSConverter<T>::convert(state, T::extractValueFromNullable(value));
+ }
+ template<typename U>
+ static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value)
+ {
+ if (T::isNullValue(value))
+ return JSC::jsNull();
+ return JSConverter<T>::convert(state, globalObject, T::extractValueFromNullable(value));
+ }
+
+ template<typename U>
+ static JSC::JSValue convertNewlyCreated(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value)
+ {
+ if (T::isNullValue(value))
+ return JSC::jsNull();
+ return JSConverter<T>::convert(state, globalObject, T::extractValueFromNullable(value));
+ }
+};
+
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertNumbers.cpp b/Source/WebCore/bindings/js/JSDOMConvertNumbers.cpp
new file mode 100644
index 000000000..ff1f97011
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertNumbers.cpp
@@ -0,0 +1,348 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004-2011, 2013, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
+ * Copyright (C) 2013 Michael Pruett <michael@68k.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "JSDOMConvertNumbers.h"
+
+#include "JSDOMExceptionHandling.h"
+#include <heap/HeapInlines.h>
+#include <runtime/JSCJSValueInlines.h>
+#include <wtf/MathExtras.h>
+#include <wtf/text/WTFString.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+static const int32_t kMaxInt32 = 0x7fffffff;
+static const int32_t kMinInt32 = -kMaxInt32 - 1;
+static const uint32_t kMaxUInt32 = 0xffffffffU;
+static const int64_t kJSMaxInteger = 0x20000000000000LL - 1; // 2^53 - 1, largest integer exactly representable in ECMAScript.
+
+static String rangeErrorString(double value, double min, double max)
+{
+ return makeString("Value ", String::numberToStringECMAScript(value), " is outside the range [", String::numberToStringECMAScript(min), ", ", String::numberToStringECMAScript(max), "]");
+}
+
+static double enforceRange(ExecState& state, double x, double minimum, double maximum)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (std::isnan(x) || std::isinf(x)) {
+ throwTypeError(&state, scope, rangeErrorString(x, minimum, maximum));
+ return 0;
+ }
+ x = trunc(x);
+ if (x < minimum || x > maximum) {
+ throwTypeError(&state, scope, rangeErrorString(x, minimum, maximum));
+ return 0;
+ }
+ return x;
+}
+
+template <typename T>
+struct IntTypeLimits {
+};
+
+template <>
+struct IntTypeLimits<int8_t> {
+ static const int8_t minValue = -128;
+ static const int8_t maxValue = 127;
+ static const unsigned numberOfValues = 256; // 2^8
+};
+
+template <>
+struct IntTypeLimits<uint8_t> {
+ static const uint8_t maxValue = 255;
+ static const unsigned numberOfValues = 256; // 2^8
+};
+
+template <>
+struct IntTypeLimits<int16_t> {
+ static const short minValue = -32768;
+ static const short maxValue = 32767;
+ static const unsigned numberOfValues = 65536; // 2^16
+};
+
+template <>
+struct IntTypeLimits<uint16_t> {
+ static const unsigned short maxValue = 65535;
+ static const unsigned numberOfValues = 65536; // 2^16
+};
+
+template <typename T>
+static inline T toSmallerInt(ExecState& state, JSValue value, IntegerConversionConfiguration configuration)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ static_assert(std::is_signed<T>::value && std::is_integral<T>::value, "Should only be used for signed integral types");
+
+ typedef IntTypeLimits<T> LimitsTrait;
+ // Fast path if the value is already a 32-bit signed integer in the right range.
+ if (value.isInt32()) {
+ int32_t d = value.asInt32();
+ if (d >= LimitsTrait::minValue && d <= LimitsTrait::maxValue)
+ return static_cast<T>(d);
+ switch (configuration) {
+ case IntegerConversionConfiguration::Normal:
+ break;
+ case IntegerConversionConfiguration::EnforceRange:
+ throwTypeError(&state, scope);
+ return 0;
+ case IntegerConversionConfiguration::Clamp:
+ return d < LimitsTrait::minValue ? LimitsTrait::minValue : LimitsTrait::maxValue;
+ }
+ d %= LimitsTrait::numberOfValues;
+ return static_cast<T>(d > LimitsTrait::maxValue ? d - LimitsTrait::numberOfValues : d);
+ }
+
+ double x = value.toNumber(&state);
+ RETURN_IF_EXCEPTION(scope, 0);
+
+ switch (configuration) {
+ case IntegerConversionConfiguration::Normal:
+ break;
+ case IntegerConversionConfiguration::EnforceRange:
+ return enforceRange(state, x, LimitsTrait::minValue, LimitsTrait::maxValue);
+ case IntegerConversionConfiguration::Clamp:
+ return std::isnan(x) ? 0 : clampTo<T>(x);
+ }
+
+ if (std::isnan(x) || std::isinf(x) || !x)
+ return 0;
+
+ x = x < 0 ? -floor(fabs(x)) : floor(fabs(x));
+ x = fmod(x, LimitsTrait::numberOfValues);
+
+ return static_cast<T>(x > LimitsTrait::maxValue ? x - LimitsTrait::numberOfValues : x);
+}
+
+template <typename T>
+static inline T toSmallerUInt(ExecState& state, JSValue value, IntegerConversionConfiguration configuration)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ static_assert(std::is_unsigned<T>::value && std::is_integral<T>::value, "Should only be used for unsigned integral types");
+
+ typedef IntTypeLimits<T> LimitsTrait;
+ // Fast path if the value is already a 32-bit unsigned integer in the right range.
+ if (value.isUInt32()) {
+ uint32_t d = value.asUInt32();
+ if (d <= LimitsTrait::maxValue)
+ return static_cast<T>(d);
+ switch (configuration) {
+ case IntegerConversionConfiguration::Normal:
+ return static_cast<T>(d);
+ case IntegerConversionConfiguration::EnforceRange:
+ throwTypeError(&state, scope);
+ return 0;
+ case IntegerConversionConfiguration::Clamp:
+ return LimitsTrait::maxValue;
+ }
+ }
+
+ double x = value.toNumber(&state);
+ RETURN_IF_EXCEPTION(scope, 0);
+
+ switch (configuration) {
+ case IntegerConversionConfiguration::Normal:
+ break;
+ case IntegerConversionConfiguration::EnforceRange:
+ return enforceRange(state, x, 0, LimitsTrait::maxValue);
+ case IntegerConversionConfiguration::Clamp:
+ return std::isnan(x) ? 0 : clampTo<T>(x);
+ }
+
+ if (std::isnan(x) || std::isinf(x) || !x)
+ return 0;
+
+ x = x < 0 ? -floor(fabs(x)) : floor(fabs(x));
+ return static_cast<T>(fmod(x, LimitsTrait::numberOfValues));
+}
+
+int8_t toInt8EnforceRange(JSC::ExecState& state, JSValue value)
+{
+ return toSmallerInt<int8_t>(state, value, IntegerConversionConfiguration::EnforceRange);
+}
+
+uint8_t toUInt8EnforceRange(JSC::ExecState& state, JSValue value)
+{
+ return toSmallerUInt<uint8_t>(state, value, IntegerConversionConfiguration::EnforceRange);
+}
+
+int8_t toInt8Clamp(JSC::ExecState& state, JSValue value)
+{
+ return toSmallerInt<int8_t>(state, value, IntegerConversionConfiguration::Clamp);
+}
+
+uint8_t toUInt8Clamp(JSC::ExecState& state, JSValue value)
+{
+ return toSmallerUInt<uint8_t>(state, value, IntegerConversionConfiguration::Clamp);
+}
+
+// http://www.w3.org/TR/WebIDL/#es-byte
+int8_t toInt8(ExecState& state, JSValue value)
+{
+ return toSmallerInt<int8_t>(state, value, IntegerConversionConfiguration::Normal);
+}
+
+// http://www.w3.org/TR/WebIDL/#es-octet
+uint8_t toUInt8(ExecState& state, JSValue value)
+{
+ return toSmallerUInt<uint8_t>(state, value, IntegerConversionConfiguration::Normal);
+}
+
+int16_t toInt16EnforceRange(ExecState& state, JSValue value)
+{
+ return toSmallerInt<int16_t>(state, value, IntegerConversionConfiguration::EnforceRange);
+}
+
+uint16_t toUInt16EnforceRange(ExecState& state, JSValue value)
+{
+ return toSmallerUInt<uint16_t>(state, value, IntegerConversionConfiguration::EnforceRange);
+}
+
+int16_t toInt16Clamp(ExecState& state, JSValue value)
+{
+ return toSmallerInt<int16_t>(state, value, IntegerConversionConfiguration::Clamp);
+}
+
+uint16_t toUInt16Clamp(ExecState& state, JSValue value)
+{
+ return toSmallerUInt<uint16_t>(state, value, IntegerConversionConfiguration::Clamp);
+}
+
+// http://www.w3.org/TR/WebIDL/#es-short
+int16_t toInt16(ExecState& state, JSValue value)
+{
+ return toSmallerInt<int16_t>(state, value, IntegerConversionConfiguration::Normal);
+}
+
+// http://www.w3.org/TR/WebIDL/#es-unsigned-short
+uint16_t toUInt16(ExecState& state, JSValue value)
+{
+ return toSmallerUInt<uint16_t>(state, value, IntegerConversionConfiguration::Normal);
+}
+
+// http://www.w3.org/TR/WebIDL/#es-long
+int32_t toInt32EnforceRange(ExecState& state, JSValue value)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (value.isInt32())
+ return value.asInt32();
+
+ double x = value.toNumber(&state);
+ RETURN_IF_EXCEPTION(scope, 0);
+ return enforceRange(state, x, kMinInt32, kMaxInt32);
+}
+
+int32_t toInt32Clamp(ExecState& state, JSValue value)
+{
+ if (value.isInt32())
+ return value.asInt32();
+
+ double x = value.toNumber(&state);
+ return std::isnan(x) ? 0 : clampTo<int32_t>(x);
+}
+
+uint32_t toUInt32Clamp(ExecState& state, JSValue value)
+{
+ if (value.isUInt32())
+ return value.asUInt32();
+
+ double x = value.toNumber(&state);
+ return std::isnan(x) ? 0 : clampTo<uint32_t>(x);
+}
+
+// http://www.w3.org/TR/WebIDL/#es-unsigned-long
+uint32_t toUInt32EnforceRange(ExecState& state, JSValue value)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (value.isUInt32())
+ return value.asUInt32();
+
+ double x = value.toNumber(&state);
+ RETURN_IF_EXCEPTION(scope, 0);
+ return enforceRange(state, x, 0, kMaxUInt32);
+}
+
+int64_t toInt64EnforceRange(ExecState& state, JSC::JSValue value)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ double x = value.toNumber(&state);
+ RETURN_IF_EXCEPTION(scope, 0);
+ return enforceRange(state, x, -kJSMaxInteger, kJSMaxInteger);
+}
+
+uint64_t toUInt64EnforceRange(ExecState& state, JSC::JSValue value)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ double x = value.toNumber(&state);
+ RETURN_IF_EXCEPTION(scope, 0);
+ return enforceRange(state, x, 0, kJSMaxInteger);
+}
+
+int64_t toInt64Clamp(ExecState& state, JSC::JSValue value)
+{
+ double x = value.toNumber(&state);
+ return std::isnan(x) ? 0 : static_cast<int64_t>(std::min<double>(std::max<double>(x, -kJSMaxInteger), kJSMaxInteger));
+}
+
+uint64_t toUInt64Clamp(ExecState& state, JSC::JSValue value)
+{
+ double x = value.toNumber(&state);
+ return std::isnan(x) ? 0 : static_cast<uint64_t>(std::min<double>(std::max<double>(x, 0), kJSMaxInteger));
+}
+
+// http://www.w3.org/TR/WebIDL/#es-long-long
+int64_t toInt64(ExecState& state, JSValue value)
+{
+ double x = value.toNumber(&state);
+
+ // Map NaNs and +/-Infinity to 0; convert finite values modulo 2^64.
+ unsigned long long n;
+ doubleToInteger(x, n);
+ return n;
+}
+
+// http://www.w3.org/TR/WebIDL/#es-unsigned-long-long
+uint64_t toUInt64(ExecState& state, JSValue value)
+{
+ double x = value.toNumber(&state);
+
+ // Map NaNs and +/-Infinity to 0; convert finite values modulo 2^64.
+ unsigned long long n;
+ doubleToInteger(x, n);
+ return n;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertNumbers.h b/Source/WebCore/bindings/js/JSDOMConvertNumbers.h
new file mode 100644
index 000000000..b79ed05eb
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertNumbers.h
@@ -0,0 +1,424 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+#include "JSDOMConvertBase.h"
+#include "JSDOMExceptionHandling.h"
+#include <runtime/JSCJSValueInlines.h>
+
+namespace WebCore {
+
+enum class IntegerConversionConfiguration { Normal, EnforceRange, Clamp };
+
+template<typename T> typename Converter<T>::ReturnType convert(JSC::ExecState&, JSC::JSValue, IntegerConversionConfiguration);
+
+template<typename T> inline typename Converter<T>::ReturnType convert(JSC::ExecState& state, JSC::JSValue value, IntegerConversionConfiguration configuration)
+{
+ return Converter<T>::convert(state, value, configuration);
+}
+
+// The following functions convert values to integers as per the WebIDL specification.
+// The conversion fails if the value cannot be converted to a number or, if EnforceRange is specified,
+// the value is outside the range of the destination integer type.
+
+WEBCORE_EXPORT int8_t toInt8EnforceRange(JSC::ExecState&, JSC::JSValue);
+WEBCORE_EXPORT uint8_t toUInt8EnforceRange(JSC::ExecState&, JSC::JSValue);
+WEBCORE_EXPORT int16_t toInt16EnforceRange(JSC::ExecState&, JSC::JSValue);
+WEBCORE_EXPORT uint16_t toUInt16EnforceRange(JSC::ExecState&, JSC::JSValue);
+WEBCORE_EXPORT int32_t toInt32EnforceRange(JSC::ExecState&, JSC::JSValue);
+WEBCORE_EXPORT uint32_t toUInt32EnforceRange(JSC::ExecState&, JSC::JSValue);
+WEBCORE_EXPORT int64_t toInt64EnforceRange(JSC::ExecState&, JSC::JSValue);
+WEBCORE_EXPORT uint64_t toUInt64EnforceRange(JSC::ExecState&, JSC::JSValue);
+
+WEBCORE_EXPORT int8_t toInt8Clamp(JSC::ExecState&, JSC::JSValue);
+WEBCORE_EXPORT uint8_t toUInt8Clamp(JSC::ExecState&, JSC::JSValue);
+WEBCORE_EXPORT int16_t toInt16Clamp(JSC::ExecState&, JSC::JSValue);
+WEBCORE_EXPORT uint16_t toUInt16Clamp(JSC::ExecState&, JSC::JSValue);
+WEBCORE_EXPORT int32_t toInt32Clamp(JSC::ExecState&, JSC::JSValue);
+WEBCORE_EXPORT uint32_t toUInt32Clamp(JSC::ExecState&, JSC::JSValue);
+WEBCORE_EXPORT int64_t toInt64Clamp(JSC::ExecState&, JSC::JSValue);
+WEBCORE_EXPORT uint64_t toUInt64Clamp(JSC::ExecState&, JSC::JSValue);
+
+WEBCORE_EXPORT int8_t toInt8(JSC::ExecState&, JSC::JSValue);
+WEBCORE_EXPORT uint8_t toUInt8(JSC::ExecState&, JSC::JSValue);
+WEBCORE_EXPORT int16_t toInt16(JSC::ExecState&, JSC::JSValue);
+WEBCORE_EXPORT uint16_t toUInt16(JSC::ExecState&, JSC::JSValue);
+WEBCORE_EXPORT int64_t toInt64(JSC::ExecState&, JSC::JSValue);
+WEBCORE_EXPORT uint64_t toUInt64(JSC::ExecState&, JSC::JSValue);
+
+
+// MARK: -
+// MARK: Integer types
+
+template<> struct Converter<IDLByte> : DefaultConverter<IDLByte> {
+ static int8_t convert(JSC::ExecState& state, JSC::JSValue value, IntegerConversionConfiguration configuration = IntegerConversionConfiguration::Normal)
+ {
+ switch (configuration) {
+ case IntegerConversionConfiguration::Normal:
+ break;
+ case IntegerConversionConfiguration::EnforceRange:
+ return toInt8EnforceRange(state, value);
+ case IntegerConversionConfiguration::Clamp:
+ return toInt8Clamp(state, value);
+ }
+ return toInt8(state, value);
+ }
+};
+
+template<> struct JSConverter<IDLByte> {
+ using Type = typename IDLByte::ImplementationType;
+
+ static constexpr bool needsState = false;
+ static constexpr bool needsGlobalObject = false;
+
+ static JSC::JSValue convert(Type value)
+ {
+ return JSC::jsNumber(value);
+ }
+};
+
+template<> struct Converter<IDLOctet> : DefaultConverter<IDLOctet> {
+ static uint8_t convert(JSC::ExecState& state, JSC::JSValue value, IntegerConversionConfiguration configuration = IntegerConversionConfiguration::Normal)
+ {
+ switch (configuration) {
+ case IntegerConversionConfiguration::Normal:
+ break;
+ case IntegerConversionConfiguration::EnforceRange:
+ return toUInt8EnforceRange(state, value);
+ case IntegerConversionConfiguration::Clamp:
+ return toUInt8Clamp(state, value);
+ }
+ return toUInt8(state, value);
+ }
+};
+
+template<> struct JSConverter<IDLOctet> {
+ using Type = typename IDLOctet::ImplementationType;
+
+ static constexpr bool needsState = false;
+ static constexpr bool needsGlobalObject = false;
+
+ static JSC::JSValue convert(Type value)
+ {
+ return JSC::jsNumber(value);
+ }
+};
+
+template<> struct Converter<IDLShort> : DefaultConverter<IDLShort> {
+ static int16_t convert(JSC::ExecState& state, JSC::JSValue value, IntegerConversionConfiguration configuration = IntegerConversionConfiguration::Normal)
+ {
+ switch (configuration) {
+ case IntegerConversionConfiguration::Normal:
+ break;
+ case IntegerConversionConfiguration::EnforceRange:
+ return toInt16EnforceRange(state, value);
+ case IntegerConversionConfiguration::Clamp:
+ return toInt16Clamp(state, value);
+ }
+ return toInt16(state, value);
+ }
+};
+
+template<> struct JSConverter<IDLShort> {
+ using Type = typename IDLShort::ImplementationType;
+
+ static constexpr bool needsState = false;
+ static constexpr bool needsGlobalObject = false;
+
+ static JSC::JSValue convert(Type value)
+ {
+ return JSC::jsNumber(value);
+ }
+};
+
+template<> struct Converter<IDLUnsignedShort> : DefaultConverter<IDLUnsignedShort> {
+ static uint16_t convert(JSC::ExecState& state, JSC::JSValue value, IntegerConversionConfiguration configuration = IntegerConversionConfiguration::Normal)
+ {
+ switch (configuration) {
+ case IntegerConversionConfiguration::Normal:
+ break;
+ case IntegerConversionConfiguration::EnforceRange:
+ return toUInt16EnforceRange(state, value);
+ case IntegerConversionConfiguration::Clamp:
+ return toUInt16Clamp(state, value);
+ }
+ return toUInt16(state, value);
+ }
+};
+
+template<> struct JSConverter<IDLUnsignedShort> {
+ using Type = typename IDLUnsignedShort::ImplementationType;
+
+ static constexpr bool needsState = false;
+ static constexpr bool needsGlobalObject = false;
+
+ static JSC::JSValue convert(Type value)
+ {
+ return JSC::jsNumber(value);
+ }
+};
+
+template<> struct Converter<IDLLong> : DefaultConverter<IDLLong> {
+ static inline int32_t convert(JSC::ExecState&, JSC::ThrowScope&, double number)
+ {
+ return JSC::toInt32(number);
+ }
+
+ static int32_t convert(JSC::ExecState& state, JSC::JSValue value, IntegerConversionConfiguration configuration = IntegerConversionConfiguration::Normal)
+ {
+ switch (configuration) {
+ case IntegerConversionConfiguration::Normal:
+ break;
+ case IntegerConversionConfiguration::EnforceRange:
+ return toInt32EnforceRange(state, value);
+ case IntegerConversionConfiguration::Clamp:
+ return toInt32Clamp(state, value);
+ }
+ return value.toInt32(&state);
+ }
+};
+
+template<> struct JSConverter<IDLLong> {
+ using Type = typename IDLLong::ImplementationType;
+
+ static constexpr bool needsState = false;
+ static constexpr bool needsGlobalObject = false;
+
+ static JSC::JSValue convert(Type value)
+ {
+ return JSC::jsNumber(value);
+ }
+};
+
+template<> struct Converter<IDLUnsignedLong> : DefaultConverter<IDLUnsignedLong> {
+ static uint32_t convert(JSC::ExecState& state, JSC::JSValue value, IntegerConversionConfiguration configuration = IntegerConversionConfiguration::Normal)
+ {
+ switch (configuration) {
+ case IntegerConversionConfiguration::Normal:
+ break;
+ case IntegerConversionConfiguration::EnforceRange:
+ return toUInt32EnforceRange(state, value);
+ case IntegerConversionConfiguration::Clamp:
+ return toUInt32Clamp(state, value);
+ }
+ return value.toUInt32(&state);
+ }
+};
+
+template<> struct JSConverter<IDLUnsignedLong> {
+ using Type = typename IDLUnsignedLong::ImplementationType;
+
+ static constexpr bool needsState = false;
+ static constexpr bool needsGlobalObject = false;
+
+ static JSC::JSValue convert(Type value)
+ {
+ return JSC::jsNumber(value);
+ }
+};
+
+template<> struct Converter<IDLLongLong> : DefaultConverter<IDLLongLong> {
+ static int64_t convert(JSC::ExecState& state, JSC::JSValue value, IntegerConversionConfiguration configuration = IntegerConversionConfiguration::Normal)
+ {
+ if (value.isInt32())
+ return value.asInt32();
+
+ switch (configuration) {
+ case IntegerConversionConfiguration::Normal:
+ break;
+ case IntegerConversionConfiguration::EnforceRange:
+ return toInt64EnforceRange(state, value);
+ case IntegerConversionConfiguration::Clamp:
+ return toInt64Clamp(state, value);
+ }
+ return toInt64(state, value);
+ }
+};
+
+template<> struct JSConverter<IDLLongLong> {
+ using Type = typename IDLLongLong::ImplementationType;
+
+ static constexpr bool needsState = false;
+ static constexpr bool needsGlobalObject = false;
+
+ static JSC::JSValue convert(Type value)
+ {
+ return JSC::jsNumber(value);
+ }
+};
+
+template<> struct Converter<IDLUnsignedLongLong> : DefaultConverter<IDLUnsignedLongLong> {
+ static uint64_t convert(JSC::ExecState& state, JSC::JSValue value, IntegerConversionConfiguration configuration = IntegerConversionConfiguration::Normal)
+ {
+ if (value.isUInt32())
+ return value.asUInt32();
+
+ switch (configuration) {
+ case IntegerConversionConfiguration::Normal:
+ break;
+ case IntegerConversionConfiguration::EnforceRange:
+ return toUInt64EnforceRange(state, value);
+ case IntegerConversionConfiguration::Clamp:
+ return toUInt64Clamp(state, value);
+ }
+ return toUInt64(state, value);
+ }
+};
+
+template<> struct JSConverter<IDLUnsignedLongLong> {
+ using Type = typename IDLUnsignedLongLong::ImplementationType;
+
+ static constexpr bool needsState = false;
+ static constexpr bool needsGlobalObject = false;
+
+ static JSC::JSValue convert(Type value)
+ {
+ return JSC::jsNumber(value);
+ }
+};
+
+// MARK: -
+// MARK: Floating point types
+
+template<> struct Converter<IDLFloat> : DefaultConverter<IDLFloat> {
+
+ static inline float convert(JSC::ExecState& state, JSC::ThrowScope& scope, double number)
+ {
+ if (UNLIKELY(!std::isfinite(number)))
+ throwNonFiniteTypeError(state, scope);
+ return static_cast<float>(number);
+ }
+
+ static float convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ JSC::VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ double number = value.toNumber(&state);
+ if (UNLIKELY(!std::isfinite(number)))
+ throwNonFiniteTypeError(state, scope);
+ return static_cast<float>(number);
+ }
+};
+
+template<> struct JSConverter<IDLFloat> {
+ using Type = typename IDLFloat::ImplementationType;
+
+ static constexpr bool needsState = false;
+ static constexpr bool needsGlobalObject = false;
+
+ static JSC::JSValue convert(Type value)
+ {
+ return JSC::jsNumber(value);
+ }
+};
+
+template<> struct Converter<IDLUnrestrictedFloat> : DefaultConverter<IDLUnrestrictedFloat> {
+ static inline float convert(JSC::ExecState&, JSC::ThrowScope&, double number)
+ {
+ return static_cast<float>(number);
+ }
+
+ static float convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ return static_cast<float>(value.toNumber(&state));
+ }
+};
+
+template<> struct JSConverter<IDLUnrestrictedFloat> {
+ using Type = typename IDLUnrestrictedFloat::ImplementationType;
+
+ static constexpr bool needsState = false;
+ static constexpr bool needsGlobalObject = false;
+
+ static JSC::JSValue convert(Type value)
+ {
+ return JSC::jsNumber(value);
+ }
+};
+
+template<> struct Converter<IDLDouble> : DefaultConverter<IDLDouble> {
+ static inline double convert(JSC::ExecState& state, JSC::ThrowScope& scope, double number)
+ {
+ if (UNLIKELY(!std::isfinite(number)))
+ throwNonFiniteTypeError(state, scope);
+ return number;
+ }
+
+ static double convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ JSC::VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ double number = value.toNumber(&state);
+ if (UNLIKELY(!std::isfinite(number)))
+ throwNonFiniteTypeError(state, scope);
+ return number;
+ }
+};
+
+template<> struct JSConverter<IDLDouble> {
+ using Type = typename IDLDouble::ImplementationType;
+
+ static constexpr bool needsState = false;
+ static constexpr bool needsGlobalObject = false;
+
+ static JSC::JSValue convert(Type value)
+ {
+ return JSC::jsNumber(value);
+ }
+};
+
+template<> struct Converter<IDLUnrestrictedDouble> : DefaultConverter<IDLUnrestrictedDouble> {
+ static inline double convert(JSC::ExecState&, JSC::ThrowScope&, double number)
+ {
+ return number;
+ }
+
+ static double convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ return value.toNumber(&state);
+ }
+};
+
+template<> struct JSConverter<IDLUnrestrictedDouble> {
+ using Type = typename IDLUnrestrictedDouble::ImplementationType;
+
+ static constexpr bool needsState = false;
+ static constexpr bool needsGlobalObject = false;
+
+ static JSC::JSValue convert(Type value)
+ {
+ return JSC::jsNumber(value);
+ }
+
+ // Add overload for MediaTime.
+ static JSC::JSValue convert(MediaTime value)
+ {
+ return JSC::jsNumber(value.toDouble());
+ }
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertObject.h b/Source/WebCore/bindings/js/JSDOMConvertObject.h
new file mode 100644
index 000000000..379eb42b8
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertObject.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+#include "JSDOMConvertBase.h"
+
+namespace WebCore {
+
+template<> struct Converter<IDLObject> : DefaultConverter<IDLObject> {
+ template<typename ExceptionThrower = DefaultExceptionThrower>
+ static JSC::Strong<JSC::JSObject> convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower())
+ {
+ JSC::VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (!value.isObject()) {
+ exceptionThrower(state, scope);
+ return { };
+ }
+
+ return { vm, JSC::asObject(value) };
+ }
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertRecord.h b/Source/WebCore/bindings/js/JSDOMConvertRecord.h
new file mode 100644
index 000000000..db1dabf8d
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertRecord.h
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+#include "JSDOMConvertStrings.h"
+#include <runtime/ObjectConstructor.h>
+
+namespace WebCore {
+
+namespace Detail {
+
+template<typename IDLStringType>
+struct IdentifierConverter;
+
+template<> struct IdentifierConverter<IDLDOMString> {
+ static String convert(JSC::ExecState&, const JSC::Identifier& identifier)
+ {
+ return identifier.string();
+ }
+};
+
+template<> struct IdentifierConverter<IDLByteString> {
+ static String convert(JSC::ExecState& state, const JSC::Identifier& identifier)
+ {
+ return identifierToByteString(state, identifier);
+ }
+};
+
+template<> struct IdentifierConverter<IDLUSVString> {
+ static String convert(JSC::ExecState& state, const JSC::Identifier& identifier)
+ {
+ return identifierToUSVString(state, identifier);
+ }
+};
+
+}
+
+template<typename K, typename V> struct Converter<IDLRecord<K, V>> : DefaultConverter<IDLRecord<K, V>> {
+ using ReturnType = typename IDLRecord<K, V>::ImplementationType;
+ using KeyType = typename K::ImplementationType;
+ using ValueType = typename V::ImplementationType;
+
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ auto& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ // 1. Let result be a new empty instance of record<K, V>.
+ // 2. If Type(O) is Undefined or Null, return result.
+ if (value.isUndefinedOrNull())
+ return { };
+
+ // 3. If Type(O) is not Object, throw a TypeError.
+ if (!value.isObject()) {
+ throwTypeError(&state, scope);
+ return { };
+ }
+
+ JSC::JSObject* object = JSC::asObject(value);
+
+ ReturnType result;
+
+ // 4. Let keys be ? O.[[OwnPropertyKeys]]().
+ JSC::PropertyNameArray keys(&vm, JSC::PropertyNameMode::Strings);
+ object->getOwnPropertyNames(object, &state, keys, JSC::EnumerationMode());
+ RETURN_IF_EXCEPTION(scope, { });
+
+ // 5. Repeat, for each element key of keys in List order:
+ for (auto& key : keys) {
+ // 1. Let desc be ? O.[[GetOwnProperty]](key).
+ JSC::PropertyDescriptor descriptor;
+ bool didGetDescriptor = object->getOwnPropertyDescriptor(&state, key, descriptor);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ if (!didGetDescriptor)
+ continue;
+
+ // 2. If desc is not undefined and desc.[[Enumerable]] is true:
+
+ // FIXME: Do we need to check for enumerable / undefined, or is this handled by the default
+ // enumeration mode?
+
+ if (!descriptor.value().isUndefined() && descriptor.enumerable()) {
+ // 1. Let typedKey be key converted to an IDL value of type K.
+ auto typedKey = Detail::IdentifierConverter<K>::convert(state, key);
+
+ // 2. Let value be ? Get(O, key).
+ auto subValue = object->get(&state, key);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ // 3. Let typedValue be value converted to an IDL value of type V.
+ auto typedValue = Converter<V>::convert(state, subValue);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ // 4. If typedKey is already a key in result, set its value to typedValue.
+ // Note: This can happen when O is a proxy object.
+ // FIXME: Handle this case.
+
+ // 5. Otherwise, append to result a mapping (typedKey, typedValue).
+ result.append({ typedKey, typedValue });
+ }
+ }
+
+ // 6. Return result.
+ return result;
+ }
+};
+
+template<typename K, typename V> struct JSConverter<IDLRecord<K, V>> {
+ static constexpr bool needsState = true;
+ static constexpr bool needsGlobalObject = true;
+
+ template<typename MapType>
+ static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const MapType& map)
+ {
+ auto& vm = state.vm();
+
+ // 1. Let result be ! ObjectCreate(%ObjectPrototype%).
+ auto result = constructEmptyObject(&state);
+
+ // 2. Repeat, for each mapping (key, value) in D:
+ for (const auto& keyValuePair : map) {
+ // 1. Let esKey be key converted to an ECMAScript value.
+ // Note, this step is not required, as we need the key to be
+ // an Identifier, not a JSValue.
+
+ // 2. Let esValue be value converted to an ECMAScript value.
+ auto esValue = toJS<V>(state, globalObject, keyValuePair.value);
+
+ // 3. Let created be ! CreateDataProperty(result, esKey, esValue).
+ bool created = result->putDirect(vm, JSC::Identifier::fromString(&vm, keyValuePair.key), esValue);
+
+ // 4. Assert: created is true.
+ ASSERT_UNUSED(created, created);
+ }
+
+ // 3. Return result.
+ return result;
+ }
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertSequences.h b/Source/WebCore/bindings/js/JSDOMConvertSequences.h
new file mode 100644
index 000000000..f42f45992
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertSequences.h
@@ -0,0 +1,317 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+#include "JSDOMConvertBase.h"
+#include <runtime/IteratorOperations.h>
+#include <runtime/JSArray.h>
+#include <runtime/JSGlobalObjectInlines.h>
+
+namespace WebCore {
+
+namespace Detail {
+
+template<typename IDLType>
+struct GenericSequenceConverter {
+ using ReturnType = Vector<typename IDLType::ImplementationType>;
+
+ static ReturnType convert(JSC::ExecState& state, JSC::JSObject* jsObject)
+ {
+ ReturnType result;
+ forEachInIterable(&state, jsObject, [&result](JSC::VM& vm, JSC::ExecState* state, JSC::JSValue jsValue) {
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto convertedValue = Converter<IDLType>::convert(*state, jsValue);
+ if (UNLIKELY(scope.exception()))
+ return;
+ result.append(WTFMove(convertedValue));
+ });
+ return result;
+ }
+};
+
+// Specialization for numeric types
+// FIXME: This is only implemented for the IDLFloatingPointTypes and IDLLong. To add
+// support for more numeric types, add an overload of Converter<IDLType>::convert that
+// takes an ExecState, ThrowScope, double as its arguments.
+template<typename IDLType>
+struct NumericSequenceConverter {
+ using GenericConverter = GenericSequenceConverter<IDLType>;
+ using ReturnType = typename GenericConverter::ReturnType;
+
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ auto& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (!value.isObject()) {
+ throwSequenceTypeError(state, scope);
+ return { };
+ }
+
+ JSC::JSObject* object = JSC::asObject(value);
+ if (!JSC::isJSArray(object))
+ return GenericConverter::convert(state, object);
+
+ JSC::JSArray* array = JSC::asArray(object);
+ if (!array->globalObject()->isArrayIteratorProtocolFastAndNonObservable())
+ return GenericConverter::convert(state, object);
+
+ unsigned length = array->length();
+
+ ReturnType result;
+ if (!result.tryReserveCapacity(length)) {
+ // FIXME: Is the right exception to throw?
+ throwTypeError(&state, scope);
+ return { };
+ }
+
+ JSC::IndexingType indexingType = array->indexingType() & JSC::IndexingShapeMask;
+
+ if (indexingType == JSC::ContiguousShape) {
+ for (unsigned i = 0; i < length; i++) {
+ auto indexValue = array->butterfly()->contiguous()[i].get();
+ if (!indexValue)
+ result.uncheckedAppend(0);
+ else {
+ auto convertedValue = Converter<IDLType>::convert(state, indexValue);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ result.uncheckedAppend(convertedValue);
+ }
+ }
+ return result;
+ }
+
+ if (indexingType == JSC::Int32Shape) {
+ for (unsigned i = 0; i < length; i++) {
+ auto indexValue = array->butterfly()->contiguousInt32()[i].get();
+ ASSERT(!indexValue || indexValue.isInt32());
+ if (!indexValue)
+ result.uncheckedAppend(0);
+ else
+ result.uncheckedAppend(indexValue.asInt32());
+ }
+ return result;
+ }
+
+ if (indexingType == JSC::DoubleShape) {
+ for (unsigned i = 0; i < length; i++) {
+ auto doubleValue = array->butterfly()->contiguousDouble()[i];
+ if (std::isnan(doubleValue))
+ result.uncheckedAppend(0);
+ else {
+ auto convertedValue = Converter<IDLType>::convert(state, scope, doubleValue);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ result.uncheckedAppend(convertedValue);
+ }
+ }
+ return result;
+ }
+
+ for (unsigned i = 0; i < length; i++) {
+ auto indexValue = array->getDirectIndex(&state, i);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ if (!indexValue)
+ result.uncheckedAppend(0);
+ else {
+ auto convertedValue = Converter<IDLType>::convert(state, indexValue);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ result.uncheckedAppend(convertedValue);
+ }
+ }
+ return result;
+ }
+};
+
+template<typename IDLType>
+struct SequenceConverter {
+ using GenericConverter = GenericSequenceConverter<IDLType>;
+ using ReturnType = typename GenericConverter::ReturnType;
+
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ auto& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (!value.isObject()) {
+ throwSequenceTypeError(state, scope);
+ return { };
+ }
+
+ JSC::JSObject* object = JSC::asObject(value);
+ if (!JSC::isJSArray(object))
+ return GenericConverter::convert(state, object);
+
+ JSC::JSArray* array = JSC::asArray(object);
+ if (!array->globalObject()->isArrayIteratorProtocolFastAndNonObservable())
+ return GenericConverter::convert(state, object);
+
+ unsigned length = array->length();
+
+ ReturnType result;
+ if (!result.tryReserveCapacity(length)) {
+ // FIXME: Is the right exception to throw?
+ throwTypeError(&state, scope);
+ return { };
+ }
+
+ JSC::IndexingType indexingType = array->indexingType() & JSC::IndexingShapeMask;
+
+ if (indexingType == JSC::ContiguousShape) {
+ for (unsigned i = 0; i < length; i++) {
+ auto indexValue = array->butterfly()->contiguous()[i].get();
+ if (!indexValue)
+ indexValue = JSC::jsUndefined();
+
+ auto convertedValue = Converter<IDLType>::convert(state, indexValue);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ result.uncheckedAppend(convertedValue);
+ }
+ return result;
+ }
+
+ for (unsigned i = 0; i < length; i++) {
+ auto indexValue = array->getDirectIndex(&state, i);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ if (!indexValue)
+ indexValue = JSC::jsUndefined();
+
+ auto convertedValue = Converter<IDLType>::convert(state, indexValue);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ result.uncheckedAppend(convertedValue);
+ }
+ return result;
+ }
+};
+
+template<>
+struct SequenceConverter<IDLLong> {
+ using ReturnType = typename GenericSequenceConverter<IDLLong>::ReturnType;
+
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ return NumericSequenceConverter<IDLLong>::convert(state, value);
+ }
+};
+
+template<>
+struct SequenceConverter<IDLFloat> {
+ using ReturnType = typename GenericSequenceConverter<IDLFloat>::ReturnType;
+
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ return NumericSequenceConverter<IDLFloat>::convert(state, value);
+ }
+};
+
+template<>
+struct SequenceConverter<IDLUnrestrictedFloat> {
+ using ReturnType = typename GenericSequenceConverter<IDLUnrestrictedFloat>::ReturnType;
+
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ return NumericSequenceConverter<IDLUnrestrictedFloat>::convert(state, value);
+ }
+};
+
+template<>
+struct SequenceConverter<IDLDouble> {
+ using ReturnType = typename GenericSequenceConverter<IDLDouble>::ReturnType;
+
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ return NumericSequenceConverter<IDLDouble>::convert(state, value);
+ }
+};
+
+template<>
+struct SequenceConverter<IDLUnrestrictedDouble> {
+ using ReturnType = typename GenericSequenceConverter<IDLUnrestrictedDouble>::ReturnType;
+
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ return NumericSequenceConverter<IDLUnrestrictedDouble>::convert(state, value);
+ }
+};
+
+}
+
+template<typename T> struct Converter<IDLSequence<T>> : DefaultConverter<IDLSequence<T>> {
+ using ReturnType = typename Detail::SequenceConverter<T>::ReturnType;
+
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ return Detail::SequenceConverter<T>::convert(state, value);
+ }
+};
+
+template<typename T> struct JSConverter<IDLSequence<T>> {
+ static constexpr bool needsState = true;
+ static constexpr bool needsGlobalObject = true;
+
+ template<typename U, size_t inlineCapacity>
+ static JSC::JSValue convert(JSC::ExecState& exec, JSDOMGlobalObject& globalObject, const Vector<U, inlineCapacity>& vector)
+ {
+ JSC::MarkedArgumentBuffer list;
+ for (auto& element : vector)
+ list.append(toJS<T>(exec, globalObject, element));
+ return JSC::constructArray(&exec, nullptr, &globalObject, list);
+ }
+};
+
+template<typename T> struct Converter<IDLFrozenArray<T>> : DefaultConverter<IDLFrozenArray<T>> {
+ using ReturnType = typename Detail::SequenceConverter<T>::ReturnType;
+
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ return Detail::SequenceConverter<T>::convert(state, value);
+ }
+};
+
+template<typename T> struct JSConverter<IDLFrozenArray<T>> {
+ static constexpr bool needsState = true;
+ static constexpr bool needsGlobalObject = true;
+
+ template<typename U, size_t inlineCapacity>
+ static JSC::JSValue convert(JSC::ExecState& exec, JSDOMGlobalObject& globalObject, const Vector<U, inlineCapacity>& vector)
+ {
+ JSC::MarkedArgumentBuffer list;
+ for (auto& element : vector)
+ list.append(toJS<T>(exec, globalObject, element));
+ auto* array = JSC::constructArray(&exec, nullptr, &globalObject, list);
+ return JSC::objectConstructorFreeze(&exec, array);
+ }
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertSerializedScriptValue.h b/Source/WebCore/bindings/js/JSDOMConvertSerializedScriptValue.h
new file mode 100644
index 000000000..10b69f9ac
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertSerializedScriptValue.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+#include "JSDOMConvertStrings.h"
+
+namespace WebCore {
+
+template<typename T> struct Converter<IDLSerializedScriptValue<T>> : DefaultConverter<IDLSerializedScriptValue<T>> {
+ static RefPtr<T> convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ return T::create(state, value);
+ }
+};
+
+template<typename T> struct JSConverter<IDLSerializedScriptValue<T>> {
+ static constexpr bool needsState = true;
+ static constexpr bool needsGlobalObject = true;
+
+ static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, RefPtr<T> value)
+ {
+ return value ? value->deserialize(state, &globalObject) : JSC::jsNull();
+ }
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertStrings.cpp b/Source/WebCore/bindings/js/JSDOMConvertStrings.cpp
new file mode 100644
index 000000000..6c95f6680
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertStrings.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004-2011, 2013, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
+ * Copyright (C) 2013 Michael Pruett <michael@68k.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "JSDOMConvertStrings.h"
+
+#include "JSDOMExceptionHandling.h"
+#include <heap/HeapInlines.h>
+#include <runtime/JSCJSValueInlines.h>
+#include <wtf/text/StringBuilder.h>
+#include <wtf/unicode/CharacterNames.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+static inline String stringToByteString(ExecState& state, JSC::ThrowScope& scope, String&& string)
+{
+ if (!string.containsOnlyLatin1()) {
+ throwTypeError(&state, scope);
+ return { };
+ }
+
+ return string;
+}
+
+String identifierToByteString(ExecState& state, const Identifier& identifier)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto string = identifier.string();
+ return stringToByteString(state, scope, WTFMove(string));
+}
+
+String valueToByteString(ExecState& state, JSValue value)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto string = value.toWTFString(&state);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ return stringToByteString(state, scope, WTFMove(string));
+}
+
+static inline bool hasUnpairedSurrogate(StringView string)
+{
+ // Fast path for 8-bit strings; they can't have any surrogates.
+ if (string.is8Bit())
+ return false;
+ for (auto codePoint : string.codePoints()) {
+ if (U_IS_SURROGATE(codePoint))
+ return true;
+ }
+ return false;
+}
+
+static inline String stringToUSVString(String&& string)
+{
+ // Fast path for the case where there are no unpaired surrogates.
+ if (!hasUnpairedSurrogate(string))
+ return string;
+
+ // Slow path: http://heycam.github.io/webidl/#dfn-obtain-unicode
+ // Replaces unpaired surrogates with the replacement character.
+ StringBuilder result;
+ result.reserveCapacity(string.length());
+ StringView view { string };
+ for (auto codePoint : view.codePoints()) {
+ if (U_IS_SURROGATE(codePoint))
+ result.append(replacementCharacter);
+ else
+ result.append(codePoint);
+ }
+ return result.toString();
+}
+
+String identifierToUSVString(ExecState&, const Identifier& identifier)
+{
+ auto string = identifier.string();
+ return stringToUSVString(WTFMove(string));
+}
+
+String valueToUSVString(ExecState& state, JSValue value)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto string = value.toWTFString(&state);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ return stringToUSVString(WTFMove(string));
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertStrings.h b/Source/WebCore/bindings/js/JSDOMConvertStrings.h
new file mode 100644
index 000000000..dd9bfad77
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertStrings.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+#include "JSDOMConvertBase.h"
+#include "JSDOMExceptionHandling.h"
+
+namespace WebCore {
+
+enum class StringConversionConfiguration { Normal, TreatNullAsEmptyString };
+
+template<typename T> typename Converter<T>::ReturnType convert(JSC::ExecState&, JSC::JSValue, StringConversionConfiguration);
+
+template<typename T> inline typename Converter<T>::ReturnType convert(JSC::ExecState& state, JSC::JSValue value, StringConversionConfiguration configuration)
+{
+ return Converter<T>::convert(state, value, configuration);
+}
+
+WEBCORE_EXPORT String identifierToByteString(JSC::ExecState&, const JSC::Identifier&);
+WEBCORE_EXPORT String valueToByteString(JSC::ExecState&, JSC::JSValue);
+WEBCORE_EXPORT String identifierToUSVString(JSC::ExecState&, const JSC::Identifier&);
+WEBCORE_EXPORT String valueToUSVString(JSC::ExecState&, JSC::JSValue);
+
+inline String propertyNameToString(JSC::PropertyName propertyName)
+{
+ ASSERT(!propertyName.isSymbol());
+ return propertyName.uid() ? propertyName.uid() : propertyName.publicName();
+}
+
+inline AtomicString propertyNameToAtomicString(JSC::PropertyName propertyName)
+{
+ return AtomicString(propertyName.uid() ? propertyName.uid() : propertyName.publicName());
+}
+
+// MARK: -
+// MARK: String types
+
+template<> struct Converter<IDLDOMString> : DefaultConverter<IDLDOMString> {
+ static String convert(JSC::ExecState& state, JSC::JSValue value, StringConversionConfiguration configuration = StringConversionConfiguration::Normal)
+ {
+ if (configuration == StringConversionConfiguration::TreatNullAsEmptyString && value.isNull())
+ return emptyString();
+ return value.toWTFString(&state);
+ }
+};
+
+template<> struct JSConverter<IDLDOMString> {
+ static constexpr bool needsState = true;
+ static constexpr bool needsGlobalObject = false;
+
+ static JSC::JSValue convert(JSC::ExecState& state, const String& value)
+ {
+ return JSC::jsStringWithCache(&state, value);
+ }
+};
+
+template<> struct Converter<IDLByteString> : DefaultConverter<IDLByteString> {
+ static String convert(JSC::ExecState& state, JSC::JSValue value, StringConversionConfiguration configuration = StringConversionConfiguration::Normal)
+ {
+ if (configuration == StringConversionConfiguration::TreatNullAsEmptyString && value.isNull())
+ return emptyString();
+ return valueToByteString(state, value);
+ }
+};
+
+template<> struct JSConverter<IDLByteString> {
+ static constexpr bool needsState = true;
+ static constexpr bool needsGlobalObject = false;
+
+ static JSC::JSValue convert(JSC::ExecState& state, const String& value)
+ {
+ return JSC::jsStringWithCache(&state, value);
+ }
+};
+
+template<> struct Converter<IDLUSVString> : DefaultConverter<IDLUSVString> {
+ static String convert(JSC::ExecState& state, JSC::JSValue value, StringConversionConfiguration configuration = StringConversionConfiguration::Normal)
+ {
+ if (configuration == StringConversionConfiguration::TreatNullAsEmptyString && value.isNull())
+ return emptyString();
+ return valueToUSVString(state, value);
+ }
+};
+
+template<> struct JSConverter<IDLUSVString> {
+ static constexpr bool needsState = true;
+ static constexpr bool needsGlobalObject = false;
+
+ static JSC::JSValue convert(JSC::ExecState& state, const String& value)
+ {
+ return JSC::jsStringWithCache(&state, value);
+ }
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertUnion.h b/Source/WebCore/bindings/js/JSDOMConvertUnion.h
new file mode 100644
index 000000000..6a2501464
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertUnion.h
@@ -0,0 +1,286 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+#include "JSDOMBinding.h"
+#include "JSDOMConvertBase.h"
+#include <runtime/IteratorOperations.h>
+
+namespace WebCore {
+
+template<typename ReturnType, typename T, bool enabled>
+struct ConditionalConverter;
+
+template<typename ReturnType, typename T>
+struct ConditionalConverter<ReturnType, T, true> {
+ static std::optional<ReturnType> convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ return ReturnType(Converter<T>::convert(state, value));
+ }
+};
+
+template<typename ReturnType, typename T>
+struct ConditionalConverter<ReturnType, T, false> {
+ static std::optional<ReturnType> convert(JSC::ExecState&, JSC::JSValue)
+ {
+ return std::nullopt;
+ }
+};
+
+namespace Detail {
+
+template<typename List, bool condition>
+struct ConditionalFront;
+
+template<typename List>
+struct ConditionalFront<List, true> {
+ using type = brigand::front<List>;
+};
+
+template<typename List>
+struct ConditionalFront<List, false> {
+ using type = void;
+};
+
+}
+
+template<typename List, bool condition>
+using ConditionalFront = typename Detail::ConditionalFront<List, condition>::type;
+
+template<typename... T> struct Converter<IDLUnion<T...>> : DefaultConverter<IDLUnion<T...>> {
+ using Type = IDLUnion<T...>;
+ using TypeList = typename Type::TypeList;
+ using ReturnType = typename Type::ImplementationType;
+
+ using NumericTypeList = brigand::filter<TypeList, IsIDLNumber<brigand::_1>>;
+ static constexpr size_t numberOfNumericTypes = brigand::size<NumericTypeList>::value;
+ static_assert(numberOfNumericTypes == 0 || numberOfNumericTypes == 1, "There can be 0 or 1 numeric types in an IDLUnion.");
+ using NumericType = ConditionalFront<NumericTypeList, numberOfNumericTypes != 0>;
+
+ // FIXME: This should also check for IDLEnumeration<T>.
+ using StringTypeList = brigand::filter<TypeList, std::is_base_of<IDLString, brigand::_1>>;
+ static constexpr size_t numberOfStringTypes = brigand::size<StringTypeList>::value;
+ static_assert(numberOfStringTypes == 0 || numberOfStringTypes == 1, "There can be 0 or 1 string types in an IDLUnion.");
+ using StringType = ConditionalFront<StringTypeList, numberOfStringTypes != 0>;
+
+ using SequenceTypeList = brigand::filter<TypeList, IsIDLSequence<brigand::_1>>;
+ static constexpr size_t numberOfSequenceTypes = brigand::size<SequenceTypeList>::value;
+ static_assert(numberOfSequenceTypes == 0 || numberOfSequenceTypes == 1, "There can be 0 or 1 sequence types in an IDLUnion.");
+ using SequenceType = ConditionalFront<SequenceTypeList, numberOfSequenceTypes != 0>;
+
+ using FrozenArrayTypeList = brigand::filter<TypeList, IsIDLFrozenArray<brigand::_1>>;
+ static constexpr size_t numberOfFrozenArrayTypes = brigand::size<FrozenArrayTypeList>::value;
+ static_assert(numberOfFrozenArrayTypes == 0 || numberOfFrozenArrayTypes == 1, "There can be 0 or 1 FrozenArray types in an IDLUnion.");
+ using FrozenArrayType = ConditionalFront<FrozenArrayTypeList, numberOfFrozenArrayTypes != 0>;
+
+ using DictionaryTypeList = brigand::filter<TypeList, IsIDLDictionary<brigand::_1>>;
+ static constexpr size_t numberOfDictionaryTypes = brigand::size<DictionaryTypeList>::value;
+ static_assert(numberOfDictionaryTypes == 0 || numberOfDictionaryTypes == 1, "There can be 0 or 1 dictionary types in an IDLUnion.");
+ static constexpr bool hasDictionaryType = numberOfDictionaryTypes != 0;
+ using DictionaryType = ConditionalFront<DictionaryTypeList, hasDictionaryType>;
+
+ using RecordTypeList = brigand::filter<TypeList, IsIDLRecord<brigand::_1>>;
+ static constexpr size_t numberOfRecordTypes = brigand::size<RecordTypeList>::value;
+ static_assert(numberOfRecordTypes == 0 || numberOfRecordTypes == 1, "There can be 0 or 1 record types in an IDLUnion.");
+ static constexpr bool hasRecordType = numberOfRecordTypes != 0;
+ using RecordType = ConditionalFront<RecordTypeList, hasRecordType>;
+
+ static constexpr bool hasObjectType = (numberOfSequenceTypes + numberOfFrozenArrayTypes + numberOfDictionaryTypes + numberOfRecordTypes) > 0;
+
+ using InterfaceTypeList = brigand::filter<TypeList, IsIDLInterface<brigand::_1>>;
+
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ JSC::VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ // 1. If the union type includes a nullable type and V is null or undefined, then return the IDL value null.
+ constexpr bool hasNullType = brigand::any<TypeList, std::is_same<IDLNull, brigand::_1>>::value;
+ if (hasNullType) {
+ if (value.isUndefinedOrNull())
+ return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, IDLNull, hasNullType>::convert(state, value).value());
+ }
+
+ // 2. Let types be the flattened member types of the union type.
+ // NOTE: Union is expected to be pre-flattented.
+
+ // 3. If V is null or undefined then:
+ if (hasDictionaryType || hasRecordType) {
+ if (value.isUndefinedOrNull()) {
+ // 1. If types includes a dictionary type, then return the result of converting V to that dictionary type.
+ if (hasDictionaryType)
+ return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, DictionaryType, hasDictionaryType>::convert(state, value).value());
+
+ // 2. If types includes a record type, then return the result of converting V to that record type.
+ if (hasRecordType)
+ return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, RecordType, hasRecordType>::convert(state, value).value());
+ }
+ }
+
+ // 4. If V is a platform object, then:
+ // 1. If types includes an interface type that V implements, then return the IDL value that is a reference to the object V.
+ // 2. If types includes object, then return the IDL value that is a reference to the object V.
+ // (FIXME: Add support for object and step 4.2)
+ if (brigand::any<TypeList, IsIDLInterface<brigand::_1>>::value) {
+ std::optional<ReturnType> returnValue;
+ brigand::for_each<InterfaceTypeList>([&](auto&& type) {
+ if (returnValue)
+ return;
+
+ using Type = typename WTF::RemoveCVAndReference<decltype(type)>::type::type;
+ using ImplementationType = typename Type::ImplementationType;
+ using RawType = typename Type::RawType;
+ using WrapperType = typename JSDOMWrapperConverterTraits<RawType>::WrapperClass;
+
+ auto castedValue = WrapperType::toWrapped(vm, value);
+ if (!castedValue)
+ return;
+
+ returnValue = ReturnType(ImplementationType(castedValue));
+ });
+
+ if (returnValue)
+ return WTFMove(returnValue.value());
+ }
+
+ // FIXME: Add support for steps 5 - 10.
+
+ // 11. If V is any kind of object, then:
+ if (hasObjectType) {
+ if (value.isCell()) {
+ JSC::JSCell* cell = value.asCell();
+ if (cell->isObject()) {
+ // FIXME: We should be able to optimize the following code by making use
+ // of the fact that we have proved that the value is an object.
+
+ // 1. If types includes a sequence type, then:
+ // 1. Let method be the result of GetMethod(V, @@iterator).
+ // 2. ReturnIfAbrupt(method).
+ // 3. If method is not undefined, return the result of creating a
+ // sequence of that type from V and method.
+ constexpr bool hasSequenceType = numberOfSequenceTypes != 0;
+ if (hasSequenceType) {
+ bool hasIterator = JSC::hasIteratorMethod(state, value);
+ RETURN_IF_EXCEPTION(scope, ReturnType());
+ if (hasIterator)
+ return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, SequenceType, hasSequenceType>::convert(state, value).value());
+ }
+
+ // 2. If types includes a frozen array type, then:
+ // 1. Let method be the result of GetMethod(V, @@iterator).
+ // 2. ReturnIfAbrupt(method).
+ // 3. If method is not undefined, return the result of creating a
+ // frozen array of that type from V and method.
+ constexpr bool hasFrozenArrayType = numberOfFrozenArrayTypes != 0;
+ if (hasFrozenArrayType) {
+ bool hasIterator = JSC::hasIteratorMethod(state, value);
+ RETURN_IF_EXCEPTION(scope, ReturnType());
+ if (hasIterator)
+ return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, FrozenArrayType, hasFrozenArrayType>::convert(state, value).value());
+ }
+
+ // 3. If types includes a dictionary type, then return the result of
+ // converting V to that dictionary type.
+ if (hasDictionaryType)
+ return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, DictionaryType, hasDictionaryType>::convert(state, value).value());
+
+ // 4. If types includes a record type, then return the result of converting V to that record type.
+ if (hasRecordType)
+ return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, RecordType, hasRecordType>::convert(state, value).value());
+
+ // 5. If types includes a callback interface type, then return the result of converting V to that interface type.
+ // (FIXME: Add support for callback interface type and step 12.5)
+ // 6. If types includes object, then return the IDL value that is a reference to the object V.
+ // (FIXME: Add support for object and step 12.6)
+ }
+ }
+ }
+
+ // 12. If V is a Boolean value, then:
+ // 1. If types includes a boolean, then return the result of converting V to boolean.
+ constexpr bool hasBooleanType = brigand::any<TypeList, std::is_same<IDLBoolean, brigand::_1>>::value;
+ if (hasBooleanType) {
+ if (value.isBoolean())
+ return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, IDLBoolean, hasBooleanType>::convert(state, value).value());
+ }
+
+ // 13. If V is a Number value, then:
+ // 1. If types includes a numeric type, then return the result of converting V to that numeric type.
+ constexpr bool hasNumericType = brigand::size<NumericTypeList>::value != 0;
+ if (hasNumericType) {
+ if (value.isNumber())
+ return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, NumericType, hasNumericType>::convert(state, value).value());
+ }
+
+ // 14. If types includes a string type, then return the result of converting V to that type.
+ constexpr bool hasStringType = brigand::size<StringTypeList>::value != 0;
+ if (hasStringType)
+ return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, StringType, hasStringType>::convert(state, value).value());
+
+ // 15. If types includes a numeric type, then return the result of converting V to that numeric type.
+ if (hasNumericType)
+ return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, NumericType, hasNumericType>::convert(state, value).value());
+
+ // 16. If types includes a boolean, then return the result of converting V to boolean.
+ if (hasBooleanType)
+ return std::move<WTF::CheckMoveParameter>(ConditionalConverter<ReturnType, IDLBoolean, hasBooleanType>::convert(state, value).value());
+
+ // 17. Throw a TypeError.
+ throwTypeError(&state, scope);
+ return ReturnType();
+ }
+};
+
+template<typename... T> struct JSConverter<IDLUnion<T...>> {
+ using Type = IDLUnion<T...>;
+ using TypeList = typename Type::TypeList;
+ using ImplementationType = typename Type::ImplementationType;
+
+ static constexpr bool needsState = true;
+ static constexpr bool needsGlobalObject = true;
+
+ using Sequence = brigand::make_sequence<brigand::ptrdiff_t<0>, WTF::variant_size<ImplementationType>::value>;
+
+ static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const ImplementationType& variant)
+ {
+ auto index = variant.index();
+
+ std::optional<JSC::JSValue> returnValue;
+ brigand::for_each<Sequence>([&](auto&& type) {
+ using I = typename WTF::RemoveCVAndReference<decltype(type)>::type::type;
+ if (I::value == index) {
+ ASSERT(!returnValue);
+ returnValue = toJS<brigand::at<TypeList, I>>(state, globalObject, WTF::get<I::value>(variant));
+ }
+ });
+
+ ASSERT(returnValue);
+ return returnValue.value();
+ }
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertVariadic.h b/Source/WebCore/bindings/js/JSDOMConvertVariadic.h
new file mode 100644
index 000000000..79b2b9d55
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertVariadic.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+#include "JSDOMConvertBase.h"
+
+namespace WebCore {
+
+namespace Detail {
+
+template<typename IDLType>
+struct VariadicConverterBase;
+
+template<typename IDLType>
+struct VariadicConverterBase {
+ using Item = typename IDLType::ImplementationType;
+
+ static std::optional<Item> convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ auto& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto result = Converter<IDLType>::convert(state, value);
+ RETURN_IF_EXCEPTION(scope, std::nullopt);
+
+ return WTFMove(result);
+ }
+};
+
+template<typename T>
+struct VariadicConverterBase<IDLInterface<T>> {
+ using Item = std::reference_wrapper<T>;
+
+ static std::optional<Item> convert(JSC::ExecState& state, JSC::JSValue value)
+ {
+ auto* result = Converter<IDLInterface<T>>::convert(state, value);
+ if (!result)
+ return std::nullopt;
+ return std::optional<Item>(*result);
+ }
+};
+
+template<typename IDLType>
+struct VariadicConverter : VariadicConverterBase<IDLType> {
+ using Item = typename VariadicConverterBase<IDLType>::Item;
+ using Container = Vector<Item>;
+
+ struct Result {
+ size_t argumentIndex;
+ std::optional<Container> arguments;
+ };
+};
+
+}
+
+template<typename IDLType> typename Detail::VariadicConverter<IDLType>::Result convertVariadicArguments(JSC::ExecState& state, size_t startIndex)
+{
+ size_t length = state.argumentCount();
+ if (startIndex > length)
+ return { 0, std::nullopt };
+
+ typename Detail::VariadicConverter<IDLType>::Container result;
+ result.reserveInitialCapacity(length - startIndex);
+
+ for (size_t i = startIndex; i < length; ++i) {
+ auto value = Detail::VariadicConverter<IDLType>::convert(state, state.uncheckedArgument(i));
+ if (!value)
+ return { i, std::nullopt };
+ result.uncheckedAppend(WTFMove(*value));
+ }
+
+ return { length, WTFMove(result) };
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertWebGL.h b/Source/WebCore/bindings/js/JSDOMConvertWebGL.h
new file mode 100644
index 000000000..c2740d529
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertWebGL.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(WEBGL)
+
+#include "IDLTypes.h"
+#include "JSDOMConvertBase.h"
+
+namespace WebCore {
+
+template<> struct JSConverter<IDLWebGLAny> {
+ static constexpr bool needsState = true;
+ static constexpr bool needsGlobalObject = true;
+
+ static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const WebGLAny& value)
+ {
+ return convertToJSValue(state, globalObject, value);
+ }
+};
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/bindings/js/JSDOMConvertXPathNSResolver.h b/Source/WebCore/bindings/js/JSDOMConvertXPathNSResolver.h
new file mode 100644
index 000000000..94df3f45a
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMConvertXPathNSResolver.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+#include "JSDOMConvertBase.h"
+
+namespace WebCore {
+
+template<typename T> struct Converter<IDLXPathNSResolver<T>> : DefaultConverter<IDLXPathNSResolver<T>> {
+ using ReturnType = RefPtr<T>;
+ using WrapperType = typename JSDOMWrapperConverterTraits<T>::WrapperClass;
+
+ template<typename ExceptionThrower = DefaultExceptionThrower>
+ static ReturnType convert(JSC::ExecState& state, JSC::JSValue value, ExceptionThrower&& exceptionThrower = ExceptionThrower())
+ {
+ JSC::VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ ReturnType object = WrapperType::toWrapped(vm, state, value);
+ if (UNLIKELY(!object))
+ exceptionThrower(state, scope);
+ return object;
+ }
+};
+
+template<typename T> struct JSConverter<IDLXPathNSResolver<T>> {
+ static constexpr bool needsState = true;
+ static constexpr bool needsGlobalObject = true;
+
+ template <typename U>
+ static JSC::JSValue convert(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const U& value)
+ {
+ return toJS(&state, &globalObject, Detail::getPtrOrRef(value));
+ }
+
+ template<typename U>
+ static JSC::JSValue convertNewlyCreated(JSC::ExecState& state, JSDOMGlobalObject& globalObject, U&& value)
+ {
+ return toJSNewlyCreated(&state, &globalObject, std::forward<U>(value));
+ }
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMExceptionHandling.cpp b/Source/WebCore/bindings/js/JSDOMExceptionHandling.cpp
new file mode 100644
index 000000000..585553d16
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMExceptionHandling.cpp
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004-2011, 2013, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
+ * Copyright (C) 2013 Michael Pruett <michael@68k.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "JSDOMExceptionHandling.h"
+
+#include "CachedScript.h"
+#include "DOMWindow.h"
+#include "ExceptionCodeDescription.h"
+#include "ExceptionHeaders.h"
+#include "ExceptionInterfaces.h"
+#include "JSDOMPromise.h"
+#include "JSDOMWindow.h"
+#include "JSDynamicDowncast.h"
+#include "JSExceptionBase.h"
+#include <inspector/ScriptCallStack.h>
+#include <inspector/ScriptCallStackFactory.h>
+#include <runtime/ErrorHandlingScope.h>
+#include <runtime/Exception.h>
+#include <runtime/ExceptionHelpers.h>
+#include <wtf/text/StringBuilder.h>
+
+#if ENABLE(INDEXED_DATABASE)
+#include "IDBDatabaseException.h"
+#endif
+
+using namespace JSC;
+
+namespace WebCore {
+
+void reportException(ExecState* exec, JSValue exceptionValue, CachedScript* cachedScript)
+{
+ VM& vm = exec->vm();
+ RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
+ auto* exception = jsDynamicDowncast<JSC::Exception*>(vm, exceptionValue);
+ if (!exception) {
+ exception = vm.lastException();
+ if (!exception)
+ exception = JSC::Exception::create(exec->vm(), exceptionValue, JSC::Exception::DoNotCaptureStack);
+ }
+
+ reportException(exec, exception, cachedScript);
+}
+
+String retrieveErrorMessage(ExecState& state, VM& vm, JSValue exception, CatchScope& catchScope)
+{
+ if (auto* exceptionBase = toExceptionBase(vm, exception))
+ return exceptionBase->toString();
+
+ // FIXME: <http://webkit.org/b/115087> Web Inspector: WebCore::reportException should not evaluate JavaScript handling exceptions
+ // If this is a custom exception object, call toString on it to try and get a nice string representation for the exception.
+ String errorMessage;
+ if (auto* error = jsDynamicDowncast<ErrorInstance*>(vm, exception))
+ errorMessage = error->sanitizedToString(&state);
+ else
+ errorMessage = exception.toWTFString(&state);
+
+ // We need to clear any new exception that may be thrown in the toString() call above.
+ // reportException() is not supposed to be making new exceptions.
+ catchScope.clearException();
+ vm.clearLastException();
+ return errorMessage;
+}
+
+void reportException(ExecState* exec, JSC::Exception* exception, CachedScript* cachedScript, ExceptionDetails* exceptionDetails)
+{
+ VM& vm = exec->vm();
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+
+ RELEASE_ASSERT(vm.currentThreadIsHoldingAPILock());
+ if (isTerminatedExecutionException(vm, exception))
+ return;
+
+ ErrorHandlingScope errorScope(exec->vm());
+
+ auto callStack = Inspector::createScriptCallStackFromException(exec, exception, Inspector::ScriptCallStack::maxCallStackSizeToCapture);
+ scope.clearException();
+ vm.clearLastException();
+
+ auto* globalObject = jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject());
+ if (auto* window = jsDynamicDowncast<JSDOMWindow*>(vm, globalObject)) {
+ if (!window->wrapped().isCurrentlyDisplayedInFrame())
+ return;
+ }
+
+ int lineNumber = 0;
+ int columnNumber = 0;
+ String exceptionSourceURL;
+ if (auto* callFrame = callStack->firstNonNativeCallFrame()) {
+ lineNumber = callFrame->lineNumber();
+ columnNumber = callFrame->columnNumber();
+ exceptionSourceURL = callFrame->sourceURL();
+ }
+
+ auto errorMessage = retrieveErrorMessage(*exec, vm, exception->value(), scope);
+ globalObject->scriptExecutionContext()->reportException(errorMessage, lineNumber, columnNumber, exceptionSourceURL, exception, callStack->size() ? callStack.ptr() : nullptr, cachedScript);
+
+ if (exceptionDetails) {
+ exceptionDetails->message = errorMessage;
+ exceptionDetails->lineNumber = lineNumber;
+ exceptionDetails->columnNumber = columnNumber;
+ exceptionDetails->sourceURL = exceptionSourceURL;
+ }
+}
+
+void reportCurrentException(ExecState* exec)
+{
+ VM& vm = exec->vm();
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+ auto* exception = scope.exception();
+ scope.clearException();
+ reportException(exec, exception);
+}
+
+static JSValue createDOMException(ExecState* exec, ExceptionCode ec, const String* message = nullptr)
+{
+ if (!ec || ec == ExistingExceptionError)
+ return jsUndefined();
+
+ // FIXME: Handle other WebIDL exception types.
+ if (ec == TypeError) {
+ if (!message || message->isEmpty())
+ return createTypeError(exec);
+ return createTypeError(exec, *message);
+ }
+
+ if (ec == RangeError) {
+ if (!message || message->isEmpty())
+ return createRangeError(exec, ASCIILiteral("Bad value"));
+ return createRangeError(exec, *message);
+ }
+
+ if (ec == StackOverflowError)
+ return createStackOverflowError(exec);
+
+ // FIXME: All callers to createDOMException need to pass in the correct global object.
+ // For now, we're going to assume the lexicalGlobalObject. Which is wrong in cases like this:
+ // frames[0].document.createElement(null, null); // throws an exception which should have the subframe's prototypes.
+ JSDOMGlobalObject* globalObject = deprecatedGlobalObjectForPrototype(exec);
+
+ ExceptionCodeDescription description(ec);
+
+ CString messageCString;
+ if (message)
+ messageCString = message->utf8();
+ if (message && !message->isEmpty()) {
+ // It is safe to do this because the char* contents of the CString are copied into a new WTF::String before the CString is destroyed.
+ description.description = messageCString.data();
+ }
+
+ JSValue errorObject;
+ switch (description.type) {
+ case DOMCoreExceptionType:
+#if ENABLE(INDEXED_DATABASE)
+ case IDBDatabaseExceptionType:
+#endif
+ errorObject = toJS(exec, globalObject, DOMCoreException::create(description));
+ break;
+ case FileExceptionType:
+ errorObject = toJS(exec, globalObject, FileException::create(description));
+ break;
+ case SQLExceptionType:
+ errorObject = toJS(exec, globalObject, SQLException::create(description));
+ break;
+ case SVGExceptionType:
+ errorObject = toJS(exec, globalObject, SVGException::create(description));
+ break;
+ case XPathExceptionType:
+ errorObject = toJS(exec, globalObject, XPathException::create(description));
+ break;
+ }
+
+ ASSERT(errorObject);
+ addErrorInfo(exec, asObject(errorObject), true);
+ return errorObject;
+}
+
+JSValue createDOMException(ExecState* exec, ExceptionCode ec, const String& message)
+{
+ return createDOMException(exec, ec, &message);
+}
+
+JSValue createDOMException(ExecState& state, Exception&& exception)
+{
+ return createDOMException(&state, exception.code(), exception.releaseMessage());
+}
+
+void propagateExceptionSlowPath(JSC::ExecState& state, JSC::ThrowScope& throwScope, Exception&& exception)
+{
+ ASSERT(!throwScope.exception());
+ throwException(&state, throwScope, createDOMException(state, WTFMove(exception)));
+}
+
+static EncodedJSValue throwTypeError(JSC::ExecState& state, JSC::ThrowScope& scope, const String& errorMessage)
+{
+ return throwVMTypeError(&state, scope, errorMessage);
+}
+
+static void appendArgumentMustBe(StringBuilder& builder, unsigned argumentIndex, const char* argumentName, const char* interfaceName, const char* functionName)
+{
+ builder.appendLiteral("Argument ");
+ builder.appendNumber(argumentIndex + 1);
+ builder.appendLiteral(" ('");
+ builder.append(argumentName);
+ builder.appendLiteral("') to ");
+ if (!functionName) {
+ builder.appendLiteral("the ");
+ builder.append(interfaceName);
+ builder.appendLiteral(" constructor");
+ } else {
+ builder.append(interfaceName);
+ builder.append('.');
+ builder.append(functionName);
+ }
+ builder.appendLiteral(" must be ");
+}
+
+JSC::EncodedJSValue reportDeprecatedGetterError(JSC::ExecState& state, const char* interfaceName, const char* attributeName)
+{
+ auto& context = *jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject())->scriptExecutionContext();
+ context.addConsoleMessage(MessageSource::JS, MessageLevel::Error, makeString("Deprecated attempt to access property '", attributeName, "' on a non-", interfaceName, " object."));
+ return JSValue::encode(jsUndefined());
+}
+
+void reportDeprecatedSetterError(JSC::ExecState& state, const char* interfaceName, const char* attributeName)
+{
+ auto& context = *jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject())->scriptExecutionContext();
+ context.addConsoleMessage(MessageSource::JS, MessageLevel::Error, makeString("Deprecated attempt to set property '", attributeName, "' on a non-", interfaceName, " object."));
+}
+
+void throwNotSupportedError(JSC::ExecState& state, JSC::ThrowScope& scope)
+{
+ ASSERT(!scope.exception());
+ throwException(&state, scope, createDOMException(&state, NOT_SUPPORTED_ERR));
+}
+
+void throwNotSupportedError(JSC::ExecState& state, JSC::ThrowScope& scope, const char* message)
+{
+ ASSERT(!scope.exception());
+ String messageString(message);
+ throwException(&state, scope, createDOMException(&state, NOT_SUPPORTED_ERR, &messageString));
+}
+
+void throwInvalidStateError(JSC::ExecState& state, JSC::ThrowScope& scope, const char* message)
+{
+ ASSERT(!scope.exception());
+ String messageString(message);
+ throwException(&state, scope, createDOMException(&state, INVALID_STATE_ERR, &messageString));
+}
+
+void throwSecurityError(JSC::ExecState& state, JSC::ThrowScope& scope, const String& message)
+{
+ ASSERT(!scope.exception());
+ throwException(&state, scope, createDOMException(&state, SECURITY_ERR, message));
+}
+
+JSC::EncodedJSValue throwArgumentMustBeEnumError(JSC::ExecState& state, JSC::ThrowScope& scope, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedValues)
+{
+ StringBuilder builder;
+ appendArgumentMustBe(builder, argumentIndex, argumentName, functionInterfaceName, functionName);
+ builder.appendLiteral("one of: ");
+ builder.append(expectedValues);
+ return throwVMTypeError(&state, scope, builder.toString());
+}
+
+JSC::EncodedJSValue throwArgumentMustBeFunctionError(JSC::ExecState& state, JSC::ThrowScope& scope, unsigned argumentIndex, const char* argumentName, const char* interfaceName, const char* functionName)
+{
+ StringBuilder builder;
+ appendArgumentMustBe(builder, argumentIndex, argumentName, interfaceName, functionName);
+ builder.appendLiteral("a function");
+ return throwVMTypeError(&state, scope, builder.toString());
+}
+
+JSC::EncodedJSValue throwArgumentTypeError(JSC::ExecState& state, JSC::ThrowScope& scope, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedType)
+{
+ StringBuilder builder;
+ appendArgumentMustBe(builder, argumentIndex, argumentName, functionInterfaceName, functionName);
+ builder.appendLiteral("an instance of ");
+ builder.append(expectedType);
+ return throwVMTypeError(&state, scope, builder.toString());
+}
+
+void throwArrayElementTypeError(JSC::ExecState& state, JSC::ThrowScope& scope)
+{
+ throwTypeError(state, scope, ASCIILiteral("Invalid Array element type"));
+}
+
+void throwAttributeTypeError(JSC::ExecState& state, JSC::ThrowScope& scope, const char* interfaceName, const char* attributeName, const char* expectedType)
+{
+ throwTypeError(state, scope, makeString("The ", interfaceName, '.', attributeName, " attribute must be an instance of ", expectedType));
+}
+
+JSC::EncodedJSValue throwRequiredMemberTypeError(JSC::ExecState& state, JSC::ThrowScope& scope, const char* memberName, const char* dictionaryName, const char* expectedType)
+{
+ StringBuilder builder;
+ builder.appendLiteral("Member ");
+ builder.append(dictionaryName);
+ builder.append('.');
+ builder.append(memberName);
+ builder.appendLiteral(" is required and must be an instance of ");
+ builder.append(expectedType);
+ return throwVMTypeError(&state, scope, builder.toString());
+}
+
+JSC::EncodedJSValue throwConstructorScriptExecutionContextUnavailableError(JSC::ExecState& state, JSC::ThrowScope& scope, const char* interfaceName)
+{
+ return throwVMError(&state, scope, createReferenceError(&state, makeString(interfaceName, " constructor associated execution context is unavailable")));
+}
+
+void throwSequenceTypeError(JSC::ExecState& state, JSC::ThrowScope& scope)
+{
+ throwTypeError(state, scope, ASCIILiteral("Value is not a sequence"));
+}
+
+void throwNonFiniteTypeError(ExecState& state, JSC::ThrowScope& scope)
+{
+ throwTypeError(&state, scope, ASCIILiteral("The provided value is non-finite"));
+}
+
+String makeGetterTypeErrorMessage(const char* interfaceName, const char* attributeName)
+{
+ return makeString("The ", interfaceName, '.', attributeName, " getter can only be used on instances of ", interfaceName);
+}
+
+JSC::EncodedJSValue throwGetterTypeError(JSC::ExecState& state, JSC::ThrowScope& scope, const char* interfaceName, const char* attributeName)
+{
+ return throwVMTypeError(&state, scope, makeGetterTypeErrorMessage(interfaceName, attributeName));
+}
+
+JSC::EncodedJSValue rejectPromiseWithGetterTypeError(JSC::ExecState& state, const char* interfaceName, const char* attributeName)
+{
+ return createRejectedPromiseWithTypeError(state, makeGetterTypeErrorMessage(interfaceName, attributeName));
+}
+
+bool throwSetterTypeError(JSC::ExecState& state, JSC::ThrowScope& scope, const char* interfaceName, const char* attributeName)
+{
+ throwTypeError(state, scope, makeString("The ", interfaceName, '.', attributeName, " setter can only be used on instances of ", interfaceName));
+ return false;
+}
+
+String makeThisTypeErrorMessage(const char* interfaceName, const char* functionName)
+{
+ return makeString("Can only call ", interfaceName, '.', functionName, " on instances of ", interfaceName);
+}
+
+EncodedJSValue throwThisTypeError(JSC::ExecState& state, JSC::ThrowScope& scope, const char* interfaceName, const char* functionName)
+{
+ return throwTypeError(state, scope, makeThisTypeErrorMessage(interfaceName, functionName));
+}
+
+JSC::EncodedJSValue rejectPromiseWithThisTypeError(DeferredPromise& promise, const char* interfaceName, const char* methodName)
+{
+ promise.reject(TypeError, makeThisTypeErrorMessage(interfaceName, methodName));
+ return JSValue::encode(jsUndefined());
+}
+
+JSC::EncodedJSValue rejectPromiseWithThisTypeError(JSC::ExecState& state, const char* interfaceName, const char* methodName)
+{
+ return createRejectedPromiseWithTypeError(state, makeThisTypeErrorMessage(interfaceName, methodName));
+}
+
+void throwDOMSyntaxError(JSC::ExecState& state, JSC::ThrowScope& scope)
+{
+ ASSERT(!scope.exception());
+ throwException(&state, scope, createDOMException(&state, SYNTAX_ERR));
+}
+
+void throwDataCloneError(JSC::ExecState& state, JSC::ThrowScope& scope)
+{
+ ASSERT(!scope.exception());
+ throwException(&state, scope, createDOMException(&state, DATA_CLONE_ERR));
+}
+
+void throwIndexSizeError(JSC::ExecState& state, JSC::ThrowScope& scope)
+{
+ ASSERT(!scope.exception());
+ throwException(&state, scope, createDOMException(&state, INDEX_SIZE_ERR));
+}
+
+void throwTypeMismatchError(JSC::ExecState& state, JSC::ThrowScope& scope)
+{
+ ASSERT(!scope.exception());
+ throwException(&state, scope, createDOMException(&state, TYPE_MISMATCH_ERR));
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMExceptionHandling.h b/Source/WebCore/bindings/js/JSDOMExceptionHandling.h
new file mode 100644
index 000000000..0300213b2
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMExceptionHandling.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003-2006, 2008-2009, 2013, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
+ * Copyright (C) 2009 Google, Inc. All rights reserved.
+ * Copyright (C) 2012 Ericsson AB. All rights reserved.
+ * Copyright (C) 2013 Michael Pruett <michael@68k.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include "ExceptionCode.h"
+#include "ExceptionOr.h"
+#include <runtime/Error.h>
+
+namespace JSC {
+class CatchScope;
+}
+
+namespace WebCore {
+
+class CachedScript;
+class DeferredPromise;
+class JSDOMGlobalObject;
+
+struct ExceptionDetails {
+ String message;
+ int lineNumber { 0 };
+ int columnNumber { 0 };
+ String sourceURL;
+};
+
+WEBCORE_EXPORT JSC::EncodedJSValue reportDeprecatedGetterError(JSC::ExecState&, const char* interfaceName, const char* attributeName);
+WEBCORE_EXPORT void reportDeprecatedSetterError(JSC::ExecState&, const char* interfaceName, const char* attributeName);
+
+void throwAttributeTypeError(JSC::ExecState&, JSC::ThrowScope&, const char* interfaceName, const char* attributeName, const char* expectedType);
+WEBCORE_EXPORT bool throwSetterTypeError(JSC::ExecState&, JSC::ThrowScope&, const char* interfaceName, const char* attributeName);
+
+void throwArrayElementTypeError(JSC::ExecState&, JSC::ThrowScope&);
+void throwDataCloneError(JSC::ExecState&, JSC::ThrowScope&);
+void throwDOMSyntaxError(JSC::ExecState&, JSC::ThrowScope&); // Not the same as a JavaScript syntax error.
+void throwIndexSizeError(JSC::ExecState&, JSC::ThrowScope&);
+void throwInvalidStateError(JSC::ExecState&, JSC::ThrowScope&, const char* message);
+WEBCORE_EXPORT void throwNonFiniteTypeError(JSC::ExecState&, JSC::ThrowScope&);
+void throwNotSupportedError(JSC::ExecState&, JSC::ThrowScope&);
+void throwNotSupportedError(JSC::ExecState&, JSC::ThrowScope&, const char* message);
+void throwSecurityError(JSC::ExecState&, JSC::ThrowScope&, const String& message);
+WEBCORE_EXPORT void throwSequenceTypeError(JSC::ExecState&, JSC::ThrowScope&);
+void throwTypeMismatchError(JSC::ExecState&, JSC::ThrowScope&);
+
+WEBCORE_EXPORT JSC::EncodedJSValue throwArgumentMustBeEnumError(JSC::ExecState&, JSC::ThrowScope&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedValues);
+JSC::EncodedJSValue throwArgumentMustBeFunctionError(JSC::ExecState&, JSC::ThrowScope&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName);
+WEBCORE_EXPORT JSC::EncodedJSValue throwArgumentTypeError(JSC::ExecState&, JSC::ThrowScope&, unsigned argumentIndex, const char* argumentName, const char* functionInterfaceName, const char* functionName, const char* expectedType);
+WEBCORE_EXPORT JSC::EncodedJSValue throwRequiredMemberTypeError(JSC::ExecState&, JSC::ThrowScope&, const char* memberName, const char* dictionaryName, const char* expectedType);
+JSC::EncodedJSValue throwConstructorScriptExecutionContextUnavailableError(JSC::ExecState&, JSC::ThrowScope&, const char* interfaceName);
+
+String makeGetterTypeErrorMessage(const char* interfaceName, const char* attributeName);
+String makeThisTypeErrorMessage(const char* interfaceName, const char* attributeName);
+
+WEBCORE_EXPORT JSC::EncodedJSValue throwGetterTypeError(JSC::ExecState&, JSC::ThrowScope&, const char* interfaceName, const char* attributeName);
+WEBCORE_EXPORT JSC::EncodedJSValue throwThisTypeError(JSC::ExecState&, JSC::ThrowScope&, const char* interfaceName, const char* functionName);
+
+WEBCORE_EXPORT JSC::EncodedJSValue rejectPromiseWithGetterTypeError(JSC::ExecState&, const char* interfaceName, const char* attributeName);
+WEBCORE_EXPORT JSC::EncodedJSValue rejectPromiseWithThisTypeError(DeferredPromise&, const char* interfaceName, const char* operationName);
+WEBCORE_EXPORT JSC::EncodedJSValue rejectPromiseWithThisTypeError(JSC::ExecState&, const char* interfaceName, const char* operationName);
+
+String retrieveErrorMessage(JSC::ExecState&, JSC::VM&, JSC::JSValue exception, JSC::CatchScope&);
+WEBCORE_EXPORT void reportException(JSC::ExecState*, JSC::JSValue exception, CachedScript* = nullptr);
+WEBCORE_EXPORT void reportException(JSC::ExecState*, JSC::Exception*, CachedScript* = nullptr, ExceptionDetails* = nullptr);
+void reportCurrentException(JSC::ExecState*);
+
+JSC::JSValue createDOMException(JSC::ExecState&, Exception&&);
+JSC::JSValue createDOMException(JSC::ExecState*, ExceptionCode, const String&);
+
+// Convert a DOM implementation exception into a JavaScript exception in the execution state.
+WEBCORE_EXPORT void propagateExceptionSlowPath(JSC::ExecState&, JSC::ThrowScope&, Exception&&);
+
+ALWAYS_INLINE void propagateException(JSC::ExecState& state, JSC::ThrowScope& throwScope, Exception&& exception)
+{
+ if (throwScope.exception())
+ return;
+ propagateExceptionSlowPath(state, throwScope, WTFMove(exception));
+}
+
+inline void propagateException(JSC::ExecState& state, JSC::ThrowScope& throwScope, ExceptionOr<void>&& value)
+{
+ if (UNLIKELY(value.hasException()))
+ propagateException(state, throwScope, value.releaseException());
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMFormDataCustom.cpp b/Source/WebCore/bindings/js/JSDOMFormDataCustom.cpp
deleted file mode 100644
index 6d371b309..000000000
--- a/Source/WebCore/bindings/js/JSDOMFormDataCustom.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "JSDOMFormData.h"
-
-#include "DOMFormData.h"
-#include "HTMLFormElement.h"
-#include "JSBlob.h"
-#include "JSHTMLFormElement.h"
-#include <runtime/Error.h>
-
-using namespace JSC;
-
-namespace WebCore {
-
-static HTMLFormElement* toHTMLFormElement(JSC::JSValue value)
-{
- return value.inherits(JSHTMLFormElement::info()) ? &jsCast<JSHTMLFormElement*>(asObject(value))->impl() : 0;
-}
-
-EncodedJSValue JSC_HOST_CALL JSDOMFormDataConstructor::constructJSDOMFormData(ExecState* exec)
-{
- JSDOMFormDataConstructor* jsConstructor = jsCast<JSDOMFormDataConstructor*>(exec->callee());
-
- HTMLFormElement* form = 0;
- if (exec->argumentCount() > 0)
- form = toHTMLFormElement(exec->argument(0));
- RefPtr<DOMFormData> domFormData = DOMFormData::create(form);
- return JSValue::encode(asObject(toJS(exec, jsConstructor->globalObject(), domFormData.get())));
-}
-
-JSValue JSDOMFormData::append(ExecState* exec)
-{
- if (exec->argumentCount() >= 2) {
- String name = exec->argument(0).toString(exec)->value(exec);
- JSValue value = exec->argument(1);
- if (value.inherits(JSBlob::info())) {
- String filename;
- if (exec->argumentCount() >= 3 && !exec->argument(2).isUndefinedOrNull())
- filename = exec->argument(2).toString(exec)->value(exec);
- impl().append(name, toBlob(value), filename);
- } else
- impl().append(name, value.toString(exec)->value(exec));
- }
-
- return jsUndefined();
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp b/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp
index 27bd7894f..933650611 100644
--- a/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp
+++ b/Source/WebCore/bindings/js/JSDOMGlobalObject.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -28,23 +28,42 @@
#include "JSDOMGlobalObject.h"
#include "Document.h"
+#include "JSDOMPromise.h"
#include "JSDOMWindow.h"
#include "JSEventListener.h"
+#include "JSMediaStream.h"
+#include "JSMediaStreamTrack.h"
+#include "JSRTCIceCandidate.h"
+#include "JSRTCSessionDescription.h"
+#include "JSReadableStream.h"
+#include "JSReadableStreamPrivateConstructors.h"
#include "JSWorkerGlobalScope.h"
+#include "RuntimeEnabledFeatures.h"
+#include "StructuredClone.h"
+#include "WebCoreJSClientData.h"
#include "WorkerGlobalScope.h"
+#include <builtins/BuiltinNames.h>
using namespace JSC;
namespace WebCore {
-const ClassInfo JSDOMGlobalObject::s_info = { "DOMGlobalObject", &JSGlobalObject::s_info, 0, 0, CREATE_METHOD_TABLE(JSDOMGlobalObject) };
+EncodedJSValue JSC_HOST_CALL makeThisTypeErrorForBuiltins(ExecState*);
+EncodedJSValue JSC_HOST_CALL makeGetterTypeErrorForBuiltins(ExecState*);
-JSDOMGlobalObject::JSDOMGlobalObject(VM& vm, Structure* structure, PassRefPtr<DOMWrapperWorld> world, const GlobalObjectMethodTable* globalObjectMethodTable)
+const ClassInfo JSDOMGlobalObject::s_info = { "DOMGlobalObject", &JSGlobalObject::s_info, 0, CREATE_METHOD_TABLE(JSDOMGlobalObject) };
+
+JSDOMGlobalObject::JSDOMGlobalObject(VM& vm, Structure* structure, Ref<DOMWrapperWorld>&& world, const GlobalObjectMethodTable* globalObjectMethodTable)
: JSGlobalObject(vm, structure, globalObjectMethodTable)
, m_currentEvent(0)
- , m_world(world)
+ , m_world(WTFMove(world))
+ , m_worldIsNormal(m_world->isNormal())
+ , m_builtinInternalFunctions(vm)
+{
+}
+
+JSDOMGlobalObject::~JSDOMGlobalObject()
{
- ASSERT(m_world);
}
void JSDOMGlobalObject::destroy(JSCell* cell)
@@ -52,33 +71,118 @@ void JSDOMGlobalObject::destroy(JSCell* cell)
static_cast<JSDOMGlobalObject*>(cell)->JSDOMGlobalObject::~JSDOMGlobalObject();
}
+EncodedJSValue JSC_HOST_CALL makeThisTypeErrorForBuiltins(ExecState* execState)
+{
+ ASSERT(execState);
+ ASSERT(execState->argumentCount() == 2);
+ VM& vm = execState->vm();
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+
+ auto interfaceName = execState->uncheckedArgument(0).getString(execState);
+ ASSERT_UNUSED(scope, !scope.exception());
+ auto functionName = execState->uncheckedArgument(1).getString(execState);
+ ASSERT(!scope.exception());
+ return JSValue::encode(createTypeError(execState, makeThisTypeErrorMessage(interfaceName.utf8().data(), functionName.utf8().data())));
+}
+
+EncodedJSValue JSC_HOST_CALL makeGetterTypeErrorForBuiltins(ExecState* execState)
+{
+ ASSERT(execState);
+ ASSERT(execState->argumentCount() == 2);
+ VM& vm = execState->vm();
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+
+ auto interfaceName = execState->uncheckedArgument(0).getString(execState);
+ ASSERT_UNUSED(scope, !scope.exception());
+ auto attributeName = execState->uncheckedArgument(1).getString(execState);
+ ASSERT(!scope.exception());
+ return JSValue::encode(createTypeError(execState, makeGetterTypeErrorMessage(interfaceName.utf8().data(), attributeName.utf8().data())));
+}
+
+void JSDOMGlobalObject::addBuiltinGlobals(VM& vm)
+{
+ m_builtinInternalFunctions.initialize(*this);
+
+#if ENABLE(READABLE_STREAM_API)
+ JSObject* privateReadableStreamDefaultControllerConstructor = createReadableStreamDefaultControllerPrivateConstructor(vm, *this);
+#if ENABLE(READABLE_BYTE_STREAM_API)
+ JSObject* privateReadableByteStreamControllerConstructor = createReadableByteStreamControllerPrivateConstructor(vm, *this);
+#endif
+ JSObject* privateReadableStreamDefaultReaderConstructor = createReadableStreamDefaultReaderPrivateConstructor(vm, *this);
+
+ ASSERT(!constructors(NoLockingNecessary).get(privateReadableStreamDefaultControllerConstructor->info()).get());
+#if ENABLE(READABLE_BYTE_STREAM_API)
+ ASSERT(!constructors(NoLockingNecessary).get(privateReadableByteStreamControllerConstructor->info()).get());
+#endif
+ ASSERT(!constructors(NoLockingNecessary).get(privateReadableStreamDefaultReaderConstructor->info()).get());
+ JSC::WriteBarrier<JSC::JSObject> temp;
+ {
+ auto locker = lockDuringMarking(vm.heap, m_gcLock);
+ constructors(locker).add(privateReadableStreamDefaultControllerConstructor->info(), temp).iterator->value.set(vm, this, privateReadableStreamDefaultControllerConstructor);
+#if ENABLE(READABLE_BYTE_STREAM_API)
+ constructors(locker).add(privateReadableByteStreamControllerConstructor->info(), temp).iterator->value.set(vm, this, privateReadableByteStreamControllerConstructor);
+#endif
+ constructors(locker).add(privateReadableStreamDefaultReaderConstructor->info(), temp).iterator->value.set(vm, this, privateReadableStreamDefaultReaderConstructor);
+ }
+#endif
+ JSVMClientData& clientData = *static_cast<JSVMClientData*>(vm.clientData);
+ JSDOMGlobalObject::GlobalPropertyInfo staticGlobals[] = {
+ JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().makeThisTypeErrorPrivateName(),
+ JSFunction::create(vm, this, 2, String(), makeThisTypeErrorForBuiltins), DontDelete | ReadOnly),
+ JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().makeGetterTypeErrorPrivateName(),
+ JSFunction::create(vm, this, 2, String(), makeGetterTypeErrorForBuiltins), DontDelete | ReadOnly),
+ JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().structuredCloneArrayBufferPrivateName(),
+ JSFunction::create(vm, this, 1, String(), structuredCloneArrayBuffer), DontDelete | ReadOnly),
+ JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().structuredCloneArrayBufferViewPrivateName(),
+ JSFunction::create(vm, this, 1, String(), structuredCloneArrayBufferView), DontDelete | ReadOnly),
+ JSDOMGlobalObject::GlobalPropertyInfo(vm.propertyNames->builtinNames().ArrayBufferPrivateName(), getDirect(vm, vm.propertyNames->ArrayBuffer), DontDelete | ReadOnly),
+#if ENABLE(READABLE_STREAM_API) || ENABLE(WRITABLE_STREAM_API)
+ JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().streamClosedPrivateName(), jsNumber(1), DontDelete | ReadOnly),
+ JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().streamClosingPrivateName(), jsNumber(2), DontDelete | ReadOnly),
+ JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().streamErroredPrivateName(), jsNumber(3), DontDelete | ReadOnly),
+ JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().streamReadablePrivateName(), jsNumber(4), DontDelete | ReadOnly),
+ JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().streamWaitingPrivateName(), jsNumber(5), DontDelete | ReadOnly),
+ JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().streamWritablePrivateName(), jsNumber(6), DontDelete | ReadOnly),
+#endif
+#if ENABLE(READABLE_STREAM_API)
+ JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().ReadableStreamDefaultControllerPrivateName(), privateReadableStreamDefaultControllerConstructor, DontDelete | ReadOnly),
+#if ENABLE(READABLE_BYTE_STREAM_API)
+ JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().ReadableByteStreamControllerPrivateName(), privateReadableByteStreamControllerConstructor, DontDelete | ReadOnly),
+#endif
+ JSDOMGlobalObject::GlobalPropertyInfo(clientData.builtinNames().ReadableStreamDefaultReaderPrivateName(), privateReadableStreamDefaultReaderConstructor, DontDelete | ReadOnly),
+#endif
+ };
+ addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals));
+}
+
void JSDOMGlobalObject::finishCreation(VM& vm)
{
Base::finishCreation(vm);
- ASSERT(inherits(info()));
+ ASSERT(inherits(vm, info()));
-#if ENABLE(REMOTE_INSPECTOR)
- setRemoteDebuggingEnabled(false);
-#endif
+ addBuiltinGlobals(vm);
+
+ RELEASE_ASSERT(classInfo());
}
void JSDOMGlobalObject::finishCreation(VM& vm, JSObject* thisValue)
{
Base::finishCreation(vm, thisValue);
- ASSERT(inherits(info()));
+ ASSERT(inherits(vm, info()));
-#if ENABLE(REMOTE_INSPECTOR)
- setRemoteDebuggingEnabled(false);
-#endif
+ addBuiltinGlobals(vm);
+
+ RELEASE_ASSERT(classInfo());
}
ScriptExecutionContext* JSDOMGlobalObject::scriptExecutionContext() const
{
- if (inherits(JSDOMWindowBase::info()))
+ if (inherits(vm(), JSDOMWindowBase::info()))
return jsCast<const JSDOMWindowBase*>(this)->scriptExecutionContext();
- if (inherits(JSWorkerGlobalScopeBase::info()))
+ if (inherits(vm(), JSWorkerGlobalScopeBase::info()))
return jsCast<const JSWorkerGlobalScopeBase*>(this)->scriptExecutionContext();
- ASSERT_NOT_REACHED();
+ dataLog("Unexpected global object: ", JSValue(this), "\n");
+ RELEASE_ASSERT_NOT_REACHED();
return 0;
}
@@ -86,17 +190,22 @@ void JSDOMGlobalObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
JSDOMGlobalObject* thisObject = jsCast<JSDOMGlobalObject*>(cell);
ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
Base::visitChildren(thisObject, visitor);
-
- JSDOMStructureMap::iterator end = thisObject->structures().end();
- for (JSDOMStructureMap::iterator it = thisObject->structures().begin(); it != end; ++it)
- visitor.append(&it->value);
-
- JSDOMConstructorMap::iterator end2 = thisObject->constructors().end();
- for (JSDOMConstructorMap::iterator it2 = thisObject->constructors().begin(); it2 != end2; ++it2)
- visitor.append(&it2->value);
+
+ {
+ auto locker = holdLock(thisObject->m_gcLock);
+
+ for (auto& structure : thisObject->structures(locker).values())
+ visitor.append(structure);
+
+ for (auto& constructor : thisObject->constructors(locker).values())
+ visitor.append(constructor);
+
+ for (auto& deferredPromise : thisObject->deferredPromises(locker))
+ deferredPromise->visitAggregate(visitor);
+ }
+
+ thisObject->m_builtinInternalFunctions.visit(visitor);
}
void JSDOMGlobalObject::setCurrentEvent(Event* currentEvent)
@@ -116,14 +225,14 @@ JSDOMGlobalObject* toJSDOMGlobalObject(Document* document, JSC::ExecState* exec)
JSDOMGlobalObject* toJSDOMGlobalObject(ScriptExecutionContext* scriptExecutionContext, JSC::ExecState* exec)
{
- if (scriptExecutionContext->isDocument())
- return toJSDOMGlobalObject(toDocument(scriptExecutionContext), exec);
+ if (is<Document>(*scriptExecutionContext))
+ return toJSDOMGlobalObject(downcast<Document>(scriptExecutionContext), exec);
- if (scriptExecutionContext->isWorkerGlobalScope())
- return static_cast<WorkerGlobalScope*>(scriptExecutionContext)->script()->workerGlobalScopeWrapper();
+ if (is<WorkerGlobalScope>(*scriptExecutionContext))
+ return downcast<WorkerGlobalScope>(*scriptExecutionContext).script()->workerGlobalScopeWrapper();
ASSERT_NOT_REACHED();
- return 0;
+ return nullptr;
}
JSDOMGlobalObject* toJSDOMGlobalObject(Document* document, DOMWrapperWorld& world)
@@ -133,14 +242,14 @@ JSDOMGlobalObject* toJSDOMGlobalObject(Document* document, DOMWrapperWorld& worl
JSDOMGlobalObject* toJSDOMGlobalObject(ScriptExecutionContext* scriptExecutionContext, DOMWrapperWorld& world)
{
- if (scriptExecutionContext->isDocument())
- return toJSDOMGlobalObject(toDocument(scriptExecutionContext), world);
+ if (is<Document>(*scriptExecutionContext))
+ return toJSDOMGlobalObject(downcast<Document>(scriptExecutionContext), world);
- if (scriptExecutionContext->isWorkerGlobalScope())
- return static_cast<WorkerGlobalScope*>(scriptExecutionContext)->script()->workerGlobalScopeWrapper();
+ if (is<WorkerGlobalScope>(*scriptExecutionContext))
+ return downcast<WorkerGlobalScope>(*scriptExecutionContext).script()->workerGlobalScopeWrapper();
ASSERT_NOT_REACHED();
- return 0;
+ return nullptr;
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMGlobalObject.h b/Source/WebCore/bindings/js/JSDOMGlobalObject.h
index 6eab99967..456d953ba 100644
--- a/Source/WebCore/bindings/js/JSDOMGlobalObject.h
+++ b/Source/WebCore/bindings/js/JSDOMGlobalObject.h
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -24,15 +24,17 @@
*
*/
-#ifndef JSDOMGlobalObject_h
-#define JSDOMGlobalObject_h
+#pragma once
#include "PlatformExportMacros.h"
+#include "WebCoreJSBuiltinInternals.h"
+#include <heap/LockDuringMarking.h>
#include <runtime/JSGlobalObject.h>
-#include <runtime/Operations.h>
+#include <runtime/StructureInlines.h>
namespace WebCore {
+ class DeferredPromise;
class Document;
class Event;
class DOMWrapperWorld;
@@ -40,20 +42,25 @@ namespace WebCore {
typedef HashMap<const JSC::ClassInfo*, JSC::WriteBarrier<JSC::Structure>> JSDOMStructureMap;
typedef HashMap<const JSC::ClassInfo*, JSC::WriteBarrier<JSC::JSObject>> JSDOMConstructorMap;
+ typedef HashSet<DeferredPromise*> DeferredPromiseSet;
- class JSDOMGlobalObject : public JSC::JSGlobalObject {
+ class WEBCORE_EXPORT JSDOMGlobalObject : public JSC::JSGlobalObject {
typedef JSC::JSGlobalObject Base;
protected:
struct JSDOMGlobalObjectData;
- JSDOMGlobalObject(JSC::VM&, JSC::Structure*, PassRefPtr<DOMWrapperWorld>, const JSC::GlobalObjectMethodTable* = 0);
+ JSDOMGlobalObject(JSC::VM&, JSC::Structure*, Ref<DOMWrapperWorld>&&, const JSC::GlobalObjectMethodTable* = 0);
static void destroy(JSC::JSCell*);
void finishCreation(JSC::VM&);
void finishCreation(JSC::VM&, JSC::JSObject*);
public:
- JSDOMStructureMap& structures() { return m_structures; }
- JSDOMConstructorMap& constructors() { return m_constructors; }
+ Lock& gcLock() { return m_gcLock; }
+
+ JSDOMStructureMap& structures(const AbstractLocker&) { return m_structures; }
+ JSDOMConstructorMap& constructors(const AbstractLocker&) { return m_constructors; }
+
+ DeferredPromiseSet& deferredPromises(const AbstractLocker&) { return m_deferredPromises; }
ScriptExecutionContext* scriptExecutionContext() const;
@@ -65,13 +72,19 @@ namespace WebCore {
static void visitChildren(JSC::JSCell*, JSC::SlotVisitor&);
- DOMWrapperWorld& world() { return *m_world; }
+ DOMWrapperWorld& world() { return m_world.get(); }
+ bool worldIsNormal() const { return m_worldIsNormal; }
+ static ptrdiff_t offsetOfWorldIsNormal() { return OBJECT_OFFSETOF(JSDOMGlobalObject, m_worldIsNormal); }
+
+ JSBuiltinInternalFunctions& builtinInternalFunctions() { return m_builtinInternalFunctions; }
protected:
- static WEBKIT_EXPORTDATA const JSC::ClassInfo s_info;
+ static const JSC::ClassInfo s_info;
public:
- static const JSC::ClassInfo* info() { return &s_info; }
+ ~JSDOMGlobalObject();
+
+ static constexpr const JSC::ClassInfo* info() { return &s_info; }
static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSValue prototype)
{
@@ -81,20 +94,31 @@ namespace WebCore {
protected:
JSDOMStructureMap m_structures;
JSDOMConstructorMap m_constructors;
+ DeferredPromiseSet m_deferredPromises;
Event* m_currentEvent;
- RefPtr<DOMWrapperWorld> m_world;
+ Ref<DOMWrapperWorld> m_world;
+ uint8_t m_worldIsNormal;
+ Lock m_gcLock;
+
+ private:
+ void addBuiltinGlobals(JSC::VM&);
+ friend void JSBuiltinInternalFunctions::initialize(JSDOMGlobalObject&);
+
+ JSBuiltinInternalFunctions m_builtinInternalFunctions;
};
template<class ConstructorClass>
- inline JSC::JSObject* getDOMConstructor(JSC::VM& vm, const JSDOMGlobalObject* globalObject)
+ inline JSC::JSObject* getDOMConstructor(JSC::VM& vm, const JSDOMGlobalObject& globalObject)
{
- if (JSC::JSObject* constructor = const_cast<JSDOMGlobalObject*>(globalObject)->constructors().get(ConstructorClass::info()).get())
+ if (JSC::JSObject* constructor = const_cast<JSDOMGlobalObject&>(globalObject).constructors(NoLockingNecessary).get(ConstructorClass::info()).get())
return constructor;
- JSC::JSObject* constructor = ConstructorClass::create(vm, ConstructorClass::createStructure(vm, const_cast<JSDOMGlobalObject*>(globalObject), globalObject->objectPrototype()), const_cast<JSDOMGlobalObject*>(globalObject));
- ASSERT(!const_cast<JSDOMGlobalObject*>(globalObject)->constructors().contains(ConstructorClass::info()));
+ JSC::JSObject* constructor = ConstructorClass::create(vm, ConstructorClass::createStructure(vm, const_cast<JSDOMGlobalObject&>(globalObject), ConstructorClass::prototypeForStructure(vm, globalObject)), const_cast<JSDOMGlobalObject&>(globalObject));
+ ASSERT(!const_cast<JSDOMGlobalObject&>(globalObject).constructors(NoLockingNecessary).contains(ConstructorClass::info()));
JSC::WriteBarrier<JSC::JSObject> temp;
- const_cast<JSDOMGlobalObject*>(globalObject)->constructors().add(ConstructorClass::info(), temp).iterator->value.set(vm, globalObject, constructor);
+ JSDOMGlobalObject& mutableGlobalObject = const_cast<JSDOMGlobalObject&>(globalObject);
+ auto locker = JSC::lockDuringMarking(vm.heap, mutableGlobalObject.gcLock());
+ mutableGlobalObject.constructors(locker).add(ConstructorClass::info(), temp).iterator->value.set(vm, &globalObject, constructor);
return constructor;
}
@@ -105,5 +129,3 @@ namespace WebCore {
JSDOMGlobalObject* toJSDOMGlobalObject(ScriptExecutionContext*, DOMWrapperWorld&);
} // namespace WebCore
-
-#endif // JSDOMGlobalObject_h
diff --git a/Source/WebCore/bindings/js/JSDOMGlobalObjectTask.cpp b/Source/WebCore/bindings/js/JSDOMGlobalObjectTask.cpp
index 847dbd164..0be269683 100644
--- a/Source/WebCore/bindings/js/JSDOMGlobalObjectTask.cpp
+++ b/Source/WebCore/bindings/js/JSDOMGlobalObjectTask.cpp
@@ -38,9 +38,9 @@ namespace WebCore {
class JSGlobalObjectCallback final : public RefCounted<JSGlobalObjectCallback>, private ActiveDOMCallback {
public:
- static PassRefPtr<JSGlobalObjectCallback> create(JSDOMGlobalObject* globalObject, PassRefPtr<Microtask> task)
+ static Ref<JSGlobalObjectCallback> create(JSDOMGlobalObject* globalObject, Ref<Microtask>&& task)
{
- return adoptRef(new JSGlobalObjectCallback(globalObject, task));
+ return adoptRef(*new JSGlobalObjectCallback(globalObject, WTFMove(task)));
}
void call()
@@ -48,8 +48,10 @@ public:
if (!canInvokeCallback())
return;
- Ref<JSGlobalObjectCallback> protect(*this);
- JSLockHolder lock(m_globalObject->vm());
+ Ref<JSGlobalObjectCallback> protectedThis(*this);
+ VM& vm = m_globalObject->vm();
+ JSLockHolder lock(vm);
+ auto scope = DECLARE_THROW_SCOPE(vm);
ExecState* exec = m_globalObject->globalExec();
@@ -60,37 +62,32 @@ public:
// When on the main thread (e.g. the document's thread), we need to make sure to
// push the current ExecState on to the JSMainThreadExecState stack.
- if (context->isDocument()) {
- JSMainThreadExecState currentState(exec);
- m_task->run(exec);
- } else
+ if (context->isDocument())
+ JSMainThreadExecState::runTask(exec, m_task);
+ else
m_task->run(exec);
+ ASSERT_UNUSED(scope, !scope.exception());
}
private:
- JSGlobalObjectCallback(JSDOMGlobalObject* globalObject, PassRefPtr<Microtask> task)
+ JSGlobalObjectCallback(JSDOMGlobalObject* globalObject, Ref<Microtask>&& task)
: ActiveDOMCallback(globalObject->scriptExecutionContext())
, m_globalObject(globalObject->vm(), globalObject)
- , m_task(task)
+ , m_task(WTFMove(task))
{
}
Strong<JSDOMGlobalObject> m_globalObject;
- RefPtr<Microtask> m_task;
+ Ref<Microtask> m_task;
};
-JSGlobalObjectTask::JSGlobalObjectTask(JSDOMGlobalObject* globalObject, PassRefPtr<Microtask> task)
- : m_callback(JSGlobalObjectCallback::create(globalObject, task))
-{
-}
-
-JSGlobalObjectTask::~JSGlobalObjectTask()
-{
-}
-
-void JSGlobalObjectTask::performTask(ScriptExecutionContext*)
+JSGlobalObjectTask::JSGlobalObjectTask(JSDOMGlobalObject* globalObject, Ref<Microtask>&& task)
+ : ScriptExecutionContext::Task({ })
{
- m_callback->call();
+ RefPtr<JSGlobalObjectCallback> callback = JSGlobalObjectCallback::create(globalObject, WTFMove(task));
+ m_task = [callback] (ScriptExecutionContext&) {
+ callback->call();
+ };
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMGlobalObjectTask.h b/Source/WebCore/bindings/js/JSDOMGlobalObjectTask.h
index 3cb93f311..cc0ffb0e1 100644
--- a/Source/WebCore/bindings/js/JSDOMGlobalObjectTask.h
+++ b/Source/WebCore/bindings/js/JSDOMGlobalObjectTask.h
@@ -23,33 +23,16 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSDOMGlobalObjectTask_h
-#define JSDOMGlobalObjectTask_h
+#pragma once
#include "JSDOMGlobalObject.h"
#include "ScriptExecutionContext.h"
namespace WebCore {
-class JSGlobalObjectCallback;
-
-class JSGlobalObjectTask final : public ScriptExecutionContext::Task {
+class JSGlobalObjectTask : public ScriptExecutionContext::Task {
public:
- static PassOwnPtr<JSGlobalObjectTask> create(JSDOMGlobalObject* globalObject, PassRefPtr<JSC::Microtask> task)
- {
- return adoptPtr(new JSGlobalObjectTask(globalObject, task));
- }
-
- virtual ~JSGlobalObjectTask();
-
-private:
- JSGlobalObjectTask(JSDOMGlobalObject*, PassRefPtr<JSC::Microtask>);
-
- virtual void performTask(ScriptExecutionContext*) override;
-
- RefPtr<JSGlobalObjectCallback> m_callback;
+ JSGlobalObjectTask(JSDOMGlobalObject*, Ref<JSC::Microtask>&&);
};
} // namespace WebCore
-
-#endif // JSDOMGlobalObjectTask_h
diff --git a/Source/WebCore/bindings/js/JSDOMIterator.cpp b/Source/WebCore/bindings/js/JSDOMIterator.cpp
new file mode 100644
index 000000000..45ef3a755
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMIterator.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 Apple, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSDOMIterator.h"
+
+#include <builtins/BuiltinNames.h>
+#include <runtime/ArrayPrototype.h>
+
+namespace WebCore {
+
+void addValueIterableMethods(JSC::JSGlobalObject& globalObject, JSC::JSObject& prototype)
+{
+ JSC::ArrayPrototype* arrayPrototype = globalObject.arrayPrototype();
+ ASSERT(arrayPrototype);
+
+ JSC::ExecState* state = globalObject.globalExec();
+ ASSERT(state);
+ JSC::VM& vm = state->vm();
+
+ auto copyProperty = [&] (const JSC::Identifier& arrayIdentifier, const JSC::Identifier& otherIdentifier, unsigned attributes = 0) {
+ JSC::JSValue value = arrayPrototype->getDirect(vm, arrayIdentifier);
+ ASSERT(value);
+ prototype.putDirect(vm, otherIdentifier, value, attributes);
+ };
+
+ copyProperty(vm.propertyNames->builtinNames().entriesPrivateName(), vm.propertyNames->builtinNames().entriesPublicName());
+ copyProperty(vm.propertyNames->builtinNames().forEachPrivateName(), vm.propertyNames->builtinNames().forEachPublicName());
+ copyProperty(vm.propertyNames->builtinNames().keysPrivateName(), vm.propertyNames->builtinNames().keysPublicName());
+ copyProperty(vm.propertyNames->builtinNames().valuesPrivateName(), vm.propertyNames->builtinNames().valuesPublicName());
+ copyProperty(vm.propertyNames->builtinNames().valuesPrivateName(), vm.propertyNames->builtinNames().iteratorSymbol(), JSC::DontEnum);
+}
+
+}
diff --git a/Source/WebCore/bindings/js/JSDOMIterator.h b/Source/WebCore/bindings/js/JSDOMIterator.h
new file mode 100644
index 000000000..101749ab9
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMIterator.h
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 2016 Canon, Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CANON INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL CANON INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "JSDOMConvert.h"
+#include <runtime/IteratorPrototype.h>
+#include <runtime/JSDestructibleObject.h>
+#include <type_traits>
+
+namespace WebCore {
+
+void addValueIterableMethods(JSC::JSGlobalObject&, JSC::JSObject&);
+
+enum class JSDOMIteratorType { Set, Map };
+
+// struct IteratorTraits {
+// static constexpr JSDOMIteratorType type = [Map|Set];
+// using KeyType = [IDLType|void];
+// using ValueType = [IDLType];
+// };
+
+template<typename T, typename U = void> using EnableIfMap = typename std::enable_if<T::type == JSDOMIteratorType::Map, U>::type;
+template<typename T, typename U = void> using EnableIfSet = typename std::enable_if<T::type == JSDOMIteratorType::Set, U>::type;
+
+template<typename JSWrapper, typename IteratorTraits> class JSDOMIteratorPrototype : public JSC::JSNonFinalObject {
+public:
+ using Base = JSC::JSNonFinalObject;
+ using DOMWrapped = typename JSWrapper::DOMWrapped;
+
+ static JSDOMIteratorPrototype* create(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::Structure* structure)
+ {
+ JSDOMIteratorPrototype* prototype = new (NotNull, JSC::allocateCell<JSDOMIteratorPrototype>(vm.heap)) JSDOMIteratorPrototype(vm, structure);
+ prototype->finishCreation(vm, globalObject);
+ return prototype;
+ }
+
+ DECLARE_INFO;
+
+ static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+ {
+ return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+ }
+
+ static JSC::EncodedJSValue JSC_HOST_CALL next(JSC::ExecState*);
+
+private:
+ JSDOMIteratorPrototype(JSC::VM& vm, JSC::Structure* structure) : Base(vm, structure) { }
+
+ void finishCreation(JSC::VM&, JSC::JSGlobalObject*);
+};
+
+enum class IterationKind { Key, Value, KeyValue };
+
+template<typename JSWrapper, typename IteratorTraits> class JSDOMIterator : public JSDOMObject {
+public:
+ using Base = JSDOMObject;
+
+ using Wrapper = JSWrapper;
+ using Traits = IteratorTraits;
+
+ using DOMWrapped = typename Wrapper::DOMWrapped;
+ using Prototype = JSDOMIteratorPrototype<Wrapper, Traits>;
+
+ DECLARE_INFO;
+
+ static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+ {
+ return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+ }
+
+ static JSDOMIterator* create(JSC::VM& vm, JSC::Structure* structure, JSWrapper& iteratedObject, IterationKind kind)
+ {
+ JSDOMIterator* instance = new (NotNull, JSC::allocateCell<JSDOMIterator>(vm.heap)) JSDOMIterator(structure, iteratedObject, kind);
+ instance->finishCreation(vm);
+ return instance;
+ }
+
+ static Prototype* createPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
+ {
+ return Prototype::create(vm, globalObject, Prototype::createStructure(vm, globalObject, globalObject->iteratorPrototype()));
+ }
+
+ JSC::JSValue next(JSC::ExecState&);
+
+private:
+ JSDOMIterator(JSC::Structure* structure, JSWrapper& iteratedObject, IterationKind kind)
+ : Base(structure, *iteratedObject.globalObject())
+ , m_iterator(iteratedObject.wrapped().createIterator())
+ , m_kind(kind)
+ {
+ }
+
+ template<typename IteratorValue, typename T = Traits> EnableIfMap<T, JSC::JSValue> asJS(JSC::ExecState&, IteratorValue&);
+ template<typename IteratorValue, typename T = Traits> EnableIfSet<T, JSC::JSValue> asJS(JSC::ExecState&, IteratorValue&);
+
+ static void destroy(JSC::JSCell*);
+
+ std::optional<typename DOMWrapped::Iterator> m_iterator;
+ IterationKind m_kind;
+};
+
+inline JSC::JSValue jsPair(JSC::ExecState& state, JSDOMGlobalObject& globalObject, JSC::JSValue value1, JSC::JSValue value2)
+{
+ JSC::MarkedArgumentBuffer arguments;
+ arguments.append(value1);
+ arguments.append(value2);
+ return constructArray(&state, nullptr, &globalObject, arguments);
+}
+
+template<typename FirstType, typename SecondType, typename T, typename U>
+inline JSC::JSValue jsPair(JSC::ExecState& state, JSDOMGlobalObject& globalObject, const T& value1, const U& value2)
+{
+ return jsPair(state, globalObject, toJS<FirstType>(state, globalObject, value1), toJS<SecondType>(state, globalObject, value2));
+}
+
+template<typename JSIterator> JSC::JSValue iteratorCreate(typename JSIterator::Wrapper&, IterationKind);
+template<typename JSIterator> JSC::JSValue iteratorForEach(JSC::ExecState&, typename JSIterator::Wrapper&, JSC::ThrowScope&);
+
+template<typename JSIterator> JSC::JSValue iteratorCreate(typename JSIterator::Wrapper& thisObject, IterationKind kind)
+{
+ ASSERT(thisObject.globalObject());
+ JSDOMGlobalObject& globalObject = *thisObject.globalObject();
+ return JSIterator::create(globalObject.vm(), getDOMStructure<JSIterator>(globalObject.vm(), globalObject), thisObject, kind);
+}
+
+template<typename JSWrapper, typename IteratorTraits>
+template<typename IteratorValue, typename T> inline EnableIfMap<T, JSC::JSValue> JSDOMIterator<JSWrapper, IteratorTraits>::asJS(JSC::ExecState& state, IteratorValue& value)
+{
+ ASSERT(value);
+
+ switch (m_kind) {
+ case IterationKind::Key:
+ return toJS<typename Traits::KeyType>(state, *globalObject(), value->key);
+ case IterationKind::Value:
+ return toJS<typename Traits::ValueType>(state, *globalObject(), value->value);
+ case IterationKind::KeyValue:
+ return jsPair<typename Traits::KeyType, typename Traits::ValueType>(state, *globalObject(), value->key, value->value);
+ };
+
+ ASSERT_NOT_REACHED();
+ return { };
+}
+
+template<typename JSWrapper, typename IteratorTraits>
+template<typename IteratorValue, typename T> inline EnableIfSet<T, JSC::JSValue> JSDOMIterator<JSWrapper, IteratorTraits>::asJS(JSC::ExecState& state, IteratorValue& value)
+{
+ ASSERT(value);
+
+ auto globalObject = this->globalObject();
+ auto result = toJS<typename Traits::ValueType>(state, *globalObject, value);
+
+ switch (m_kind) {
+ case IterationKind::Key:
+ case IterationKind::Value:
+ return result;
+ case IterationKind::KeyValue:
+ return jsPair(state, *globalObject, result, result);
+ };
+
+ ASSERT_NOT_REACHED();
+ return { };
+}
+
+template<typename JSIterator, typename IteratorValue> EnableIfMap<typename JSIterator::Traits> appendForEachArguments(JSC::ExecState& state, JSDOMGlobalObject& globalObject, JSC::MarkedArgumentBuffer& arguments, IteratorValue& value)
+{
+ ASSERT(value);
+ arguments.append(toJS<typename JSIterator::Traits::ValueType>(state, globalObject, value->value));
+ arguments.append(toJS<typename JSIterator::Traits::KeyType>(state, globalObject, value->key));
+}
+
+template<typename JSIterator, typename IteratorValue> EnableIfSet<typename JSIterator::Traits> appendForEachArguments(JSC::ExecState& state, JSDOMGlobalObject& globalObject, JSC::MarkedArgumentBuffer& arguments, IteratorValue& value)
+{
+ ASSERT(value);
+ auto argument = toJS<typename JSIterator::Traits::ValueType>(state, globalObject, value);
+ arguments.append(argument);
+ arguments.append(argument);
+}
+
+template<typename JSIterator> JSC::JSValue iteratorForEach(JSC::ExecState& state, typename JSIterator::Wrapper& thisObject, JSC::ThrowScope& scope)
+{
+ JSC::JSValue callback = state.argument(0);
+ JSC::JSValue thisValue = state.argument(1);
+
+ JSC::CallData callData;
+ JSC::CallType callType = JSC::getCallData(callback, callData);
+ if (callType == JSC::CallType::None)
+ return throwTypeError(&state, scope, ASCIILiteral("Cannot call callback"));
+
+ auto iterator = thisObject.wrapped().createIterator();
+ while (auto value = iterator.next()) {
+ JSC::MarkedArgumentBuffer arguments;
+ appendForEachArguments<JSIterator>(state, *thisObject.globalObject(), arguments, value);
+ arguments.append(&thisObject);
+ JSC::call(&state, callback, callType, callData, thisValue, arguments);
+ if (UNLIKELY(scope.exception()))
+ break;
+ }
+ return JSC::jsUndefined();
+}
+
+template<typename JSWrapper, typename IteratorTraits>
+void JSDOMIterator<JSWrapper, IteratorTraits>::destroy(JSCell* cell)
+{
+ JSDOMIterator<JSWrapper, IteratorTraits>* thisObject = static_cast<JSDOMIterator<JSWrapper, IteratorTraits>*>(cell);
+ thisObject->JSDOMIterator<JSWrapper, IteratorTraits>::~JSDOMIterator();
+}
+
+template<typename JSWrapper, typename IteratorTraits>
+JSC::JSValue JSDOMIterator<JSWrapper, IteratorTraits>::next(JSC::ExecState& state)
+{
+ if (m_iterator) {
+ auto iteratorValue = m_iterator->next();
+ if (iteratorValue)
+ return createIteratorResultObject(&state, asJS(state, iteratorValue), false);
+ m_iterator = std::nullopt;
+ }
+ return createIteratorResultObject(&state, JSC::jsUndefined(), true);
+}
+
+template<typename JSWrapper, typename IteratorTraits>
+JSC::EncodedJSValue JSC_HOST_CALL JSDOMIteratorPrototype<JSWrapper, IteratorTraits>::next(JSC::ExecState* state)
+{
+ JSC::VM& vm = state->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto iterator = jsDynamicDowncast<JSDOMIterator<JSWrapper, IteratorTraits>*>(vm, state->thisValue());
+ if (!iterator)
+ return JSC::JSValue::encode(throwTypeError(state, scope, ASCIILiteral("Cannot call next() on a non-Iterator object")));
+
+ return JSC::JSValue::encode(iterator->next(*state));
+}
+
+template<typename JSWrapper, typename IteratorTraits>
+void JSDOMIteratorPrototype<JSWrapper, IteratorTraits>::finishCreation(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
+{
+ Base::finishCreation(vm);
+ ASSERT(inherits(vm, info()));
+
+ JSC_NATIVE_INTRINSIC_FUNCTION_WITHOUT_TRANSITION(vm.propertyNames->next, next, 0, 0, JSC::NoIntrinsic);
+}
+
+}
diff --git a/Source/WebCore/bindings/js/JSDOMMimeTypeArrayCustom.cpp b/Source/WebCore/bindings/js/JSDOMMimeTypeArrayCustom.cpp
deleted file mode 100644
index e1c910590..000000000
--- a/Source/WebCore/bindings/js/JSDOMMimeTypeArrayCustom.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "config.h"
-#include "JSDOMMimeTypeArray.h"
-
-#include "DOMMimeTypeArray.h"
-#include "JSDOMMimeType.h"
-#include <wtf/text/AtomicString.h>
-
-namespace WebCore {
-
-using namespace JSC;
-
-bool JSDOMMimeTypeArray::canGetItemsForName(ExecState*, DOMMimeTypeArray* mimeTypeArray, PropertyName propertyName)
-{
- return mimeTypeArray->canGetItemsForName(propertyNameToAtomicString(propertyName));
-}
-
-EncodedJSValue JSDOMMimeTypeArray::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName)
-{
- JSDOMMimeTypeArray* thisObj = jsDynamicCast<JSDOMMimeTypeArray*>(JSValue::decode(slotBase));
- if (!thisObj)
- return throwVMTypeError(exec);
- return JSValue::encode(toJS(exec, thisObj->globalObject(), thisObj->impl().namedItem(propertyNameToAtomicString(propertyName))));
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMNamedConstructor.h b/Source/WebCore/bindings/js/JSDOMNamedConstructor.h
new file mode 100644
index 000000000..265e6d3e3
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMNamedConstructor.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2015, 2016 Canon Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include "JSDOMConstructorWithDocument.h"
+
+namespace WebCore {
+
+// FIMXE: Why can't named constructors be used with workers?
+template<typename JSClass> class JSDOMNamedConstructor : public JSDOMConstructorWithDocument {
+public:
+ using Base = JSDOMConstructorWithDocument;
+
+ static JSDOMNamedConstructor* create(JSC::VM&, JSC::Structure*, JSDOMGlobalObject&);
+ static JSC::Structure* createStructure(JSC::VM&, JSC::JSGlobalObject&, JSC::JSValue prototype);
+
+ DECLARE_INFO;
+
+ // Must be defined for each specialization class.
+ static JSC::JSValue prototypeForStructure(JSC::VM&, const JSDOMGlobalObject&);
+
+private:
+ JSDOMNamedConstructor(JSC::Structure* structure, JSDOMGlobalObject& globalObject)
+ : Base(structure, globalObject)
+ {
+ }
+
+ void finishCreation(JSC::VM&, JSDOMGlobalObject&);
+ static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&);
+
+ // Usually defined for each specialization class.
+ void initializeProperties(JSC::VM&, JSDOMGlobalObject&) { }
+ // Must be defined for each specialization class.
+ static JSC::EncodedJSValue JSC_HOST_CALL construct(JSC::ExecState*);
+};
+
+template<typename JSClass> inline JSDOMNamedConstructor<JSClass>* JSDOMNamedConstructor<JSClass>::create(JSC::VM& vm, JSC::Structure* structure, JSDOMGlobalObject& globalObject)
+{
+ JSDOMNamedConstructor* constructor = new (NotNull, JSC::allocateCell<JSDOMNamedConstructor>(vm.heap)) JSDOMNamedConstructor(structure, globalObject);
+ constructor->finishCreation(vm, globalObject);
+ return constructor;
+}
+
+template<typename JSClass> inline JSC::Structure* JSDOMNamedConstructor<JSClass>::createStructure(JSC::VM& vm, JSC::JSGlobalObject& globalObject, JSC::JSValue prototype)
+{
+ return JSC::Structure::create(vm, &globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+}
+
+template<typename JSClass> inline void JSDOMNamedConstructor<JSClass>::finishCreation(JSC::VM& vm, JSDOMGlobalObject& globalObject)
+{
+ Base::finishCreation(globalObject);
+ ASSERT(inherits(vm, info()));
+ initializeProperties(vm, globalObject);
+}
+
+template<typename JSClass> inline JSC::ConstructType JSDOMNamedConstructor<JSClass>::getConstructData(JSC::JSCell*, JSC::ConstructData& constructData)
+{
+ constructData.native.function = construct;
+ return JSC::ConstructType::Host;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMPluginArrayCustom.cpp b/Source/WebCore/bindings/js/JSDOMPluginArrayCustom.cpp
deleted file mode 100644
index 807f63afe..000000000
--- a/Source/WebCore/bindings/js/JSDOMPluginArrayCustom.cpp
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "config.h"
-#include "JSDOMPluginArray.h"
-
-#include "DOMPluginArray.h"
-#include "JSDOMPlugin.h"
-#include <wtf/text/AtomicString.h>
-
-namespace WebCore {
-
-using namespace JSC;
-
-bool JSDOMPluginArray::canGetItemsForName(ExecState*, DOMPluginArray* pluginArray, PropertyName propertyName)
-{
- return pluginArray->canGetItemsForName(propertyNameToAtomicString(propertyName));
-}
-
-EncodedJSValue JSDOMPluginArray::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName)
-{
- JSDOMPluginArray* thisObj = jsCast<JSDOMPluginArray*>(JSValue::decode(slotBase));
- return JSValue::encode(toJS(exec, thisObj->globalObject(), thisObj->impl().namedItem(propertyNameToAtomicString(propertyName))));
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMPromise.cpp b/Source/WebCore/bindings/js/JSDOMPromise.cpp
index fa5aa95b9..188d20fef 100644
--- a/Source/WebCore/bindings/js/JSDOMPromise.cpp
+++ b/Source/WebCore/bindings/js/JSDOMPromise.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,47 +26,200 @@
#include "config.h"
#include "JSDOMPromise.h"
+#include "ExceptionCode.h"
+#include "JSDOMError.h"
+#include "JSDOMWindow.h"
+#include <builtins/BuiltinNames.h>
+#include <runtime/Exception.h>
+#include <runtime/JSONObject.h>
+#include <runtime/JSPromiseConstructor.h>
+
using namespace JSC;
namespace WebCore {
-DeferredWrapper::DeferredWrapper(ExecState* exec, JSDOMGlobalObject* globalObject)
- : m_globalObject(exec->vm(), globalObject)
- , m_deferred(exec->vm(), JSPromiseDeferred::create(exec, globalObject))
+DeferredPromise::DeferredPromise(JSDOMGlobalObject& globalObject, JSPromiseDeferred& promiseDeferred)
+ : ActiveDOMCallback(globalObject.scriptExecutionContext())
+ , m_deferred(&promiseDeferred)
+ , m_globalObject(&globalObject)
+{
+ auto locker = lockDuringMarking(globalObject.vm().heap, globalObject.gcLock());
+ globalObject.vm().heap.writeBarrier(&globalObject, &promiseDeferred);
+ globalObject.deferredPromises(locker).add(this);
+}
+
+DeferredPromise::~DeferredPromise()
+{
+ clear();
+}
+
+void DeferredPromise::clear()
{
+ ASSERT(!m_deferred || m_globalObject);
+ if (m_deferred && m_globalObject) {
+ auto locker = lockDuringMarking(m_globalObject->vm().heap, m_globalObject->gcLock());
+ m_globalObject->deferredPromises(locker).remove(this);
+ }
+ m_deferred.clear();
}
-JSObject* DeferredWrapper::promise() const
+void DeferredPromise::contextDestroyed()
{
+ ActiveDOMCallback::contextDestroyed();
+ clear();
+}
+
+JSC::JSValue DeferredPromise::promise() const
+{
+ ASSERT(m_deferred);
return m_deferred->promise();
}
-void DeferredWrapper::resolve(ExecState* exec, JSValue resolution)
+void DeferredPromise::callFunction(ExecState& exec, JSValue function, JSValue resolution)
{
- JSValue deferredResolve = m_deferred->resolve();
+ if (!canInvokeCallback())
+ return;
- CallData resolveCallData;
- CallType resolveCallType = getCallData(deferredResolve, resolveCallData);
- ASSERT(resolveCallType != CallTypeNone);
+ CallData callData;
+ CallType callType = getCallData(function, callData);
+ ASSERT(callType != CallType::None);
MarkedArgumentBuffer arguments;
arguments.append(resolution);
- call(exec, deferredResolve, resolveCallType, resolveCallData, jsUndefined(), arguments);
+ call(&exec, function, callType, callData, jsUndefined(), arguments);
+
+ clear();
}
-void DeferredWrapper::reject(ExecState* exec, JSValue reason)
+void DeferredPromise::reject()
{
- JSValue deferredReject = m_deferred->reject();
+ if (isSuspended())
+ return;
- CallData rejectCallData;
- CallType rejectCallType = getCallData(deferredReject, rejectCallData);
- ASSERT(rejectCallType != CallTypeNone);
+ ASSERT(m_deferred);
+ ASSERT(m_globalObject);
+ auto& state = *m_globalObject->globalExec();
+ JSC::JSLockHolder locker(&state);
+ reject(state, JSC::jsUndefined());
+}
+
+void DeferredPromise::reject(std::nullptr_t)
+{
+ if (isSuspended())
+ return;
+
+ ASSERT(m_deferred);
+ ASSERT(m_globalObject);
+ auto& state = *m_globalObject->globalExec();
+ JSC::JSLockHolder locker(&state);
+ reject(state, JSC::jsNull());
+}
+
+void DeferredPromise::reject(Exception&& exception)
+{
+ if (isSuspended())
+ return;
+
+ ASSERT(m_deferred);
+ ASSERT(m_globalObject);
+ auto& state = *m_globalObject->globalExec();
+ JSC::JSLockHolder locker(&state);
+ reject(state, createDOMException(state, WTFMove(exception)));
+}
+
+void DeferredPromise::reject(ExceptionCode ec, const String& message)
+{
+ if (isSuspended())
+ return;
+
+ ASSERT(m_deferred);
+ ASSERT(m_globalObject);
+ JSC::ExecState* state = m_globalObject->globalExec();
+ JSC::JSLockHolder locker(state);
+ reject(*state, createDOMException(state, ec, message));
+}
+
+void DeferredPromise::reject(const JSC::PrivateName& privateName)
+{
+ if (isSuspended())
+ return;
+
+ ASSERT(m_deferred);
+ ASSERT(m_globalObject);
+ JSC::ExecState* state = m_globalObject->globalExec();
+ JSC::JSLockHolder locker(state);
+ reject(*state, JSC::Symbol::create(state->vm(), privateName.uid()));
+}
+
+void rejectPromiseWithExceptionIfAny(JSC::ExecState& state, JSDOMGlobalObject& globalObject, JSPromiseDeferred& promiseDeferred)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+
+ if (LIKELY(!scope.exception()))
+ return;
+
+ JSValue error = scope.exception()->value();
+ scope.clearException();
+
+ DeferredPromise::create(globalObject, promiseDeferred)->reject<IDLAny>(error);
+}
+
+Ref<DeferredPromise> createDeferredPromise(JSC::ExecState& state, JSDOMWindow& domWindow)
+{
+ JSC::JSPromiseDeferred* deferred = JSC::JSPromiseDeferred::create(&state, &domWindow);
+ // deferred can only be null in workers.
+ ASSERT(deferred);
+ return DeferredPromise::create(domWindow, *deferred);
+}
+
+JSC::EncodedJSValue createRejectedPromiseWithTypeError(JSC::ExecState& state, const String& errorMessage)
+{
+ ASSERT(state.lexicalGlobalObject());
+ auto& globalObject = *state.lexicalGlobalObject();
+
+ auto promiseConstructor = globalObject.promiseConstructor();
+ auto rejectFunction = promiseConstructor->get(&state, state.vm().propertyNames->builtinNames().rejectPrivateName());
+ auto rejectionValue = createTypeError(&state, errorMessage);
+
+ CallData callData;
+ auto callType = getCallData(rejectFunction, callData);
+ ASSERT(callType != CallType::None);
MarkedArgumentBuffer arguments;
- arguments.append(reason);
+ arguments.append(rejectionValue);
+
+ return JSValue::encode(call(&state, rejectFunction, callType, callData, promiseConstructor, arguments));
+}
- call(exec, deferredReject, rejectCallType, rejectCallData, jsUndefined(), arguments);
+static inline JSC::JSValue parseAsJSON(JSC::ExecState* state, const String& data)
+{
+ JSC::JSLockHolder lock(state);
+ return JSC::JSONParse(state, data);
+}
+
+void fulfillPromiseWithJSON(Ref<DeferredPromise>&& promise, const String& data)
+{
+ JSC::JSValue value = parseAsJSON(promise->globalObject()->globalExec(), data);
+ if (!value)
+ promise->reject(SYNTAX_ERR);
+ else
+ promise->resolve<IDLAny>(value);
+}
+
+void fulfillPromiseWithArrayBuffer(Ref<DeferredPromise>&& promise, ArrayBuffer* arrayBuffer)
+{
+ if (!arrayBuffer) {
+ promise->reject<IDLAny>(createOutOfMemoryError(promise->globalObject()->globalExec()));
+ return;
+ }
+ promise->resolve<IDLInterface<ArrayBuffer>>(*arrayBuffer);
+}
+
+void fulfillPromiseWithArrayBuffer(Ref<DeferredPromise>&& promise, const void* data, size_t length)
+{
+ fulfillPromiseWithArrayBuffer(WTFMove(promise), ArrayBuffer::tryCreate(data, length).get());
}
}
diff --git a/Source/WebCore/bindings/js/JSDOMPromise.h b/Source/WebCore/bindings/js/JSDOMPromise.h
index d431c4e5d..39530cc6e 100644
--- a/Source/WebCore/bindings/js/JSDOMPromise.h
+++ b/Source/WebCore/bindings/js/JSDOMPromise.h
@@ -23,87 +23,245 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSDOMPromise_h
-#define JSDOMPromise_h
+#pragma once
-#include "JSCryptoKey.h"
-#include "JSCryptoKeyPair.h"
-#include "JSDOMBinding.h"
+#include "ActiveDOMCallback.h"
+#include "JSDOMConvert.h"
#include <heap/StrongInlines.h>
#include <runtime/JSPromiseDeferred.h>
namespace WebCore {
-class DeferredWrapper {
+class DeferredPromise : public RefCounted<DeferredPromise>, public ActiveDOMCallback {
public:
- DeferredWrapper(JSC::ExecState*, JSDOMGlobalObject*);
+ static Ref<DeferredPromise> create(JSDOMGlobalObject& globalObject, JSC::JSPromiseDeferred& deferred)
+ {
+ return adoptRef(*new DeferredPromise(globalObject, deferred));
+ }
- template<class ResolveResultType>
- void resolve(const ResolveResultType&);
+ ~DeferredPromise();
- template<class RejectResultType>
- void reject(const RejectResultType&);
+ template<class IDLType>
+ void resolve(typename IDLType::ParameterType value)
+ {
+ if (isSuspended())
+ return;
+ ASSERT(m_deferred);
+ ASSERT(m_globalObject);
+ JSC::ExecState* exec = m_globalObject->globalExec();
+ JSC::JSLockHolder locker(exec);
+ resolve(*exec, toJS<IDLType>(*exec, *m_globalObject.get(), std::forward<typename IDLType::ParameterType>(value)));
+ }
- JSC::JSObject* promise() const;
+ void resolve()
+ {
+ if (isSuspended())
+ return;
+ ASSERT(m_deferred);
+ ASSERT(m_globalObject);
+ JSC::ExecState* exec = m_globalObject->globalExec();
+ JSC::JSLockHolder locker(exec);
+ resolve(*exec, JSC::jsUndefined());
+ }
+
+ template<class IDLType>
+ void resolveWithNewlyCreated(typename IDLType::ParameterType value)
+ {
+ if (isSuspended())
+ return;
+ ASSERT(m_deferred);
+ ASSERT(m_globalObject);
+ JSC::ExecState* exec = m_globalObject->globalExec();
+ JSC::JSLockHolder locker(exec);
+ resolve(*exec, toJSNewlyCreated<IDLType>(*exec, *m_globalObject.get(), std::forward<typename IDLType::ParameterType>(value)));
+ }
+
+ template<class IDLType>
+ void reject(typename IDLType::ParameterType value)
+ {
+ if (isSuspended())
+ return;
+ ASSERT(m_deferred);
+ ASSERT(m_globalObject);
+ JSC::ExecState* exec = m_globalObject->globalExec();
+ JSC::JSLockHolder locker(exec);
+ reject(*exec, toJS<IDLType>(*exec, *m_globalObject.get(), std::forward<typename IDLType::ParameterType>(value)));
+ }
+
+ void reject();
+ void reject(std::nullptr_t);
+ void reject(Exception&&);
+ void reject(ExceptionCode, const String& = { });
+ void reject(const JSC::PrivateName&);
+
+ template<typename Callback>
+ void resolveWithCallback(Callback callback)
+ {
+ if (isSuspended())
+ return;
+ ASSERT(m_deferred);
+ ASSERT(m_globalObject);
+ JSC::ExecState* exec = m_globalObject->globalExec();
+ JSC::JSLockHolder locker(exec);
+ resolve(*exec, callback(*exec, *m_globalObject.get()));
+ }
+
+ template<typename Callback>
+ void rejectWithCallback(Callback callback)
+ {
+ if (isSuspended())
+ return;
+ ASSERT(m_deferred);
+ ASSERT(m_globalObject);
+ JSC::ExecState* exec = m_globalObject->globalExec();
+ JSC::JSLockHolder locker(exec);
+ reject(*exec, callback(*exec, *m_globalObject.get()));
+ }
+
+ JSC::JSValue promise() const;
+
+ bool isSuspended() { return !m_deferred || !canInvokeCallback(); } // The wrapper world has gone away or active DOM objects have been suspended.
+ JSDOMGlobalObject* globalObject() { return m_globalObject.get(); }
+
+ void visitAggregate(JSC::SlotVisitor& visitor) { visitor.append(m_deferred); }
private:
- void resolve(JSC::ExecState*, JSC::JSValue);
- void reject(JSC::ExecState*, JSC::JSValue);
+ DeferredPromise(JSDOMGlobalObject&, JSC::JSPromiseDeferred&);
+
+ void clear();
+ void contextDestroyed() override;
- JSC::Strong<JSDOMGlobalObject> m_globalObject;
- JSC::Strong<JSC::JSPromiseDeferred> m_deferred;
+ void callFunction(JSC::ExecState&, JSC::JSValue function, JSC::JSValue resolution);
+ void resolve(JSC::ExecState& state, JSC::JSValue resolution) { callFunction(state, m_deferred->resolve(), resolution); }
+ void reject(JSC::ExecState& state, JSC::JSValue resolution) { callFunction(state, m_deferred->reject(), resolution); }
+
+ JSC::Weak<JSC::JSPromiseDeferred> m_deferred;
+ JSC::Weak<JSDOMGlobalObject> m_globalObject;
};
-template<class ResolveResultType>
-inline void DeferredWrapper::resolve(const ResolveResultType& result)
-{
- JSC::ExecState* exec = m_globalObject->globalExec();
- resolve(exec, toJS(exec, m_globalObject.get(), result));
-}
+class DOMPromiseBase {
+public:
+ DOMPromiseBase(Ref<DeferredPromise>&& genericPromise)
+ : m_promiseDeferred(WTFMove(genericPromise))
+ {
+ }
-template<class RejectResultType>
-inline void DeferredWrapper::reject(const RejectResultType& result)
-{
- JSC::ExecState* exec = m_globalObject->globalExec();
- reject(exec, toJS(exec, m_globalObject.get(), result));
-}
+ DOMPromiseBase(DOMPromiseBase&& promise)
+ : m_promiseDeferred(WTFMove(promise.m_promiseDeferred))
+ {
+ }
-template<>
-inline void DeferredWrapper::reject(const std::nullptr_t&)
-{
- JSC::ExecState* exec = m_globalObject->globalExec();
- reject(exec, JSC::jsNull());
-}
+ DOMPromiseBase(const DOMPromiseBase& other)
+ : m_promiseDeferred(other.m_promiseDeferred.copyRef())
+ {
+ }
-template<>
-inline void DeferredWrapper::resolve<String>(const String& result)
-{
- JSC::ExecState* exec = m_globalObject->globalExec();
- resolve(exec, jsString(exec, result));
-}
+ DOMPromiseBase& operator=(const DOMPromiseBase& other)
+ {
+ m_promiseDeferred = other.m_promiseDeferred.copyRef();
+ return *this;
+ }
-template<>
-inline void DeferredWrapper::resolve<bool>(const bool& result)
-{
- JSC::ExecState* exec = m_globalObject->globalExec();
- resolve(exec, JSC::jsBoolean(result));
-}
+ DOMPromiseBase& operator=(DOMPromiseBase&& other)
+ {
+ m_promiseDeferred = WTFMove(other.m_promiseDeferred);
+ return *this;
+ }
+
+ void reject()
+ {
+ m_promiseDeferred->reject();
+ }
+
+ template<typename... ErrorType>
+ void reject(ErrorType&&... error)
+ {
+ m_promiseDeferred->reject(std::forward<ErrorType>(error)...);
+ }
-template<>
-inline void DeferredWrapper::resolve<Vector<unsigned char>>(const Vector<unsigned char>& result)
+ template<typename IDLType>
+ void rejectType(typename IDLType::ParameterType value)
+ {
+ m_promiseDeferred->reject<IDLType>(std::forward<typename IDLType::ParameterType>(value));
+ }
+
+ JSC::JSValue promise() const { return m_promiseDeferred->promise(); };
+
+protected:
+ Ref<DeferredPromise> m_promiseDeferred;
+};
+
+template<typename IDLType>
+class DOMPromise : public DOMPromiseBase {
+public:
+ using DOMPromiseBase::DOMPromiseBase;
+ using DOMPromiseBase::operator=;
+ using DOMPromiseBase::promise;
+ using DOMPromiseBase::reject;
+
+ void resolve(typename IDLType::ParameterType value)
+ {
+ m_promiseDeferred->resolve<IDLType>(std::forward<typename IDLType::ParameterType>(value));
+ }
+};
+
+template<> class DOMPromise<void> : public DOMPromiseBase {
+public:
+ using DOMPromiseBase::DOMPromiseBase;
+ using DOMPromiseBase::operator=;
+ using DOMPromiseBase::promise;
+ using DOMPromiseBase::reject;
+
+ void resolve()
+ {
+ m_promiseDeferred->resolve();
+ }
+};
+
+
+Ref<DeferredPromise> createDeferredPromise(JSC::ExecState&, JSDOMWindow&);
+
+void fulfillPromiseWithJSON(Ref<DeferredPromise>&&, const String&);
+void fulfillPromiseWithArrayBuffer(Ref<DeferredPromise>&&, ArrayBuffer*);
+void fulfillPromiseWithArrayBuffer(Ref<DeferredPromise>&&, const void*, size_t);
+void rejectPromiseWithExceptionIfAny(JSC::ExecState&, JSDOMGlobalObject&, JSC::JSPromiseDeferred&);
+JSC::EncodedJSValue createRejectedPromiseWithTypeError(JSC::ExecState&, const String&);
+
+using PromiseFunction = void(JSC::ExecState&, Ref<DeferredPromise>&&);
+
+enum class PromiseExecutionScope { WindowOnly, WindowOrWorker };
+
+template<PromiseFunction promiseFunction, PromiseExecutionScope executionScope>
+inline JSC::JSValue callPromiseFunction(JSC::ExecState& state)
{
- JSC::ExecState* exec = m_globalObject->globalExec();
- RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(result.data(), result.size());
- resolve(exec, toJS(exec, m_globalObject.get(), buffer.get()));
+ JSC::VM& vm = state.vm();
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+
+ JSDOMGlobalObject& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject());
+ JSC::JSPromiseDeferred* promiseDeferred = JSC::JSPromiseDeferred::create(&state, &globalObject);
+
+ // promiseDeferred can be null when terminating a Worker abruptly.
+ if (executionScope == PromiseExecutionScope::WindowOrWorker && !promiseDeferred)
+ return JSC::jsUndefined();
+
+ promiseFunction(state, DeferredPromise::create(globalObject, *promiseDeferred));
+
+ rejectPromiseWithExceptionIfAny(state, globalObject, *promiseDeferred);
+ ASSERT_UNUSED(scope, !scope.exception());
+ return promiseDeferred->promise();
}
-template<>
-inline void DeferredWrapper::reject<String>(const String& result)
+using BindingPromiseFunction = JSC::EncodedJSValue(JSC::ExecState*, Ref<DeferredPromise>&&);
+template<BindingPromiseFunction bindingFunction>
+inline void bindingPromiseFunctionAdapter(JSC::ExecState& state, Ref<DeferredPromise>&& promise)
{
- JSC::ExecState* exec = m_globalObject->globalExec();
- reject(exec, jsString(exec, result));
+ bindingFunction(&state, WTFMove(promise));
}
+template<BindingPromiseFunction bindingPromiseFunction, PromiseExecutionScope executionScope>
+inline JSC::JSValue callPromiseFunction(JSC::ExecState& state)
+{
+ return callPromiseFunction<bindingPromiseFunctionAdapter<bindingPromiseFunction>, executionScope>(state);
}
-#endif // JSDOMPromise_h
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMStringMapCustom.cpp b/Source/WebCore/bindings/js/JSDOMStringMapCustom.cpp
index 6ff6b9c05..b3cc70d73 100644
--- a/Source/WebCore/bindings/js/JSDOMStringMapCustom.cpp
+++ b/Source/WebCore/bindings/js/JSDOMStringMapCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010, 2014 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,64 +26,51 @@
#include "config.h"
#include "JSDOMStringMap.h"
+#include "CustomElementReactionQueue.h"
#include "DOMStringMap.h"
-#include "Element.h"
+#include "JSDOMConvert.h"
#include "JSNode.h"
+#include <runtime/IdentifierInlines.h>
#include <wtf/text/AtomicString.h>
using namespace JSC;
namespace WebCore {
-bool JSDOMStringMap::canGetItemsForName(ExecState*, DOMStringMap* impl, PropertyName propertyName)
+bool JSDOMStringMap::deleteProperty(JSCell* cell, ExecState* state, PropertyName propertyName)
{
- return impl->contains(propertyNameToAtomicString(propertyName));
+ CustomElementReactionStack customElementReactionStack;
+ if (propertyName.isSymbol())
+ return Base::deleteProperty(cell, state, propertyName);
+ return jsCast<JSDOMStringMap*>(cell)->wrapped().deleteItem(propertyNameToString(propertyName));
}
-EncodedJSValue JSDOMStringMap::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName)
+bool JSDOMStringMap::deletePropertyByIndex(JSCell* cell, ExecState* state, unsigned index)
{
- JSDOMStringMap* thisObj = jsCast<JSDOMStringMap*>(JSValue::decode(slotBase));
- return JSValue::encode(jsStringWithCache(exec, thisObj->impl().item(propertyNameToAtomicString(propertyName))));
+ return deleteProperty(cell, state, Identifier::from(state, index));
}
-void JSDOMStringMap::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+bool JSDOMStringMap::putDelegate(ExecState* state, PropertyName propertyName, JSValue value, PutPropertySlot&, bool& putResult)
{
- JSDOMStringMap* thisObject = jsCast<JSDOMStringMap*>(object);
- Vector<String> names;
- thisObject->m_impl->getNames(names);
- size_t length = names.size();
- for (size_t i = 0; i < length; ++i)
- propertyNames.add(Identifier(exec, names[i]));
+ VM& vm = state->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
- Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
-}
-
-bool JSDOMStringMap::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
-{
- JSDOMStringMap* thisObject = jsCast<JSDOMStringMap*>(cell);
- AtomicString stringName = propertyNameToAtomicString(propertyName);
- if (!thisObject->m_impl->contains(stringName))
+ if (propertyName.isSymbol())
return false;
- ExceptionCode ec = 0;
- thisObject->m_impl->deleteItem(stringName, ec);
- setDOMException(exec, ec);
- return !ec;
-}
-bool JSDOMStringMap::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned index)
-{
- return deleteProperty(cell, exec, Identifier::from(exec, index));
-}
+ CustomElementReactionStack customElementReactionStack;
-bool JSDOMStringMap::putDelegate(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot&)
-{
- String stringValue = value.toString(exec)->value(exec);
- if (exec->hadException())
- return false;
- ExceptionCode ec = 0;
- impl().setItem(propertyNameToString(propertyName), stringValue, ec);
- setDOMException(exec, ec);
- return !ec;
+ String stringValue = value.toWTFString(state);
+ RETURN_IF_EXCEPTION(scope, true);
+
+ auto result = wrapped().setItem(propertyNameToString(propertyName), WTFMove(stringValue));
+ if (result.hasException()) {
+ propagateException(*state, scope, result.releaseException());
+ return true;
+ }
+
+ putResult = true;
+ return true;
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMWindowBase.cpp b/Source/WebCore/bindings/js/JSDOMWindowBase.cpp
index c6739780b..45df5a8e0 100644
--- a/Source/WebCore/bindings/js/JSDOMWindowBase.cpp
+++ b/Source/WebCore/bindings/js/JSDOMWindowBase.cpp
@@ -1,8 +1,9 @@
/*
* Copyright (C) 2000 Harri Porten (porten@kde.org)
* Copyright (C) 2006 Jon Shier (jshier@iastate.edu)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reseved.
+ * Copyright (C) 2003-2009, 2014, 2016 Apple Inc. All rights reseved.
* Copyright (C) 2006 Alexey Proskuryakov (ap@webkit.org)
+ * Copyright (c) 2015 Canon Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -23,45 +24,60 @@
#include "config.h"
#include "JSDOMWindowBase.h"
+#include "ActiveDOMCallbackMicrotask.h"
#include "Chrome.h"
-#include "Console.h"
+#include "CommonVM.h"
#include "DOMWindow.h"
#include "Frame.h"
#include "InspectorController.h"
+#include "JSDOMBindingSecurity.h"
#include "JSDOMGlobalObjectTask.h"
#include "JSDOMWindowCustom.h"
+#include "JSMainThreadExecState.h"
#include "JSNode.h"
+#include "Language.h"
#include "Logging.h"
#include "Page.h"
+#include "RuntimeApplicationChecks.h"
#include "ScriptController.h"
+#include "ScriptModuleLoader.h"
#include "SecurityOrigin.h"
#include "Settings.h"
#include "WebCoreJSClientData.h"
+#include <bytecode/CodeBlock.h>
+#include <heap/StrongInlines.h>
+#include <runtime/JSInternalPromiseDeferred.h>
#include <runtime/Microtask.h>
#include <wtf/MainThread.h>
#if PLATFORM(IOS)
#include "ChromeClient.h"
-#include "WebSafeGCActivityCallbackIOS.h"
-#include "WebSafeIncrementalSweeperIOS.h"
#endif
using namespace JSC;
namespace WebCore {
-static bool shouldAllowAccessFrom(const JSGlobalObject* thisObject, ExecState* exec)
-{
- return BindingSecurity::shouldAllowAccessToDOMWindow(exec, asJSDOMWindow(thisObject)->impl());
-}
-
-const ClassInfo JSDOMWindowBase::s_info = { "Window", &JSDOMGlobalObject::s_info, 0, 0, CREATE_METHOD_TABLE(JSDOMWindowBase) };
-
-const GlobalObjectMethodTable JSDOMWindowBase::s_globalObjectMethodTable = { &shouldAllowAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptExperimentsEnabled, &queueTaskToEventLoop, &shouldInterruptScriptBeforeTimeout };
-
-JSDOMWindowBase::JSDOMWindowBase(VM& vm, Structure* structure, PassRefPtr<DOMWindow> window, JSDOMWindowShell* shell)
- : JSDOMGlobalObject(vm, structure, &shell->world(), &s_globalObjectMethodTable)
- , m_impl(window)
+const ClassInfo JSDOMWindowBase::s_info = { "Window", &JSDOMGlobalObject::s_info, 0, CREATE_METHOD_TABLE(JSDOMWindowBase) };
+
+const GlobalObjectMethodTable JSDOMWindowBase::s_globalObjectMethodTable = {
+ &supportsRichSourceInfo,
+ &shouldInterruptScript,
+ &javaScriptRuntimeFlags,
+ &queueTaskToEventLoop,
+ &shouldInterruptScriptBeforeTimeout,
+ &moduleLoaderImportModule,
+ &moduleLoaderResolve,
+ &moduleLoaderFetch,
+ nullptr,
+ &moduleLoaderEvaluate,
+ &defaultLanguage
+};
+
+JSDOMWindowBase::JSDOMWindowBase(VM& vm, Structure* structure, RefPtr<DOMWindow>&& window, JSDOMWindowShell* shell)
+ : JSDOMGlobalObject(vm, structure, shell->world(), &s_globalObjectMethodTable)
+ , m_windowCloseWatchpoints((window && window->frame()) ? IsWatched : IsInvalidated)
+ , m_wrapped(WTFMove(window))
, m_shell(shell)
{
}
@@ -69,14 +85,24 @@ JSDOMWindowBase::JSDOMWindowBase(VM& vm, Structure* structure, PassRefPtr<DOMWin
void JSDOMWindowBase::finishCreation(VM& vm, JSDOMWindowShell* shell)
{
Base::finishCreation(vm, shell);
- ASSERT(inherits(info()));
+ ASSERT(inherits(vm, info()));
GlobalPropertyInfo staticGlobals[] = {
GlobalPropertyInfo(vm.propertyNames->document, jsNull(), DontDelete | ReadOnly),
- GlobalPropertyInfo(vm.propertyNames->window, m_shell, DontDelete | ReadOnly)
+ GlobalPropertyInfo(vm.propertyNames->window, m_shell, DontDelete | ReadOnly),
};
-
+
addStaticGlobals(staticGlobals, WTF_ARRAY_LENGTH(staticGlobals));
+
+ if (m_wrapped && m_wrapped->frame() && m_wrapped->frame()->settings().needsSiteSpecificQuirks())
+ setNeedsSiteSpecificQuirks(true);
+}
+
+void JSDOMWindowBase::visitChildren(JSCell* cell, SlotVisitor& visitor)
+{
+ JSDOMWindowBase* thisObject = jsCast<JSDOMWindowBase*>(cell);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+ Base::visitChildren(thisObject, visitor);
}
void JSDOMWindowBase::destroy(JSCell* cell)
@@ -86,48 +112,31 @@ void JSDOMWindowBase::destroy(JSCell* cell)
void JSDOMWindowBase::updateDocument()
{
- ASSERT(m_impl->document());
+ // Since "document" property is defined as { configurable: false, writable: false, enumerable: true },
+ // users cannot change its attributes further.
+ // Reaching here, the attributes of "document" property should be never changed.
+ ASSERT(m_wrapped->document());
ExecState* exec = globalExec();
- symbolTablePutWithAttributes(this, exec->vm(), exec->vm().propertyNames->document, toJS(exec, this, m_impl->document()), DontDelete | ReadOnly);
+ bool shouldThrowReadOnlyError = false;
+ bool ignoreReadOnlyErrors = true;
+ bool putResult = false;
+ symbolTablePutTouchWatchpointSet(this, exec, exec->vm().propertyNames->document, toJS(exec, this, m_wrapped->document()), shouldThrowReadOnlyError, ignoreReadOnlyErrors, putResult);
}
ScriptExecutionContext* JSDOMWindowBase::scriptExecutionContext() const
{
- return m_impl->document();
+ return m_wrapped->document();
}
void JSDOMWindowBase::printErrorMessage(const String& message) const
{
- printErrorMessageForFrame(impl().frame(), message);
-}
-
-bool JSDOMWindowBase::supportsProfiling(const JSGlobalObject* object)
-{
-#if !ENABLE(INSPECTOR)
- UNUSED_PARAM(object);
- return false;
-#else
- const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object);
- Frame* frame = thisObject->impl().frame();
- if (!frame)
- return false;
-
- Page* page = frame->page();
- if (!page)
- return false;
-
- return page->inspectorController().profilerEnabled();
-#endif // ENABLE(INSPECTOR)
+ printErrorMessageForFrame(wrapped().frame(), message);
}
bool JSDOMWindowBase::supportsRichSourceInfo(const JSGlobalObject* object)
{
-#if !ENABLE(INSPECTOR)
- UNUSED_PARAM(object);
- return false;
-#else
const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object);
- Frame* frame = thisObject->impl().frame();
+ Frame* frame = thisObject->wrapped().frame();
if (!frame)
return false;
@@ -137,9 +146,7 @@ bool JSDOMWindowBase::supportsRichSourceInfo(const JSGlobalObject* object)
bool enabled = page->inspectorController().enabled();
ASSERT(enabled || !thisObject->debugger());
- ASSERT(enabled || !supportsProfiling(thisObject));
return enabled;
-#endif
}
static inline bool shouldInterruptScriptToPreventInfiniteRecursionWhenClosingPage(Page* page)
@@ -157,16 +164,16 @@ static inline bool shouldInterruptScriptToPreventInfiniteRecursionWhenClosingPag
bool JSDOMWindowBase::shouldInterruptScript(const JSGlobalObject* object)
{
const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object);
- ASSERT(thisObject->impl().frame());
- Page* page = thisObject->impl().frame()->page();
- return shouldInterruptScriptToPreventInfiniteRecursionWhenClosingPage(page) || page->chrome().shouldInterruptJavaScript();
+ ASSERT(thisObject->wrapped().frame());
+ Page* page = thisObject->wrapped().frame()->page();
+ return shouldInterruptScriptToPreventInfiniteRecursionWhenClosingPage(page);
}
bool JSDOMWindowBase::shouldInterruptScriptBeforeTimeout(const JSGlobalObject* object)
{
const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object);
- ASSERT(thisObject->impl().frame());
- Page* page = thisObject->impl().frame()->page();
+ ASSERT(thisObject->wrapped().frame());
+ Page* page = thisObject->wrapped().frame()->page();
if (shouldInterruptScriptToPreventInfiniteRecursionWhenClosingPage(page))
return true;
@@ -179,85 +186,79 @@ bool JSDOMWindowBase::shouldInterruptScriptBeforeTimeout(const JSGlobalObject* o
return JSGlobalObject::shouldInterruptScriptBeforeTimeout(object);
}
-bool JSDOMWindowBase::javaScriptExperimentsEnabled(const JSGlobalObject* object)
+RuntimeFlags JSDOMWindowBase::javaScriptRuntimeFlags(const JSGlobalObject* object)
{
const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object);
- Frame* frame = thisObject->impl().frame();
+ Frame* frame = thisObject->wrapped().frame();
if (!frame)
- return false;
- return frame->settings().javaScriptExperimentsEnabled();
+ return RuntimeFlags();
+ return frame->settings().javaScriptRuntimeFlags();
}
-void JSDOMWindowBase::queueTaskToEventLoop(const JSGlobalObject* object, PassRefPtr<Microtask> task)
-{
- const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object);
- thisObject->scriptExecutionContext()->postTask(JSGlobalObjectTask::create((JSDOMWindowBase*)thisObject, task));
-}
+class JSDOMWindowMicrotaskCallback : public RefCounted<JSDOMWindowMicrotaskCallback> {
+public:
+ static Ref<JSDOMWindowMicrotaskCallback> create(JSDOMWindowBase* globalObject, Ref<JSC::Microtask>&& task)
+ {
+ return adoptRef(*new JSDOMWindowMicrotaskCallback(globalObject, WTFMove(task)));
+ }
-void JSDOMWindowBase::willRemoveFromWindowShell()
-{
- setCurrentEvent(0);
-}
+ void call()
+ {
+ Ref<JSDOMWindowMicrotaskCallback> protectedThis(*this);
+ VM& vm = m_globalObject->vm();
+ JSLockHolder lock(vm);
+ auto scope = DECLARE_THROW_SCOPE(vm);
-JSDOMWindowShell* JSDOMWindowBase::shell() const
-{
- return m_shell;
-}
+ ExecState* exec = m_globalObject->globalExec();
-VM* JSDOMWindowBase::commonVM()
-{
- ASSERT(isMainThread());
+ JSMainThreadExecState::runTask(exec, m_task);
-#if !PLATFORM(IOS)
- static VM* vm = 0;
-#else
- VM*& vm = commonVMInternal();
-#endif
- if (!vm) {
- ScriptController::initializeThreading();
- vm = VM::createLeaked(LargeHeap).leakRef();
-#if PLATFORM(IOS)
- PassOwnPtr<WebSafeGCActivityCallback> activityCallback = WebSafeGCActivityCallback::create(&vm->heap);
- vm->heap.setActivityCallback(activityCallback);
- PassOwnPtr<WebSafeIncrementalSweeper> incrementalSweeper = WebSafeIncrementalSweeper::create(&vm->heap);
- vm->heap.setIncrementalSweeper(incrementalSweeper);
- vm->makeUsableFromMultipleThreads();
- vm->heap.machineThreads().addCurrentThread();
-#else
- vm->exclusiveThread = currentThread();
-#endif // !PLATFORM(IOS)
- initNormalWorldClientData(vm);
+ ASSERT_UNUSED(scope, !scope.exception());
}
- return vm;
+private:
+ JSDOMWindowMicrotaskCallback(JSDOMWindowBase* globalObject, Ref<JSC::Microtask>&& task)
+ : m_globalObject(globalObject->vm(), globalObject)
+ , m_task(WTFMove(task))
+ {
+ }
+
+ Strong<JSDOMWindowBase> m_globalObject;
+ Ref<JSC::Microtask> m_task;
+};
+
+void JSDOMWindowBase::queueTaskToEventLoop(const JSGlobalObject* object, Ref<JSC::Microtask>&& task)
+{
+ const JSDOMWindowBase* thisObject = static_cast<const JSDOMWindowBase*>(object);
+
+ RefPtr<JSDOMWindowMicrotaskCallback> callback = JSDOMWindowMicrotaskCallback::create((JSDOMWindowBase*)thisObject, WTFMove(task));
+ auto microtask = std::make_unique<ActiveDOMCallbackMicrotask>(MicrotaskQueue::mainThreadQueue(), *thisObject->scriptExecutionContext(), [callback]() mutable {
+ callback->call();
+ });
+
+ MicrotaskQueue::mainThreadQueue().append(WTFMove(microtask));
}
-#if PLATFORM(IOS)
-bool JSDOMWindowBase::commonVMExists()
+void JSDOMWindowBase::willRemoveFromWindowShell()
{
- return commonVMInternal();
+ setCurrentEvent(0);
}
-VM*& JSDOMWindowBase::commonVMInternal()
+JSDOMWindowShell* JSDOMWindowBase::shell() const
{
- ASSERT(isMainThread());
- static VM* commonVM;
- return commonVM;
+ return m_shell;
}
-#endif
// JSDOMGlobalObject* is ignored, accessing a window in any context will
// use that DOMWindow's prototype chain.
-JSValue toJS(ExecState* exec, JSDOMGlobalObject*, DOMWindow* domWindow)
+JSValue toJS(ExecState* exec, JSDOMGlobalObject*, DOMWindow& domWindow)
{
return toJS(exec, domWindow);
}
-JSValue toJS(ExecState* exec, DOMWindow* domWindow)
+JSValue toJS(ExecState* exec, DOMWindow& domWindow)
{
- if (!domWindow)
- return jsNull();
- Frame* frame = domWindow->frame();
+ Frame* frame = domWindow.frame();
if (!frame)
return jsNull();
return frame->script().windowShell(currentWorld(exec));
@@ -270,16 +271,124 @@ JSDOMWindow* toJSDOMWindow(Frame* frame, DOMWrapperWorld& world)
return frame->script().windowShell(world)->window();
}
-JSDOMWindow* toJSDOMWindow(JSValue value)
+JSDOMWindow* toJSDOMWindow(JSC::VM& vm, JSValue value)
{
if (!value.isObject())
return 0;
- const ClassInfo* classInfo = asObject(value)->classInfo();
- if (classInfo == JSDOMWindow::info())
- return jsCast<JSDOMWindow*>(asObject(value));
- if (classInfo == JSDOMWindowShell::info())
- return jsCast<JSDOMWindowShell*>(asObject(value))->window();
+
+ while (!value.isNull()) {
+ JSObject* object = asObject(value);
+ const ClassInfo* classInfo = object->classInfo(vm);
+ if (classInfo == JSDOMWindow::info())
+ return jsCast<JSDOMWindow*>(object);
+ if (classInfo == JSDOMWindowShell::info())
+ return jsCast<JSDOMWindowShell*>(object)->window();
+ value = object->getPrototypeDirect();
+ }
return 0;
}
+DOMWindow& callerDOMWindow(ExecState* exec)
+{
+ class GetCallerGlobalObjectFunctor {
+ public:
+ GetCallerGlobalObjectFunctor() = default;
+
+ StackVisitor::Status operator()(StackVisitor& visitor) const
+ {
+ if (!m_hasSkippedFirstFrame) {
+ m_hasSkippedFirstFrame = true;
+ return StackVisitor::Continue;
+ }
+
+ if (auto* codeBlock = visitor->codeBlock())
+ m_globalObject = codeBlock->globalObject();
+ else {
+ ASSERT(visitor->callee());
+ // FIXME: Callee is not an object if the caller is Web Assembly.
+ // Figure out what to do here. We can probably get the global object
+ // from the top-most Wasm Instance. https://bugs.webkit.org/show_bug.cgi?id=165721
+ if (visitor->callee()->isObject())
+ m_globalObject = jsCast<JSObject*>(visitor->callee())->globalObject();
+ }
+ return StackVisitor::Done;
+ }
+
+ JSGlobalObject* globalObject() const { return m_globalObject; }
+
+ private:
+ mutable bool m_hasSkippedFirstFrame { false };
+ mutable JSGlobalObject* m_globalObject { nullptr };
+ };
+
+ GetCallerGlobalObjectFunctor iter;
+ exec->iterate(iter);
+ return iter.globalObject() ? asJSDOMWindow(iter.globalObject())->wrapped() : firstDOMWindow(exec);
+}
+
+DOMWindow& activeDOMWindow(ExecState* exec)
+{
+ return asJSDOMWindow(exec->lexicalGlobalObject())->wrapped();
+}
+
+DOMWindow& firstDOMWindow(ExecState* exec)
+{
+ return asJSDOMWindow(exec->vmEntryGlobalObject())->wrapped();
+}
+
+void JSDOMWindowBase::fireFrameClearedWatchpointsForWindow(DOMWindow* window)
+{
+ JSC::VM& vm = commonVM();
+ JSVMClientData* clientData = static_cast<JSVMClientData*>(vm.clientData);
+ Vector<Ref<DOMWrapperWorld>> wrapperWorlds;
+ clientData->getAllWorlds(wrapperWorlds);
+ for (unsigned i = 0; i < wrapperWorlds.size(); ++i) {
+ DOMObjectWrapperMap& wrappers = wrapperWorlds[i]->m_wrappers;
+ auto result = wrappers.find(window);
+ if (result == wrappers.end())
+ continue;
+ JSC::JSObject* wrapper = result->value.get();
+ if (!wrapper)
+ continue;
+ JSDOMWindowBase* jsWindow = JSC::jsCast<JSDOMWindowBase*>(wrapper);
+ jsWindow->m_windowCloseWatchpoints.fireAll(vm, "Frame cleared");
+ }
+}
+
+
+JSC::JSInternalPromise* JSDOMWindowBase::moduleLoaderResolve(JSC::JSGlobalObject* globalObject, JSC::ExecState* exec, JSC::JSModuleLoader* moduleLoader, JSC::JSValue moduleName, JSC::JSValue importerModuleKey, JSC::JSValue scriptFetcher)
+{
+ JSDOMWindowBase* thisObject = JSC::jsCast<JSDOMWindowBase*>(globalObject);
+ if (RefPtr<Document> document = thisObject->wrapped().document())
+ return document->moduleLoader()->resolve(globalObject, exec, moduleLoader, moduleName, importerModuleKey, scriptFetcher);
+ JSC::JSInternalPromiseDeferred* deferred = JSC::JSInternalPromiseDeferred::create(exec, globalObject);
+ return deferred->reject(exec, jsUndefined());
+}
+
+JSC::JSInternalPromise* JSDOMWindowBase::moduleLoaderFetch(JSC::JSGlobalObject* globalObject, JSC::ExecState* exec, JSC::JSModuleLoader* moduleLoader, JSC::JSValue moduleKey, JSC::JSValue scriptFetcher)
+{
+ JSDOMWindowBase* thisObject = JSC::jsCast<JSDOMWindowBase*>(globalObject);
+ if (RefPtr<Document> document = thisObject->wrapped().document())
+ return document->moduleLoader()->fetch(globalObject, exec, moduleLoader, moduleKey, scriptFetcher);
+ JSC::JSInternalPromiseDeferred* deferred = JSC::JSInternalPromiseDeferred::create(exec, globalObject);
+ return deferred->reject(exec, jsUndefined());
+}
+
+JSC::JSValue JSDOMWindowBase::moduleLoaderEvaluate(JSC::JSGlobalObject* globalObject, JSC::ExecState* exec, JSC::JSModuleLoader* moduleLoader, JSC::JSValue moduleKey, JSC::JSValue moduleRecord, JSC::JSValue scriptFetcher)
+{
+ JSDOMWindowBase* thisObject = JSC::jsCast<JSDOMWindowBase*>(globalObject);
+ if (RefPtr<Document> document = thisObject->wrapped().document())
+ return document->moduleLoader()->evaluate(globalObject, exec, moduleLoader, moduleKey, moduleRecord, scriptFetcher);
+ return JSC::jsUndefined();
+}
+
+JSC::JSInternalPromise* JSDOMWindowBase::moduleLoaderImportModule(JSC::JSGlobalObject* globalObject, JSC::ExecState* exec, JSC::JSModuleLoader* moduleLoader, JSC::JSString* moduleName, const JSC::SourceOrigin& sourceOrigin)
+{
+ JSDOMWindowBase* thisObject = JSC::jsCast<JSDOMWindowBase*>(globalObject);
+ if (RefPtr<Document> document = thisObject->wrapped().document())
+ return document->moduleLoader()->importModule(globalObject, exec, moduleLoader, moduleName, sourceOrigin);
+ JSC::JSInternalPromiseDeferred* deferred = JSC::JSInternalPromiseDeferred::create(exec, globalObject);
+ return deferred->reject(exec, jsUndefined());
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMWindowBase.h b/Source/WebCore/bindings/js/JSDOMWindowBase.h
index fb4c601bc..19c3da4a7 100644
--- a/Source/WebCore/bindings/js/JSDOMWindowBase.h
+++ b/Source/WebCore/bindings/js/JSDOMWindowBase.h
@@ -17,8 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef JSDOMWindowBase_h
-#define JSDOMWindowBase_h
+#pragma once
#include "JSDOMBinding.h"
#include "JSDOMGlobalObject.h"
@@ -34,10 +33,10 @@ namespace WebCore {
class JSDOMWindowBasePrivate;
- class JSDOMWindowBase : public JSDOMGlobalObject {
+ class WEBCORE_EXPORT JSDOMWindowBase : public JSDOMGlobalObject {
typedef JSDOMGlobalObject Base;
protected:
- JSDOMWindowBase(JSC::VM&, JSC::Structure*, PassRefPtr<DOMWindow>, JSDOMWindowShell*);
+ JSDOMWindowBase(JSC::VM&, JSC::Structure*, RefPtr<DOMWindow>&&, JSDOMWindowShell*);
void finishCreation(JSC::VM&, JSDOMWindowShell*);
static void destroy(JSCell*);
@@ -45,7 +44,7 @@ namespace WebCore {
public:
void updateDocument();
- DOMWindow& impl() const { return *m_impl; }
+ DOMWindow& wrapped() const { return *m_wrapped; }
ScriptExecutionContext* scriptExecutionContext() const;
// Called just before removing this window from the JSDOMWindowShell.
@@ -60,38 +59,46 @@ namespace WebCore {
static const JSC::GlobalObjectMethodTable s_globalObjectMethodTable;
- static bool supportsProfiling(const JSC::JSGlobalObject*);
static bool supportsRichSourceInfo(const JSC::JSGlobalObject*);
static bool shouldInterruptScript(const JSC::JSGlobalObject*);
static bool shouldInterruptScriptBeforeTimeout(const JSC::JSGlobalObject*);
- static bool javaScriptExperimentsEnabled(const JSC::JSGlobalObject*);
- static void queueTaskToEventLoop(const JSC::JSGlobalObject*, PassRefPtr<JSC::Microtask>);
+ static JSC::RuntimeFlags javaScriptRuntimeFlags(const JSC::JSGlobalObject*);
+ static void queueTaskToEventLoop(const JSC::JSGlobalObject*, Ref<JSC::Microtask>&&);
void printErrorMessage(const String&) const;
JSDOMWindowShell* shell() const;
- static JSC::VM* commonVM();
-#if PLATFORM(IOS)
- static bool commonVMExists();
- static JSC::VM*& commonVMInternal();
-#endif
+ static void fireFrameClearedWatchpointsForWindow(DOMWindow*);
+ static void visitChildren(JSC::JSCell*, JSC::SlotVisitor&);
+
+ protected:
+ JSC::WatchpointSet m_windowCloseWatchpoints;
private:
- RefPtr<DOMWindow> m_impl;
+ static JSC::JSInternalPromise* moduleLoaderResolve(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSValue, JSC::JSValue);
+ static JSC::JSInternalPromise* moduleLoaderFetch(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSValue);
+ static JSC::JSValue moduleLoaderEvaluate(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue, JSC::JSValue, JSC::JSValue);
+ static JSC::JSInternalPromise* moduleLoaderImportModule(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSString*, const JSC::SourceOrigin&);
+
+ RefPtr<DOMWindow> m_wrapped;
JSDOMWindowShell* m_shell;
};
// Returns a JSDOMWindow or jsNull()
// JSDOMGlobalObject* is ignored, accessing a window in any context will
// use that DOMWindow's prototype chain.
- JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, DOMWindow*);
- JSC::JSValue toJS(JSC::ExecState*, DOMWindow*);
+ WEBCORE_EXPORT JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, DOMWindow&);
+ inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, DOMWindow* window) { return window ? toJS(exec, globalObject, *window) : JSC::jsNull(); }
+ JSC::JSValue toJS(JSC::ExecState*, DOMWindow&);
+ inline JSC::JSValue toJS(JSC::ExecState* exec, DOMWindow* window) { return window ? toJS(exec, *window) : JSC::jsNull(); }
// Returns JSDOMWindow or 0
JSDOMWindow* toJSDOMWindow(Frame*, DOMWrapperWorld&);
- JSDOMWindow* toJSDOMWindow(JSC::JSValue);
+ WEBCORE_EXPORT JSDOMWindow* toJSDOMWindow(JSC::VM&, JSC::JSValue);
-} // namespace WebCore
+ DOMWindow& callerDOMWindow(JSC::ExecState*);
+ DOMWindow& activeDOMWindow(JSC::ExecState*);
+ DOMWindow& firstDOMWindow(JSC::ExecState*);
-#endif // JSDOMWindowBase_h
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp b/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp
index 795da5a49..c00484af5 100644
--- a/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp
+++ b/Source/WebCore/bindings/js/JSDOMWindowCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2007-2017 Apple Inc. All rights reserved.
* Copyright (C) 2011 Google Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
@@ -21,117 +21,74 @@
#include "config.h"
#include "JSDOMWindowCustom.h"
+#include "DOMWindowIndexedDatabase.h"
#include "Frame.h"
#include "HTMLCollection.h"
#include "HTMLDocument.h"
+#include "HTMLFrameOwnerElement.h"
+#include "JSDOMBindingSecurity.h"
#include "JSEvent.h"
#include "JSEventListener.h"
#include "JSHTMLAudioElement.h"
#include "JSHTMLCollection.h"
#include "JSHTMLOptionElement.h"
-#include "JSImageConstructor.h"
-#include "JSMessagePortCustom.h"
+#include "JSIDBFactory.h"
#include "JSWorker.h"
#include "Location.h"
+#include "RuntimeEnabledFeatures.h"
#include "ScheduledAction.h"
#include "Settings.h"
-#include "SharedWorkerRepository.h"
+#include <runtime/JSCInlines.h>
+#include <runtime/Lookup.h>
-#if ENABLE(SHARED_WORKERS)
-#include "JSSharedWorker.h"
-#endif
-
-#if ENABLE(IOS_TOUCH_EVENTS)
-#include "JSTouchConstructorIOS.h"
-#include "JSTouchListConstructorIOS.h"
-#endif
-
-#if ENABLE(WEB_AUDIO)
-#include "JSAudioContext.h"
-#endif
-
-#if ENABLE(WEB_SOCKETS)
-#include "JSWebSocket.h"
+#if ENABLE(USER_MESSAGE_HANDLERS)
+#include "JSWebKitNamespace.h"
#endif
using namespace JSC;
namespace WebCore {
-void JSDOMWindow::visitChildren(JSCell* cell, SlotVisitor& visitor)
-{
- JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(thisObject, visitor);
-
- thisObject->impl().visitJSEventListeners(visitor);
- if (Frame* frame = thisObject->impl().frame())
- visitor.addOpaqueRoot(frame);
-}
-
-template<NativeFunction nativeFunction, int length>
-EncodedJSValue nonCachingStaticFunctionGetter(ExecState* exec, EncodedJSValue, EncodedJSValue, PropertyName propertyName)
-{
- return JSValue::encode(JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), length, propertyName.publicName(), nativeFunction));
-}
+EncodedJSValue JSC_HOST_CALL jsDOMWindowInstanceFunctionShowModalDialog(ExecState*);
-static EncodedJSValue childFrameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName)
+void JSDOMWindow::visitAdditionalChildren(SlotVisitor& visitor)
{
- return JSValue::encode(toJS(exec, jsCast<JSDOMWindow*>(JSValue::decode(slotBase))->impl().frame()->tree().scopedChild(propertyNameToAtomicString(propertyName))->document()->domWindow()));
-}
-
-static EncodedJSValue indexGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, unsigned index)
-{
- return JSValue::encode(toJS(exec, jsCast<JSDOMWindow*>(JSValue::decode(slotBase))->impl().frame()->tree().scopedChild(index)->document()->domWindow()));
+ if (Frame* frame = wrapped().frame())
+ visitor.addOpaqueRoot(frame);
+
+ // Normally JSEventTargetCustom.cpp's JSEventTarget::visitAdditionalChildren() would call this. But
+ // even though DOMWindow is an EventTarget, JSDOMWindow does not subclass JSEventTarget, so we need
+ // to do this here.
+ wrapped().visitJSEventListeners(visitor);
}
-static EncodedJSValue namedItemGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName)
+#if ENABLE(USER_MESSAGE_HANDLERS)
+static EncodedJSValue jsDOMWindowWebKit(ExecState* exec, EncodedJSValue thisValue, PropertyName)
{
- JSDOMWindowBase* thisObj = jsCast<JSDOMWindow*>(JSValue::decode(slotBase));
- Document* document = thisObj->impl().frame()->document();
-
- ASSERT(BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObj->impl()));
- ASSERT(document);
- ASSERT(document->isHTMLDocument());
-
- AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName);
- if (!atomicPropertyName || !toHTMLDocument(document)->hasWindowNamedItem(*atomicPropertyName))
+ VM& vm = exec->vm();
+ JSDOMWindow* castedThis = toJSDOMWindow(vm, JSValue::decode(thisValue));
+ if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, castedThis->wrapped()))
return JSValue::encode(jsUndefined());
-
- if (UNLIKELY(toHTMLDocument(document)->windowNamedItemContainsMultipleElements(*atomicPropertyName))) {
- RefPtr<HTMLCollection> collection = document->windowNamedItems(atomicPropertyName);
- ASSERT(collection->length() > 1);
- return JSValue::encode(toJS(exec, thisObj->globalObject(), WTF::getPtr(collection)));
- }
-
- return JSValue::encode(toJS(exec, thisObj->globalObject(), toHTMLDocument(document)->windowNamedItem(*atomicPropertyName)));
+ return JSValue::encode(toJS(exec, castedThis->globalObject(), castedThis->wrapped().webkitNamespace()));
}
+#endif
-bool JSDOMWindow::getOwnPropertySlot(JSObject* object, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
+static bool jsDOMWindowGetOwnPropertySlotRestrictedAccess(JSDOMWindow* thisObject, Frame* frame, ExecState* exec, PropertyName propertyName, PropertySlot& slot, const String& errorMessage)
{
- JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
- // When accessing a Window cross-domain, functions are always the native built-in ones, and they
- // are not affected by properties changed on the Window or anything in its prototype chain.
- // This is consistent with the behavior of Firefox.
-
- const HashEntry* entry;
-
- // We don't want any properties other than "close" and "closed" on a frameless window (i.e. one whose page got closed,
- // or whose iframe got removed).
- // FIXME: This doesn't fully match Firefox, which allows at least toString in addition to those.
- if (!thisObject->impl().frame()) {
- // The following code is safe for cross-domain and same domain use.
- // It ignores any custom properties that might be set on the DOMWindow (including a custom prototype).
- entry = s_info.propHashTable(exec)->entry(exec, propertyName);
- if (entry && !(entry->attributes() & JSC::Function) && entry->propertyGetter() == jsDOMWindowClosed) {
- slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, entry->propertyGetter());
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ // We don't want any properties other than "close" and "closed" on a frameless window
+ // (i.e. one whose page got closed, or whose iframe got removed).
+ // FIXME: This handling for frameless windows duplicates similar behaviour for cross-origin
+ // access below; we should try to find a way to merge the two.
+ if (!frame) {
+ if (propertyName == exec->propertyNames().closed) {
+ slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, jsDOMWindowClosed);
return true;
}
- entry = JSDOMWindowPrototype::info()->propHashTable(exec)->entry(exec, propertyName);
- if (entry && (entry->attributes() & JSC::Function) && entry->function() == jsDOMWindowPrototypeFunctionClose) {
- slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>);
+ if (propertyName == exec->propertyNames().close) {
+ slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionClose, 0>);
return true;
}
@@ -141,240 +98,186 @@ bool JSDOMWindow::getOwnPropertySlot(JSObject* object, ExecState* exec, Property
return true;
}
- // We need to check for cross-domain access here without printing the generic warning message
- // because we always allow access to some function, just different ones depending whether access
- // is allowed.
- String errorMessage;
- bool allowsAccess = shouldAllowAccessToDOMWindow(exec, thisObject->impl(), errorMessage);
-
- // Look for overrides before looking at any of our own properties, but ignore overrides completely
- // if this is cross-domain access.
- if (allowsAccess && JSGlobalObject::getOwnPropertySlot(thisObject, exec, propertyName, slot))
+ // https://html.spec.whatwg.org/#crossorigingetownpropertyhelper-(-o,-p-)
+ if (propertyName == exec->propertyNames().toStringTagSymbol || propertyName == exec->propertyNames().hasInstanceSymbol || propertyName == exec->propertyNames().isConcatSpreadableSymbol) {
+ slot.setValue(thisObject, ReadOnly | DontEnum, jsUndefined());
return true;
-
- // We need this code here because otherwise JSDOMWindowBase will stop the search before we even get to the
- // prototype due to the blanket same origin (shouldAllowAccessToDOMWindow) check at the end of getOwnPropertySlot.
- // Also, it's important to get the implementation straight out of the DOMWindow prototype regardless of
- // what prototype is actually set on this object.
- entry = JSDOMWindowPrototype::info()->propHashTable(exec)->entry(exec, propertyName);
- if (entry) {
- if (entry->attributes() & JSC::Function) {
- if (entry->function() == jsDOMWindowPrototypeFunctionBlur) {
- if (!allowsAccess) {
- slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionBlur, 0>);
- return true;
- }
- } else if (entry->function() == jsDOMWindowPrototypeFunctionClose) {
- if (!allowsAccess) {
- slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionClose, 0>);
- return true;
- }
- } else if (entry->function() == jsDOMWindowPrototypeFunctionFocus) {
- if (!allowsAccess) {
- slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionFocus, 0>);
- return true;
- }
- } else if (entry->function() == jsDOMWindowPrototypeFunctionPostMessage) {
- if (!allowsAccess) {
- slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowPrototypeFunctionPostMessage, 2>);
- return true;
- }
- } else if (entry->function() == jsDOMWindowPrototypeFunctionShowModalDialog) {
- if (!DOMWindow::canShowModalDialog(thisObject->impl().frame())) {
- slot.setUndefined();
- return true;
- }
- }
- }
- } else {
- // Allow access to toString() cross-domain, but always Object.prototype.toString.
- if (propertyName == exec->propertyNames().toString) {
- if (!allowsAccess) {
- slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, objectToStringFunctionGetter);
- return true;
- }
- }
}
- entry = JSDOMWindow::info()->propHashTable(exec)->entry(exec, propertyName);
- if (entry) {
- slot.setCustom(thisObject, allowsAccess ? entry->attributes() : ReadOnly | DontDelete | DontEnum, entry->propertyGetter());
+ // These are the functions we allow access to cross-origin (DoNotCheckSecurity in IDL).
+ // Always provide the original function, on a fresh uncached function object.
+ if (propertyName == exec->propertyNames().blur) {
+ slot.setCustom(thisObject, ReadOnly | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionBlur, 0>);
return true;
}
-
- // Check for child frames by name before built-in properties to
- // match Mozilla. This does not match IE, but some sites end up
- // naming frames things that conflict with window properties that
- // are in Moz but not IE. Since we have some of these, we have to do
- // it the Moz way.
- if (thisObject->impl().frame()->tree().scopedChild(propertyNameToAtomicString(propertyName))) {
- slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, childFrameGetter);
+ if (propertyName == exec->propertyNames().close) {
+ slot.setCustom(thisObject, ReadOnly | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionClose, 0>);
return true;
}
-
- // Do prototype lookup early so that functions and attributes in the prototype can have
- // precedence over the index and name getters.
- JSValue proto = thisObject->prototype();
- if (proto.isObject()) {
- if (asObject(proto)->getPropertySlot(exec, propertyName, slot)) {
- if (!allowsAccess) {
- thisObject->printErrorMessage(errorMessage);
- slot.setUndefined();
- }
- return true;
- }
- }
-
- // FIXME: Search the whole frame hierarchy somewhere around here.
- // We need to test the correct priority order.
-
- // allow window[1] or parent[1] etc. (#56983)
- unsigned i = propertyName.asIndex();
- if (i < thisObject->impl().frame()->tree().scopedChildCount()) {
- ASSERT(i != PropertyName::NotAnIndex);
- slot.setCustomIndex(thisObject, ReadOnly | DontDelete | DontEnum, i, indexGetter);
+ if (propertyName == exec->propertyNames().focus) {
+ slot.setCustom(thisObject, ReadOnly | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionFocus, 0>);
return true;
}
-
- if (!allowsAccess) {
- thisObject->printErrorMessage(errorMessage);
- slot.setUndefined();
+ if (propertyName == exec->propertyNames().postMessage) {
+ slot.setCustom(thisObject, ReadOnly | DontEnum, nonCachingStaticFunctionGetter<jsDOMWindowInstanceFunctionPostMessage, 2>);
return true;
}
- // Allow shortcuts like 'Image1' instead of document.images.Image1
- Document* document = thisObject->impl().frame()->document();
- if (document->isHTMLDocument()) {
- AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName);
- if (atomicPropertyName && toHTMLDocument(document)->hasWindowNamedItem(*atomicPropertyName)) {
- slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, namedItemGetter);
+ // When accessing cross-origin known Window properties, we always use the original property getter,
+ // even if the property was removed / redefined. As of early 2016, this matches Firefox and Chrome's
+ // behavior.
+ if (auto* entry = JSDOMWindow::info()->staticPropHashTable->entry(propertyName)) {
+ // Only allow access to these specific properties.
+ if (propertyName == exec->propertyNames().location
+ || propertyName == exec->propertyNames().closed
+ || propertyName == exec->propertyNames().length
+ || propertyName == exec->propertyNames().self
+ || propertyName == exec->propertyNames().window
+ || propertyName == exec->propertyNames().frames
+ || propertyName == exec->propertyNames().opener
+ || propertyName == exec->propertyNames().parent
+ || propertyName == exec->propertyNames().top) {
+ bool shouldExposeSetter = propertyName == exec->propertyNames().location;
+ CustomGetterSetter* customGetterSetter = CustomGetterSetter::create(vm, entry->propertyGetter(), shouldExposeSetter ? entry->propertyPutter() : nullptr);
+ slot.setCustomGetterSetter(thisObject, DontEnum | CustomAccessor, customGetterSetter);
return true;
}
+
+ // For any other entries in the static property table, deny access. (Early return also prevents
+ // named getter from returning frames with matching names - this seems a little questionable, see
+ // FIXME comment on prototype search below.)
+ throwSecurityError(*exec, scope, errorMessage);
+ slot.setUndefined();
+ return false;
}
- return Base::getOwnPropertySlot(thisObject, exec, propertyName, slot);
+ // Check for child frames by name before built-in properties to match Mozilla. This does
+ // not match IE, but some sites end up naming frames things that conflict with window
+ // properties that are in Moz but not IE. Since we have some of these, we have to do it
+ // the Moz way.
+ if (auto* scopedChild = frame->tree().scopedChild(propertyNameToAtomicString(propertyName))) {
+ slot.setValue(thisObject, ReadOnly | DontDelete | DontEnum, toJS(exec, scopedChild->document()->domWindow()));
+ return true;
+ }
+
+ throwSecurityError(*exec, scope, errorMessage);
+ slot.setUndefined();
+ return false;
}
-bool JSDOMWindow::getOwnPropertySlotByIndex(JSObject* object, ExecState* exec, unsigned index, PropertySlot& slot)
+// Property access sequence is:
+// (1) indexed properties,
+// (2) regular own properties,
+// (3) named properties (in fact, these shouldn't be on the window, should be on the NPO).
+bool JSDOMWindow::getOwnPropertySlot(JSObject* object, ExecState* state, PropertyName propertyName, PropertySlot& slot)
{
- JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
-
- if (!thisObject->impl().frame()) {
- // FIXME: We should have a message here that explains why the property access/function call was
- // not allowed.
- slot.setUndefined();
- return true;
- }
+ // (1) First, indexed properties.
+ // Hand off all indexed access to getOwnPropertySlotByIndex, which supports the indexed getter.
+ if (std::optional<unsigned> index = parseIndex(propertyName))
+ return getOwnPropertySlotByIndex(object, state, index.value(), slot);
- // We need to check for cross-domain access here without printing the generic warning message
- // because we always allow access to some function, just different ones depending whether access
- // is allowed.
- String errorMessage;
- bool allowsAccess = shouldAllowAccessToDOMWindow(exec, thisObject->impl(), errorMessage);
+ auto* thisObject = jsCast<JSDOMWindow*>(object);
+ auto* frame = thisObject->wrapped().frame();
- // Look for overrides before looking at any of our own properties, but ignore overrides completely
- // if this is cross-domain access.
- if (allowsAccess && JSGlobalObject::getOwnPropertySlotByIndex(thisObject, exec, index, slot))
- return true;
-
- PropertyName propertyName = Identifier::from(exec, index);
-
- // Check for child frames by name before built-in properties to
- // match Mozilla. This does not match IE, but some sites end up
- // naming frames things that conflict with window properties that
- // are in Moz but not IE. Since we have some of these, we have to do
- // it the Moz way.
- if (thisObject->impl().frame()->tree().scopedChild(propertyNameToAtomicString(propertyName))) {
- slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, childFrameGetter);
- return true;
- }
+ // Hand off all cross-domain/frameless access to jsDOMWindowGetOwnPropertySlotRestrictedAccess.
+ String errorMessage;
+ if (!frame || !BindingSecurity::shouldAllowAccessToDOMWindow(*state, thisObject->wrapped(), errorMessage))
+ return jsDOMWindowGetOwnPropertySlotRestrictedAccess(thisObject, frame, state, propertyName, slot, errorMessage);
- // Do prototype lookup early so that functions and attributes in the prototype can have
- // precedence over the index and name getters.
- JSValue proto = thisObject->prototype();
- if (proto.isObject()) {
- if (asObject(proto)->getPropertySlot(exec, index, slot)) {
- if (!allowsAccess) {
- thisObject->printErrorMessage(errorMessage);
- slot.setUndefined();
- }
+ // FIXME: this need more explanation.
+ // (Particularly, is it correct that this exists here but not in getOwnPropertySlotByIndex?)
+ slot.setWatchpointSet(thisObject->m_windowCloseWatchpoints);
+
+ // (2) Regular own properties.
+ PropertySlot slotCopy = slot;
+ if (Base::getOwnPropertySlot(thisObject, state, propertyName, slot)) {
+ // Detect when we're getting the property 'showModalDialog', this is disabled, and has its original value.
+ bool isShowModalDialogAndShouldHide = propertyName == state->propertyNames().showModalDialog
+ && !DOMWindow::canShowModalDialog(*frame)
+ && slot.isValue() && isHostFunction(slot.getValue(state, propertyName), jsDOMWindowInstanceFunctionShowModalDialog);
+ // Unless we're in the showModalDialog special case, we're done.
+ if (!isShowModalDialogAndShouldHide)
return true;
- }
+ slot = slotCopy;
}
- // FIXME: Search the whole frame hierarchy somewhere around here.
- // We need to test the correct priority order.
-
- // allow window[1] or parent[1] etc. (#56983)
- if (index < thisObject->impl().frame()->tree().scopedChildCount()) {
- ASSERT(index != PropertyName::NotAnIndex);
- slot.setCustomIndex(thisObject, ReadOnly | DontDelete | DontEnum, index, indexGetter);
+#if ENABLE(USER_MESSAGE_HANDLERS)
+ if (propertyName == state->propertyNames().webkit && thisObject->wrapped().shouldHaveWebKitNamespaceForWorld(thisObject->world())) {
+ slot.setCacheableCustom(thisObject, DontDelete | ReadOnly, jsDOMWindowWebKit);
return true;
}
+#endif
- if (!allowsAccess) {
- thisObject->printErrorMessage(errorMessage);
- slot.setUndefined();
+ return false;
+}
+
+// Property access sequence is:
+// (1) indexed properties,
+// (2) regular own properties,
+// (3) named properties (in fact, these shouldn't be on the window, should be on the NPO).
+bool JSDOMWindow::getOwnPropertySlotByIndex(JSObject* object, ExecState* state, unsigned index, PropertySlot& slot)
+{
+ auto* thisObject = jsCast<JSDOMWindow*>(object);
+ auto* frame = thisObject->wrapped().frame();
+
+ // Indexed getters take precendence over regular properties, so caching would be invalid.
+ slot.disableCaching();
+
+ // (1) First, indexed properties.
+ // These are also allowed cross-orgin, so come before the access check.
+ if (frame && index < frame->tree().scopedChildCount()) {
+ slot.setValue(thisObject, ReadOnly | DontEnum, toJS(state, frame->tree().scopedChild(index)->document()->domWindow()));
return true;
}
- // Allow shortcuts like 'Image1' instead of document.images.Image1
- Document* document = thisObject->impl().frame()->document();
- if (document->isHTMLDocument()) {
- AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName);
- if (atomicPropertyName && toHTMLDocument(document)->hasWindowNamedItem(*atomicPropertyName)) {
- slot.setCustom(thisObject, ReadOnly | DontDelete | DontEnum, namedItemGetter);
- return true;
- }
- }
+ // Hand off all cross-domain/frameless access to jsDOMWindowGetOwnPropertySlotRestrictedAccess.
+ String errorMessage;
+ if (!frame || !BindingSecurity::shouldAllowAccessToDOMWindow(*state, thisObject->wrapped(), errorMessage))
+ return jsDOMWindowGetOwnPropertySlotRestrictedAccess(thisObject, frame, state, Identifier::from(state, index), slot, errorMessage);
- return Base::getOwnPropertySlotByIndex(thisObject, exec, index, slot);
+ // (2) Regular own properties.
+ return Base::getOwnPropertySlotByIndex(thisObject, state, index, slot);
}
-void JSDOMWindow::put(JSCell* cell, ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
+bool JSDOMWindow::put(JSCell* cell, ExecState* state, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
{
- JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(cell);
- if (!thisObject->impl().frame())
- return;
+ VM& vm = state->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
- // Optimization: access JavaScript global variables directly before involving the DOM.
- if (thisObject->JSGlobalObject::hasOwnPropertyForWrite(exec, propertyName)) {
- if (BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl()))
- JSGlobalObject::put(thisObject, exec, propertyName, value, slot);
- return;
- }
+ auto* thisObject = jsCast<JSDOMWindow*>(cell);
+ if (!thisObject->wrapped().frame())
+ return false;
- if (lookupPut(exec, propertyName, thisObject, value, *s_info.propHashTable(exec), slot))
- return;
+ String errorMessage;
+ if (!BindingSecurity::shouldAllowAccessToDOMWindow(*state, thisObject->wrapped(), errorMessage)) {
+ // We only allow setting "location" attribute cross-origin.
+ if (propertyName == state->propertyNames().location) {
+ bool putResult = false;
+ if (lookupPut(state, propertyName, thisObject, value, *s_info.staticPropHashTable, slot, putResult))
+ return putResult;
+ return false;
+ }
+ throwSecurityError(*state, scope, errorMessage);
+ return false;
+ }
- if (BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl()))
- Base::put(thisObject, exec, propertyName, value, slot);
+ return Base::put(thisObject, state, propertyName, value, slot);
}
-void JSDOMWindow::putByIndex(JSCell* cell, ExecState* exec, unsigned index, JSValue value, bool shouldThrow)
+bool JSDOMWindow::putByIndex(JSCell* cell, ExecState* exec, unsigned index, JSValue value, bool shouldThrow)
{
- JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(cell);
- if (!thisObject->impl().frame())
- return;
-
- PropertyName propertyName = Identifier::from(exec, index);
-
- // Optimization: access JavaScript global variables directly before involving the DOM.
- if (thisObject->JSGlobalObject::hasOwnPropertyForWrite(exec, propertyName)) {
- if (BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl()))
- JSGlobalObject::putByIndex(thisObject, exec, index, value, shouldThrow);
- return;
- }
+ auto* thisObject = jsCast<JSDOMWindow*>(cell);
+ if (!thisObject->wrapped().frame() || !BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped()))
+ return false;
- if (BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl()))
- Base::putByIndex(thisObject, exec, index, value, shouldThrow);
+ return Base::putByIndex(thisObject, exec, index, value, shouldThrow);
}
bool JSDOMWindow::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
{
JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(cell);
// Only allow deleting properties by frames in the same origin.
- if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl()))
+ if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), ThrowSecurityError))
return false;
return Base::deleteProperty(thisObject, exec, propertyName);
}
@@ -383,26 +286,128 @@ bool JSDOMWindow::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned
{
JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(cell);
// Only allow deleting properties by frames in the same origin.
- if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl()))
+ if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), ThrowSecurityError))
return false;
return Base::deletePropertyByIndex(thisObject, exec, propertyName);
}
+uint32_t JSDOMWindow::getEnumerableLength(ExecState* exec, JSObject* object)
+{
+ JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
+ // Only allow the window to enumerated by frames in the same origin.
+ if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped()))
+ return 0;
+ return Base::getEnumerableLength(exec, thisObject);
+}
+
+void JSDOMWindow::getStructurePropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+ JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
+ // Only allow the window to enumerated by frames in the same origin.
+ if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped()))
+ return;
+ Base::getStructurePropertyNames(thisObject, exec, propertyNames, mode);
+}
+
+void JSDOMWindow::getGenericPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+{
+ JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
+ // Only allow the window to enumerated by frames in the same origin.
+ if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped()))
+ return;
+ Base::getGenericPropertyNames(thisObject, exec, propertyNames, mode);
+}
+
void JSDOMWindow::getPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
{
JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
// Only allow the window to enumerated by frames in the same origin.
- if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl()))
+ if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped()))
return;
Base::getPropertyNames(thisObject, exec, propertyNames, mode);
}
+static bool inScope(Frame& frame, TreeScope& scope)
+{
+ auto* document = frame.document();
+ if (!document)
+ return false;
+ auto* owner = document->ownerElement();
+ return owner && &owner->treeScope() == &scope;
+}
+
+static void addScopedChildrenNames(ExecState& state, DOMWindow& window, PropertyNameArray& propertyNames)
+{
+ auto* document = window.document();
+ if (!document)
+ return;
+
+ auto* frame = document->frame();
+ if (!frame)
+ return;
+
+ for (auto* child = frame->tree().firstChild(); child; child = child->tree().nextSibling()) {
+ if (!inScope(*child, *document))
+ continue;
+ if (!child->tree().name().isEmpty())
+ propertyNames.add(Identifier::fromString(&state, child->tree().name()));
+ }
+}
+
+// https://html.spec.whatwg.org/#crossoriginproperties-(-o-)
+static void addCrossOriginPropertyNames(ExecState& state, DOMWindow& window, PropertyNameArray& propertyNames)
+{
+ static const Identifier* const properties[] = {
+ &state.propertyNames().blur, &state.propertyNames().close, &state.propertyNames().closed,
+ &state.propertyNames().focus, &state.propertyNames().frames, &state.propertyNames().length,
+ &state.propertyNames().location, &state.propertyNames().opener, &state.propertyNames().parent,
+ &state.propertyNames().postMessage, &state.propertyNames().self, &state.propertyNames().top,
+ &state.propertyNames().window
+ };
+ for (auto* property : properties)
+ propertyNames.add(*property);
+
+ addScopedChildrenNames(state, window, propertyNames);
+}
+
+static void addScopedChildrenIndexes(ExecState& state, DOMWindow& window, PropertyNameArray& propertyNames)
+{
+ auto* document = window.document();
+ if (!document)
+ return;
+
+ auto* frame = document->frame();
+ if (!frame)
+ return;
+
+ unsigned scopedChildCount = frame->tree().scopedChildCount();
+ for (unsigned i = 0; i < scopedChildCount; ++i)
+ propertyNames.add(Identifier::from(&state, i));
+}
+
+// https://html.spec.whatwg.org/#crossoriginownpropertykeys-(-o-)
+static void addCrossOriginOwnPropertyNames(ExecState& state, DOMWindow& window, PropertyNameArray& propertyNames)
+{
+ addCrossOriginPropertyNames(state, window, propertyNames);
+
+ propertyNames.add(state.propertyNames().toStringTagSymbol);
+ propertyNames.add(state.propertyNames().hasInstanceSymbol);
+ propertyNames.add(state.propertyNames().isConcatSpreadableSymbol);
+}
+
+// https://html.spec.whatwg.org/#windowproxy-ownpropertykeys
void JSDOMWindow::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
{
JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
- // Only allow the window to enumerated by frames in the same origin.
- if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl()))
+
+ if (mode.includeDontEnumProperties())
+ addScopedChildrenIndexes(*exec, thisObject->wrapped(), propertyNames);
+
+ if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), DoNotReportSecurityError)) {
+ if (mode.includeDontEnumProperties())
+ addCrossOriginOwnPropertyNames(*exec, thisObject->wrapped(), propertyNames);
return;
+ }
Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
}
@@ -410,88 +415,99 @@ bool JSDOMWindow::defineOwnProperty(JSC::JSObject* object, JSC::ExecState* exec,
{
JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
// Only allow defining properties in this way by frames in the same origin, as it allows setters to be introduced.
- if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->impl()))
+ if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), ThrowSecurityError))
return false;
// Don't allow shadowing location using accessor properties.
- if (descriptor.isAccessorDescriptor() && propertyName == Identifier(exec, "location"))
+ if (descriptor.isAccessorDescriptor() && propertyName == Identifier::fromString(exec, "location"))
return false;
return Base::defineOwnProperty(thisObject, exec, propertyName, descriptor, shouldThrow);
}
+JSValue JSDOMWindow::getPrototype(JSObject* object, ExecState* exec)
+{
+ JSDOMWindow* thisObject = jsCast<JSDOMWindow*>(object);
+ if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), DoNotReportSecurityError))
+ return jsNull();
+
+ return Base::getPrototype(object, exec);
+}
+
+bool JSDOMWindow::preventExtensions(JSObject*, ExecState* exec)
+{
+ auto scope = DECLARE_THROW_SCOPE(exec->vm());
+
+ throwTypeError(exec, scope, ASCIILiteral("Cannot prevent extensions on this object"));
+ return false;
+}
+
+String JSDOMWindow::toStringName(const JSObject* object, ExecState* exec)
+{
+ auto* thisObject = jsCast<const JSDOMWindow*>(object);
+ if (!BindingSecurity::shouldAllowAccessToDOMWindow(exec, thisObject->wrapped(), DoNotReportSecurityError))
+ return ASCIILiteral("Object");
+ return ASCIILiteral("Window");
+}
+
// Custom Attributes
-void JSDOMWindow::setLocation(ExecState* exec, JSValue value)
+void JSDOMWindow::setLocation(ExecState& state, JSValue value)
{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
#if ENABLE(DASHBOARD_SUPPORT)
// To avoid breaking old widgets, make "var location =" in a top-level frame create
// a property named "location" instead of performing a navigation (<rdar://problem/5688039>).
- if (Frame* activeFrame = activeDOMWindow(exec).frame()) {
+ if (Frame* activeFrame = activeDOMWindow(&state).frame()) {
if (activeFrame->settings().usesDashboardBackwardCompatibilityMode() && !activeFrame->tree().parent()) {
- if (BindingSecurity::shouldAllowAccessToDOMWindow(exec, impl()))
- putDirect(exec->vm(), Identifier(exec, "location"), value);
+ if (BindingSecurity::shouldAllowAccessToDOMWindow(&state, wrapped()))
+ putDirect(state.vm(), Identifier::fromString(&state, "location"), value);
return;
}
}
#endif
- String locationString = value.toString(exec)->value(exec);
- if (exec->hadException())
- return;
+ String locationString = value.toWTFString(&state);
+ RETURN_IF_EXCEPTION(scope, void());
- if (Location* location = impl().location())
- location->setHref(locationString, activeDOMWindow(exec), firstDOMWindow(exec));
+ if (Location* location = wrapped().location())
+ location->setHref(activeDOMWindow(&state), firstDOMWindow(&state), locationString);
}
-JSValue JSDOMWindow::event(ExecState* exec) const
+JSValue JSDOMWindow::event(ExecState& state) const
{
Event* event = currentEvent();
if (!event)
return jsUndefined();
- return toJS(exec, const_cast<JSDOMWindow*>(this), event);
-}
-
-JSValue JSDOMWindow::image(ExecState* exec) const
-{
- return getDOMConstructor<JSImageConstructor>(exec->vm(), this);
-}
-
-#if ENABLE(IOS_TOUCH_EVENTS)
-JSValue JSDOMWindow::touch(ExecState* exec) const
-{
- return getDOMConstructor<JSTouchConstructor>(exec->vm(), this);
+ return toJS(&state, const_cast<JSDOMWindow*>(this), event);
}
-JSValue JSDOMWindow::touchList(ExecState* exec) const
-{
- return getDOMConstructor<JSTouchListConstructor>(exec->vm(), this);
-}
-#endif
-
// Custom functions
-JSValue JSDOMWindow::open(ExecState* exec)
+JSValue JSDOMWindow::open(ExecState& state)
{
- String urlString = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0));
- if (exec->hadException())
- return jsUndefined();
- AtomicString frameName = exec->argument(1).isUndefinedOrNull() ? "_blank" : exec->argument(1).toString(exec)->value(exec);
- if (exec->hadException())
- return jsUndefined();
- String windowFeaturesString = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(2));
- if (exec->hadException())
- return jsUndefined();
-
- RefPtr<DOMWindow> openedWindow = impl().open(urlString, frameName, windowFeaturesString, activeDOMWindow(exec), firstDOMWindow(exec));
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ String urlString = convert<IDLNullable<IDLUSVString>>(state, state.argument(0));
+ RETURN_IF_EXCEPTION(scope, JSValue());
+ JSValue targetValue = state.argument(1);
+ AtomicString target = targetValue.isUndefinedOrNull() ? AtomicString("_blank", AtomicString::ConstructFromLiteral) : targetValue.toString(&state)->toAtomicString(&state);
+ RETURN_IF_EXCEPTION(scope, JSValue());
+ String windowFeaturesString = convert<IDLNullable<IDLDOMString>>(state, state.argument(2));
+ RETURN_IF_EXCEPTION(scope, JSValue());
+
+ RefPtr<DOMWindow> openedWindow = wrapped().open(urlString, target, windowFeaturesString, activeDOMWindow(&state), firstDOMWindow(&state));
if (!openedWindow)
- return jsUndefined();
- return toJS(exec, openedWindow.get());
+ return jsNull();
+ return toJS(&state, openedWindow.get());
}
class DialogHandler {
public:
- explicit DialogHandler(ExecState* exec)
+ explicit DialogHandler(ExecState& exec)
: m_exec(exec)
{
}
@@ -500,7 +516,7 @@ public:
JSValue returnValue() const;
private:
- ExecState* m_exec;
+ ExecState& m_exec;
RefPtr<Frame> m_frame;
};
@@ -510,162 +526,91 @@ inline void DialogHandler::dialogCreated(DOMWindow& dialog)
// FIXME: This looks like a leak between the normal world and an isolated
// world if dialogArguments comes from an isolated world.
- JSDOMWindow* globalObject = toJSDOMWindow(m_frame.get(), normalWorld(m_exec->vm()));
- if (JSValue dialogArguments = m_exec->argument(1))
- globalObject->putDirect(m_exec->vm(), Identifier(m_exec, "dialogArguments"), dialogArguments);
+ JSDOMWindow* globalObject = toJSDOMWindow(m_frame.get(), normalWorld(m_exec.vm()));
+ if (JSValue dialogArguments = m_exec.argument(1))
+ globalObject->putDirect(m_exec.vm(), Identifier::fromString(&m_exec, "dialogArguments"), dialogArguments);
}
inline JSValue DialogHandler::returnValue() const
{
- JSDOMWindow* globalObject = toJSDOMWindow(m_frame.get(), normalWorld(m_exec->vm()));
+ JSDOMWindow* globalObject = toJSDOMWindow(m_frame.get(), normalWorld(m_exec.vm()));
if (!globalObject)
return jsUndefined();
- Identifier identifier(m_exec, "returnValue");
- PropertySlot slot(globalObject);
- if (!JSGlobalObject::getOwnPropertySlot(globalObject, m_exec, identifier, slot))
+ Identifier identifier = Identifier::fromString(&m_exec, "returnValue");
+ PropertySlot slot(globalObject, PropertySlot::InternalMethodType::Get);
+ if (!JSGlobalObject::getOwnPropertySlot(globalObject, &m_exec, identifier, slot))
return jsUndefined();
- return slot.getValue(m_exec, identifier);
+ return slot.getValue(&m_exec, identifier);
}
-JSValue JSDOMWindow::showModalDialog(ExecState* exec)
+JSValue JSDOMWindow::showModalDialog(ExecState& state)
{
- String urlString = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0));
- if (exec->hadException())
- return jsUndefined();
- String dialogFeaturesString = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(2));
- if (exec->hadException())
- return jsUndefined();
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (UNLIKELY(state.argumentCount() < 1))
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+
+ String urlString = convert<IDLNullable<IDLDOMString>>(state, state.argument(0));
+ RETURN_IF_EXCEPTION(scope, JSValue());
+ String dialogFeaturesString = convert<IDLNullable<IDLDOMString>>(state, state.argument(2));
+ RETURN_IF_EXCEPTION(scope, JSValue());
- DialogHandler handler(exec);
+ DialogHandler handler(state);
- impl().showModalDialog(urlString, dialogFeaturesString, activeDOMWindow(exec), firstDOMWindow(exec), [&handler](DOMWindow& dialog) {
+ wrapped().showModalDialog(urlString, dialogFeaturesString, activeDOMWindow(&state), firstDOMWindow(&state), [&handler](DOMWindow& dialog) {
handler.dialogCreated(dialog);
});
return handler.returnValue();
}
-static JSValue handlePostMessage(DOMWindow* impl, ExecState* exec)
+JSValue JSDOMWindow::setTimeout(ExecState& state)
{
- MessagePortArray messagePorts;
- ArrayBufferArray arrayBuffers;
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
- // This function has variable arguments and can be:
- // Per current spec:
- // postMessage(message, targetOrigin)
- // postMessage(message, targetOrigin, {sequence of transferrables})
- // Legacy non-standard implementations in webkit allowed:
- // postMessage(message, {sequence of transferrables}, targetOrigin);
- int targetOriginArgIndex = 1;
- if (exec->argumentCount() > 2) {
- int transferablesArgIndex = 2;
- if (exec->argument(2).isString()) {
- targetOriginArgIndex = 2;
- transferablesArgIndex = 1;
- }
- fillMessagePortArray(exec, exec->argument(transferablesArgIndex), messagePorts, arrayBuffers);
- }
- if (exec->hadException())
- return jsUndefined();
-
- RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(exec, exec->argument(0),
- &messagePorts,
- &arrayBuffers);
-
- if (exec->hadException())
- return jsUndefined();
-
- String targetOrigin = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(targetOriginArgIndex));
- if (exec->hadException())
- return jsUndefined();
-
- ExceptionCode ec = 0;
- impl->postMessage(message.release(), &messagePorts, targetOrigin, activeDOMWindow(exec), ec);
- setDOMException(exec, ec);
-
- return jsUndefined();
-}
-
-JSValue JSDOMWindow::postMessage(ExecState* exec)
-{
- return handlePostMessage(&impl(), exec);
-}
-
-JSValue JSDOMWindow::setTimeout(ExecState* exec)
-{
- ContentSecurityPolicy* contentSecurityPolicy = impl().document() ? impl().document()->contentSecurityPolicy() : 0;
- OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, currentWorld(exec), contentSecurityPolicy);
- if (exec->hadException())
- return jsUndefined();
+ if (UNLIKELY(state.argumentCount() < 1))
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+ auto* contentSecurityPolicy = wrapped().document() ? wrapped().document()->contentSecurityPolicy() : nullptr;
+ auto action = ScheduledAction::create(&state, globalObject()->world(), contentSecurityPolicy);
+ RETURN_IF_EXCEPTION(scope, JSValue());
if (!action)
return jsNumber(0);
- int delay = exec->argument(1).toInt32(exec);
-
- ExceptionCode ec = 0;
- int result = impl().setTimeout(action.release(), delay, ec);
- setDOMException(exec, ec);
-
- return jsNumber(result);
+ int delay = state.argument(1).toInt32(&state);
+ return toJS<IDLLong>(state, scope, wrapped().setTimeout(WTFMove(action), delay));
}
-JSValue JSDOMWindow::setInterval(ExecState* exec)
+JSValue JSDOMWindow::setInterval(ExecState& state)
{
- ContentSecurityPolicy* contentSecurityPolicy = impl().document() ? impl().document()->contentSecurityPolicy() : 0;
- OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, currentWorld(exec), contentSecurityPolicy);
- if (exec->hadException())
- return jsUndefined();
- int delay = exec->argument(1).toInt32(exec);
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ if (UNLIKELY(state.argumentCount() < 1))
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+
+ auto* contentSecurityPolicy = wrapped().document() ? wrapped().document()->contentSecurityPolicy() : nullptr;
+ auto action = ScheduledAction::create(&state, globalObject()->world(), contentSecurityPolicy);
+ RETURN_IF_EXCEPTION(scope, JSValue());
if (!action)
return jsNumber(0);
- ExceptionCode ec = 0;
- int result = impl().setInterval(action.release(), delay, ec);
- setDOMException(exec, ec);
-
- return jsNumber(result);
-}
-
-JSValue JSDOMWindow::addEventListener(ExecState* exec)
-{
- Frame* frame = impl().frame();
- if (!frame)
- return jsUndefined();
-
- JSValue listener = exec->argument(1);
- if (!listener.isObject())
- return jsUndefined();
-
- impl().addEventListener(exec->argument(0).toString(exec)->value(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)), exec->argument(2).toBoolean(exec));
- return jsUndefined();
+ int delay = state.argument(1).toInt32(&state);
+ return toJS<IDLLong>(state, scope, wrapped().setInterval(WTFMove(action), delay));
}
-JSValue JSDOMWindow::removeEventListener(ExecState* exec)
-{
- Frame* frame = impl().frame();
- if (!frame)
- return jsUndefined();
-
- JSValue listener = exec->argument(1);
- if (!listener.isObject())
- return jsUndefined();
-
- impl().removeEventListener(exec->argument(0).toString(exec)->value(exec), JSEventListener::create(asObject(listener), this, false, currentWorld(exec)).get(), exec->argument(2).toBoolean(exec));
- return jsUndefined();
-}
-
-DOMWindow* toDOMWindow(JSValue value)
+DOMWindow* JSDOMWindow::toWrapped(VM& vm, JSValue value)
{
if (!value.isObject())
- return 0;
+ return nullptr;
JSObject* object = asObject(value);
- if (object->inherits(JSDOMWindow::info()))
- return &jsCast<JSDOMWindow*>(object)->impl();
- if (object->inherits(JSDOMWindowShell::info()))
- return &jsCast<JSDOMWindowShell*>(object)->impl();
- return 0;
+ if (object->inherits(vm, JSDOMWindow::info()))
+ return &jsCast<JSDOMWindow*>(object)->wrapped();
+ if (object->inherits(vm, JSDOMWindowShell::info()))
+ return &jsCast<JSDOMWindowShell*>(object)->wrapped();
+ return nullptr;
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMWindowCustom.h b/Source/WebCore/bindings/js/JSDOMWindowCustom.h
index b72ff0d05..ab629d6dc 100644
--- a/Source/WebCore/bindings/js/JSDOMWindowCustom.h
+++ b/Source/WebCore/bindings/js/JSDOMWindowCustom.h
@@ -16,8 +16,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef JSDOMWindowCustom_h
-#define JSDOMWindowCustom_h
+#pragma once
#include "JSDOMWindow.h"
#include "JSDOMWindowShell.h"
@@ -34,6 +33,4 @@ inline const JSDOMWindow* asJSDOMWindow(const JSC::JSGlobalObject* globalObject)
return static_cast<const JSDOMWindow*>(globalObject);
}
-}
-
-#endif // JSDOMWindowCustom_h
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMWindowProperties.cpp b/Source/WebCore/bindings/js/JSDOMWindowProperties.cpp
new file mode 100644
index 000000000..c364f2fde
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMWindowProperties.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSDOMWindowProperties.h"
+
+#include "Frame.h"
+#include "HTMLDocument.h"
+#include "JSDOMBinding.h"
+#include "JSDOMBindingSecurity.h"
+#include "JSDOMWindowBase.h"
+#include "JSElement.h"
+#include "JSHTMLCollection.h"
+
+namespace WebCore {
+
+using namespace JSC;
+
+const ClassInfo JSDOMWindowProperties::s_info = { "WindowProperties", &Base::s_info, 0, CREATE_METHOD_TABLE(JSDOMWindowProperties) };
+
+static bool jsDOMWindowPropertiesGetOwnPropertySlotNamedItemGetter(JSDOMWindowProperties* thisObject, Frame& frame, ExecState* exec, PropertyName propertyName, PropertySlot& slot)
+{
+ // Check for child frames by name before built-in properties to match Mozilla. This does
+ // not match IE, but some sites end up naming frames things that conflict with window
+ // properties that are in Moz but not IE. Since we have some of these, we have to do it
+ // the Moz way.
+ if (auto* scopedChild = frame.tree().scopedChild(propertyNameToAtomicString(propertyName))) {
+ slot.setValue(thisObject, ReadOnly | DontDelete | DontEnum, toJS(exec, scopedChild->document()->domWindow()));
+ return true;
+ }
+
+ if (!BindingSecurity::shouldAllowAccessToFrame(exec, &frame, ThrowSecurityError))
+ return false;
+
+ // FIXME: Search the whole frame hierarchy somewhere around here.
+ // We need to test the correct priority order.
+
+ // Allow shortcuts like 'Image1' instead of document.images.Image1
+ Document* document = frame.document();
+ if (is<HTMLDocument>(*document)) {
+ auto& htmlDocument = downcast<HTMLDocument>(*document);
+ auto* atomicPropertyName = propertyName.publicName();
+ if (atomicPropertyName && htmlDocument.hasWindowNamedItem(*atomicPropertyName)) {
+ JSValue namedItem;
+ if (UNLIKELY(htmlDocument.windowNamedItemContainsMultipleElements(*atomicPropertyName))) {
+ Ref<HTMLCollection> collection = document->windowNamedItems(atomicPropertyName);
+ ASSERT(collection->length() > 1);
+ namedItem = toJS(exec, thisObject->globalObject(), collection);
+ } else
+ namedItem = toJS(exec, thisObject->globalObject(), htmlDocument.windowNamedItem(*atomicPropertyName));
+ slot.setValue(thisObject, ReadOnly | DontDelete | DontEnum, namedItem);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool JSDOMWindowProperties::getOwnPropertySlot(JSObject* object, ExecState* state, PropertyName propertyName, PropertySlot& slot)
+{
+ auto* thisObject = jsCast<JSDOMWindowProperties*>(object);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+ if (Base::getOwnPropertySlot(thisObject, state, propertyName, slot))
+ return true;
+ JSValue proto = thisObject->getPrototypeDirect();
+ if (proto.isObject() && jsCast<JSObject*>(proto)->hasProperty(state, propertyName))
+ return false;
+
+ auto& window = jsCast<JSDOMWindowBase*>(thisObject->globalObject())->wrapped();
+ if (auto* frame = window.frame())
+ return jsDOMWindowPropertiesGetOwnPropertySlotNamedItemGetter(thisObject, *frame, state, propertyName, slot);
+
+ return false;
+}
+
+bool JSDOMWindowProperties::getOwnPropertySlotByIndex(JSObject* object, ExecState* state, unsigned index, PropertySlot& slot)
+{
+ return getOwnPropertySlot(object, state, Identifier::from(state, index), slot);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMWindowProperties.h b/Source/WebCore/bindings/js/JSDOMWindowProperties.h
new file mode 100644
index 000000000..a3c47de31
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMWindowProperties.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "DOMWindow.h"
+#include "JSDOMWindow.h"
+#include "JSDOMWrapper.h"
+
+namespace WebCore {
+
+class JSDOMWindowProperties : public JSDOMObject {
+public:
+ static JSDOMWindowProperties* create(JSC::Structure* structure, JSC::JSGlobalObject& globalObject)
+ {
+ JSDOMWindowProperties* ptr = new (NotNull, JSC::allocateCell<JSDOMWindowProperties>(globalObject.vm().heap)) JSDOMWindowProperties(structure, globalObject);
+ ptr->finishCreation(globalObject.vm());
+ return ptr;
+ }
+
+ DECLARE_INFO;
+
+ static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
+ {
+ return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
+ }
+
+ static bool getOwnPropertySlot(JSC::JSObject*, JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&);
+ static bool getOwnPropertySlotByIndex(JSC::JSObject*, JSC::ExecState*, unsigned propertyName, JSC::PropertySlot&);
+
+ static const unsigned StructureFlags = JSC::GetOwnPropertySlotIsImpureForPropertyAbsence | JSC::InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | JSC::OverridesGetOwnPropertySlot | JSC::IsImmutablePrototypeExoticObject | Base::StructureFlags;
+
+protected:
+ JSDOMWindowProperties(JSC::Structure* structure, JSC::JSGlobalObject& globalObject)
+ : JSDOMObject(structure, globalObject)
+ { }
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMWindowShell.cpp b/Source/WebCore/bindings/js/JSDOMWindowShell.cpp
index b5fc83e99..a42a030e9 100644
--- a/Source/WebCore/bindings/js/JSDOMWindowShell.cpp
+++ b/Source/WebCore/bindings/js/JSDOMWindowShell.cpp
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -29,10 +29,12 @@
#include "config.h"
#include "JSDOMWindowShell.h"
+#include "CommonVM.h"
#include "Frame.h"
#include "GCController.h"
#include "JSDOMWindow.h"
-#include "DOMWindow.h"
+#include "JSDOMWindowProperties.h"
+#include "JSEventTarget.h"
#include "ScriptController.h"
#include <heap/StrongInlines.h>
#include <runtime/JSObject.h>
@@ -41,7 +43,7 @@ using namespace JSC;
namespace WebCore {
-const ClassInfo JSDOMWindowShell::s_info = { "JSDOMWindowShell", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSDOMWindowShell) };
+const ClassInfo JSDOMWindowShell::s_info = { "JSDOMWindowShell", &Base::s_info, 0, CREATE_METHOD_TABLE(JSDOMWindowShell) };
JSDOMWindowShell::JSDOMWindowShell(VM& vm, Structure* structure, DOMWrapperWorld& world)
: Base(vm, structure)
@@ -49,11 +51,11 @@ JSDOMWindowShell::JSDOMWindowShell(VM& vm, Structure* structure, DOMWrapperWorld
{
}
-void JSDOMWindowShell::finishCreation(VM& vm, PassRefPtr<DOMWindow> window)
+void JSDOMWindowShell::finishCreation(VM& vm, RefPtr<DOMWindow>&& window)
{
Base::finishCreation(vm);
- ASSERT(inherits(info()));
- setWindow(window);
+ ASSERT(inherits(vm, info()));
+ setWindow(WTFMove(window));
}
void JSDOMWindowShell::destroy(JSCell* cell)
@@ -66,25 +68,30 @@ void JSDOMWindowShell::setWindow(VM& vm, JSDOMWindow* window)
ASSERT_ARG(window, window);
setTarget(vm, window);
structure()->setGlobalObject(vm, window);
- gcController().garbageCollectSoon();
+ GCController::singleton().garbageCollectSoon();
}
-void JSDOMWindowShell::setWindow(PassRefPtr<DOMWindow> domWindow)
+void JSDOMWindowShell::setWindow(RefPtr<DOMWindow>&& domWindow)
{
// Replacing JSDOMWindow via telling JSDOMWindowShell to use the same DOMWindow it already uses makes no sense,
// so we'd better never try to.
- ASSERT(!window() || domWindow.get() != &window()->impl());
+ ASSERT(!window() || domWindow.get() != &window()->wrapped());
// Explicitly protect the global object's prototype so it isn't collected
// when we allocate the global object. (Once the global object is fully
// constructed, it can mark its own prototype.)
- VM& vm = *JSDOMWindow::commonVM();
+ VM& vm = commonVM();
Structure* prototypeStructure = JSDOMWindowPrototype::createStructure(vm, 0, jsNull());
Strong<JSDOMWindowPrototype> prototype(vm, JSDOMWindowPrototype::create(vm, 0, prototypeStructure));
Structure* structure = JSDOMWindow::createStructure(vm, 0, prototype.get());
- JSDOMWindow* jsDOMWindow = JSDOMWindow::create(vm, structure, domWindow, this);
+ JSDOMWindow* jsDOMWindow = JSDOMWindow::create(vm, structure, *domWindow, this);
prototype->structure()->setGlobalObject(vm, jsDOMWindow);
+
+ Structure* windowPropertiesStructure = JSDOMWindowProperties::createStructure(vm, jsDOMWindow, JSEventTarget::prototype(vm, jsDOMWindow));
+ JSDOMWindowProperties* windowProperties = JSDOMWindowProperties::create(windowPropertiesStructure, *jsDOMWindow);
+
+ prototype->structure()->setPrototypeWithoutTransition(vm, windowProperties);
setWindow(vm, jsDOMWindow);
ASSERT(jsDOMWindow->globalObject() == jsDOMWindow);
ASSERT(prototype->globalObject() == jsDOMWindow);
@@ -94,9 +101,17 @@ void JSDOMWindowShell::setWindow(PassRefPtr<DOMWindow> domWindow)
// JSDOMWindow methods
// ----
-DOMWindow& JSDOMWindowShell::impl() const
+DOMWindow& JSDOMWindowShell::wrapped() const
+{
+ return window()->wrapped();
+}
+
+DOMWindow* JSDOMWindowShell::toWrapped(VM& vm, JSObject* value)
{
- return window()->impl();
+ auto* wrapper = jsDynamicDowncast<JSDOMWindowShell*>(vm, value);
+ if (!wrapper)
+ return nullptr;
+ return &wrapper->window()->wrapped();
}
// ----
diff --git a/Source/WebCore/bindings/js/JSDOMWindowShell.h b/Source/WebCore/bindings/js/JSDOMWindowShell.h
index 85a6fd873..17129237b 100644
--- a/Source/WebCore/bindings/js/JSDOMWindowShell.h
+++ b/Source/WebCore/bindings/js/JSDOMWindowShell.h
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -26,15 +26,14 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSDOMWindowShell_h
-#define JSDOMWindowShell_h
+#pragma once
+#include "DOMWindow.h"
#include "JSDOMWindow.h"
#include <runtime/JSProxy.h>
namespace WebCore {
- class DOMWindow;
class Frame;
class JSDOMWindowShell : public JSC::JSProxy {
@@ -44,29 +43,30 @@ namespace WebCore {
JSDOMWindow* window() const { return JSC::jsCast<JSDOMWindow*>(target()); }
void setWindow(JSC::VM&, JSDOMWindow*);
- void setWindow(PassRefPtr<DOMWindow>);
+ void setWindow(RefPtr<DOMWindow>&&);
DECLARE_INFO;
- DOMWindow& impl() const;
+ DOMWindow& wrapped() const;
+ static WEBCORE_EXPORT DOMWindow* toWrapped(JSC::VM&, JSC::JSObject*);
- static JSDOMWindowShell* create(JSC::VM& vm, PassRefPtr<DOMWindow> window, JSC::Structure* structure, DOMWrapperWorld& world)
+ static JSDOMWindowShell* create(JSC::VM& vm, RefPtr<DOMWindow>&& window, JSC::Structure* structure, DOMWrapperWorld& world)
{
JSDOMWindowShell* shell = new (NotNull, JSC::allocateCell<JSDOMWindowShell>(vm.heap)) JSDOMWindowShell(vm, structure, world);
- shell->finishCreation(vm, window);
+ shell->finishCreation(vm, WTFMove(window));
return shell;
}
static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSValue prototype)
{
- return JSC::Structure::create(vm, 0, prototype, JSC::TypeInfo(JSC::ProxyType, StructureFlags), info());
+ return JSC::Structure::create(vm, 0, prototype, JSC::TypeInfo(JSC::PureForwardingProxyType, StructureFlags), info());
}
- DOMWrapperWorld& world() { return m_world.get(); }
+ DOMWrapperWorld& world() { return m_world; }
protected:
JSDOMWindowShell(JSC::VM&, JSC::Structure*, DOMWrapperWorld&);
- void finishCreation(JSC::VM&, PassRefPtr<DOMWindow>);
+ void finishCreation(JSC::VM&, RefPtr<DOMWindow>&&);
Ref<DOMWrapperWorld> m_world;
};
@@ -75,5 +75,3 @@ namespace WebCore {
JSDOMWindowShell* toJSDOMWindowShell(Frame*, DOMWrapperWorld&);
} // namespace WebCore
-
-#endif // JSDOMWindowShell_h
diff --git a/Source/WebCore/bindings/js/JSDOMWrapper.cpp b/Source/WebCore/bindings/js/JSDOMWrapper.cpp
index 1629ae57e..21da86365 100644
--- a/Source/WebCore/bindings/js/JSDOMWrapper.cpp
+++ b/Source/WebCore/bindings/js/JSDOMWrapper.cpp
@@ -26,12 +26,32 @@
#include "config.h"
#include "JSDOMWrapper.h"
+#include "DOMWrapperWorld.h"
+#include "JSDOMWindow.h"
+#include "WebCoreJSClientData.h"
#include <runtime/Error.h>
using namespace JSC;
namespace WebCore {
-STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSDOMWrapper);
+STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSDOMObject);
+
+JSDOMWindow& JSDOMObject::domWindow() const
+{
+ auto* domWindow = JSC::jsCast<JSDOMWindow*>(JSC::JSNonFinalObject::globalObject());
+ ASSERT(domWindow);
+ return *domWindow;
+}
+
+Subspace* outputConstraintSubspaceFor(VM& vm)
+{
+ return &static_cast<JSVMClientData*>(vm.clientData)->outputConstraintSpace();
+}
+
+Subspace* globalObjectOutputConstraintSubspaceFor(VM& vm)
+{
+ return &static_cast<JSVMClientData*>(vm.clientData)->globalObjectOutputConstraintSpace();
+}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMWrapper.h b/Source/WebCore/bindings/js/JSDOMWrapper.h
index 026dcd931..11d439ce2 100644
--- a/Source/WebCore/bindings/js/JSDOMWrapper.h
+++ b/Source/WebCore/bindings/js/JSDOMWrapper.h
@@ -19,31 +19,101 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef JSDOMWrapper_h
-#define JSDOMWrapper_h
+#pragma once
#include "JSDOMGlobalObject.h"
+#include "NodeConstants.h"
#include <runtime/JSDestructibleObject.h>
namespace WebCore {
+class JSDOMWindow;
class ScriptExecutionContext;
-class JSDOMWrapper : public JSC::JSDestructibleObject {
+// JSC allows us to extend JSType. If the highest bit is set, we can add any Object types and they are
+// recognized as OtherObj in JSC. And we encode Node type into JSType if the given JSType is subclass of Node.
+// offset | 7 | 6 | 5 4 | 3 2 1 0 |
+// value | 1 | 0 | Non-node DOM types |
+// If the given JSType is a subclass of Node, the format is the following.
+// offset | 7 | 6 | 5 4 | 3 2 1 0 |
+// value | 1 | 1 | Kind | NodeType |
+static const uint8_t JSNodeTypeMask = 0b00001111;
+
+static const uint8_t JSDOMWrapperType = 0b10000000;
+static const uint8_t JSEventType = 0b10000001;
+static const uint8_t JSNodeType = 0b11000000;
+static const uint8_t JSTextNodeType = JSNodeType | NodeConstants::TEXT_NODE;
+static const uint8_t JSProcessingInstructionNodeType = JSNodeType | NodeConstants::PROCESSING_INSTRUCTION_NODE;
+static const uint8_t JSDocumentTypeNodeType = JSNodeType | NodeConstants::DOCUMENT_TYPE_NODE;
+static const uint8_t JSDocumentFragmentNodeType = JSNodeType | NodeConstants::DOCUMENT_FRAGMENT_NODE;
+static const uint8_t JSDocumentWrapperType = JSNodeType | NodeConstants::DOCUMENT_NODE;
+static const uint8_t JSCommentNodeType = JSNodeType | NodeConstants::COMMENT_NODE;
+static const uint8_t JSCDATASectionNodeType = JSNodeType | NodeConstants::CDATA_SECTION_NODE;
+static const uint8_t JSAttrNodeType = JSNodeType | NodeConstants::ATTRIBUTE_NODE;
+static const uint8_t JSElementType = 0b11010000 | NodeConstants::ELEMENT_NODE;
+
+static_assert(JSDOMWrapperType > JSC::LastJSCObjectType, "JSC::JSType offers the highest bit.");
+static_assert(NodeConstants::LastNodeType <= JSNodeTypeMask, "NodeType should be represented in 4bit.");
+
+class JSDOMObject : public JSC::JSDestructibleObject {
public:
typedef JSC::JSDestructibleObject Base;
+ static constexpr bool isDOMWrapper = false;
JSDOMGlobalObject* globalObject() const { return JSC::jsCast<JSDOMGlobalObject*>(JSC::JSNonFinalObject::globalObject()); }
ScriptExecutionContext* scriptExecutionContext() const { return globalObject()->scriptExecutionContext(); }
+ JSDOMWindow& domWindow() const;
+
protected:
- JSDOMWrapper(JSC::Structure* structure, JSC::JSGlobalObject* globalObject)
- : JSDestructibleObject(globalObject->vm(), structure)
+ JSDOMObject(JSC::Structure* structure, JSC::JSGlobalObject& globalObject)
+ : Base(globalObject.vm(), structure)
{
ASSERT(scriptExecutionContext());
}
};
-} // namespace WebCore
+WEBCORE_EXPORT JSC::Subspace* outputConstraintSubspaceFor(JSC::VM&);
+WEBCORE_EXPORT JSC::Subspace* globalObjectOutputConstraintSubspaceFor(JSC::VM&);
+
+template<typename ImplementationClass> class JSDOMWrapper : public JSDOMObject {
+public:
+ typedef JSDOMObject Base;
+ typedef ImplementationClass DOMWrapped;
+ static constexpr bool isDOMWrapper = true;
+
+ ImplementationClass& wrapped() const { return m_wrapped; }
+ static ptrdiff_t offsetOfWrapped() { return OBJECT_OFFSETOF(JSDOMWrapper<ImplementationClass>, m_wrapped); }
+
+protected:
+ JSDOMWrapper(JSC::Structure* structure, JSC::JSGlobalObject& globalObject, Ref<ImplementationClass>&& impl)
+ : Base(structure, globalObject)
+ , m_wrapped(WTFMove(impl)) { }
+
+private:
+ Ref<ImplementationClass> m_wrapped;
+};
+
+template<typename ImplementationClass> struct JSDOMWrapperConverterTraits;
+
+template<typename JSClass, typename Enable = void>
+struct JSDOMObjectInspector {
+public:
+ static constexpr bool isSimpleWrapper = false;
+ static constexpr bool isComplexWrapper = false;
+ static constexpr bool isBuiltin = true;
+};
-#endif // JSDOMWrapper_h
+template<typename JSClass>
+struct JSDOMObjectInspector<JSClass, typename std::enable_if<JSClass::isDOMWrapper>::type> {
+private:
+ template<typename T> static constexpr auto test(int) -> decltype(T::create(), bool()) { return true; }
+ template<typename T> static constexpr bool test(...) { return false; }
+
+public:
+ static constexpr bool isSimpleWrapper = test<typename JSClass::DOMWrapped>(0);
+ static constexpr bool isComplexWrapper = !isSimpleWrapper;
+ static constexpr bool isBuiltin = false;
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMWrapperCache.cpp b/Source/WebCore/bindings/js/JSDOMWrapperCache.cpp
new file mode 100644
index 000000000..6d875d58a
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMWrapperCache.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2004-2011, 2013, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
+ * Copyright (C) 2013 Michael Pruett <michael@68k.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "JSDOMWrapperCache.h"
+
+#include <runtime/JSCInlines.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+Structure* getCachedDOMStructure(JSDOMGlobalObject& globalObject, const ClassInfo* classInfo)
+{
+ JSDOMStructureMap& structures = globalObject.structures(NoLockingNecessary);
+ return structures.get(classInfo).get();
+}
+
+Structure* cacheDOMStructure(JSDOMGlobalObject& globalObject, Structure* structure, const ClassInfo* classInfo)
+{
+ auto locker = lockDuringMarking(globalObject.vm().heap, globalObject.gcLock());
+ JSDOMStructureMap& structures = globalObject.structures(locker);
+ ASSERT(!structures.contains(classInfo));
+ return structures.set(classInfo, WriteBarrier<Structure>(globalObject.vm(), &globalObject, structure)).iterator->value.get();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMWrapperCache.h b/Source/WebCore/bindings/js/JSDOMWrapperCache.h
new file mode 100644
index 000000000..dd8c4b206
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDOMWrapperCache.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
+ * Copyright (C) 2003-2006, 2008-2009, 2013, 2016 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
+ * Copyright (C) 2009 Google, Inc. All rights reserved.
+ * Copyright (C) 2012 Ericsson AB. All rights reserved.
+ * Copyright (C) 2013 Michael Pruett <michael@68k.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#pragma once
+
+#include "DOMWrapperWorld.h"
+#include "JSDOMGlobalObject.h"
+#include "JSDOMWrapper.h"
+#include "JSDynamicDowncast.h"
+#include "ScriptWrappable.h"
+#include "ScriptWrappableInlines.h"
+#include "WebCoreTypedArrayController.h"
+#include <heap/Weak.h>
+#include <heap/WeakInlines.h>
+#include <runtime/JSArrayBuffer.h>
+#include <runtime/TypedArrayInlines.h>
+#include <runtime/TypedArrays.h>
+
+namespace WebCore {
+
+WEBCORE_EXPORT JSC::Structure* getCachedDOMStructure(JSDOMGlobalObject&, const JSC::ClassInfo*);
+WEBCORE_EXPORT JSC::Structure* cacheDOMStructure(JSDOMGlobalObject&, JSC::Structure*, const JSC::ClassInfo*);
+
+template<typename WrapperClass> JSC::Structure* getDOMStructure(JSC::VM&, JSDOMGlobalObject&);
+template<typename WrapperClass> JSC::Structure* deprecatedGetDOMStructure(JSC::ExecState*);
+template<typename WrapperClass> JSC::JSObject* getDOMPrototype(JSC::VM&, JSC::JSGlobalObject*);
+
+JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld&, JSC::ArrayBuffer*);
+void* wrapperKey(JSC::ArrayBuffer*);
+
+JSDOMObject* getInlineCachedWrapper(DOMWrapperWorld&, void*);
+JSDOMObject* getInlineCachedWrapper(DOMWrapperWorld&, ScriptWrappable*);
+JSC::JSArrayBuffer* getInlineCachedWrapper(DOMWrapperWorld&, JSC::ArrayBuffer*);
+
+bool setInlineCachedWrapper(DOMWrapperWorld&, void*, JSDOMObject*, JSC::WeakHandleOwner*);
+bool setInlineCachedWrapper(DOMWrapperWorld&, ScriptWrappable*, JSDOMObject* wrapper, JSC::WeakHandleOwner* wrapperOwner);
+bool setInlineCachedWrapper(DOMWrapperWorld&, JSC::ArrayBuffer*, JSC::JSArrayBuffer* wrapper, JSC::WeakHandleOwner* wrapperOwner);
+
+bool clearInlineCachedWrapper(DOMWrapperWorld&, void*, JSDOMObject*);
+bool clearInlineCachedWrapper(DOMWrapperWorld&, ScriptWrappable*, JSDOMObject* wrapper);
+bool clearInlineCachedWrapper(DOMWrapperWorld&, JSC::ArrayBuffer*, JSC::JSArrayBuffer* wrapper);
+
+template<typename DOMClass> JSC::JSObject* getCachedWrapper(DOMWrapperWorld&, DOMClass&);
+template<typename DOMClass> inline JSC::JSObject* getCachedWrapper(DOMWrapperWorld& world, Ref<DOMClass>& object) { return getCachedWrapper(world, object.get()); }
+template<typename DOMClass, typename WrapperClass> void cacheWrapper(DOMWrapperWorld&, DOMClass*, WrapperClass*);
+template<typename DOMClass, typename WrapperClass> void uncacheWrapper(DOMWrapperWorld&, DOMClass*, WrapperClass*);
+template<typename DOMClass, typename T> auto createWrapper(JSDOMGlobalObject*, Ref<T>&&) -> typename std::enable_if<std::is_same<DOMClass, T>::value, typename JSDOMWrapperConverterTraits<DOMClass>::WrapperClass*>::type;
+template<typename DOMClass, typename T> auto createWrapper(JSDOMGlobalObject*, Ref<T>&&) -> typename std::enable_if<!std::is_same<DOMClass, T>::value, typename JSDOMWrapperConverterTraits<DOMClass>::WrapperClass*>::type;
+
+template<typename DOMClass> JSC::JSValue wrap(JSC::ExecState*, JSDOMGlobalObject*, DOMClass&);
+
+
+// Inline functions and template definitions.
+
+inline JSDOMGlobalObject* deprecatedGlobalObjectForPrototype(JSC::ExecState* exec)
+{
+ // FIXME: Callers to this function should be using the global object
+ // from which the object is being created, instead of assuming the lexical one.
+ // e.g. subframe.document.body should use the subframe's global object, not the lexical one.
+ return JSC::jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject());
+}
+
+template<typename WrapperClass> inline JSC::Structure* getDOMStructure(JSC::VM& vm, JSDOMGlobalObject& globalObject)
+{
+ if (JSC::Structure* structure = getCachedDOMStructure(globalObject, WrapperClass::info()))
+ return structure;
+ return cacheDOMStructure(globalObject, WrapperClass::createStructure(vm, &globalObject, WrapperClass::createPrototype(vm, &globalObject)), WrapperClass::info());
+}
+
+template<typename WrapperClass> inline JSC::Structure* deprecatedGetDOMStructure(JSC::ExecState* exec)
+{
+ // FIXME: This function is wrong. It uses the wrong global object for creating the prototype structure.
+ return getDOMStructure<WrapperClass>(exec->vm(), *deprecatedGlobalObjectForPrototype(exec));
+}
+
+template<typename WrapperClass> inline JSC::JSObject* getDOMPrototype(JSC::VM& vm, JSC::JSGlobalObject* globalObject)
+{
+ return JSC::jsCast<JSC::JSObject*>(asObject(getDOMStructure<WrapperClass>(vm, *JSC::jsCast<JSDOMGlobalObject*>(globalObject))->storedPrototype()));
+}
+
+inline JSC::WeakHandleOwner* wrapperOwner(DOMWrapperWorld& world, JSC::ArrayBuffer*)
+{
+ return static_cast<WebCoreTypedArrayController*>(world.vm().m_typedArrayController.get())->wrapperOwner();
+}
+
+inline void* wrapperKey(JSC::ArrayBuffer* domObject)
+{
+ return domObject;
+}
+
+inline JSDOMObject* getInlineCachedWrapper(DOMWrapperWorld&, void*) { return nullptr; }
+inline bool setInlineCachedWrapper(DOMWrapperWorld&, void*, JSDOMObject*, JSC::WeakHandleOwner*) { return false; }
+inline bool clearInlineCachedWrapper(DOMWrapperWorld&, void*, JSDOMObject*) { return false; }
+
+inline JSDOMObject* getInlineCachedWrapper(DOMWrapperWorld& world, ScriptWrappable* domObject)
+{
+ if (!world.isNormal())
+ return nullptr;
+ return domObject->wrapper();
+}
+
+inline JSC::JSArrayBuffer* getInlineCachedWrapper(DOMWrapperWorld& world, JSC::ArrayBuffer* buffer)
+{
+ if (!world.isNormal())
+ return nullptr;
+ return buffer->m_wrapper.get();
+}
+
+inline bool setInlineCachedWrapper(DOMWrapperWorld& world, ScriptWrappable* domObject, JSDOMObject* wrapper, JSC::WeakHandleOwner* wrapperOwner)
+{
+ if (!world.isNormal())
+ return false;
+ domObject->setWrapper(wrapper, wrapperOwner, &world);
+ return true;
+}
+
+inline bool setInlineCachedWrapper(DOMWrapperWorld& world, JSC::ArrayBuffer* domObject, JSC::JSArrayBuffer* wrapper, JSC::WeakHandleOwner* wrapperOwner)
+{
+ if (!world.isNormal())
+ return false;
+ domObject->m_wrapper = JSC::Weak<JSC::JSArrayBuffer>(wrapper, wrapperOwner, &world);
+ return true;
+}
+
+inline bool clearInlineCachedWrapper(DOMWrapperWorld& world, ScriptWrappable* domObject, JSDOMObject* wrapper)
+{
+ if (!world.isNormal())
+ return false;
+ domObject->clearWrapper(wrapper);
+ return true;
+}
+
+inline bool clearInlineCachedWrapper(DOMWrapperWorld& world, JSC::ArrayBuffer* domObject, JSC::JSArrayBuffer* wrapper)
+{
+ if (!world.isNormal())
+ return false;
+ weakClear(domObject->m_wrapper, wrapper);
+ return true;
+}
+
+template<typename DOMClass> inline JSC::JSObject* getCachedWrapper(DOMWrapperWorld& world, DOMClass& domObject)
+{
+ if (auto* wrapper = getInlineCachedWrapper(world, &domObject))
+ return wrapper;
+ return world.m_wrappers.get(wrapperKey(&domObject));
+}
+
+template<typename DOMClass, typename WrapperClass> inline void cacheWrapper(DOMWrapperWorld& world, DOMClass* domObject, WrapperClass* wrapper)
+{
+ JSC::WeakHandleOwner* owner = wrapperOwner(world, domObject);
+ if (setInlineCachedWrapper(world, domObject, wrapper, owner))
+ return;
+ weakAdd(world.m_wrappers, wrapperKey(domObject), JSC::Weak<JSC::JSObject>(wrapper, owner, &world));
+}
+
+template<typename DOMClass, typename WrapperClass> inline void uncacheWrapper(DOMWrapperWorld& world, DOMClass* domObject, WrapperClass* wrapper)
+{
+ if (clearInlineCachedWrapper(world, domObject, wrapper))
+ return;
+ weakRemove(world.m_wrappers, wrapperKey(domObject), wrapper);
+}
+
+template<typename DOMClass, typename T> inline auto createWrapper(JSDOMGlobalObject* globalObject, Ref<T>&& domObject) -> typename std::enable_if<std::is_same<DOMClass, T>::value, typename JSDOMWrapperConverterTraits<DOMClass>::WrapperClass*>::type
+{
+ using WrapperClass = typename JSDOMWrapperConverterTraits<DOMClass>::WrapperClass;
+
+ ASSERT(!getCachedWrapper(globalObject->world(), domObject));
+ auto* domObjectPtr = domObject.ptr();
+ auto* wrapper = WrapperClass::create(getDOMStructure<WrapperClass>(globalObject->vm(), *globalObject), globalObject, WTFMove(domObject));
+ cacheWrapper(globalObject->world(), domObjectPtr, wrapper);
+ return wrapper;
+}
+
+template<typename DOMClass, typename T> inline auto createWrapper(JSDOMGlobalObject* globalObject, Ref<T>&& domObject) -> typename std::enable_if<!std::is_same<DOMClass, T>::value, typename JSDOMWrapperConverterTraits<DOMClass>::WrapperClass*>::type
+{
+ return createWrapper<DOMClass>(globalObject, static_reference_cast<DOMClass>(WTFMove(domObject)));
+}
+
+template<typename DOMClass> inline JSC::JSValue wrap(JSC::ExecState* state, JSDOMGlobalObject* globalObject, DOMClass& domObject)
+{
+ if (auto* wrapper = getCachedWrapper(globalObject->world(), domObject))
+ return wrapper;
+ return toJSNewlyCreated(state, globalObject, Ref<DOMClass>(domObject));
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDedicatedWorkerGlobalScopeCustom.cpp b/Source/WebCore/bindings/js/JSDedicatedWorkerGlobalScopeCustom.cpp
deleted file mode 100644
index ea62e28ed..000000000
--- a/Source/WebCore/bindings/js/JSDedicatedWorkerGlobalScopeCustom.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2009 Apple, Inc. All rights reserved.
- * Copyright (C) 2009, 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "JSDedicatedWorkerGlobalScope.h"
-
-#include "JSDOMBinding.h"
-#include "JSMessagePortCustom.h"
-
-using namespace JSC;
-
-namespace WebCore {
-
-JSC::JSValue JSDedicatedWorkerGlobalScope::postMessage(JSC::ExecState* exec)
-{
- return handlePostMessage(exec, &impl());
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDeviceMotionEventCustom.cpp b/Source/WebCore/bindings/js/JSDeviceMotionEventCustom.cpp
deleted file mode 100644
index b4d5c4f8d..000000000
--- a/Source/WebCore/bindings/js/JSDeviceMotionEventCustom.cpp
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(DEVICE_ORIENTATION)
-
-#include "JSDeviceMotionEvent.h"
-
-#include "DeviceMotionData.h"
-#include "DeviceMotionEvent.h"
-#include <runtime/ObjectConstructor.h>
-
-using namespace JSC;
-
-namespace WebCore {
-
-static PassRefPtr<DeviceMotionData::Acceleration> readAccelerationArgument(JSValue value, ExecState* exec)
-{
- if (value.isUndefinedOrNull())
- return 0;
-
- // Given the above test, this will always yield an object.
- JSObject* object = value.toObject(exec);
-
- JSValue xValue = object->get(exec, Identifier(exec, "x"));
- if (exec->hadException())
- return 0;
- bool canProvideX = !xValue.isUndefinedOrNull();
- double x = xValue.toNumber(exec);
- if (exec->hadException())
- return 0;
-
- JSValue yValue = object->get(exec, Identifier(exec, "y"));
- if (exec->hadException())
- return 0;
- bool canProvideY = !yValue.isUndefinedOrNull();
- double y = yValue.toNumber(exec);
- if (exec->hadException())
- return 0;
-
- JSValue zValue = object->get(exec, Identifier(exec, "z"));
- if (exec->hadException())
- return 0;
- bool canProvideZ = !zValue.isUndefinedOrNull();
- double z = zValue.toNumber(exec);
- if (exec->hadException())
- return 0;
-
- if (!canProvideX && !canProvideY && !canProvideZ)
- return 0;
-
- return DeviceMotionData::Acceleration::create(canProvideX, x, canProvideY, y, canProvideZ, z);
-}
-
-static PassRefPtr<DeviceMotionData::RotationRate> readRotationRateArgument(JSValue value, ExecState* exec)
-{
- if (value.isUndefinedOrNull())
- return 0;
-
- // Given the above test, this will always yield an object.
- JSObject* object = value.toObject(exec);
-
- JSValue alphaValue = object->get(exec, Identifier(exec, "alpha"));
- if (exec->hadException())
- return 0;
- bool canProvideAlpha = !alphaValue.isUndefinedOrNull();
- double alpha = alphaValue.toNumber(exec);
- if (exec->hadException())
- return 0;
-
- JSValue betaValue = object->get(exec, Identifier(exec, "beta"));
- if (exec->hadException())
- return 0;
- bool canProvideBeta = !betaValue.isUndefinedOrNull();
- double beta = betaValue.toNumber(exec);
- if (exec->hadException())
- return 0;
-
- JSValue gammaValue = object->get(exec, Identifier(exec, "gamma"));
- if (exec->hadException())
- return 0;
- bool canProvideGamma = !gammaValue.isUndefinedOrNull();
- double gamma = gammaValue.toNumber(exec);
- if (exec->hadException())
- return 0;
-
- if (!canProvideAlpha && !canProvideBeta && !canProvideGamma)
- return 0;
-
- return DeviceMotionData::RotationRate::create(canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma);
-}
-
-static JSObject* createAccelerationObject(const DeviceMotionData::Acceleration* acceleration, ExecState* exec)
-{
- JSObject* object = constructEmptyObject(exec);
- object->putDirect(exec->vm(), Identifier(exec, "x"), acceleration->canProvideX() ? jsNumber(acceleration->x()) : jsNull());
- object->putDirect(exec->vm(), Identifier(exec, "y"), acceleration->canProvideY() ? jsNumber(acceleration->y()) : jsNull());
- object->putDirect(exec->vm(), Identifier(exec, "z"), acceleration->canProvideZ() ? jsNumber(acceleration->z()) : jsNull());
- return object;
-}
-
-static JSObject* createRotationRateObject(const DeviceMotionData::RotationRate* rotationRate, ExecState* exec)
-{
- JSObject* object = constructEmptyObject(exec);
- object->putDirect(exec->vm(), Identifier(exec, "alpha"), rotationRate->canProvideAlpha() ? jsNumber(rotationRate->alpha()) : jsNull());
- object->putDirect(exec->vm(), Identifier(exec, "beta"), rotationRate->canProvideBeta() ? jsNumber(rotationRate->beta()) : jsNull());
- object->putDirect(exec->vm(), Identifier(exec, "gamma"), rotationRate->canProvideGamma() ? jsNumber(rotationRate->gamma()) : jsNull());
- return object;
-}
-
-JSValue JSDeviceMotionEvent::acceleration(ExecState* exec) const
-{
- DeviceMotionEvent& imp = impl();
- if (!imp.deviceMotionData()->acceleration())
- return jsNull();
- return createAccelerationObject(imp.deviceMotionData()->acceleration(), exec);
-}
-
-JSValue JSDeviceMotionEvent::accelerationIncludingGravity(ExecState* exec) const
-{
- DeviceMotionEvent& imp = impl();
- if (!imp.deviceMotionData()->accelerationIncludingGravity())
- return jsNull();
- return createAccelerationObject(imp.deviceMotionData()->accelerationIncludingGravity(), exec);
-}
-
-JSValue JSDeviceMotionEvent::rotationRate(ExecState* exec) const
-{
- DeviceMotionEvent& imp = impl();
- if (!imp.deviceMotionData()->rotationRate())
- return jsNull();
- return createRotationRateObject(imp.deviceMotionData()->rotationRate(), exec);
-}
-
-JSValue JSDeviceMotionEvent::interval(ExecState*) const
-{
- DeviceMotionEvent& imp = impl();
- if (!imp.deviceMotionData()->canProvideInterval())
- return jsNull();
- return jsNumber(imp.deviceMotionData()->interval());
-}
-
-JSValue JSDeviceMotionEvent::initDeviceMotionEvent(ExecState* exec)
-{
- const String type = exec->argument(0).toString(exec)->value(exec);
- bool bubbles = exec->argument(1).toBoolean(exec);
- bool cancelable = exec->argument(2).toBoolean(exec);
-
- // If any of the parameters are null or undefined, mark them as not provided.
- // Otherwise, use the standard JavaScript conversion.
- RefPtr<DeviceMotionData::Acceleration> acceleration = readAccelerationArgument(exec->argument(3), exec);
- if (exec->hadException())
- return jsUndefined();
-
- RefPtr<DeviceMotionData::Acceleration> accelerationIncludingGravity = readAccelerationArgument(exec->argument(4), exec);
- if (exec->hadException())
- return jsUndefined();
-
- RefPtr<DeviceMotionData::RotationRate> rotationRate = readRotationRateArgument(exec->argument(5), exec);
- if (exec->hadException())
- return jsUndefined();
-
- bool intervalProvided = !exec->argument(6).isUndefinedOrNull();
- double interval = exec->argument(6).toNumber(exec);
- RefPtr<DeviceMotionData> deviceMotionData = DeviceMotionData::create(acceleration, accelerationIncludingGravity, rotationRate, intervalProvided, interval);
- impl().initDeviceMotionEvent(type, bubbles, cancelable, deviceMotionData.get());
- return jsUndefined();
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(DEVICE_ORIENTATION)
diff --git a/Source/WebCore/bindings/js/JSDeviceOrientationEventCustom.cpp b/Source/WebCore/bindings/js/JSDeviceOrientationEventCustom.cpp
deleted file mode 100644
index 86ddc96aa..000000000
--- a/Source/WebCore/bindings/js/JSDeviceOrientationEventCustom.cpp
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(DEVICE_ORIENTATION)
-
-#include "JSDeviceOrientationEvent.h"
-
-#include "DeviceOrientationData.h"
-#include "DeviceOrientationEvent.h"
-
-using namespace JSC;
-
-namespace WebCore {
-
-JSValue JSDeviceOrientationEvent::alpha(ExecState*) const
-{
- DeviceOrientationEvent& imp = impl();
- if (!imp.orientation()->canProvideAlpha())
- return jsNull();
- return jsNumber(imp.orientation()->alpha());
-}
-
-JSValue JSDeviceOrientationEvent::beta(ExecState*) const
-{
- DeviceOrientationEvent& imp = impl();
- if (!imp.orientation()->canProvideBeta())
- return jsNull();
- return jsNumber(imp.orientation()->beta());
-}
-
-JSValue JSDeviceOrientationEvent::gamma(ExecState*) const
-{
- DeviceOrientationEvent& imp = impl();
- if (!imp.orientation()->canProvideGamma())
- return jsNull();
- return jsNumber(imp.orientation()->gamma());
-}
-
-#if PLATFORM(IOS)
-JSValue JSDeviceOrientationEvent::webkitCompassHeading(ExecState*) const
-{
- DeviceOrientationEvent& imp = impl();
- if (!imp.orientation()->canProvideCompassHeading())
- return jsNull();
- return jsNumber(imp.orientation()->compassHeading());
-}
-
-JSValue JSDeviceOrientationEvent::webkitCompassAccuracy(ExecState*) const
-{
- DeviceOrientationEvent& imp = impl();
- if (!imp.orientation()->canProvideCompassAccuracy())
- return jsNull();
- return jsNumber(imp.orientation()->compassAccuracy());
-}
-#endif
-
-#if !PLATFORM(IOS)
-JSValue JSDeviceOrientationEvent::absolute(ExecState*) const
-{
- DeviceOrientationEvent& imp = impl();
- if (!imp.orientation()->canProvideAbsolute())
- return jsNull();
- return jsBoolean(imp.orientation()->absolute());
-}
-#endif
-
-JSValue JSDeviceOrientationEvent::initDeviceOrientationEvent(ExecState* exec)
-{
- const String type = exec->argument(0).toString(exec)->value(exec);
- bool bubbles = exec->argument(1).toBoolean(exec);
- bool cancelable = exec->argument(2).toBoolean(exec);
- // If alpha, beta or gamma are null or undefined, mark them as not provided.
- // Otherwise, use the standard JavaScript conversion.
- bool alphaProvided = !exec->argument(3).isUndefinedOrNull();
- double alpha = exec->argument(3).toNumber(exec);
- bool betaProvided = !exec->argument(4).isUndefinedOrNull();
- double beta = exec->argument(4).toNumber(exec);
- bool gammaProvided = !exec->argument(5).isUndefinedOrNull();
- double gamma = exec->argument(5).toNumber(exec);
-#if PLATFORM(IOS)
- bool compassHeadingProvided = !exec->argument(6).isUndefinedOrNull();
- double compassHeading = exec->argument(6).toNumber(exec);
- bool compassAccuracyProvided = !exec->argument(7).isUndefinedOrNull();
- double compassAccuracy = exec->argument(7).toNumber(exec);
- RefPtr<DeviceOrientationData> orientation = DeviceOrientationData::create(alphaProvided, alpha, betaProvided, beta, gammaProvided, gamma, compassHeadingProvided, compassHeading, compassAccuracyProvided, compassAccuracy);
-#else
- bool absoluteProvided = !exec->argument(6).isUndefinedOrNull();
- bool absolute = exec->argument(6).toBoolean(exec);
- RefPtr<DeviceOrientationData> orientation = DeviceOrientationData::create(alphaProvided, alpha, betaProvided, beta, gammaProvided, gamma, absoluteProvided, absolute);
-#endif
- impl().initDeviceOrientationEvent(type, bubbles, cancelable, orientation.get());
- return jsUndefined();
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(DEVICE_ORIENTATION)
diff --git a/Source/WebCore/bindings/js/JSDictionary.cpp b/Source/WebCore/bindings/js/JSDictionary.cpp
deleted file mode 100644
index 4c2882611..000000000
--- a/Source/WebCore/bindings/js/JSDictionary.cpp
+++ /dev/null
@@ -1,279 +0,0 @@
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "JSDictionary.h"
-
-#include "ArrayValue.h"
-#include "Dictionary.h"
-#include "JSCSSFontFaceRule.h"
-#include "JSDOMError.h"
-#include "JSDOMWindow.h"
-#include "JSEventTarget.h"
-#include "JSMessagePortCustom.h"
-#include "JSNode.h"
-#include "JSStorage.h"
-#include "JSTrackCustom.h"
-#include "JSVoidCallback.h"
-#include "SerializedScriptValue.h"
-#include <runtime/JSTypedArrays.h>
-#include <wtf/HashMap.h>
-#include <wtf/MathExtras.h>
-#include <wtf/text/AtomicString.h>
-
-#if ENABLE(ENCRYPTED_MEDIA)
-#include "JSMediaKeyError.h"
-#endif
-
-#if ENABLE(MEDIA_STREAM)
-#include "JSMediaStream.h"
-#include "JSMediaStreamTrack.h"
-#endif
-
-#if ENABLE(SCRIPTED_SPEECH)
-#include "JSSpeechRecognitionResultList.h"
-#endif
-
-using namespace JSC;
-
-namespace WebCore {
-
-JSDictionary::GetPropertyResult JSDictionary::tryGetProperty(const char* propertyName, JSValue& finalResult) const
-{
- ASSERT(isValid());
- Identifier identifier(m_exec, propertyName);
- PropertySlot slot(m_initializerObject.get());
-
- if (!m_initializerObject.get()->getPropertySlot(m_exec, identifier, slot))
- return NoPropertyFound;
-
- if (m_exec->hadException())
- return ExceptionThrown;
-
- finalResult = slot.getValue(m_exec, identifier);
- if (m_exec->hadException())
- return ExceptionThrown;
-
- return PropertyFound;
-}
-
-void JSDictionary::convertValue(ExecState* exec, JSValue value, bool& result)
-{
- result = value.toBoolean(exec);
-}
-
-void JSDictionary::convertValue(ExecState* exec, JSValue value, int& result)
-{
- result = value.toInt32(exec);
-}
-
-void JSDictionary::convertValue(ExecState* exec, JSValue value, unsigned& result)
-{
- result = value.toUInt32(exec);
-}
-
-void JSDictionary::convertValue(ExecState* exec, JSValue value, unsigned short& result)
-{
- result = static_cast<unsigned short>(value.toUInt32(exec));
-}
-
-void JSDictionary::convertValue(ExecState* exec, JSValue value, unsigned long& result)
-{
- result = static_cast<unsigned long>(value.toUInt32(exec));
-}
-
-void JSDictionary::convertValue(ExecState* exec, JSValue value, unsigned long long& result)
-{
- double d = value.toNumber(exec);
- doubleToInteger(d, result);
-}
-
-void JSDictionary::convertValue(ExecState* exec, JSValue value, double& result)
-{
- result = value.toNumber(exec);
-}
-
-void JSDictionary::convertValue(JSC::ExecState* exec, JSC::JSValue value, Dictionary& result)
-{
- result = Dictionary(exec, value);
-}
-
-void JSDictionary::convertValue(ExecState* exec, JSValue value, String& result)
-{
- result = value.toString(exec)->value(exec);
-}
-
-void JSDictionary::convertValue(ExecState* exec, JSValue value, Vector<String>& result)
-{
- if (value.isUndefinedOrNull())
- return;
-
- unsigned length = 0;
- JSObject* object = toJSSequence(exec, value, length);
- if (exec->hadException())
- return;
-
- for (unsigned i = 0 ; i < length; ++i) {
- JSValue itemValue = object->get(exec, i);
- if (exec->hadException())
- return;
- result.append(itemValue.toString(exec)->value(exec));
- }
-}
-
-void JSDictionary::convertValue(ExecState* exec, JSValue value, Deprecated::ScriptValue& result)
-{
- result = Deprecated::ScriptValue(exec->vm(), value);
-}
-
-void JSDictionary::convertValue(ExecState* exec, JSValue value, RefPtr<SerializedScriptValue>& result)
-{
- result = SerializedScriptValue::create(exec, value, 0, 0);
-}
-
-void JSDictionary::convertValue(ExecState*, JSValue value, RefPtr<DOMWindow>& result)
-{
- result = toDOMWindow(value);
-}
-
-void JSDictionary::convertValue(ExecState*, JSValue value, RefPtr<EventTarget>& result)
-{
- result = toEventTarget(value);
-}
-
-void JSDictionary::convertValue(ExecState*, JSValue value, RefPtr<Node>& result)
-{
- result = toNode(value);
-}
-
-void JSDictionary::convertValue(ExecState*, JSValue value, RefPtr<Storage>& result)
-{
- result = toStorage(value);
-}
-
-void JSDictionary::convertValue(ExecState* exec, JSValue value, MessagePortArray& result)
-{
- ArrayBufferArray arrayBuffers;
- fillMessagePortArray(exec, value, result, arrayBuffers);
-}
-
-#if ENABLE(VIDEO_TRACK)
-void JSDictionary::convertValue(ExecState*, JSValue value, RefPtr<TrackBase>& result)
-{
- result = toTrack(value);
-}
-#endif
-
-void JSDictionary::convertValue(ExecState* exec, JSValue value, HashSet<AtomicString>& result)
-{
- result.clear();
-
- if (value.isUndefinedOrNull())
- return;
-
- unsigned length = 0;
- JSObject* object = toJSSequence(exec, value, length);
- if (exec->hadException())
- return;
-
- for (unsigned i = 0 ; i < length; ++i) {
- JSValue itemValue = object->get(exec, i);
- if (exec->hadException())
- return;
- result.add(itemValue.toString(exec)->value(exec));
- }
-}
-
-void JSDictionary::convertValue(ExecState* exec, JSValue value, ArrayValue& result)
-{
- if (value.isUndefinedOrNull())
- return;
-
- result = ArrayValue(exec, value);
-}
-
-void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<Uint8Array>& result)
-{
- result = toUint8Array(value);
-}
-
-#if ENABLE(ENCRYPTED_MEDIA)
-void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<MediaKeyError>& result)
-{
- result = toMediaKeyError(value);
-}
-#endif
-
-#if ENABLE(MEDIA_STREAM)
-void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<MediaStream>& result)
-{
- result = toMediaStream(value);
-}
-
-void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<MediaStreamTrack>& result)
-{
- result = toMediaStreamTrack(value);
-}
-#endif
-
-#if ENABLE(FONT_LOAD_EVENTS)
-void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<CSSFontFaceRule>& result)
-{
- result = toCSSFontFaceRule(value);
-}
-
-void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<DOMError>& result)
-{
- result = toDOMError(value);
-}
-
-void JSDictionary::convertValue(JSC::ExecState* exec, JSC::JSValue value, RefPtr<VoidCallback>& result)
-{
- if (!value.isFunction())
- return;
-
- result = JSVoidCallback::create(asObject(value), jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject()));
-}
-#endif
-
-#if ENABLE(SCRIPTED_SPEECH)
-void JSDictionary::convertValue(JSC::ExecState*, JSC::JSValue value, RefPtr<SpeechRecognitionResultList>& result)
-{
- result = toSpeechRecognitionResultList(value);
-}
-#endif
-
-bool JSDictionary::getWithUndefinedOrNullCheck(const String& propertyName, String& result) const
-{
- ASSERT(isValid());
- JSValue value;
- if (tryGetProperty(propertyName.utf8().data(), value) != PropertyFound || value.isUndefinedOrNull())
- return false;
-
- result = value.toWTFString(m_exec);
- return true;
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDictionary.h b/Source/WebCore/bindings/js/JSDictionary.h
deleted file mode 100644
index 3a8e2cc6f..000000000
--- a/Source/WebCore/bindings/js/JSDictionary.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef JSDictionary_h
-#define JSDictionary_h
-
-#include "MessagePort.h"
-#include <heap/Strong.h>
-#include <heap/StrongInlines.h>
-#include <interpreter/CallFrame.h>
-#include <runtime/Operations.h>
-#include <runtime/Uint8Array.h>
-#include <wtf/Forward.h>
-
-namespace Deprecated {
-class ScriptValue;
-}
-
-namespace WebCore {
-
-class ArrayValue;
-class CSSFontFaceRule;
-class Dictionary;
-class DOMError;
-class DOMWindow;
-class EventTarget;
-class MediaKeyError;
-class MediaStream;
-class MediaStreamTrack;
-class Node;
-class SerializedScriptValue;
-class Storage;
-class TrackBase;
-class VoidCallback;
-
-#if ENABLE(SCRIPTED_SPEECH)
-class SpeechRecognitionResultList;
-#endif
-
-class JSDictionary {
-public:
- JSDictionary(JSC::ExecState* exec, JSC::JSObject* initializerObject)
- : m_exec(exec)
- {
- if (exec && initializerObject)
- m_initializerObject = JSC::Strong<JSC::JSObject>(exec->vm(), initializerObject);
- }
-
- // Returns false if any exceptions were thrown, regardless of whether the property was found.
- template <typename Result>
- bool tryGetProperty(const char* propertyName, Result&) const;
- template <typename T, typename Result>
- bool tryGetProperty(const char* propertyName, T* context, void (*setter)(T* context, const Result&)) const;
-
- // Returns true if the property was found in the dictionary, and the value could be converted to the desired type.
- template <typename Result>
- bool get(const char* propertyName, Result&) const;
- bool getWithUndefinedOrNullCheck(const String& propertyName, String& value) const;
-
- JSC::ExecState* execState() const { return m_exec; }
- JSC::JSObject* initializerObject() const { return m_initializerObject.get(); }
- bool isValid() const { return m_exec && m_initializerObject; }
-
-private:
- template <typename Result>
- struct IdentitySetter {
- static void identitySetter(Result* context, const Result& result)
- {
- *context = result;
- }
- };
-
- enum GetPropertyResult {
- ExceptionThrown,
- NoPropertyFound,
- PropertyFound
- };
-
- template <typename T, typename Result>
- GetPropertyResult tryGetPropertyAndResult(const char* propertyName, T* context, void (*setter)(T* context, const Result&)) const;
- GetPropertyResult tryGetProperty(const char* propertyName, JSC::JSValue&) const;
-
- static void convertValue(JSC::ExecState*, JSC::JSValue, bool& result);
- static void convertValue(JSC::ExecState*, JSC::JSValue, int& result);
- static void convertValue(JSC::ExecState*, JSC::JSValue, unsigned& result);
- static void convertValue(JSC::ExecState*, JSC::JSValue, unsigned short& result);
- static void convertValue(JSC::ExecState*, JSC::JSValue, unsigned long& result);
- static void convertValue(JSC::ExecState*, JSC::JSValue, unsigned long long& result);
- static void convertValue(JSC::ExecState*, JSC::JSValue, double& result);
- static void convertValue(JSC::ExecState*, JSC::JSValue, Dictionary& result);
- static void convertValue(JSC::ExecState*, JSC::JSValue, String& result);
- static void convertValue(JSC::ExecState*, JSC::JSValue, Deprecated::ScriptValue& result);
- static void convertValue(JSC::ExecState*, JSC::JSValue, Vector<String>& result);
- static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<SerializedScriptValue>& result);
- static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<DOMWindow>& result);
- static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<EventTarget>& result);
- static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<Node>& result);
- static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<Storage>& result);
- static void convertValue(JSC::ExecState*, JSC::JSValue, MessagePortArray& result);
-#if ENABLE(VIDEO_TRACK)
- static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<TrackBase>& result);
-#endif
- static void convertValue(JSC::ExecState*, JSC::JSValue, HashSet<AtomicString>& result);
- static void convertValue(JSC::ExecState*, JSC::JSValue, ArrayValue& result);
- static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<JSC::Uint8Array>& result);
-#if ENABLE(ENCRYPTED_MEDIA)
- static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<MediaKeyError>& result);
-#endif
-#if ENABLE(MEDIA_STREAM)
- static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<MediaStream>& result);
- static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<MediaStreamTrack>& result);
-#endif
-#if ENABLE(FONT_LOAD_EVENTS)
- static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<CSSFontFaceRule>& result);
- static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<DOMError>& result);
- static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<VoidCallback>& result);
-#endif
-#if ENABLE(SCRIPTED_SPEECH)
- static void convertValue(JSC::ExecState*, JSC::JSValue, RefPtr<SpeechRecognitionResultList>&);
-#endif
-
- JSC::ExecState* m_exec;
- JSC::Strong<JSC::JSObject> m_initializerObject;
-};
-
-template <typename T, typename Result>
-bool JSDictionary::tryGetProperty(const char* propertyName, T* context, void (*setter)(T* context, const Result&)) const
-{
- return tryGetPropertyAndResult(propertyName, context, setter) != ExceptionThrown;
-}
-
-template <typename Result>
-bool JSDictionary::tryGetProperty(const char* propertyName, Result& finalResult) const
-{
- return tryGetPropertyAndResult(propertyName, &finalResult, IdentitySetter<Result>::identitySetter) != ExceptionThrown;
-}
-
-template <typename Result>
-bool JSDictionary::get(const char* propertyName, Result& finalResult) const
-{
- return tryGetPropertyAndResult(propertyName, &finalResult, IdentitySetter<Result>::identitySetter) == PropertyFound;
-}
-
-template <typename T, typename Result>
-JSDictionary::GetPropertyResult JSDictionary::tryGetPropertyAndResult(const char* propertyName, T* context, void (*setter)(T* context, const Result&)) const
-{
- JSC::JSValue value;
- GetPropertyResult getPropertyResult = tryGetProperty(propertyName, value);
- switch (getPropertyResult) {
- case ExceptionThrown:
- return getPropertyResult;
- case PropertyFound: {
- Result result;
- convertValue(m_exec, value, result);
-
- if (m_exec->hadException())
- return ExceptionThrown;
-
- setter(context, result);
- break;
- }
- case NoPropertyFound:
- break;
- }
-
- return getPropertyResult;
-}
-
-} // namespace WebCore
-
-#endif // JSDictionary_h
diff --git a/Source/WebCore/bindings/js/JSDocumentCustom.cpp b/Source/WebCore/bindings/js/JSDocumentCustom.cpp
index 34088ca48..a78b01844 100644
--- a/Source/WebCore/bindings/js/JSDocumentCustom.cpp
+++ b/Source/WebCore/bindings/js/JSDocumentCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008, 2009, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2007-2009, 2011, 2016 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -25,108 +25,138 @@
#include "FrameLoader.h"
#include "HTMLDocument.h"
#include "JSCanvasRenderingContext2D.h"
-#if ENABLE(WEBGL)
-#include "JSWebGLRenderingContext.h"
-#endif
+#include "JSDOMConvert.h"
#include "JSDOMWindowCustom.h"
#include "JSHTMLDocument.h"
#include "JSLocation.h"
-#include "JSTouch.h"
-#include "JSTouchList.h"
+#include "JSXMLDocument.h"
#include "Location.h"
#include "NodeTraversal.h"
+#include "SVGDocument.h"
#include "ScriptController.h"
#include "TouchList.h"
+#include "XMLDocument.h"
+#include <wtf/GetPtr.h>
-#if ENABLE(SVG)
-#include "JSSVGDocument.h"
-#include "SVGDocument.h"
+#if ENABLE(WEBGL)
+#include "JSWebGLRenderingContextBase.h"
#endif
-#include <wtf/GetPtr.h>
+#if ENABLE(TOUCH_EVENTS)
+#include "JSTouch.h"
+#include "JSTouchList.h"
+#endif
using namespace JSC;
namespace WebCore {
-JSValue JSDocument::location(ExecState* exec) const
+static inline JSValue createNewDocumentWrapper(ExecState& state, JSDOMGlobalObject& globalObject, Ref<Document>&& passedDocument)
{
- RefPtr<Frame> frame = impl().frame();
- if (!frame)
- return jsNull();
+ auto& document = passedDocument.get();
+ JSObject* wrapper;
+ if (document.isHTMLDocument())
+ wrapper = createWrapper<HTMLDocument>(&globalObject, WTFMove(passedDocument));
+ else if (document.isXMLDocument())
+ wrapper = createWrapper<XMLDocument>(&globalObject, WTFMove(passedDocument));
+ else
+ wrapper = createWrapper<Document>(&globalObject, WTFMove(passedDocument));
+
+ reportMemoryForDocumentIfFrameless(state, document);
- RefPtr<Location> location = frame->document()->domWindow()->location();
- if (JSObject* wrapper = getCachedWrapper(currentWorld(exec), location.get()))
+ return wrapper;
+}
+
+JSObject* cachedDocumentWrapper(ExecState& state, JSDOMGlobalObject& globalObject, Document& document)
+{
+ if (auto* wrapper = getCachedWrapper(globalObject.world(), document))
return wrapper;
- JSLocation* jsLocation = JSLocation::create(getDOMStructure<JSLocation>(exec->vm(), globalObject()), globalObject(), location.get());
- cacheWrapper(currentWorld(exec), location.get(), jsLocation);
- return jsLocation;
+ auto* window = document.domWindow();
+ if (!window)
+ return nullptr;
+
+ // Creating a wrapper for domWindow might have created a wrapper for document as well.
+ return getCachedWrapper(toJSDOMWindow(state.vm(), toJS(&state, *window))->world(), document);
}
-void JSDocument::setLocation(ExecState* exec, JSValue value)
+void reportMemoryForDocumentIfFrameless(ExecState& state, Document& document)
{
- String locationString = value.toString(exec)->value(exec);
- if (exec->hadException())
+ // Make sure the document is kept around by the window object, and works right with the back/forward cache.
+ if (document.frame())
return;
- RefPtr<Frame> frame = impl().frame();
- if (!frame)
- return;
+ size_t memoryCost = 0;
+ for (Node* node = &document; node; node = NodeTraversal::next(*node))
+ memoryCost += node->approximateMemoryCost();
- if (RefPtr<Location> location = frame->document()->domWindow()->location())
- location->setHref(locationString, activeDOMWindow(exec), firstDOMWindow(exec));
+ // FIXME: Adopt reportExtraMemoryVisited, and switch to reportExtraMemoryAllocated.
+ // https://bugs.webkit.org/show_bug.cgi?id=142595
+ state.heap()->deprecatedReportExtraMemory(memoryCost);
}
-JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Document* document)
+JSValue toJSNewlyCreated(ExecState* state, JSDOMGlobalObject* globalObject, Ref<Document>&& document)
{
- if (!document)
- return jsNull();
+ return createNewDocumentWrapper(*state, *globalObject, WTFMove(document));
+}
- JSObject* wrapper = getCachedWrapper(currentWorld(exec), document);
- if (wrapper)
+JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, Document& document)
+{
+ if (auto* wrapper = cachedDocumentWrapper(*state, *globalObject, document))
return wrapper;
+ return toJSNewlyCreated(state, globalObject, Ref<Document>(document));
+}
- if (DOMWindow* domWindow = document->domWindow()) {
- globalObject = toJSDOMWindow(toJS(exec, domWindow));
- // Creating a wrapper for domWindow might have created a wrapper for document as well.
- wrapper = getCachedWrapper(currentWorld(exec), document);
- if (wrapper)
- return wrapper;
- }
+#if ENABLE(TOUCH_EVENTS)
+JSValue JSDocument::createTouchList(ExecState& state)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
- if (document->isHTMLDocument())
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, HTMLDocument, document);
-#if ENABLE(SVG)
- else if (document->isSVGDocument())
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, SVGDocument, document);
-#endif
- else
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, Document, document);
-
- // Make sure the document is kept around by the window object, and works right with the
- // back/forward cache.
- if (!document->frame()) {
- size_t nodeCount = 0;
- for (Node* n = document; n; n = NodeTraversal::next(n))
- nodeCount++;
-
- exec->heap()->reportExtraMemoryCost(nodeCount * sizeof(Node));
- }
+ auto touchList = TouchList::create();
- return wrapper;
+ for (size_t i = 0; i < state.argumentCount(); ++i) {
+ auto* item = JSTouch::toWrapped(vm, state.uncheckedArgument(i));
+ if (!item)
+ return JSValue::decode(throwArgumentTypeError(state, scope, i, "touches", "Document", "createTouchList", "Touch"));
+
+ touchList->append(*item);
+ }
+ return toJSNewlyCreated(&state, globalObject(), WTFMove(touchList));
}
+#endif
-#if ENABLE(TOUCH_EVENTS)
-JSValue JSDocument::createTouchList(ExecState* exec)
+JSValue JSDocument::getCSSCanvasContext(JSC::ExecState& state)
{
- RefPtr<TouchList> touchList = TouchList::create();
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (UNLIKELY(state.argumentCount() < 4))
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+ auto contextId = state.uncheckedArgument(0).toWTFString(&state);
+ RETURN_IF_EXCEPTION(scope, JSValue());
+ auto name = state.uncheckedArgument(1).toWTFString(&state);
+ RETURN_IF_EXCEPTION(scope, JSValue());
+ auto width = convert<IDLLong>(state, state.uncheckedArgument(2), IntegerConversionConfiguration::Normal);
+ RETURN_IF_EXCEPTION(scope, JSValue());
+ auto height = convert<IDLLong>(state, state.uncheckedArgument(3), IntegerConversionConfiguration::Normal);
+ RETURN_IF_EXCEPTION(scope, JSValue());
+
+ auto* context = wrapped().getCSSCanvasContext(WTFMove(contextId), WTFMove(name), WTFMove(width), WTFMove(height));
+ if (!context)
+ return jsNull();
- for (size_t i = 0; i < exec->argumentCount(); i++)
- touchList->append(toTouch(exec->argument(i)));
+#if ENABLE(WEBGL)
+ if (is<WebGLRenderingContextBase>(*context))
+ return toJS(&state, globalObject(), downcast<WebGLRenderingContextBase>(*context));
+#endif
- return toJS(exec, globalObject(), touchList.release());
+ return toJS(&state, globalObject(), downcast<CanvasRenderingContext2D>(*context));
+}
+
+void JSDocument::visitAdditionalChildren(SlotVisitor& visitor)
+{
+ visitor.addOpaqueRoot(static_cast<ScriptExecutionContext*>(&wrapped()));
}
-#endif
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSHTMLMediaElementCustom.cpp b/Source/WebCore/bindings/js/JSDocumentCustom.h
index 1d40c60d8..5b60f5442 100644
--- a/Source/WebCore/bindings/js/JSHTMLMediaElementCustom.cpp
+++ b/Source/WebCore/bindings/js/JSDocumentCustom.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,25 +23,20 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include "config.h"
-#if ENABLE(VIDEO)
+#pragma once
-#include "JSHTMLMediaElement.h"
-
-#include "JSMediaController.h"
+#include "JSDOMBinding.h"
+#include "JSDocument.h"
namespace WebCore {
-using namespace JSC;
-
-void JSHTMLMediaElement::setController(ExecState*, JSValue value)
+template<typename From>
+ALWAYS_INLINE JSDynamicCastResult<JSDocument, From> jsDocumentCast(From* value)
{
- // 4.8.10.11.2 Media controllers: controller attribute.
- // On setting, it must first remove the element's mediagroup attribute, if any,
- impl().setMediaGroup(String());
- // and then set the current media controller to the given value.
- impl().setController(toMediaController(value));
+ return value->type() == JSDocumentWrapperType ? JSC::jsCast<JSDynamicCastResult<JSDocument, From>>(value) : nullptr;
}
-}
-#endif
+JSC::JSObject* cachedDocumentWrapper(JSC::ExecState&, JSDOMGlobalObject&, Document&);
+void reportMemoryForDocumentIfFrameless(JSC::ExecState&, Document&);
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDocumentFragmentCustom.cpp b/Source/WebCore/bindings/js/JSDocumentFragmentCustom.cpp
new file mode 100644
index 000000000..11557165e
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDocumentFragmentCustom.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSDocumentFragment.h"
+
+#include "ExceptionCode.h"
+#include "JSShadowRoot.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<DocumentFragment>&& impl)
+{
+ if (impl->isShadowRoot())
+ return createWrapper<ShadowRoot>(globalObject, WTFMove(impl));
+ return createWrapper<DocumentFragment>(globalObject, WTFMove(impl));
+}
+
+JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, DocumentFragment& impl)
+{
+ return wrap(state, globalObject, impl);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDynamicDowncast.h b/Source/WebCore/bindings/js/JSDynamicDowncast.h
new file mode 100644
index 000000000..0160126e1
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSDynamicDowncast.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <runtime/JSCJSValueInlines.h>
+#include <runtime/JSCellInlines.h>
+#include <type_traits>
+
+namespace WebCore {
+
+template<typename To, typename From>
+using JSDynamicCastResult = typename std::conditional<std::is_const<From>::value, const To, To>::type*;
+
+class JSNode;
+template<typename From>
+JSDynamicCastResult<JSNode, From> jsNodeCast(From* value);
+class JSElement;
+template<typename From>
+JSDynamicCastResult<JSElement, From> jsElementCast(From* value);
+class JSDocument;
+template<typename From>
+JSDynamicCastResult<JSDocument, From> jsDocumentCast(From* value);
+class JSEvent;
+template<typename From>
+JSDynamicCastResult<JSEvent, From> jsEventCast(From* value);
+
+template<typename Select>
+struct JSDynamicCastTrait {
+ template<typename To, typename From>
+ ALWAYS_INLINE static To cast(JSC::VM& vm, From* from)
+ {
+ return JSC::jsDynamicCast<To>(vm, from);
+ }
+};
+
+template<>
+struct JSDynamicCastTrait<JSNode> {
+ template<typename To, typename From>
+ ALWAYS_INLINE static To cast(JSC::VM&, From* from)
+ {
+ return jsNodeCast(from);
+ }
+};
+
+template<>
+struct JSDynamicCastTrait<JSElement> {
+ template<typename To, typename From>
+ ALWAYS_INLINE static To cast(JSC::VM&, From* from)
+ {
+ return jsElementCast(from);
+ }
+};
+
+template<>
+struct JSDynamicCastTrait<JSDocument> {
+ template<typename To, typename From>
+ ALWAYS_INLINE static To cast(JSC::VM&, From* from)
+ {
+ return jsDocumentCast(from);
+ }
+};
+
+template<>
+struct JSDynamicCastTrait<JSEvent> {
+ template<typename To, typename From>
+ ALWAYS_INLINE static To cast(JSC::VM&, From* from)
+ {
+ return jsEventCast(from);
+ }
+};
+
+template<typename To, typename From>
+ALWAYS_INLINE To jsDynamicDowncast(JSC::VM& vm, From* from)
+{
+ typedef JSDynamicCastTrait<typename std::remove_cv<typename std::remove_pointer<To>::type>::type> Dispatcher;
+ return Dispatcher::template cast<To>(vm, from);
+}
+
+template<typename To>
+ALWAYS_INLINE To jsDynamicDowncast(JSC::VM& vm, JSC::JSValue from)
+{
+ if (UNLIKELY(!from.isCell()))
+ return nullptr;
+ return jsDynamicDowncast<To>(vm, from.asCell());
+}
+
+}
diff --git a/Source/WebCore/bindings/js/JSElementCustom.cpp b/Source/WebCore/bindings/js/JSElementCustom.cpp
index 021f0a683..91bb3e0d9 100644
--- a/Source/WebCore/bindings/js/JSElementCustom.cpp
+++ b/Source/WebCore/bindings/js/JSElementCustom.cpp
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -38,12 +38,9 @@
#include "JSDOMBinding.h"
#include "JSHTMLElementWrapperFactory.h"
#include "JSNodeList.h"
-#include "NodeList.h"
-
-#if ENABLE(SVG)
#include "JSSVGElementWrapperFactory.h"
+#include "NodeList.h"
#include "SVGElement.h"
-#endif
using namespace JSC;
@@ -51,24 +48,28 @@ namespace WebCore {
using namespace HTMLNames;
-JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, Element* element)
+static JSValue createNewElementWrapper(JSDOMGlobalObject* globalObject, Ref<Element>&& element)
{
- if (!element)
- return jsNull();
-
- ASSERT(!getCachedWrapper(currentWorld(exec), element));
+ if (is<HTMLElement>(element.get()))
+ return createJSHTMLWrapper(globalObject, static_reference_cast<HTMLElement>(WTFMove(element)));
+ if (is<SVGElement>(element.get()))
+ return createJSSVGWrapper(globalObject, static_reference_cast<SVGElement>(WTFMove(element)));
+ return createWrapper<Element>(globalObject, WTFMove(element));
+}
- JSDOMWrapper* wrapper;
- if (element->isHTMLElement())
- wrapper = createJSHTMLWrapper(exec, globalObject, toHTMLElement(element));
-#if ENABLE(SVG)
- else if (element->isSVGElement())
- wrapper = createJSSVGWrapper(exec, globalObject, toSVGElement(element));
-#endif
- else
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, Element, element);
+JSValue toJS(ExecState*, JSDOMGlobalObject* globalObject, Element& element)
+{
+ if (auto* wrapper = getCachedWrapper(globalObject->world(), element))
+ return wrapper;
+ return createNewElementWrapper(globalObject, element);
+}
- return wrapper;
+JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<Element>&& element)
+{
+ if (element->isDefinedCustomElement())
+ return getCachedWrapper(globalObject->world(), element);
+ ASSERT(!getCachedWrapper(globalObject->world(), element));
+ return createNewElementWrapper(globalObject, WTFMove(element));
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSElementCustom.h b/Source/WebCore/bindings/js/JSElementCustom.h
new file mode 100644
index 000000000..b2b65f53a
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSElementCustom.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "JSDOMBinding.h"
+#include "JSElement.h"
+
+namespace WebCore {
+
+template<typename From>
+ALWAYS_INLINE JSDynamicCastResult<JSElement, From> jsElementCast(From* value)
+{
+ return value->type() >= JSElementType ? JSC::jsCast<JSDynamicCastResult<JSElement, From>>(value) : nullptr;
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSErrorHandler.cpp b/Source/WebCore/bindings/js/JSErrorHandler.cpp
index f72c334bd..a99c808fa 100644
--- a/Source/WebCore/bindings/js/JSErrorHandler.cpp
+++ b/Source/WebCore/bindings/js/JSErrorHandler.cpp
@@ -30,15 +30,15 @@
*/
#include "config.h"
-
#include "JSErrorHandler.h"
#include "Document.h"
#include "ErrorEvent.h"
#include "Event.h"
-#include "EventNames.h"
+#include "JSDOMConvert.h"
#include "JSEvent.h"
#include "JSMainThreadExecState.h"
+#include "JSMainThreadExecStateInstrumentation.h"
#include <runtime/JSLock.h>
#include <runtime/VMEntryScope.h>
#include <wtf/Ref.h>
@@ -58,15 +58,14 @@ JSErrorHandler::~JSErrorHandler()
void JSErrorHandler::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event)
{
-
- if (event->eventInterface() != ErrorEventInterfaceType)
+ if (!is<ErrorEvent>(*event))
return JSEventListener::handleEvent(scriptExecutionContext, event);
ASSERT(scriptExecutionContext);
if (!scriptExecutionContext)
return;
- ErrorEvent* errorEvent = static_cast<ErrorEvent*>(event);
+ ErrorEvent& errorEvent = downcast<ErrorEvent>(*event);
JSLockHolder lock(scriptExecutionContext->vm());
@@ -83,29 +82,35 @@ void JSErrorHandler::handleEvent(ScriptExecutionContext* scriptExecutionContext,
CallData callData;
CallType callType = jsFunction->methodTable()->getCallData(jsFunction, callData);
- if (callType != CallTypeNone) {
- Ref<JSErrorHandler> protectedctor(*this);
+ if (callType != CallType::None) {
+ Ref<JSErrorHandler> protectedThis(*this);
Event* savedEvent = globalObject->currentEvent();
globalObject->setCurrentEvent(event);
MarkedArgumentBuffer args;
- args.append(jsStringWithCache(exec, errorEvent->message()));
- args.append(jsStringWithCache(exec, errorEvent->filename()));
- args.append(jsNumber(errorEvent->lineno()));
- args.append(jsNumber(errorEvent->colno()));
+ args.append(toJS<IDLDOMString>(*exec, errorEvent.message()));
+ args.append(toJS<IDLUSVString>(*exec, errorEvent.filename()));
+ args.append(toJS<IDLUnsignedLong>(errorEvent.lineno()));
+ args.append(toJS<IDLUnsignedLong>(errorEvent.colno()));
+ args.append(errorEvent.error(*exec, *globalObject));
VM& vm = globalObject->vm();
VMEntryScope entryScope(vm, vm.entryScope ? vm.entryScope->globalObject() : globalObject);
+ InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(scriptExecutionContext, callType, callData);
+
+ NakedPtr<JSC::Exception> exception;
JSValue returnValue = scriptExecutionContext->isDocument()
- ? JSMainThreadExecState::call(exec, jsFunction, callType, callData, globalObject, args)
- : JSC::call(exec, jsFunction, callType, callData, globalObject, args);
+ ? JSMainThreadExecState::profiledCall(exec, JSC::ProfilingReason::Other, jsFunction, callType, callData, globalObject, args, exception)
+ : JSC::profiledCall(exec, JSC::ProfilingReason::Other, jsFunction, callType, callData, globalObject, args, exception);
+
+ InspectorInstrumentation::didCallFunction(cookie, scriptExecutionContext);
globalObject->setCurrentEvent(savedEvent);
- if (exec->hadException())
- reportCurrentException(exec);
+ if (exception)
+ reportException(exec, exception);
else {
if (returnValue.isTrue())
event->preventDefault();
diff --git a/Source/WebCore/bindings/js/JSErrorHandler.h b/Source/WebCore/bindings/js/JSErrorHandler.h
index 55d2d53e0..ba01c0e0b 100644
--- a/Source/WebCore/bindings/js/JSErrorHandler.h
+++ b/Source/WebCore/bindings/js/JSErrorHandler.h
@@ -28,37 +28,34 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSErrorHandler_h
-#define JSErrorHandler_h
+#pragma once
#include "JSEventListener.h"
namespace WebCore {
-class JSErrorHandler : public JSEventListener {
+class JSErrorHandler final : public JSEventListener {
public:
- static PassRefPtr<JSErrorHandler> create(JSC::JSObject* listener, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld& world)
+ static Ref<JSErrorHandler> create(JSC::JSObject* listener, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld& world)
{
- return adoptRef(new JSErrorHandler(listener, wrapper, isAttribute, world));
+ return adoptRef(*new JSErrorHandler(listener, wrapper, isAttribute, world));
}
virtual ~JSErrorHandler();
private:
JSErrorHandler(JSC::JSObject* function, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld&);
- virtual void handleEvent(ScriptExecutionContext*, Event*);
+ void handleEvent(ScriptExecutionContext*, Event*) final;
};
// Creates a JS EventListener for "onerror" event handler in worker context. It has custom implementation because
// unlike other event listeners it accepts three parameters.
-inline PassRefPtr<JSErrorHandler> createJSErrorHandler(JSC::ExecState* exec, JSC::JSValue listener, JSC::JSObject* wrapper)
+inline RefPtr<JSErrorHandler> createJSErrorHandler(JSC::ExecState* exec, JSC::JSValue listener, JSC::JSObject* wrapper)
{
if (!listener.isObject())
- return 0;
+ return nullptr;
return JSErrorHandler::create(asObject(listener), wrapper, true, currentWorld(exec));
}
} // namespace WebCore
-
-#endif // JSErrorHandler_h
diff --git a/Source/WebCore/bindings/js/JSEventCustom.cpp b/Source/WebCore/bindings/js/JSEventCustom.cpp
index e1698db17..72917973f 100644
--- a/Source/WebCore/bindings/js/JSEventCustom.cpp
+++ b/Source/WebCore/bindings/js/JSEventCustom.cpp
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -29,45 +29,35 @@
#include "config.h"
#include "JSEvent.h"
-#include "Clipboard.h"
+#include "DataTransfer.h"
#include "Event.h"
#include "EventHeaders.h"
#include "EventInterfaces.h"
-#include "EventNames.h"
-#include "JSClipboard.h"
+#include "JSDOMBinding.h"
+#include "JSDataTransfer.h"
#include <runtime/JSLock.h>
-#include <wtf/HashMap.h>
#include <wtf/text/AtomicString.h>
using namespace JSC;
namespace WebCore {
-JSValue JSEvent::clipboardData(ExecState* exec) const
-{
- return impl().isClipboardEvent() ? toJS(exec, globalObject(), impl().clipboardData()) : jsUndefined();
-}
-
#define TRY_TO_WRAP_WITH_INTERFACE(interfaceName) \
case interfaceName##InterfaceType: \
- return CREATE_DOM_WRAPPER(exec, globalObject, interfaceName, event);
+ return createWrapper<interfaceName>(globalObject, WTFMove(event));
-JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, Event* event)
+JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<Event>&& event)
{
- JSLockHolder lock(exec);
-
- if (!event)
- return jsNull();
-
- JSObject* wrapper = getCachedWrapper(currentWorld(exec), event);
- if (wrapper)
- return wrapper;
-
switch (event->eventInterface()) {
DOM_EVENT_INTERFACES_FOR_EACH(TRY_TO_WRAP_WITH_INTERFACE)
}
- return CREATE_DOM_WRAPPER(exec, globalObject, Event, event);
+ return createWrapper<Event>(globalObject, WTFMove(event));
+}
+
+JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, Event& event)
+{
+ return wrap(state, globalObject, event);
}
#undef TRY_TO_WRAP_WITH_INTERFACE
diff --git a/Source/WebCore/bindings/js/ScriptProfileNode.h b/Source/WebCore/bindings/js/JSEventCustom.h
index 2b9ec5beb..2b85293c4 100644
--- a/Source/WebCore/bindings/js/ScriptProfileNode.h
+++ b/Source/WebCore/bindings/js/JSEventCustom.h
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
- * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -11,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -24,15 +23,16 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ScriptProfileNode_h
-#define ScriptProfileNode_h
+#pragma once
-#include <profiler/ProfileNode.h>
+#include "JSDOMBinding.h"
namespace WebCore {
-typedef JSC::ProfileNode ScriptProfileNode;
+template<typename From>
+ALWAYS_INLINE JSDynamicCastResult<JSEvent, From> jsEventCast(From* value)
+{
+ return value->type() == JSEventType ? JSC::jsCast<JSDynamicCastResult<JSEvent, From>>(value) : nullptr;
+}
} // namespace WebCore
-
-#endif // ScriptProfileNode_h
diff --git a/Source/WebCore/bindings/js/JSEventListener.cpp b/Source/WebCore/bindings/js/JSEventListener.cpp
index 00d16c849..621a210bb 100644
--- a/Source/WebCore/bindings/js/JSEventListener.cpp
+++ b/Source/WebCore/bindings/js/JSEventListener.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2003-2017 Apple Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -21,9 +21,12 @@
#include "JSEventListener.h"
#include "BeforeUnloadEvent.h"
+#include "ContentSecurityPolicy.h"
#include "Event.h"
#include "Frame.h"
-#include "InspectorCounters.h"
+#include "HTMLElement.h"
+#include "JSDOMConvert.h"
+#include "JSDocument.h"
#include "JSEvent.h"
#include "JSEventTarget.h"
#include "JSMainThreadExecState.h"
@@ -33,8 +36,8 @@
#include <runtime/ExceptionHelpers.h>
#include <runtime/JSLock.h>
#include <runtime/VMEntryScope.h>
+#include <runtime/Watchdog.h>
#include <wtf/Ref.h>
-#include <wtf/RefCountedLeakCounter.h>
using namespace JSC;
@@ -44,28 +47,22 @@ JSEventListener::JSEventListener(JSObject* function, JSObject* wrapper, bool isA
: EventListener(JSEventListenerType)
, m_wrapper(wrapper)
, m_isAttribute(isAttribute)
- , m_isolatedWorld(&isolatedWorld)
+ , m_isolatedWorld(isolatedWorld)
{
if (wrapper) {
- JSC::Heap::writeBarrier(wrapper, function);
+ JSC::Heap::heap(wrapper)->writeBarrier(wrapper, function);
m_jsFunction = JSC::Weak<JSC::JSObject>(function);
} else
ASSERT(!function);
-#if ENABLE(INSPECTOR)
- ThreadLocalInspectorCounters::current().incrementCounter(ThreadLocalInspectorCounters::JSEventListenerCounter);
-#endif
}
JSEventListener::~JSEventListener()
{
-#if ENABLE(INSPECTOR)
- ThreadLocalInspectorCounters::current().decrementCounter(ThreadLocalInspectorCounters::JSEventListenerCounter);
-#endif
}
JSObject* JSEventListener::initializeJSFunction(ScriptExecutionContext*) const
{
- return 0;
+ return nullptr;
}
void JSEventListener::visitJSFunction(SlotVisitor& visitor)
@@ -74,7 +71,17 @@ void JSEventListener::visitJSFunction(SlotVisitor& visitor)
if (!m_wrapper)
return;
- visitor.appendUnbarrieredWeak(&m_jsFunction);
+ visitor.append(m_jsFunction);
+}
+
+static void handleBeforeUnloadEventReturnValue(BeforeUnloadEvent& event, const String& returnValue)
+{
+ if (returnValue.isNull())
+ return;
+
+ event.preventDefault();
+ if (event.returnValue().isEmpty())
+ event.setReturnValue(returnValue);
}
void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext, Event* event)
@@ -83,22 +90,29 @@ void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext
if (!scriptExecutionContext || scriptExecutionContext->isJSExecutionForbidden())
return;
- JSLockHolder lock(scriptExecutionContext->vm());
+ VM& vm = scriptExecutionContext->vm();
+ JSLockHolder lock(vm);
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+ // See https://dom.spec.whatwg.org/#dispatching-events spec on calling handleEvent.
+ // "If this throws an exception, report the exception." It should not propagate the
+ // exception.
JSObject* jsFunction = this->jsFunction(scriptExecutionContext);
if (!jsFunction)
return;
- JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext, *m_isolatedWorld);
+ JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(scriptExecutionContext, m_isolatedWorld);
if (!globalObject)
return;
if (scriptExecutionContext->isDocument()) {
JSDOMWindow* window = jsCast<JSDOMWindow*>(globalObject);
- if (!window->impl().isCurrentlyDisplayedInFrame())
+ if (!window->wrapped().isCurrentlyDisplayedInFrame())
+ return;
+ if (wasCreatedFromMarkup() && !scriptExecutionContext->contentSecurityPolicy()->allowInlineEventHandlers(sourceURL(), sourcePosition().m_line))
return;
// FIXME: Is this check needed for other contexts?
- ScriptController& script = window->impl().frame()->script();
+ ScriptController& script = window->wrapped().frame()->script();
if (!script.canExecuteScripts(AboutToExecuteScript) || script.isPaused())
return;
}
@@ -109,13 +123,21 @@ void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext
CallData callData;
CallType callType = getCallData(handleEventFunction, callData);
// If jsFunction is not actually a function, see if it implements the EventListener interface and use that
- if (callType == CallTypeNone) {
- handleEventFunction = jsFunction->get(exec, Identifier(exec, "handleEvent"));
+ if (callType == CallType::None) {
+ handleEventFunction = jsFunction->get(exec, Identifier::fromString(exec, "handleEvent"));
+ if (UNLIKELY(scope.exception())) {
+ auto* exception = scope.exception();
+ scope.clearException();
+
+ event->target()->uncaughtExceptionInEventHandler();
+ reportException(exec, exception);
+ return;
+ }
callType = getCallData(handleEventFunction, callData);
}
- if (callType != CallTypeNone) {
- Ref<JSEventListener> protect(*this);
+ if (callType != CallType::None) {
+ Ref<JSEventListener> protectedThis(*this);
MarkedArgumentBuffer args;
args.append(toJS(exec, globalObject, event));
@@ -123,32 +145,34 @@ void JSEventListener::handleEvent(ScriptExecutionContext* scriptExecutionContext
Event* savedEvent = globalObject->currentEvent();
globalObject->setCurrentEvent(event);
- VM& vm = globalObject->vm();
VMEntryScope entryScope(vm, vm.entryScope ? vm.entryScope->globalObject() : globalObject);
InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(scriptExecutionContext, callType, callData);
JSValue thisValue = handleEventFunction == jsFunction ? toJS(exec, globalObject, event->currentTarget()) : jsFunction;
+ NakedPtr<JSC::Exception> exception;
JSValue retval = scriptExecutionContext->isDocument()
- ? JSMainThreadExecState::call(exec, handleEventFunction, callType, callData, thisValue, args)
- : JSC::call(exec, handleEventFunction, callType, callData, thisValue, args);
+ ? JSMainThreadExecState::profiledCall(exec, JSC::ProfilingReason::Other, handleEventFunction, callType, callData, thisValue, args, exception)
+ : JSC::profiledCall(exec, JSC::ProfilingReason::Other, handleEventFunction, callType, callData, thisValue, args, exception);
- InspectorInstrumentation::didCallFunction(cookie);
+ InspectorInstrumentation::didCallFunction(cookie, scriptExecutionContext);
globalObject->setCurrentEvent(savedEvent);
- if (scriptExecutionContext->isWorkerGlobalScope()) {
- bool terminatorCausedException = (exec->hadException() && isTerminatedExecutionException(exec->exception()));
- if (terminatorCausedException || vm.watchdog.didFire())
- static_cast<WorkerGlobalScope*>(scriptExecutionContext)->script()->forbidExecution();
+ if (is<WorkerGlobalScope>(*scriptExecutionContext)) {
+ auto scriptController = downcast<WorkerGlobalScope>(*scriptExecutionContext).script();
+ bool terminatorCausedException = (scope.exception() && isTerminatedExecutionException(vm, scope.exception()));
+ if (terminatorCausedException || scriptController->isTerminatingExecution())
+ scriptController->forbidExecution();
}
- if (exec->hadException()) {
+ if (exception) {
event->target()->uncaughtExceptionInEventHandler();
- reportCurrentException(exec);
+ reportException(exec, exception);
} else {
- if (!retval.isUndefinedOrNull() && event->isBeforeUnloadEvent())
- toBeforeUnloadEvent(event)->setReturnValue(retval.toString(exec)->value(exec));
+ if (is<BeforeUnloadEvent>(*event))
+ handleBeforeUnloadEventReturnValue(downcast<BeforeUnloadEvent>(*event), convert<IDLNullable<IDLDOMString>>(*exec, retval, StringConversionConfiguration::Normal));
+
if (m_isAttribute) {
if (retval.isFalse())
event->preventDefault();
@@ -162,11 +186,91 @@ bool JSEventListener::virtualisAttribute() const
return m_isAttribute;
}
-bool JSEventListener::operator==(const EventListener& listener)
+bool JSEventListener::operator==(const EventListener& listener) const
{
if (const JSEventListener* jsEventListener = JSEventListener::cast(&listener))
return m_jsFunction == jsEventListener->m_jsFunction && m_isAttribute == jsEventListener->m_isAttribute;
return false;
}
+static inline JSC::JSValue eventHandlerAttribute(EventListener* abstractListener, ScriptExecutionContext& context)
+{
+ if (!abstractListener)
+ return jsNull();
+
+ auto* listener = JSEventListener::cast(abstractListener);
+ if (!listener)
+ return jsNull();
+
+ auto* function = listener->jsFunction(&context);
+ if (!function)
+ return jsNull();
+
+ return function;
+}
+
+static inline RefPtr<JSEventListener> createEventListenerForEventHandlerAttribute(JSC::ExecState& state, JSC::JSValue listener, JSC::JSObject& wrapper)
+{
+ if (!listener.isObject())
+ return nullptr;
+ return JSEventListener::create(asObject(listener), &wrapper, true, currentWorld(&state));
+}
+
+JSC::JSValue eventHandlerAttribute(EventTarget& target, const AtomicString& eventType, DOMWrapperWorld& isolatedWorld)
+{
+ return eventHandlerAttribute(target.attributeEventListener(eventType, isolatedWorld), *target.scriptExecutionContext());
+}
+
+void setEventHandlerAttribute(JSC::ExecState& state, JSC::JSObject& wrapper, EventTarget& target, const AtomicString& eventType, JSC::JSValue value)
+{
+ target.setAttributeEventListener(eventType, createEventListenerForEventHandlerAttribute(state, value, wrapper), currentWorld(&state));
+}
+
+JSC::JSValue windowEventHandlerAttribute(HTMLElement& element, const AtomicString& eventType, DOMWrapperWorld& isolatedWorld)
+{
+ auto& document = element.document();
+ return eventHandlerAttribute(document.getWindowAttributeEventListener(eventType, isolatedWorld), document);
+}
+
+void setWindowEventHandlerAttribute(JSC::ExecState& state, JSC::JSObject& wrapper, HTMLElement& element, const AtomicString& eventType, JSC::JSValue value)
+{
+ ASSERT(wrapper.globalObject());
+ element.document().setWindowAttributeEventListener(eventType, createEventListenerForEventHandlerAttribute(state, value, *wrapper.globalObject()), currentWorld(&state));
+}
+
+JSC::JSValue windowEventHandlerAttribute(DOMWindow& window, const AtomicString& eventType, DOMWrapperWorld& isolatedWorld)
+{
+ return eventHandlerAttribute(window, eventType, isolatedWorld);
+}
+
+void setWindowEventHandlerAttribute(JSC::ExecState& state, JSC::JSObject& wrapper, DOMWindow& window, const AtomicString& eventType, JSC::JSValue value)
+{
+ setEventHandlerAttribute(state, wrapper, window, eventType, value);
+}
+
+JSC::JSValue documentEventHandlerAttribute(HTMLElement& element, const AtomicString& eventType, DOMWrapperWorld& isolatedWorld)
+{
+ auto& document = element.document();
+ return eventHandlerAttribute(document.attributeEventListener(eventType, isolatedWorld), document);
+}
+
+void setDocumentEventHandlerAttribute(JSC::ExecState& state, JSC::JSObject& wrapper, HTMLElement& element, const AtomicString& eventType, JSC::JSValue value)
+{
+ ASSERT(wrapper.globalObject());
+ auto& document = element.document();
+ auto* documentWrapper = JSC::jsCast<JSDocument*>(toJS(&state, JSC::jsCast<JSDOMGlobalObject*>(wrapper.globalObject()), document));
+ ASSERT(documentWrapper);
+ document.setAttributeEventListener(eventType, createEventListenerForEventHandlerAttribute(state, value, *documentWrapper), currentWorld(&state));
+}
+
+JSC::JSValue documentEventHandlerAttribute(Document& document, const AtomicString& eventType, DOMWrapperWorld& isolatedWorld)
+{
+ return eventHandlerAttribute(document, eventType, isolatedWorld);
+}
+
+void setDocumentEventHandlerAttribute(JSC::ExecState& state, JSC::JSObject& wrapper, Document& document, const AtomicString& eventType, JSC::JSValue value)
+{
+ setEventHandlerAttribute(state, wrapper, document, eventType, value);
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSEventListener.h b/Source/WebCore/bindings/js/JSEventListener.h
index 303ff691c..693853adb 100644
--- a/Source/WebCore/bindings/js/JSEventListener.h
+++ b/Source/WebCore/bindings/js/JSEventListener.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2003-2017 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -17,103 +17,129 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef JSEventListener_h
-#define JSEventListener_h
+#pragma once
+#include "DOMWrapperWorld.h"
#include "EventListener.h"
-#include "JSDOMWindow.h"
#include <heap/StrongInlines.h>
#include <heap/Weak.h>
#include <heap/WeakInlines.h>
#include <wtf/Ref.h>
+#include <wtf/TypeCasts.h>
+#include <wtf/text/TextPosition.h>
+#include <wtf/text/WTFString.h>
namespace WebCore {
- class JSDOMGlobalObject;
+class DOMWindow;
+class EventTarget;
+class HTMLElement;
+class JSDOMGlobalObject;
- class JSEventListener : public EventListener {
- public:
- static PassRefPtr<JSEventListener> create(JSC::JSObject* listener, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld& world)
- {
- return adoptRef(new JSEventListener(listener, wrapper, isAttribute, world));
- }
+class JSEventListener : public EventListener {
+public:
+ static Ref<JSEventListener> create(JSC::JSObject* listener, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld& world)
+ {
+ return adoptRef(*new JSEventListener(listener, wrapper, isAttribute, world));
+ }
- static const JSEventListener* cast(const EventListener* listener)
- {
- return listener->type() == JSEventListenerType
- ? static_cast<const JSEventListener*>(listener)
- : 0;
- }
+ static RefPtr<JSEventListener> create(JSC::JSValue listener, JSC::JSObject& wrapper, bool isAttribute, DOMWrapperWorld& world)
+ {
+ if (UNLIKELY(!listener.isObject()))
+ return nullptr;
- virtual ~JSEventListener();
+ return adoptRef(new JSEventListener(JSC::asObject(listener), &wrapper, isAttribute, world));
+ }
- virtual bool operator==(const EventListener& other) override;
+ static const JSEventListener* cast(const EventListener* listener)
+ {
+ return listener->type() == JSEventListenerType
+ ? static_cast<const JSEventListener*>(listener)
+ : nullptr;
+ }
- // Returns true if this event listener was created for an event handler attribute, like "onload" or "onclick".
- bool isAttribute() const { return m_isAttribute; }
+ virtual ~JSEventListener();
- JSC::JSObject* jsFunction(ScriptExecutionContext*) const;
- DOMWrapperWorld& isolatedWorld() const { return *m_isolatedWorld; }
+ bool operator==(const EventListener& other) const override;
- JSC::JSObject* wrapper() const { return m_wrapper.get(); }
- void setWrapper(JSC::VM&, JSC::JSObject* wrapper) const { m_wrapper = JSC::Weak<JSC::JSObject>(wrapper); }
+ // Returns true if this event listener was created for an event handler attribute, like "onload" or "onclick".
+ bool isAttribute() const { return m_isAttribute; }
- private:
- virtual JSC::JSObject* initializeJSFunction(ScriptExecutionContext*) const;
- virtual void visitJSFunction(JSC::SlotVisitor&) override;
- virtual bool virtualisAttribute() const override;
+ JSC::JSObject* jsFunction(ScriptExecutionContext*) const;
+ DOMWrapperWorld& isolatedWorld() const { return m_isolatedWorld; }
- protected:
- JSEventListener(JSC::JSObject* function, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld&);
- virtual void handleEvent(ScriptExecutionContext*, Event*) override;
+ JSC::JSObject* wrapper() const { return m_wrapper.get(); }
+ void setWrapper(JSC::VM&, JSC::JSObject* wrapper) const { m_wrapper = JSC::Weak<JSC::JSObject>(wrapper); }
- private:
- mutable JSC::Weak<JSC::JSObject> m_jsFunction;
- mutable JSC::Weak<JSC::JSObject> m_wrapper;
+ virtual String sourceURL() const { return String(); }
+ virtual TextPosition sourcePosition() const { return TextPosition(); }
- bool m_isAttribute;
- RefPtr<DOMWrapperWorld> m_isolatedWorld;
- };
+private:
+ virtual JSC::JSObject* initializeJSFunction(ScriptExecutionContext*) const;
+ void visitJSFunction(JSC::SlotVisitor&) override;
+ bool virtualisAttribute() const override;
- inline JSC::JSObject* JSEventListener::jsFunction(ScriptExecutionContext* scriptExecutionContext) const
- {
- // initializeJSFunction can trigger code that deletes this event listener
- // before we're done. It should always return 0 in this case.
- Ref<JSEventListener> protect(const_cast<JSEventListener&>(*this));
- JSC::Strong<JSC::JSObject> wrapper(*m_isolatedWorld->vm(), m_wrapper.get());
-
- if (!m_jsFunction) {
- JSC::JSObject* function = initializeJSFunction(scriptExecutionContext);
- JSC::Heap::writeBarrier(m_wrapper.get(), function);
- m_jsFunction = JSC::Weak<JSC::JSObject>(function);
- }
-
- // Verify that we have a valid wrapper protecting our function from
- // garbage collection. That is except for when we're not in the normal
- // world and can have zombie m_jsFunctions.
- ASSERT(!m_isolatedWorld->isNormal() || m_wrapper || !m_jsFunction);
-
- // If m_wrapper is 0, then m_jsFunction is zombied, and should never be accessed.
- if (!m_wrapper)
- return 0;
-
- // Try to verify that m_jsFunction wasn't recycled. (Not exact, since an
- // event listener can be almost anything, but this makes test-writing easier).
- ASSERT(!m_jsFunction || static_cast<JSC::JSCell*>(m_jsFunction.get())->isObject());
-
- return m_jsFunction.get();
- }
+protected:
+ JSEventListener(JSC::JSObject* function, JSC::JSObject* wrapper, bool isAttribute, DOMWrapperWorld&);
+ void handleEvent(ScriptExecutionContext*, Event*) override;
- // Creates a JS EventListener for an "onXXX" event attribute.
- inline PassRefPtr<JSEventListener> createJSAttributeEventListener(JSC::ExecState* exec, JSC::JSValue listener, JSC::JSObject* wrapper)
- {
- if (!listener.isObject())
- return 0;
+private:
+ mutable JSC::Weak<JSC::JSObject> m_jsFunction;
+ mutable JSC::Weak<JSC::JSObject> m_wrapper;
- return JSEventListener::create(asObject(listener), wrapper, true, currentWorld(exec));
+ bool m_isAttribute;
+ Ref<DOMWrapperWorld> m_isolatedWorld;
+};
+
+// For "onxxx" attributes that automatically set up JavaScript event listeners.
+JSC::JSValue eventHandlerAttribute(EventTarget&, const AtomicString& eventType, DOMWrapperWorld&);
+void setEventHandlerAttribute(JSC::ExecState&, JSC::JSObject&, EventTarget&, const AtomicString& eventType, JSC::JSValue);
+
+// Like the functions above, but for attributes that forward event handlers to the window object rather than setting them on the target.
+JSC::JSValue windowEventHandlerAttribute(HTMLElement&, const AtomicString& eventType, DOMWrapperWorld&);
+void setWindowEventHandlerAttribute(JSC::ExecState&, JSC::JSObject&, HTMLElement&, const AtomicString& eventType, JSC::JSValue);
+JSC::JSValue windowEventHandlerAttribute(DOMWindow&, const AtomicString& eventType, DOMWrapperWorld&);
+void setWindowEventHandlerAttribute(JSC::ExecState&, JSC::JSObject&, DOMWindow&, const AtomicString& eventType, JSC::JSValue);
+
+// Like the functions above, but for attributes that forward event handlers to the document rather than setting them on the target.
+JSC::JSValue documentEventHandlerAttribute(HTMLElement&, const AtomicString& eventType, DOMWrapperWorld&);
+void setDocumentEventHandlerAttribute(JSC::ExecState&, JSC::JSObject&, HTMLElement&, const AtomicString& eventType, JSC::JSValue);
+JSC::JSValue documentEventHandlerAttribute(Document&, const AtomicString& eventType, DOMWrapperWorld&);
+void setDocumentEventHandlerAttribute(JSC::ExecState&, JSC::JSObject&, Document&, const AtomicString& eventType, JSC::JSValue);
+
+inline JSC::JSObject* JSEventListener::jsFunction(ScriptExecutionContext* scriptExecutionContext) const
+{
+ // initializeJSFunction can trigger code that deletes this event listener
+ // before we're done. It should always return 0 in this case.
+ auto protect = makeRef(const_cast<JSEventListener&>(*this));
+ JSC::Strong<JSC::JSObject> wrapper(m_isolatedWorld->vm(), m_wrapper.get());
+
+ if (!m_jsFunction) {
+ JSC::JSObject* function = initializeJSFunction(scriptExecutionContext);
+ JSC::JSObject* wrapper = m_wrapper.get();
+ if (wrapper)
+ JSC::Heap::heap(wrapper)->writeBarrier(wrapper, function);
+ m_jsFunction = JSC::Weak<JSC::JSObject>(function);
}
+ // Verify that we have a valid wrapper protecting our function from
+ // garbage collection. That is except for when we're not in the normal
+ // world and can have zombie m_jsFunctions.
+ ASSERT(!m_isolatedWorld->isNormal() || m_wrapper || !m_jsFunction);
+
+ // If m_wrapper is 0, then m_jsFunction is zombied, and should never be accessed.
+ if (!m_wrapper)
+ return nullptr;
+
+ // Try to verify that m_jsFunction wasn't recycled. (Not exact, since an
+ // event listener can be almost anything, but this makes test-writing easier).
+ ASSERT(!m_jsFunction || static_cast<JSC::JSCell*>(m_jsFunction.get())->isObject());
+
+ return m_jsFunction.get();
+}
} // namespace WebCore
-#endif // JSEventListener_h
+SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::JSEventListener)
+static bool isType(const WebCore::EventListener& input) { return input.type() == WebCore::JSEventListener::JSEventListenerType; }
+SPECIALIZE_TYPE_TRAITS_END()
diff --git a/Source/WebCore/bindings/js/JSEventTargetCustom.cpp b/Source/WebCore/bindings/js/JSEventTargetCustom.cpp
index 5210f12bb..07b46899e 100644
--- a/Source/WebCore/bindings/js/JSEventTargetCustom.cpp
+++ b/Source/WebCore/bindings/js/JSEventTargetCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008-2017 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -26,10 +26,15 @@
#include "config.h"
#include "JSEventTarget.h"
+#include "DOMWindow.h"
+#include "EventTarget.h"
#include "EventTargetHeaders.h"
#include "EventTargetInterfaces.h"
+#include "JSDOMWindow.h"
#include "JSDOMWindowShell.h"
#include "JSEventListener.h"
+#include "JSWorkerGlobalScope.h"
+#include "WorkerGlobalScope.h"
using namespace JSC;
@@ -37,14 +42,11 @@ namespace WebCore {
#define TRY_TO_WRAP_WITH_INTERFACE(interfaceName) \
case interfaceName##EventTargetInterfaceType: \
- return toJS(exec, globalObject, static_cast<interfaceName*>(target));
+ return toJS(exec, globalObject, static_cast<interfaceName&>(target));
-JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, EventTarget* target)
+JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, EventTarget& target)
{
- if (!target)
- return jsNull();
-
- switch (target->eventTargetInterface()) {
+ switch (target.eventTargetInterface()) {
DOM_EVENT_TARGET_INTERFACES_FOR_EACH(TRY_TO_WRAP_WITH_INTERFACE)
}
@@ -55,18 +57,34 @@ JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, EventTarget* targ
#undef TRY_TO_WRAP_WITH_INTERFACE
#define TRY_TO_UNWRAP_WITH_INTERFACE(interfaceName) \
- if (value.inherits(JS##interfaceName::info())) \
- return &jsCast<JS##interfaceName*>(asObject(value))->impl();
+ if (value.inherits(vm, JS##interfaceName::info())) \
+ return &jsCast<JS##interfaceName*>(asObject(value))->wrapped();
-EventTarget* toEventTarget(JSC::JSValue value)
+EventTarget* JSEventTarget::toWrapped(VM& vm, JSValue value)
{
TRY_TO_UNWRAP_WITH_INTERFACE(DOMWindowShell)
+ TRY_TO_UNWRAP_WITH_INTERFACE(DOMWindow)
+ TRY_TO_UNWRAP_WITH_INTERFACE(WorkerGlobalScope)
TRY_TO_UNWRAP_WITH_INTERFACE(EventTarget)
- // FIXME: Remove this once all event targets extend EventTarget
- DOM_EVENT_TARGET_INTERFACES_FOR_EACH(TRY_TO_UNWRAP_WITH_INTERFACE)
- return 0;
+ return nullptr;
}
#undef TRY_TO_UNWRAP_WITH_INTERFACE
+std::unique_ptr<JSEventTargetWrapper> jsEventTargetCast(VM& vm, JSValue thisValue)
+{
+ if (auto* target = jsDynamicDowncast<JSEventTarget*>(vm, thisValue))
+ return std::make_unique<JSEventTargetWrapper>(target->wrapped(), *target);
+ if (auto* window = toJSDOMWindow(vm, thisValue))
+ return std::make_unique<JSEventTargetWrapper>(window->wrapped(), *window);
+ if (auto* scope = toJSWorkerGlobalScope(vm, thisValue))
+ return std::make_unique<JSEventTargetWrapper>(scope->wrapped(), *scope);
+ return nullptr;
+}
+
+void JSEventTarget::visitAdditionalChildren(SlotVisitor& visitor)
+{
+ wrapped().visitJSEventListeners(visitor);
+}
+
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSEventTargetCustom.h b/Source/WebCore/bindings/js/JSEventTargetCustom.h
new file mode 100644
index 000000000..7f55358d5
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSEventTargetCustom.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "DOMWindow.h"
+#include "JSDOMBinding.h"
+#include "JSDOMBindingCaller.h"
+#include "JSDOMBindingSecurity.h"
+
+namespace WebCore {
+
+// Wrapper type for JSEventTarget's castedThis because JSDOMWindow and JSWorkerGlobalScope do not inherit JSEventTarget.
+class JSEventTargetWrapper {
+ WTF_MAKE_FAST_ALLOCATED;
+public:
+ JSEventTargetWrapper(EventTarget& wrapped, JSC::JSObject& wrapper)
+ : m_wrapped(wrapped)
+ , m_wrapper(wrapper)
+ { }
+
+ EventTarget& wrapped() { return m_wrapped; }
+
+ operator JSC::JSObject&() { return m_wrapper; }
+
+private:
+ EventTarget& m_wrapped;
+ JSC::JSObject& m_wrapper;
+};
+
+std::unique_ptr<JSEventTargetWrapper> jsEventTargetCast(JSC::VM&, JSC::JSValue thisValue);
+
+template<> struct BindingCaller<JSEventTarget> {
+ using OperationCallerFunction = JSC::EncodedJSValue(JSC::ExecState*, JSEventTargetWrapper*, JSC::ThrowScope&);
+
+ template<OperationCallerFunction operationCaller>
+ static JSC::EncodedJSValue callOperation(JSC::ExecState* state, const char* operationName)
+ {
+ ASSERT(state);
+ JSC::VM& vm = state->vm();
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
+
+ auto thisObject = jsEventTargetCast(vm, state->thisValue().toThis(state, JSC::NotStrictMode));
+ if (UNLIKELY(!thisObject))
+ return throwThisTypeError(*state, throwScope, "EventTarget", operationName);
+
+ if (auto* window = thisObject->wrapped().toDOMWindow()) {
+ if (!window->frame() || !BindingSecurity::shouldAllowAccessToDOMWindow(state, *window, ThrowSecurityError))
+ return JSC::JSValue::encode(JSC::jsUndefined());
+ }
+
+ return operationCaller(state, thisObject.get(), throwScope);
+ }
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSExceptionBase.cpp b/Source/WebCore/bindings/js/JSExceptionBase.cpp
index 8a51e0c97..f9238f333 100644
--- a/Source/WebCore/bindings/js/JSExceptionBase.cpp
+++ b/Source/WebCore/bindings/js/JSExceptionBase.cpp
@@ -27,40 +27,23 @@
#include "JSExceptionBase.h"
#include "JSDOMCoreException.h"
-#include "JSEventException.h"
-#include "JSRangeException.h"
-#include "JSXMLHttpRequestException.h"
-#if ENABLE(SQL_DATABASE)
-#include "SQLException.h"
#include "JSSQLException.h"
-#endif
-#if ENABLE(SVG)
#include "JSSVGException.h"
-#endif
#include "JSXPathException.h"
+#include "SQLException.h"
namespace WebCore {
-ExceptionBase* toExceptionBase(JSC::JSValue value)
+ExceptionBase* toExceptionBase(JSC::VM& vm, JSC::JSValue value)
{
- if (DOMCoreException* domException = toDOMCoreException(value))
+ if (DOMCoreException* domException = JSDOMCoreException::toWrapped(vm, value))
return reinterpret_cast<ExceptionBase*>(domException);
- if (RangeException* rangeException = toRangeException(value))
- return reinterpret_cast<ExceptionBase*>(rangeException);
- if (EventException* eventException = toEventException(value))
- return reinterpret_cast<ExceptionBase*>(eventException);
- if (XMLHttpRequestException* xmlHttpException = toXMLHttpRequestException(value))
- return reinterpret_cast<ExceptionBase*>(xmlHttpException);
-#if ENABLE(SVG)
- if (SVGException* svgException = toSVGException(value))
+ if (SVGException* svgException = JSSVGException::toWrapped(vm, value))
return reinterpret_cast<ExceptionBase*>(svgException);
-#endif
- if (XPathException* pathException = toXPathException(value))
+ if (XPathException* pathException = JSXPathException::toWrapped(vm, value))
return reinterpret_cast<ExceptionBase*>(pathException);
-#if ENABLE(SQL_DATABASE)
- if (SQLException* pathException = toSQLException(value))
+ if (SQLException* pathException = JSSQLException::toWrapped(vm, value))
return reinterpret_cast<ExceptionBase*>(pathException);
-#endif
return 0;
}
diff --git a/Source/WebCore/bindings/js/JSExceptionBase.h b/Source/WebCore/bindings/js/JSExceptionBase.h
index 771300293..d88141e02 100644
--- a/Source/WebCore/bindings/js/JSExceptionBase.h
+++ b/Source/WebCore/bindings/js/JSExceptionBase.h
@@ -23,21 +23,17 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSExceptionBase_h
-#define JSExceptionBase_h
+#pragma once
namespace JSC {
-
class JSValue;
-
-} // namespace JSC
+class VM;
+}
namespace WebCore {
class ExceptionBase;
-ExceptionBase* toExceptionBase(JSC::JSValue);
+ExceptionBase* toExceptionBase(JSC::VM&, JSC::JSValue);
} // namespace WebCore
-
-#endif // JSExceptionBase_h
diff --git a/Source/WebCore/bindings/js/JSFileReaderCustom.cpp b/Source/WebCore/bindings/js/JSFileReaderCustom.cpp
deleted file mode 100644
index f2970b27b..000000000
--- a/Source/WebCore/bindings/js/JSFileReaderCustom.cpp
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(BLOB)
-
-#include "JSFileReader.h"
-
-#include "FileReader.h"
-#include <runtime/ArrayBuffer.h>
-#include <runtime/JSArrayBuffer.h>
-
-using namespace JSC;
-
-namespace WebCore {
-
-JSValue JSFileReader::result(ExecState* exec) const
-{
- FileReader& imp = impl();
- if (imp.readType() == FileReaderLoader::ReadAsArrayBuffer)
- return toJS(exec, globalObject(), WTF::getPtr(imp.arrayBufferResult()));
- return jsOwnedStringOrNull(exec, imp.stringResult());
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(BLOB)
diff --git a/Source/WebCore/bindings/js/JSFontFaceCustom.cpp b/Source/WebCore/bindings/js/JSFontFaceCustom.cpp
new file mode 100644
index 000000000..af460e4ec
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSFontFaceCustom.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSFontFace.h"
+
+#include "CSSFontSelector.h"
+#include "CSSValue.h"
+#include "CSSValueList.h"
+#include "ExceptionCode.h"
+#include "JSDOMConstructor.h"
+
+namespace WebCore {
+
+JSC::JSValue JSFontFace::loaded(JSC::ExecState& state) const
+{
+ if (!m_loaded) {
+ if (!wrapped().promise()) {
+ auto promise = createDeferredPromise(state, domWindow());
+ m_loaded.set(state.vm(), this, promise->promise());
+ wrapped().registerLoaded(WTFMove(promise));
+ } else
+ m_loaded.set(state.vm(), this, wrapped().promise().value().promise());
+ }
+ return m_loaded.get();
+}
+
+JSC::JSValue JSFontFace::load(JSC::ExecState& state)
+{
+ wrapped().load();
+ return loaded(state);
+}
+
+}
diff --git a/Source/WebCore/bindings/js/JSFontFaceSetCustom.cpp b/Source/WebCore/bindings/js/JSFontFaceSetCustom.cpp
new file mode 100644
index 000000000..22560d44f
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSFontFaceSetCustom.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSFontFaceSet.h"
+
+#include "FontFace.h"
+#include "JSFontFace.h"
+
+namespace WebCore {
+
+JSC::JSValue JSFontFaceSet::ready(JSC::ExecState& state) const
+{
+ if (!m_ready) {
+ auto promise = createDeferredPromise(state, domWindow());
+ m_ready.set(state.vm(), this, promise->promise());
+ wrapped().registerReady(WTFMove(promise));
+ }
+ return m_ready.get();
+}
+
+}
diff --git a/Source/WebCore/bindings/js/JSGeolocationCustom.cpp b/Source/WebCore/bindings/js/JSGeolocationCustom.cpp
deleted file mode 100644
index d1a2daa1a..000000000
--- a/Source/WebCore/bindings/js/JSGeolocationCustom.cpp
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "JSGeolocation.h"
-
-#if ENABLE(GEOLOCATION)
-
-#include "CallbackFunction.h"
-#include "DOMWindow.h"
-#include "Geolocation.h"
-#include "JSDOMWindow.h"
-#include "JSDictionary.h"
-#include "JSPositionCallback.h"
-#include "JSPositionErrorCallback.h"
-#include "PositionOptions.h"
-
-using namespace JSC;
-
-namespace WebCore {
-
-// JSDictionary helper functions
-
-static void setEnableHighAccuracy(PositionOptions* options, const bool& enableHighAccuracy)
-{
- options->setEnableHighAccuracy(enableHighAccuracy);
-}
-
-static void setTimeout(PositionOptions* options, const double& timeout)
-{
- // If the value is positive infinity, there's nothing to do.
- if (!(std::isinf(timeout) && (timeout > 0))) {
- // Wrap to int32 and force non-negative to match behavior of window.setTimeout.
- options->setTimeout(std::max<int>(0, timeout));
- }
-}
-
-static void setMaximumAge(PositionOptions* options, const double& maximumAge)
-{
- if (std::isinf(maximumAge) && (maximumAge > 0)) {
- // If the value is positive infinity, clear maximumAge.
- options->clearMaximumAge();
- } else {
- // Wrap to int32 and force non-negative to match behavior of window.setTimeout.
- options->setMaximumAge(std::max<int>(0, maximumAge));
- }
-}
-
-
-static PassRefPtr<PositionOptions> createPositionOptions(ExecState* exec, JSValue value)
-{
- // Create default options.
- RefPtr<PositionOptions> options = PositionOptions::create();
-
- // Argument is optional (hence undefined is allowed), and null is allowed.
- if (value.isUndefinedOrNull()) {
- // Use default options.
- return options.release();
- }
-
- // Given the above test, this will always yield an object.
- JSObject* object = value.toObject(exec);
-
- // Create the dictionary wrapper from the initializer object.
- JSDictionary dictionary(exec, object);
-
- if (!dictionary.tryGetProperty("enableHighAccuracy", options.get(), setEnableHighAccuracy))
- return 0;
- if (!dictionary.tryGetProperty("timeout", options.get(), setTimeout))
- return 0;
- if (!dictionary.tryGetProperty("maximumAge", options.get(), setMaximumAge))
- return 0;
-
- return options.release();
-}
-
-JSValue JSGeolocation::getCurrentPosition(ExecState* exec)
-{
- // Arguments: PositionCallback, (optional)PositionErrorCallback, (optional)PositionOptions
-
- RefPtr<PositionCallback> positionCallback = createFunctionOnlyCallback<JSPositionCallback>(exec, globalObject(), exec->argument(0));
- if (exec->hadException())
- return jsUndefined();
- ASSERT(positionCallback);
-
- RefPtr<PositionErrorCallback> positionErrorCallback = createFunctionOnlyCallback<JSPositionErrorCallback>(exec, globalObject(), exec->argument(1), CallbackAllowUndefined | CallbackAllowNull);
- if (exec->hadException())
- return jsUndefined();
-
- RefPtr<PositionOptions> positionOptions = createPositionOptions(exec, exec->argument(2));
- if (exec->hadException())
- return jsUndefined();
- ASSERT(positionOptions);
-
- m_impl->getCurrentPosition(positionCallback.release(), positionErrorCallback.release(), positionOptions.release());
- return jsUndefined();
-}
-
-JSValue JSGeolocation::watchPosition(ExecState* exec)
-{
- // Arguments: PositionCallback, (optional)PositionErrorCallback, (optional)PositionOptions
-
- RefPtr<PositionCallback> positionCallback = createFunctionOnlyCallback<JSPositionCallback>(exec, globalObject(), exec->argument(0));
- if (exec->hadException())
- return jsUndefined();
- ASSERT(positionCallback);
-
- RefPtr<PositionErrorCallback> positionErrorCallback = createFunctionOnlyCallback<JSPositionErrorCallback>(exec, globalObject(), exec->argument(1), CallbackAllowUndefined | CallbackAllowNull);
- if (exec->hadException())
- return jsUndefined();
-
- RefPtr<PositionOptions> positionOptions = createPositionOptions(exec, exec->argument(2));
- if (exec->hadException())
- return jsUndefined();
- ASSERT(positionOptions);
-
- int watchID = m_impl->watchPosition(positionCallback.release(), positionErrorCallback.release(), positionOptions.release());
- return jsNumber(watchID);
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(GEOLOCATION)
diff --git a/Source/WebCore/bindings/js/JSHTMLAllCollectionCustom.cpp b/Source/WebCore/bindings/js/JSHTMLAllCollectionCustom.cpp
index 227c34dfb..d8286a52a 100644
--- a/Source/WebCore/bindings/js/JSHTMLAllCollectionCustom.cpp
+++ b/Source/WebCore/bindings/js/JSHTMLAllCollectionCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -27,63 +27,61 @@
#include "JSHTMLAllCollection.h"
#include "HTMLAllCollection.h"
-#include "JSDOMBinding.h"
#include "JSNode.h"
#include "JSNodeList.h"
-#include "Node.h"
#include "StaticNodeList.h"
-#include <runtime/JSCJSValue.h>
-#include <wtf/Vector.h>
-#include <wtf/text/AtomicString.h>
+#include <runtime/IdentifierInlines.h>
using namespace JSC;
namespace WebCore {
-static JSValue getNamedItems(ExecState* exec, JSHTMLAllCollection* collection, PropertyName propertyName)
+static JSValue namedItems(ExecState& state, JSHTMLAllCollection* collection, PropertyName propertyName)
{
- Vector<Ref<Element>> namedItems;
- collection->impl().namedItems(propertyNameToAtomicString(propertyName), namedItems);
+ Vector<Ref<Element>> namedItems = collection->wrapped().namedItems(propertyNameToAtomicString(propertyName));
if (namedItems.isEmpty())
return jsUndefined();
if (namedItems.size() == 1)
- return toJS(exec, collection->globalObject(), &namedItems[0].get());
+ return toJS(&state, collection->globalObject(), namedItems[0]);
// FIXME: HTML5 specification says this should be a HTMLCollection.
// http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#htmlallcollection
- return toJS(exec, collection->globalObject(), StaticElementList::adopt(namedItems).get());
+ return toJS(&state, collection->globalObject(), StaticElementList::create(WTFMove(namedItems)));
}
// HTMLAllCollections are strange objects, they support both get and call.
static EncodedJSValue JSC_HOST_CALL callHTMLAllCollection(ExecState* exec)
{
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
if (exec->argumentCount() < 1)
return JSValue::encode(jsUndefined());
// Do not use thisObj here. It can be the JSHTMLDocument, in the document.forms(i) case.
- JSHTMLAllCollection* jsCollection = jsCast<JSHTMLAllCollection*>(exec->callee());
- HTMLAllCollection& collection = jsCollection->impl();
+ JSHTMLAllCollection* jsCollection = jsCast<JSHTMLAllCollection*>(exec->jsCallee());
+ HTMLAllCollection& collection = jsCollection->wrapped();
// Also, do we need the TypeError test here ?
if (exec->argumentCount() == 1) {
// Support for document.all(<index>) etc.
- String string = exec->argument(0).toString(exec)->value(exec);
- unsigned index = toUInt32FromStringImpl(string.impl());
- if (index != PropertyName::NotAnIndex)
- return JSValue::encode(toJS(exec, jsCollection->globalObject(), collection.item(index)));
+ String string = exec->argument(0).toWTFString(exec);
+ RETURN_IF_EXCEPTION(scope, encodedJSValue());
+ if (std::optional<uint32_t> index = parseIndex(*string.impl()))
+ return JSValue::encode(toJS(exec, jsCollection->globalObject(), collection.item(index.value())));
// Support for document.images('<name>') etc.
- return JSValue::encode(getNamedItems(exec, jsCollection, Identifier(exec, string)));
+ return JSValue::encode(namedItems(*exec, jsCollection, Identifier::fromString(exec, string)));
}
// The second arg, if set, is the index of the item we want
- String string = exec->argument(0).toString(exec)->value(exec);
- unsigned index = toUInt32FromStringImpl(exec->argument(1).toWTFString(exec).impl());
- if (index != PropertyName::NotAnIndex) {
- if (Node* node = collection.namedItemWithIndex(string, index))
- return JSValue::encode(toJS(exec, jsCollection->globalObject(), node));
+ String string = exec->argument(0).toWTFString(exec);
+ RETURN_IF_EXCEPTION(scope, encodedJSValue());
+ if (std::optional<uint32_t> index = parseIndex(*exec->argument(1).toWTFString(exec).impl())) {
+ if (auto* item = collection.namedItemWithIndex(string, index.value()))
+ return JSValue::encode(toJS(exec, jsCollection->globalObject(), *item));
}
return JSValue::encode(jsUndefined());
@@ -92,31 +90,36 @@ static EncodedJSValue JSC_HOST_CALL callHTMLAllCollection(ExecState* exec)
CallType JSHTMLAllCollection::getCallData(JSCell*, CallData& callData)
{
callData.native.function = callHTMLAllCollection;
- return CallTypeHost;
+ return CallType::Host;
}
-bool JSHTMLAllCollection::canGetItemsForName(ExecState*, HTMLAllCollection* collection, PropertyName propertyName)
+bool JSHTMLAllCollection::nameGetter(ExecState* state, PropertyName propertyName, JSValue& value)
{
- return collection->hasNamedItem(propertyNameToAtomicString(propertyName));
-}
+ JSValue items = namedItems(*state, this, propertyName);
+ if (items.isUndefined())
+ return false;
-EncodedJSValue JSHTMLAllCollection::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName)
-{
- JSHTMLAllCollection* thisObj = jsCast<JSHTMLAllCollection*>(JSValue::decode(slotBase));
- return JSValue::encode(getNamedItems(exec, thisObj, propertyName));
+ value = items;
+ return true;
}
-JSValue JSHTMLAllCollection::item(ExecState* exec)
+JSValue JSHTMLAllCollection::item(ExecState& state)
{
- uint32_t index = toUInt32FromStringImpl(exec->argument(0).toString(exec)->value(exec).impl());
- if (index != PropertyName::NotAnIndex)
- return toJS(exec, globalObject(), impl().item(index));
- return getNamedItems(exec, this, Identifier(exec, exec->argument(0).toString(exec)->value(exec)));
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (UNLIKELY(state.argumentCount() < 1))
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+
+ String argument = state.uncheckedArgument(0).toWTFString(&state);
+ if (std::optional<uint32_t> index = parseIndex(*argument.impl()))
+ return toJS(&state, globalObject(), wrapped().item(index.value()));
+ return namedItems(state, this, Identifier::fromString(&state, argument));
}
-JSValue JSHTMLAllCollection::namedItem(ExecState* exec)
+JSValue JSHTMLAllCollection::namedItem(ExecState& state)
{
- JSValue value = getNamedItems(exec, this, Identifier(exec, exec->argument(0).toString(exec)->value(exec)));
+ JSValue value = namedItems(state, this, Identifier::fromString(&state, state.argument(0).toWTFString(&state)));
return value.isUndefined() ? jsNull() : value;
}
diff --git a/Source/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp
index 9994d4205..229e68399 100644
--- a/Source/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp
+++ b/Source/WebCore/bindings/js/JSHTMLAppletElementCustom.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -38,9 +38,9 @@ bool JSHTMLAppletElement::getOwnPropertySlotDelegate(ExecState* exec, PropertyNa
return pluginElementCustomGetOwnPropertySlot<JSHTMLAppletElement, Base>(exec, propertyName, slot, this);
}
-bool JSHTMLAppletElement::putDelegate(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
+bool JSHTMLAppletElement::putDelegate(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot, bool& putResult)
{
- return pluginElementCustomPut(exec, propertyName, value, this, slot);
+ return pluginElementCustomPut(exec, propertyName, value, this, slot, putResult);
}
CallType JSHTMLAppletElement::getCallData(JSCell* cell, CallData& callData)
diff --git a/Source/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp
index 7ad36f8b2..172c0d997 100644
--- a/Source/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp
+++ b/Source/WebCore/bindings/js/JSHTMLCanvasElementCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2016 Apple Inc. All rights reserved.
* Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -11,10 +11,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -27,119 +27,67 @@
#include "config.h"
#include "JSHTMLCanvasElement.h"
-#include "CanvasContextAttributes.h"
#include "HTMLCanvasElement.h"
-#include "InspectorCanvasInstrumentation.h"
#include "JSCanvasRenderingContext2D.h"
#include <bindings/ScriptObject.h>
#include <wtf/GetPtr.h>
#if ENABLE(WEBGL)
-#include "JSDictionary.h"
-#include "JSWebGLRenderingContext.h"
-#include "WebGLContextAttributes.h"
+#include "JSWebGLContextAttributes.h"
+#include "JSWebGLRenderingContextBase.h"
#endif
using namespace JSC;
namespace WebCore {
-#if ENABLE(WEBGL)
-static void get3DContextAttributes(ExecState* exec, RefPtr<CanvasContextAttributes>& attrs)
+JSValue JSHTMLCanvasElement::getContext(ExecState& state)
{
- JSValue initializerValue = exec->argument(1);
- if (initializerValue.isUndefinedOrNull())
- return;
-
- JSObject* initializerObject = initializerValue.toObject(exec);
- JSDictionary dictionary(exec, initializerObject);
-
- GraphicsContext3D::Attributes graphicsAttrs;
-
- dictionary.tryGetProperty("alpha", graphicsAttrs.alpha);
- dictionary.tryGetProperty("depth", graphicsAttrs.depth);
- dictionary.tryGetProperty("stencil", graphicsAttrs.stencil);
- dictionary.tryGetProperty("antialias", graphicsAttrs.antialias);
- dictionary.tryGetProperty("premultipliedAlpha", graphicsAttrs.premultipliedAlpha);
- dictionary.tryGetProperty("preserveDrawingBuffer", graphicsAttrs.preserveDrawingBuffer);
-
- attrs = WebGLContextAttributes::create(graphicsAttrs);
-}
-#endif
+ auto& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
-JSValue JSHTMLCanvasElement::getContext(ExecState* exec)
-{
- HTMLCanvasElement& canvas = impl();
- const String& contextId = exec->argument(0).toString(exec)->value(exec);
-
- RefPtr<CanvasContextAttributes> attrs;
-#if ENABLE(WEBGL)
- if (HTMLCanvasElement::is3dType(contextId)) {
- get3DContextAttributes(exec, attrs);
- if (exec->hadException())
- return jsUndefined();
- }
-#endif
-
- CanvasRenderingContext* context = canvas.getContext(contextId, attrs.get());
- if (!context)
- return jsNull();
- JSValue jsValue = toJS(exec, globalObject(), WTF::getPtr(context));
- if (InspectorInstrumentation::canvasAgentEnabled(&canvas.document())) {
- Deprecated::ScriptObject contextObject(exec, jsValue.getObject());
- Deprecated::ScriptObject wrapped;
- if (context->is2d())
- wrapped = InspectorInstrumentation::wrapCanvas2DRenderingContextForInstrumentation(&canvas.document(), contextObject);
-#if ENABLE(WEBGL)
- else if (context->is3d())
- wrapped = InspectorInstrumentation::wrapWebGLRenderingContextForInstrumentation(&canvas.document(), contextObject);
-#endif
- if (!wrapped.hasNoValue())
- return wrapped.jsValue();
- }
- return jsValue;
-}
+ if (UNLIKELY(state.argumentCount() < 1))
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+
+ auto contextId = convert<IDLDOMString>(state, state.uncheckedArgument(0), StringConversionConfiguration::Normal);
+ RETURN_IF_EXCEPTION(scope, JSValue());
+
+ if (HTMLCanvasElement::is2dType(contextId))
+ return toJS<IDLNullable<IDLInterface<CanvasRenderingContext2D>>>(state, *globalObject(), static_cast<CanvasRenderingContext2D*>(wrapped().getContext2d(contextId)));
-JSValue JSHTMLCanvasElement::probablySupportsContext(ExecState* exec)
-{
- HTMLCanvasElement& canvas = impl();
- if (!exec->argumentCount())
- return jsBoolean(false);
- const String& contextId = exec->uncheckedArgument(0).toString(exec)->value(exec);
- if (exec->hadException())
- return jsUndefined();
-
- RefPtr<CanvasContextAttributes> attrs;
#if ENABLE(WEBGL)
if (HTMLCanvasElement::is3dType(contextId)) {
- get3DContextAttributes(exec, attrs);
- if (exec->hadException())
- return jsUndefined();
+ auto attributes = convert<IDLDictionary<WebGLContextAttributes>>(state, state.argument(1));
+ RETURN_IF_EXCEPTION(scope, JSValue());
+
+ return toJS<IDLNullable<IDLInterface<WebGLRenderingContextBase>>>(state, *globalObject(), static_cast<WebGLRenderingContextBase*>(wrapped().getContextWebGL(contextId, WTFMove(attributes))));
}
#endif
-
- return jsBoolean(canvas.probablySupportsContext(contextId, attrs.get()));
+
+ return jsNull();
}
-JSValue JSHTMLCanvasElement::toDataURL(ExecState* exec)
+JSValue JSHTMLCanvasElement::toDataURL(ExecState& state)
{
- HTMLCanvasElement& canvas = impl();
- ExceptionCode ec = 0;
-
- const String& type = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(0));
- double quality;
- double* qualityPtr = 0;
- if (exec->argumentCount() > 1) {
- JSValue v = exec->uncheckedArgument(1);
- if (v.isNumber()) {
- quality = v.toNumber(exec);
- qualityPtr = &quality;
- }
- }
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto type = convert<IDLNullable<IDLDOMString>>(state, state.argument(0));
+ RETURN_IF_EXCEPTION(scope, JSC::JSValue());
- JSValue result = JSC::jsString(exec, canvas.toDataURL(type, qualityPtr, ec));
- setDOMException(exec, ec);
- return result;
+ std::optional<double> quality;
+ auto qualityValue = state.argument(1);
+ if (qualityValue.isNumber())
+ quality = qualityValue.toNumber(&state);
+
+ // We would use toJS<IDLString> here, but it uses jsStringWithCache and we historically
+ // did not cache here, presumably because results are likely to be differing long strings.
+ auto result = wrapped().toDataURL(type, quality);
+ if (result.hasException()) {
+ propagateException(state, scope, result.releaseException());
+ return { };
+ }
+ return jsString(&state, result.releaseReturnValue());
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSHTMLCollectionCustom.cpp b/Source/WebCore/bindings/js/JSHTMLCollectionCustom.cpp
index eecc08b0a..6c8c74d62 100644
--- a/Source/WebCore/bindings/js/JSHTMLCollectionCustom.cpp
+++ b/Source/WebCore/bindings/js/JSHTMLCollectionCustom.cpp
@@ -20,60 +20,34 @@
#include "config.h"
#include "JSHTMLCollection.h"
-#include "HTMLAllCollection.h"
-#include "HTMLCollection.h"
-#include "HTMLFormControlsCollection.h"
-#include "HTMLOptionsCollection.h"
#include "JSDOMBinding.h"
#include "JSHTMLAllCollection.h"
#include "JSHTMLFormControlsCollection.h"
#include "JSHTMLOptionsCollection.h"
-#include "JSNode.h"
-#include "JSNodeList.h"
-#include "JSRadioNodeList.h"
-#include "Node.h"
-#include "RadioNodeList.h"
-#include <wtf/Vector.h>
-#include <wtf/text/AtomicString.h>
using namespace JSC;
namespace WebCore {
-bool JSHTMLCollection::canGetItemsForName(ExecState*, HTMLCollection* collection, PropertyName propertyName)
+JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<HTMLCollection>&& collection)
{
- return collection->hasNamedItem(propertyNameToAtomicString(propertyName));
-}
-
-EncodedJSValue JSHTMLCollection::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName)
-{
- JSHTMLCollection* collection = jsCast<JSHTMLCollection*>(JSValue::decode(slotBase));
- const AtomicString& name = propertyNameToAtomicString(propertyName);
- return JSValue::encode(toJS(exec, collection->globalObject(), collection->impl().namedItem(name)));
-}
-
-JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, HTMLCollection* collection)
-{
- if (!collection)
- return jsNull();
-
- JSObject* wrapper = getCachedWrapper(currentWorld(exec), collection);
-
- if (wrapper)
- return wrapper;
-
switch (collection->type()) {
case FormControls:
- return CREATE_DOM_WRAPPER(exec, globalObject, HTMLFormControlsCollection, collection);
+ return createWrapper<HTMLFormControlsCollection>(globalObject, WTFMove(collection));
case SelectOptions:
- return CREATE_DOM_WRAPPER(exec, globalObject, HTMLOptionsCollection, collection);
+ return createWrapper<HTMLOptionsCollection>(globalObject, WTFMove(collection));
case DocAll:
- return CREATE_DOM_WRAPPER(exec, globalObject, HTMLAllCollection, collection);
+ return createWrapper<HTMLAllCollection>(globalObject, WTFMove(collection));
default:
break;
}
- return CREATE_DOM_WRAPPER(exec, globalObject, HTMLCollection, collection);
+ return createWrapper<HTMLCollection>(globalObject, WTFMove(collection));
+}
+
+JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, HTMLCollection& collection)
+{
+ return wrap(state, globalObject, collection);
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp b/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp
index 7e7bb5a44..2003cacac 100644
--- a/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp
+++ b/Source/WebCore/bindings/js/JSHTMLDocumentCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2007-2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -26,24 +26,11 @@
#include "config.h"
#include "JSHTMLDocument.h"
-#include "Frame.h"
-#include "HTMLAllCollection.h"
-#include "HTMLBodyElement.h"
-#include "HTMLCollection.h"
-#include "HTMLDocument.h"
-#include "HTMLElement.h"
#include "HTMLIFrameElement.h"
-#include "HTMLNames.h"
-#include "JSDOMWindow.h"
#include "JSDOMWindowCustom.h"
-#include "JSDOMWindowShell.h"
#include "JSHTMLCollection.h"
-#include "JSMainThreadExecState.h"
#include "SegmentedString.h"
-#include "DocumentParser.h"
-#include <runtime/Error.h>
-#include <runtime/JSCell.h>
-#include <wtf/unicode/CharacterNames.h>
+#include <runtime/Lookup.h>
using namespace JSC;
@@ -51,120 +38,153 @@ namespace WebCore {
using namespace HTMLNames;
-bool JSHTMLDocument::canGetItemsForName(ExecState*, HTMLDocument* document, PropertyName propertyName)
+JSValue toJSNewlyCreated(ExecState* state, JSDOMGlobalObject* globalObject, Ref<HTMLDocument>&& passedDocument)
{
- AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName);
- return atomicPropertyName && document->hasDocumentNamedItem(*atomicPropertyName);
+ auto& document = passedDocument.get();
+ auto* wrapper = createWrapper<HTMLDocument>(globalObject, WTFMove(passedDocument));
+ reportMemoryForDocumentIfFrameless(*state, document);
+ return wrapper;
}
-EncodedJSValue JSHTMLDocument::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName)
+JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, HTMLDocument& document)
{
- JSHTMLDocument* thisObj = jsCast<JSHTMLDocument*>(JSValue::decode(slotBase));
- HTMLDocument& document = thisObj->impl();
+ if (auto* wrapper = cachedDocumentWrapper(*state, *globalObject, document))
+ return wrapper;
+ return toJSNewlyCreated(state, globalObject, Ref<HTMLDocument>(document));
+}
+
+bool JSHTMLDocument::getOwnPropertySlot(JSObject* object, ExecState* state, PropertyName propertyName, PropertySlot& slot)
+{
+ auto& thisObject = *jsCast<JSHTMLDocument*>(object);
+ ASSERT_GC_OBJECT_INHERITS(object, info());
+
+ if (propertyName == "open") {
+ if (Base::getOwnPropertySlot(&thisObject, state, propertyName, slot))
+ return true;
+ slot.setCustom(&thisObject, ReadOnly | DontDelete | DontEnum, nonCachingStaticFunctionGetter<jsHTMLDocumentPrototypeFunctionOpen, 2>);
+ return true;
+ }
+
+ JSValue value;
+ if (thisObject.nameGetter(state, propertyName, value)) {
+ slot.setValue(&thisObject, ReadOnly | DontDelete | DontEnum, value);
+ return true;
+ }
- AtomicStringImpl* atomicPropertyName = findAtomicString(propertyName);
+ return Base::getOwnPropertySlot(&thisObject, state, propertyName, slot);
+}
+
+bool JSHTMLDocument::nameGetter(ExecState* state, PropertyName propertyName, JSValue& value)
+{
+ auto& document = wrapped();
+
+ auto* atomicPropertyName = propertyName.publicName();
if (!atomicPropertyName || !document.hasDocumentNamedItem(*atomicPropertyName))
- return JSValue::encode(jsUndefined());
+ return false;
if (UNLIKELY(document.documentNamedItemContainsMultipleElements(*atomicPropertyName))) {
- RefPtr<HTMLCollection> collection = document.documentNamedItems(atomicPropertyName);
+ auto collection = document.documentNamedItems(atomicPropertyName);
ASSERT(collection->length() > 1);
- return JSValue::encode(toJS(exec, thisObj->globalObject(), WTF::getPtr(collection)));
+ value = toJS(state, globalObject(), collection);
+ return true;
}
- Element* element = document.documentNamedItem(*atomicPropertyName);
- if (UNLIKELY(element->hasTagName(iframeTag))) {
- if (Frame* frame = toHTMLIFrameElement(element)->contentFrame())
- return JSValue::encode(toJS(exec, frame));
+ auto& element = *document.documentNamedItem(*atomicPropertyName);
+ if (UNLIKELY(is<HTMLIFrameElement>(element))) {
+ if (auto* frame = downcast<HTMLIFrameElement>(element).contentFrame()) {
+ value = toJS(state, frame);
+ return true;
+ }
}
- return JSValue::encode(toJS(exec, thisObj->globalObject(), element));
+ value = toJS(state, globalObject(), element);
+ return true;
}
// Custom attributes
-JSValue JSHTMLDocument::all(ExecState* exec) const
+JSValue JSHTMLDocument::all(ExecState& state) const
{
// If "all" has been overwritten, return the overwritten value
- JSValue v = getDirect(exec->vm(), Identifier(exec, "all"));
- if (v)
- return v;
+ if (auto overwrittenValue = getDirect(state.vm(), Identifier::fromString(&state, "all")))
+ return overwrittenValue;
- return toJS(exec, globalObject(), impl().all());
+ return toJS(&state, globalObject(), wrapped().all());
}
-void JSHTMLDocument::setAll(ExecState* exec, JSValue value)
+void JSHTMLDocument::setAll(ExecState& state, JSValue value)
{
// Add "all" to the property map.
- putDirect(exec->vm(), Identifier(exec, "all"), value);
+ putDirect(state.vm(), Identifier::fromString(&state, "all"), value);
+}
+
+static inline Document* findCallingDocument(ExecState& state)
+{
+ CallerFunctor functor;
+ state.iterate(functor);
+ auto* callerFrame = functor.callerFrame();
+ if (!callerFrame)
+ return nullptr;
+ return asJSDOMWindow(callerFrame->lexicalGlobalObject())->wrapped().document();
}
// Custom functions
-JSValue JSHTMLDocument::open(ExecState* exec)
+JSValue JSHTMLDocument::open(ExecState& state)
{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
// For compatibility with other browsers, pass open calls with more than 2 parameters to the window.
- if (exec->argumentCount() > 2) {
- if (Frame* frame = impl().frame()) {
- JSDOMWindowShell* wrapper = toJSDOMWindowShell(frame, currentWorld(exec));
- if (wrapper) {
- JSValue function = wrapper->get(exec, Identifier(exec, "open"));
+ if (state.argumentCount() > 2) {
+ if (auto* frame = wrapped().frame()) {
+ if (auto* wrapper = toJSDOMWindowShell(frame, currentWorld(&state))) {
+ auto function = wrapper->get(&state, Identifier::fromString(&state, "open"));
CallData callData;
- CallType callType = ::getCallData(function, callData);
- if (callType == CallTypeNone)
- return throwTypeError(exec);
- return JSMainThreadExecState::call(exec, function, callType, callData, wrapper, ArgList(exec));
+ auto callType = ::getCallData(function, callData);
+ if (callType == CallType::None)
+ return throwTypeError(&state, scope);
+ return JSC::call(&state, function, callType, callData, wrapper, ArgList(&state));
}
}
return jsUndefined();
}
- // document.open clobbers the security context of the document and
- // aliases it with the active security context.
- Document* activeDocument = asJSDOMWindow(exec->lexicalGlobalObject())->impl().document();
-
- // In the case of two parameters or fewer, do a normal document open.
- impl().open(activeDocument);
+ // Calling document.open clobbers the security context of the document and aliases it with the active security context.
+ // FIXME: Is it correct that this does not use findCallingDocument as the write function below does?
+ wrapped().open(asJSDOMWindow(state.lexicalGlobalObject())->wrapped().document());
+ // FIXME: Why do we return the document instead of returning undefined?
return this;
}
enum NewlineRequirement { DoNotAddNewline, DoAddNewline };
-static inline void documentWrite(ExecState* exec, HTMLDocument* document, NewlineRequirement addNewline)
+static inline JSValue documentWrite(ExecState& state, JSHTMLDocument& document, NewlineRequirement addNewline)
{
- // DOM only specifies single string argument, but browsers allow multiple or no arguments.
-
- size_t size = exec->argumentCount();
-
- String firstString = exec->argument(0).toString(exec)->value(exec);
- SegmentedString segmentedString = firstString;
- if (size != 1) {
- if (!size)
- segmentedString.clear();
- else {
- for (size_t i = 1; i < size; ++i) {
- String subsequentString = exec->uncheckedArgument(i).toString(exec)->value(exec);
- segmentedString.append(SegmentedString(subsequentString));
- }
- }
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ SegmentedString segmentedString;
+ size_t argumentCount = state.argumentCount();
+ for (size_t i = 0; i < argumentCount; ++i) {
+ segmentedString.append(state.uncheckedArgument(i).toWTFString(&state));
+ RETURN_IF_EXCEPTION(scope, { });
}
if (addNewline)
- segmentedString.append(SegmentedString(String(&newlineCharacter, 1)));
+ segmentedString.append(String { "\n" });
- Document* activeDocument = asJSDOMWindow(exec->lexicalGlobalObject())->impl().document();
- document->write(segmentedString, activeDocument);
+ document.wrapped().write(WTFMove(segmentedString), findCallingDocument(state));
+ return jsUndefined();
}
-JSValue JSHTMLDocument::write(ExecState* exec)
+JSValue JSHTMLDocument::write(ExecState& state)
{
- documentWrite(exec, &impl(), DoNotAddNewline);
- return jsUndefined();
+ return documentWrite(state, *this, DoNotAddNewline);
}
-JSValue JSHTMLDocument::writeln(ExecState* exec)
+JSValue JSHTMLDocument::writeln(ExecState& state)
{
- documentWrite(exec, &impl(), DoAddNewline);
- return jsUndefined();
+ return documentWrite(state, *this, DoAddNewline);
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSHTMLElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLElementCustom.cpp
index 4ee3fd9ef..43792a9d8 100644
--- a/Source/WebCore/bindings/js/JSHTMLElementCustom.cpp
+++ b/Source/WebCore/bindings/js/JSHTMLElementCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -26,27 +26,108 @@
#include "config.h"
#include "JSHTMLElement.h"
+#include "CustomElementRegistry.h"
+#include "DOMWindow.h"
#include "Document.h"
#include "HTMLFormElement.h"
+#include "JSCustomElementInterface.h"
+#include "JSDOMConstructorBase.h"
+#include "JSNodeCustom.h"
+#include "ScriptExecutionContext.h"
+#include <runtime/InternalFunction.h>
#include <runtime/JSWithScope.h>
namespace WebCore {
using namespace JSC;
+EncodedJSValue JSC_HOST_CALL constructJSHTMLElement(ExecState& exec)
+{
+ VM& vm = exec.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto* jsConstructor = jsCast<JSDOMConstructorBase*>(exec.jsCallee());
+ ASSERT(jsConstructor);
+
+ auto* context = jsConstructor->scriptExecutionContext();
+ if (!context)
+ return throwConstructorScriptExecutionContextUnavailableError(exec, scope, "HTMLElement");
+ ASSERT(context->isDocument());
+
+ JSValue newTargetValue = exec.thisValue();
+ auto* globalObject = jsConstructor->globalObject();
+ JSValue htmlElementConstructorValue = JSHTMLElement::getConstructor(vm, globalObject);
+ if (newTargetValue == htmlElementConstructorValue)
+ return throwVMTypeError(&exec, scope, ASCIILiteral("new.target is not a valid custom element constructor"));
+
+ auto& document = downcast<Document>(*context);
+
+ auto* window = document.domWindow();
+ if (!window)
+ return throwVMTypeError(&exec, scope, ASCIILiteral("new.target is not a valid custom element constructor"));
+
+ auto* registry = window->customElementRegistry();
+ if (!registry)
+ return throwVMTypeError(&exec, scope, ASCIILiteral("new.target is not a valid custom element constructor"));
+
+ JSObject* newTarget = newTargetValue.getObject();
+ auto* elementInterface = registry->findInterface(newTarget);
+ if (!elementInterface)
+ return throwVMTypeError(&exec, scope, ASCIILiteral("new.target does not define a custom element"));
+
+ if (!elementInterface->isUpgradingElement()) {
+ Structure* baseStructure = getDOMStructure<JSHTMLElement>(vm, *globalObject);
+ auto* newElementStructure = InternalFunction::createSubclassStructure(&exec, newTargetValue, baseStructure);
+ RETURN_IF_EXCEPTION(scope, encodedJSValue());
+
+ Ref<HTMLElement> element = HTMLElement::create(elementInterface->name(), document);
+ element->setIsDefinedCustomElement(*elementInterface);
+ auto* jsElement = JSHTMLElement::create(newElementStructure, globalObject, element.get());
+ cacheWrapper(globalObject->world(), element.ptr(), jsElement);
+ return JSValue::encode(jsElement);
+ }
+
+ Element* elementToUpgrade = elementInterface->lastElementInConstructionStack();
+ if (!elementToUpgrade) {
+ throwInvalidStateError(exec, scope, ASCIILiteral("Cannot instantiate a custom element inside its own constrcutor during upgrades"));
+ return JSValue::encode(jsUndefined());
+ }
+
+ JSValue elementWrapperValue = toJS(&exec, jsConstructor->globalObject(), *elementToUpgrade);
+ ASSERT(elementWrapperValue.isObject());
+
+ JSValue newPrototype = newTarget->get(&exec, vm.propertyNames->prototype);
+ RETURN_IF_EXCEPTION(scope, encodedJSValue());
+
+ JSObject* elementWrapperObject = asObject(elementWrapperValue);
+ JSObject::setPrototype(elementWrapperObject, &exec, newPrototype, true /* shouldThrowIfCantSet */);
+ RETURN_IF_EXCEPTION(scope, encodedJSValue());
+
+ elementInterface->didUpgradeLastElementInConstructionStack();
+
+ return JSValue::encode(elementWrapperValue);
+}
+
JSScope* JSHTMLElement::pushEventHandlerScope(ExecState* exec, JSScope* scope) const
{
- HTMLElement& element = impl();
+ HTMLElement& element = wrapped();
// The document is put on first, fall back to searching it only after the element and form.
- scope = JSWithScope::create(exec, asObject(toJS(exec, globalObject(), &element.document())), scope);
+ // FIXME: This probably may use the wrong global object. If this is called from a native
+ // function, then it would be correct but not optimal since the native function would *know*
+ // the global object. But, it may be that globalObject() is more correct.
+ // https://bugs.webkit.org/show_bug.cgi?id=134932
+ VM& vm = exec->vm();
+ JSGlobalObject* lexicalGlobalObject = exec->lexicalGlobalObject();
+
+ scope = JSWithScope::create(vm, lexicalGlobalObject, asObject(toJS(exec, globalObject(), element.document())), scope);
// The form is next, searched before the document, but after the element itself.
if (HTMLFormElement* form = element.form())
- scope = JSWithScope::create(exec, asObject(toJS(exec, globalObject(), form)), scope);
+ scope = JSWithScope::create(vm, lexicalGlobalObject, asObject(toJS(exec, globalObject(), *form)), scope);
// The element is on top, searched first.
- return JSWithScope::create(exec, asObject(toJS(exec, globalObject(), &element)), scope);
+ return JSWithScope::create(vm, lexicalGlobalObject, asObject(toJS(exec, globalObject(), element)), scope);
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp
index 73f2c2bfb..919f68662 100644
--- a/Source/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp
+++ b/Source/WebCore/bindings/js/JSHTMLEmbedElementCustom.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -38,9 +38,9 @@ bool JSHTMLEmbedElement::getOwnPropertySlotDelegate(ExecState* exec, PropertyNam
return pluginElementCustomGetOwnPropertySlot<JSHTMLEmbedElement, Base>(exec, propertyName, slot, this);
}
-bool JSHTMLEmbedElement::putDelegate(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
+bool JSHTMLEmbedElement::putDelegate(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot, bool& putResult)
{
- return pluginElementCustomPut(exec, propertyName, value, this, slot);
+ return pluginElementCustomPut(exec, propertyName, value, this, slot, putResult);
}
CallType JSHTMLEmbedElement::getCallData(JSCell* cell, CallData& callData)
diff --git a/Source/WebCore/bindings/js/JSHTMLFormControlsCollectionCustom.cpp b/Source/WebCore/bindings/js/JSHTMLFormControlsCollectionCustom.cpp
index fc41eb61a..58d9b676b 100644
--- a/Source/WebCore/bindings/js/JSHTMLFormControlsCollectionCustom.cpp
+++ b/Source/WebCore/bindings/js/JSHTMLFormControlsCollectionCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2007-2008, 2016 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -18,54 +18,51 @@
*/
#include "config.h"
-#include "HTMLFormControlsCollection.h"
-
-
-#include "HTMLAllCollection.h"
-#include "JSDOMBinding.h"
-#include "JSHTMLCollection.h"
#include "JSHTMLFormControlsCollection.h"
+
+#include "HTMLFormControlsCollection.h"
#include "JSNode.h"
-#include "JSNodeList.h"
#include "JSRadioNodeList.h"
-#include "Node.h"
#include "RadioNodeList.h"
-#include <wtf/Vector.h>
-#include <wtf/text/AtomicString.h>
+#include <runtime/IdentifierInlines.h>
using namespace JSC;
namespace WebCore {
-static JSValue getNamedItems(ExecState* exec, JSHTMLFormControlsCollection* collection, PropertyName propertyName)
+static JSValue namedItems(ExecState& state, JSHTMLFormControlsCollection* collection, PropertyName propertyName)
{
- Vector<Ref<Element>> namedItems;
const AtomicString& name = propertyNameToAtomicString(propertyName);
- collection->impl().namedItems(name, namedItems);
+ Vector<Ref<Element>> namedItems = collection->wrapped().namedItems(name);
if (namedItems.isEmpty())
return jsUndefined();
if (namedItems.size() == 1)
- return toJS(exec, collection->globalObject(), &namedItems[0].get());
+ return toJS(&state, collection->globalObject(), namedItems[0]);
- ASSERT(collection->impl().type() == FormControls);
- return toJS(exec, collection->globalObject(), collection->impl().ownerNode().radioNodeList(name).get());
+ ASSERT(collection->wrapped().type() == FormControls);
+ return toJS(&state, collection->globalObject(), collection->wrapped().ownerNode().radioNodeList(name).get());
}
-bool JSHTMLFormControlsCollection::canGetItemsForName(ExecState*, HTMLFormControlsCollection* collection, PropertyName propertyName)
+bool JSHTMLFormControlsCollection::nameGetter(ExecState* state, PropertyName propertyName, JSValue& value)
{
- return collection->hasNamedItem(propertyNameToAtomicString(propertyName));
-}
+ auto items = namedItems(*state, this, propertyName);
+ if (items.isUndefined())
+ return false;
-EncodedJSValue JSHTMLFormControlsCollection::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName)
-{
- JSHTMLFormControlsCollection* thisObj = jsCast<JSHTMLFormControlsCollection*>(JSValue::decode(slotBase));
- return JSValue::encode(getNamedItems(exec, thisObj, propertyName));
+ value = items;
+ return true;
}
-JSValue JSHTMLFormControlsCollection::namedItem(ExecState* exec)
+JSValue JSHTMLFormControlsCollection::namedItem(ExecState& state)
{
- JSValue value = getNamedItems(exec, this, Identifier(exec, exec->argument(0).toString(exec)->value(exec)));
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (UNLIKELY(state.argumentCount() < 1))
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+
+ JSValue value = namedItems(state, this, Identifier::fromString(&state, state.uncheckedArgument(0).toWTFString(&state)));
return value.isUndefined() ? jsNull() : value;
}
diff --git a/Source/WebCore/bindings/js/JSHTMLFormElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLFormElementCustom.cpp
deleted file mode 100644
index 416887261..000000000
--- a/Source/WebCore/bindings/js/JSHTMLFormElementCustom.cpp
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "JSHTMLFormElement.h"
-
-#include "Frame.h"
-#include "HTMLCollection.h"
-#include "HTMLFormElement.h"
-#include "JSDOMWindowCustom.h"
-#include "JSNodeList.h"
-#include "StaticNodeList.h"
-
-using namespace JSC;
-
-namespace WebCore {
-
-bool JSHTMLFormElement::canGetItemsForName(ExecState*, HTMLFormElement* form, PropertyName propertyName)
-{
- return form->hasNamedElement(propertyNameToAtomicString(propertyName));
-}
-
-EncodedJSValue JSHTMLFormElement::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName)
-{
- JSHTMLFormElement* jsForm = jsCast<JSHTMLFormElement*>(JSValue::decode(slotBase));
- HTMLFormElement& form = jsForm->impl();
-
- Vector<Ref<Element>> namedItems;
- form.getNamedElements(propertyNameToAtomicString(propertyName), namedItems);
-
- if (namedItems.isEmpty())
- return JSValue::encode(jsUndefined());
- if (namedItems.size() == 1)
- return JSValue::encode(toJS(exec, jsForm->globalObject(), &namedItems[0].get()));
-
- // FIXME: HTML5 specifies that this should be a RadioNodeList.
- return JSValue::encode(toJS(exec, jsForm->globalObject(), StaticElementList::adopt(namedItems).get()));
-}
-
-}
diff --git a/Source/WebCore/bindings/js/JSHTMLFrameElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLFrameElementCustom.cpp
deleted file mode 100644
index 88f82c505..000000000
--- a/Source/WebCore/bindings/js/JSHTMLFrameElementCustom.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "JSHTMLFrameElement.h"
-
-#include "Document.h"
-#include "HTMLFrameElement.h"
-#include "HTMLNames.h"
-#include "HTMLParserIdioms.h"
-#include "JSDOMBinding.h"
-
-using namespace JSC;
-
-namespace WebCore {
-
-using namespace HTMLNames;
-
-static inline bool allowSettingJavascriptURL(ExecState* exec, HTMLFrameElement* imp, const String& value)
-{
- if (protocolIsJavaScript(stripLeadingAndTrailingHTMLSpaces(value))) {
- Document* contentDocument = imp->contentDocument();
- if (contentDocument && !shouldAllowAccessToNode(exec, contentDocument))
- return false;
- }
- return true;
-}
-
-void JSHTMLFrameElement::setLocation(ExecState* exec, JSValue value)
-{
- HTMLFrameElement& imp = impl();
- String locationValue = valueToStringWithNullCheck(exec, value);
-
- if (!allowSettingJavascriptURL(exec, &imp, locationValue))
- return;
-
- imp.setLocation(locationValue);
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSHTMLFrameSetElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLFrameSetElementCustom.cpp
index 6df61d1c1..125aef7ec 100644
--- a/Source/WebCore/bindings/js/JSHTMLFrameSetElementCustom.cpp
+++ b/Source/WebCore/bindings/js/JSHTMLFrameSetElementCustom.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -30,7 +30,6 @@
#include "HTMLCollection.h"
#include "HTMLFrameElement.h"
#include "HTMLFrameSetElement.h"
-#include "HTMLNames.h"
#include "JSDOMWindow.h"
#include "JSDOMWindowShell.h"
#include "JSDOMBinding.h"
@@ -39,23 +38,19 @@ using namespace JSC;
namespace WebCore {
-using namespace HTMLNames;
-
-bool JSHTMLFrameSetElement::canGetItemsForName(ExecState*, HTMLFrameSetElement* frameSet, PropertyName propertyName)
-{
- Node* frame = frameSet->children()->namedItem(propertyNameToAtomicString(propertyName));
- return frame && frame->hasTagName(frameTag);
-}
-
-EncodedJSValue JSHTMLFrameSetElement::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName)
+bool JSHTMLFrameSetElement::nameGetter(ExecState* exec, PropertyName propertyName, JSValue& value)
{
- HTMLElement& element = jsCast<JSHTMLElement*>(JSValue::decode(slotBase))->impl();
- Node* frameElement = element.children()->namedItem(propertyNameToAtomicString(propertyName));
- if (Document* document = toHTMLFrameElement(frameElement)->contentDocument()) {
- if (JSDOMWindowShell* window = toJSDOMWindowShell(document->frame(), currentWorld(exec)))
- return JSValue::encode(window);
+ auto* frameElement = wrapped().children()->namedItem(propertyNameToAtomicString(propertyName));
+ if (!is<HTMLFrameElement>(frameElement))
+ return false;
+
+ if (auto* document = downcast<HTMLFrameElement>(*frameElement).contentDocument()) {
+ if (JSDOMWindowShell* window = toJSDOMWindowShell(document->frame(), currentWorld(exec))) {
+ value = window;
+ return true;
+ }
}
- return JSValue::encode(jsUndefined());
+ return false;
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSHTMLInputElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLInputElementCustom.cpp
deleted file mode 100644
index 42ebad315..000000000
--- a/Source/WebCore/bindings/js/JSHTMLInputElementCustom.cpp
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "JSHTMLInputElement.h"
-
-#include "HTMLInputElement.h"
-#include <runtime/Error.h>
-
-using namespace JSC;
-
-namespace WebCore {
-
-JSValue JSHTMLInputElement::selectionStart(ExecState* exec) const
-{
- HTMLInputElement& input = impl();
- if (!input.canHaveSelection())
- return throwTypeError(exec);
-
- return jsNumber(input.selectionStart());
-}
-
-void JSHTMLInputElement::setSelectionStart(ExecState* exec, JSValue value)
-{
- HTMLInputElement& input = impl();
- if (!input.canHaveSelection())
- throwTypeError(exec);
-
- input.setSelectionStart(value.toInt32(exec));
-}
-
-JSValue JSHTMLInputElement::selectionEnd(ExecState* exec) const
-{
- HTMLInputElement& input = impl();
- if (!input.canHaveSelection())
- return throwTypeError(exec);
-
- return jsNumber(input.selectionEnd());
-}
-
-void JSHTMLInputElement::setSelectionEnd(ExecState* exec, JSValue value)
-{
- HTMLInputElement& input = impl();
- if (!input.canHaveSelection())
- throwTypeError(exec);
-
- input.setSelectionEnd(value.toInt32(exec));
-}
-
-JSValue JSHTMLInputElement::selectionDirection(ExecState* exec) const
-{
- HTMLInputElement& input = impl();
- if (!input.canHaveSelection())
- return throwTypeError(exec);
-
- return jsStringWithCache(exec, input.selectionDirection());
-}
-
-void JSHTMLInputElement::setSelectionDirection(ExecState* exec, JSValue value)
-{
- HTMLInputElement& input = impl();
- if (!input.canHaveSelection()) {
- throwTypeError(exec);
- return;
- }
-
- input.setSelectionDirection(value.toString(exec)->value(exec));
-}
-
-JSValue JSHTMLInputElement::setSelectionRange(ExecState* exec)
-{
- HTMLInputElement& input = impl();
- if (!input.canHaveSelection())
- return throwTypeError(exec);
-
- int start = exec->argument(0).toInt32(exec);
- int end = exec->argument(1).toInt32(exec);
- String direction = exec->argument(2).toString(exec)->value(exec);
-
- input.setSelectionRange(start, end, direction);
- return jsUndefined();
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp
index b791186fc..4a8647f89 100644
--- a/Source/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp
+++ b/Source/WebCore/bindings/js/JSHTMLObjectElementCustom.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -38,9 +38,9 @@ bool JSHTMLObjectElement::getOwnPropertySlotDelegate(ExecState* exec, PropertyNa
return pluginElementCustomGetOwnPropertySlot<JSHTMLObjectElement, Base>(exec, propertyName, slot, this);
}
-bool JSHTMLObjectElement::putDelegate(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
+bool JSHTMLObjectElement::putDelegate(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot, bool& putResult)
{
- return pluginElementCustomPut(exec, propertyName, value, this, slot);
+ return pluginElementCustomPut(exec, propertyName, value, this, slot, putResult);
}
CallType JSHTMLObjectElement::getCallData(JSCell* cell, CallData& callData)
diff --git a/Source/WebCore/bindings/js/JSHTMLOptionsCollectionCustom.cpp b/Source/WebCore/bindings/js/JSHTMLOptionsCollectionCustom.cpp
index 74a58672f..356679a8e 100644
--- a/Source/WebCore/bindings/js/JSHTMLOptionsCollectionCustom.cpp
+++ b/Source/WebCore/bindings/js/JSHTMLOptionsCollectionCustom.cpp
@@ -20,72 +20,21 @@
#include "config.h"
#include "JSHTMLOptionsCollection.h"
+#include "CustomElementReactionQueue.h"
#include "ExceptionCode.h"
-#include "HTMLNames.h"
-#include "HTMLOptionElement.h"
-#include "HTMLOptionsCollection.h"
-#include "HTMLSelectElement.h"
#include "JSHTMLOptionElement.h"
#include "JSHTMLSelectElement.h"
#include "JSHTMLSelectElementCustom.h"
-#include "JSNodeList.h"
-#include "StaticNodeList.h"
-
#include <wtf/MathExtras.h>
using namespace JSC;
namespace WebCore {
-void JSHTMLOptionsCollection::setLength(ExecState* exec, JSValue value)
-{
- ExceptionCode ec = 0;
- unsigned newLength = 0;
- double lengthValue = value.toNumber(exec);
- if (!std::isnan(lengthValue) && !std::isinf(lengthValue)) {
- if (lengthValue < 0.0)
- ec = INDEX_SIZE_ERR;
- else if (lengthValue > static_cast<double>(UINT_MAX))
- newLength = UINT_MAX;
- else
- newLength = static_cast<unsigned>(lengthValue);
- }
- if (!ec)
- impl().setLength(newLength, ec);
- setDOMException(exec, ec);
-}
-
-void JSHTMLOptionsCollection::indexSetter(ExecState* exec, unsigned index, JSValue value)
-{
- selectIndexSetter(&impl().selectElement(), exec, index, value);
-}
-
-JSValue JSHTMLOptionsCollection::add(ExecState* exec)
-{
- HTMLOptionsCollection& imp = impl();
- HTMLOptionElement* option = toHTMLOptionElement(exec->argument(0));
- ExceptionCode ec = 0;
- if (exec->argumentCount() < 2)
- imp.add(option, ec);
- else {
- int index = exec->argument(1).toInt32(exec);
- if (exec->hadException())
- return jsUndefined();
- imp.add(option, index, ec);
- }
- setDOMException(exec, ec);
- return jsUndefined();
-}
-
-JSValue JSHTMLOptionsCollection::remove(ExecState* exec)
+void JSHTMLOptionsCollection::indexSetter(ExecState* state, unsigned index, JSValue value)
{
- // The argument can be an HTMLOptionElement or an index.
- JSValue argument = exec->argument(0);
- if (HTMLOptionElement* option = toHTMLOptionElement(argument))
- impl().remove(option);
- else
- impl().remove(argument.toInt32(exec));
- return jsUndefined();
+ CustomElementReactionStack customElementReactionStack;
+ selectElementIndexSetter(*state, wrapped().selectElement(), index, value);
}
}
diff --git a/Source/WebCore/bindings/js/JSHTMLSelectElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLSelectElementCustom.cpp
index 43f694b50..c74aed3df 100644
--- a/Source/WebCore/bindings/js/JSHTMLSelectElementCustom.cpp
+++ b/Source/WebCore/bindings/js/JSHTMLSelectElementCustom.cpp
@@ -21,55 +21,34 @@
#include "config.h"
#include "JSHTMLSelectElementCustom.h"
+#include "CustomElementReactionQueue.h"
#include "ExceptionCode.h"
#include "HTMLNames.h"
#include "HTMLOptionElement.h"
#include "HTMLSelectElement.h"
#include "JSHTMLOptionElement.h"
+#include "JSHTMLSelectElement.h"
namespace WebCore {
using namespace JSC;
using namespace HTMLNames;
-JSValue JSHTMLSelectElement::remove(ExecState* exec)
+void selectElementIndexSetter(JSC::ExecState& state, HTMLSelectElement& element, unsigned index, JSC::JSValue value)
{
- HTMLSelectElement& select = impl();
+ VM& vm = state.vm();
+ auto throwScope = DECLARE_THROW_SCOPE(vm);
- if (!exec->argumentCount()) {
- // When called with no argument, we should call Element::remove() to detach.
- ExceptionCode ec = 0;
- select.remove(ec);
- setDOMException(exec, ec);
- } else {
- // The HTMLSelectElement::remove() function can take either an option object or the index of an option.
- if (HTMLOptionElement* option = toHTMLOptionElement(exec->argument(0)))
- select.remove(option);
- else
- select.removeByIndex(exec->argument(0).toInt32(exec));
- }
+ auto* option = convert<IDLNullable<IDLInterface<HTMLOptionElement>>>(state, value);
+ RETURN_IF_EXCEPTION(throwScope, void());
- return jsUndefined();
+ propagateException(state, throwScope, element.setItem(index, option));
}
-void selectIndexSetter(HTMLSelectElement* select, JSC::ExecState* exec, unsigned index, JSC::JSValue value)
+void JSHTMLSelectElement::indexSetter(JSC::ExecState* state, unsigned index, JSC::JSValue value)
{
- if (value.isUndefinedOrNull())
- select->removeByIndex(index);
- else {
- ExceptionCode ec = 0;
- HTMLOptionElement* option = toHTMLOptionElement(value);
- if (!option)
- ec = TYPE_MISMATCH_ERR;
- else
- select->setOption(index, option, ec);
- setDOMException(exec, ec);
- }
-}
-
-void JSHTMLSelectElement::indexSetter(JSC::ExecState* exec, unsigned index, JSC::JSValue value)
-{
- selectIndexSetter(&impl(), exec, index, value);
+ CustomElementReactionStack customElementReactionStack;
+ selectElementIndexSetter(*state, wrapped(), index, value);
}
}
diff --git a/Source/WebCore/bindings/js/JSHTMLSelectElementCustom.h b/Source/WebCore/bindings/js/JSHTMLSelectElementCustom.h
index a4490380c..e012bccef 100644
--- a/Source/WebCore/bindings/js/JSHTMLSelectElementCustom.h
+++ b/Source/WebCore/bindings/js/JSHTMLSelectElementCustom.h
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -26,15 +26,17 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSHTMLSelectElementCustom_h
-#define JSHTMLSelectElementCustom_h
+#pragma once
-#include "JSHTMLSelectElement.h"
+namespace JSC {
+class ExecState;
+class JSValue;
+}
namespace WebCore {
-void selectIndexSetter(HTMLSelectElement*, JSC::ExecState*, unsigned index, JSC::JSValue);
+class HTMLSelectElement;
-}
+void selectElementIndexSetter(JSC::ExecState&, HTMLSelectElement&, unsigned index, JSC::JSValue);
-#endif
+}
diff --git a/Source/WebCore/bindings/js/JSHTMLTemplateElementCustom.cpp b/Source/WebCore/bindings/js/JSHTMLTemplateElementCustom.cpp
index e4cda2baf..ff91eada0 100644
--- a/Source/WebCore/bindings/js/JSHTMLTemplateElementCustom.cpp
+++ b/Source/WebCore/bindings/js/JSHTMLTemplateElementCustom.cpp
@@ -29,9 +29,6 @@
*/
#include "config.h"
-
-#if ENABLE(TEMPLATE_ELEMENT)
-
#include "JSHTMLTemplateElement.h"
#include "HTMLTemplateElement.h"
@@ -43,22 +40,15 @@ using namespace JSC;
namespace WebCore {
-JSValue JSHTMLTemplateElement::content(ExecState* exec) const
+JSValue JSHTMLTemplateElement::content(ExecState& state) const
{
- JSLockHolder lock(exec);
+ JSLockHolder lock(&state);
- DocumentFragment* content = impl().content();
+ auto wrapper = wrap(&state, globalObject(), wrapped().content());
- JSObject* wrapper = getCachedWrapper(currentWorld(exec), content);
- if (wrapper)
- return wrapper;
-
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject(), DocumentFragment, content);
PrivateName propertyName;
const_cast<JSHTMLTemplateElement*>(this)->putDirect(globalObject()->vm(), propertyName, wrapper);
return wrapper;
}
} // namespace WebCore
-
-#endif // ENABLE(TEMPLATE_ELEMENT)
diff --git a/Source/WebCore/bindings/js/JSHistoryCustom.cpp b/Source/WebCore/bindings/js/JSHistoryCustom.cpp
index c608f5328..1d4efac31 100644
--- a/Source/WebCore/bindings/js/JSHistoryCustom.cpp
+++ b/Source/WebCore/bindings/js/JSHistoryCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -29,8 +29,9 @@
#include "config.h"
#include "JSHistory.h"
+#include "ExceptionCode.h"
#include "Frame.h"
-#include "History.h"
+#include "JSDOMConvert.h"
#include "SerializedScriptValue.h"
#include <runtime/JSFunction.h>
@@ -38,159 +39,72 @@ using namespace JSC;
namespace WebCore {
-static EncodedJSValue nonCachingStaticBackFunctionGetter(ExecState* exec, EncodedJSValue, EncodedJSValue, PropertyName propertyName)
+JSValue JSHistory::state(ExecState& state) const
{
- return JSValue::encode(JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), 0, propertyName.publicName(), jsHistoryPrototypeFunctionBack));
-}
-
-static EncodedJSValue nonCachingStaticForwardFunctionGetter(ExecState* exec, EncodedJSValue, EncodedJSValue, PropertyName propertyName)
-{
- return JSValue::encode(JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), 0, propertyName.publicName(), jsHistoryPrototypeFunctionForward));
-}
-
-static EncodedJSValue nonCachingStaticGoFunctionGetter(ExecState* exec, EncodedJSValue, EncodedJSValue, PropertyName propertyName)
-{
- return JSValue::encode(JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), 1, propertyName.publicName(), jsHistoryPrototypeFunctionGo));
-}
-
-bool JSHistory::getOwnPropertySlotDelegate(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
-{
- // When accessing History cross-domain, functions are always the native built-in ones.
- // See JSDOMWindow::getOwnPropertySlotDelegate for additional details.
-
- // Our custom code is only needed to implement the Window cross-domain scheme, so if access is
- // allowed, return false so the normal lookup will take place.
- String message;
- if (shouldAllowAccessToFrame(exec, impl().frame(), message))
- return false;
-
- // Check for the few functions that we allow, even when called cross-domain.
- // Make these read-only / non-configurable to prevent writes via defineProperty.
- const HashEntry* entry = JSHistoryPrototype::info()->propHashTable(exec)->entry(exec, propertyName);
- if (entry) {
- // Allow access to back(), forward() and go() from any frame.
- if (entry->attributes() & JSC::Function) {
- if (entry->function() == jsHistoryPrototypeFunctionBack) {
- slot.setCustom(this, ReadOnly | DontDelete | DontEnum, nonCachingStaticBackFunctionGetter);
- return true;
- } else if (entry->function() == jsHistoryPrototypeFunctionForward) {
- slot.setCustom(this, ReadOnly | DontDelete | DontEnum, nonCachingStaticForwardFunctionGetter);
- return true;
- } else if (entry->function() == jsHistoryPrototypeFunctionGo) {
- slot.setCustom(this, ReadOnly | DontDelete | DontEnum, nonCachingStaticGoFunctionGetter);
- return true;
- }
- }
- } else {
- // Allow access to toString() cross-domain, but always Object.toString.
- if (propertyName == exec->propertyNames().toString) {
- slot.setCustom(this, ReadOnly | DontDelete | DontEnum, objectToStringFunctionGetter);
- return true;
- }
- }
-
- printErrorMessageForFrame(impl().frame(), message);
- slot.setUndefined();
- return true;
-}
-
-bool JSHistory::putDelegate(ExecState* exec, PropertyName, JSValue, PutPropertySlot&)
-{
- if (!shouldAllowAccessToFrame(exec, impl().frame()))
- return true;
- return false;
-}
-
-bool JSHistory::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
-{
- JSHistory* thisObject = jsCast<JSHistory*>(cell);
- if (!shouldAllowAccessToFrame(exec, thisObject->impl().frame()))
- return false;
- return Base::deleteProperty(thisObject, exec, propertyName);
-}
-
-bool JSHistory::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned propertyName)
-{
- JSHistory* thisObject = jsCast<JSHistory*>(cell);
- if (!shouldAllowAccessToFrame(exec, thisObject->impl().frame()))
- return false;
- return Base::deletePropertyByIndex(thisObject, exec, propertyName);
-}
-
-void JSHistory::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
-{
- JSHistory* thisObject = jsCast<JSHistory*>(object);
- if (!shouldAllowAccessToFrame(exec, thisObject->impl().frame()))
- return;
- Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
-}
-
-JSValue JSHistory::state(ExecState *exec) const
-{
- History& history = impl();
+ History& history = wrapped();
JSValue cachedValue = m_state.get();
if (!cachedValue.isEmpty() && !history.stateChanged())
return cachedValue;
RefPtr<SerializedScriptValue> serialized = history.state();
- JSValue result = serialized ? serialized->deserialize(exec, globalObject(), 0) : jsNull();
- const_cast<JSHistory*>(this)->m_state.set(exec->vm(), this, result);
+ JSValue result = serialized ? serialized->deserialize(state, globalObject()) : jsNull();
+ m_state.set(state.vm(), this, result);
return result;
}
-JSValue JSHistory::pushState(ExecState* exec)
+JSValue JSHistory::pushState(ExecState& state)
{
- if (!shouldAllowAccessToFrame(exec, impl().frame()))
- return jsUndefined();
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto argCount = state.argumentCount();
+ if (UNLIKELY(argCount < 2))
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
- RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(exec, exec->argument(0), 0, 0);
- if (exec->hadException())
- return jsUndefined();
+ auto historyState = SerializedScriptValue::create(state, state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, JSValue());
+
+ // FIXME: title should not be nullable.
+ String title = convert<IDLNullable<IDLDOMString>>(state, state.uncheckedArgument(1));
+ RETURN_IF_EXCEPTION(scope, JSValue());
- String title = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(1));
- if (exec->hadException())
- return jsUndefined();
-
String url;
- if (exec->argumentCount() > 2) {
- url = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(2));
- if (exec->hadException())
- return jsUndefined();
+ if (argCount > 2) {
+ url = convert<IDLNullable<IDLUSVString>>(state, state.uncheckedArgument(2));
+ RETURN_IF_EXCEPTION(scope, JSValue());
}
- ExceptionCode ec = 0;
- impl().stateObjectAdded(historyState.release(), title, url, History::StateObjectType::Push, ec);
- setDOMException(exec, ec);
+ propagateException(state, scope, wrapped().stateObjectAdded(WTFMove(historyState), title, url, History::StateObjectType::Push));
m_state.clear();
return jsUndefined();
}
-JSValue JSHistory::replaceState(ExecState* exec)
+JSValue JSHistory::replaceState(ExecState& state)
{
- if (!shouldAllowAccessToFrame(exec, impl().frame()))
- return jsUndefined();
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto argCount = state.argumentCount();
+ if (UNLIKELY(argCount < 2))
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+
+ auto historyState = SerializedScriptValue::create(state, state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, JSValue());
- RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(exec, exec->argument(0), 0, 0);
- if (exec->hadException())
- return jsUndefined();
+ // FIXME: title should not be nullable.
+ String title = convert<IDLNullable<IDLDOMString>>(state, state.uncheckedArgument(1));
+ RETURN_IF_EXCEPTION(scope, JSValue());
- String title = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(1));
- if (exec->hadException())
- return jsUndefined();
-
String url;
- if (exec->argumentCount() > 2) {
- url = valueToStringWithUndefinedOrNullCheck(exec, exec->argument(2));
- if (exec->hadException())
- return jsUndefined();
+ if (argCount > 2) {
+ url = convert<IDLNullable<IDLUSVString>>(state, state.uncheckedArgument(2));
+ RETURN_IF_EXCEPTION(scope, JSValue());
}
- ExceptionCode ec = 0;
- impl().stateObjectAdded(historyState.release(), title, url, History::StateObjectType::Replace, ec);
- setDOMException(exec, ec);
+ propagateException(state, scope, wrapped().stateObjectAdded(WTFMove(historyState), title, url, History::StateObjectType::Replace));
m_state.clear();
diff --git a/Source/WebCore/bindings/js/JSIDBAnyCustom.cpp b/Source/WebCore/bindings/js/JSIDBAnyCustom.cpp
deleted file mode 100644
index 5649c85ca..000000000
--- a/Source/WebCore/bindings/js/JSIDBAnyCustom.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(INDEXED_DATABASE)
-
-#include "JSIDBAny.h"
-
-#include "IDBAny.h"
-#include "IDBCursor.h"
-#include "IDBCursorWithValue.h"
-#include "IDBDatabase.h"
-#include "IDBFactory.h"
-#include "IDBIndex.h"
-#include "IDBObjectStore.h"
-#include "JSDOMStringList.h"
-#include "JSIDBCursor.h"
-#include "JSIDBCursorWithValue.h"
-#include "JSIDBDatabase.h"
-#include "JSIDBFactory.h"
-#include "JSIDBIndex.h"
-#include "JSIDBObjectStore.h"
-#include "JSIDBTransaction.h"
-#include "SerializedScriptValue.h"
-
-using namespace JSC;
-
-namespace WebCore {
-
-static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, const IDBKeyPath& value)
-{
- switch (value.type()) {
- case IDBKeyPath::NullType:
- return jsNull();
- case IDBKeyPath::StringType:
- return jsStringWithCache(exec, value.string());
- case IDBKeyPath::ArrayType:
- RefPtr<DOMStringList> keyPaths = DOMStringList::create();
- for (Vector<String>::const_iterator it = value.array().begin(); it != value.array().end(); ++it)
- keyPaths->append(*it);
- return toJS(exec, globalObject, keyPaths.release());
- }
-
- ASSERT_NOT_REACHED();
- return jsUndefined();
-}
-
-JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, IDBAny* idbAny)
-{
- if (!idbAny)
- return jsNull();
-
- switch (idbAny->type()) {
- case IDBAny::UndefinedType:
- return jsUndefined();
- case IDBAny::NullType:
- return jsNull();
- case IDBAny::DOMStringListType:
- return toJS(exec, globalObject, idbAny->domStringList());
- case IDBAny::IDBCursorType:
- return toJS(exec, globalObject, idbAny->idbCursor());
- case IDBAny::IDBCursorWithValueType:
- return wrap<JSIDBCursorWithValue>(exec, globalObject, idbAny->idbCursorWithValue().get());
- case IDBAny::IDBDatabaseType:
- return toJS(exec, globalObject, idbAny->idbDatabase());
- case IDBAny::IDBFactoryType:
- return toJS(exec, globalObject, idbAny->idbFactory());
- case IDBAny::IDBIndexType:
- return toJS(exec, globalObject, idbAny->idbIndex());
- case IDBAny::IDBObjectStoreType:
- return toJS(exec, globalObject, idbAny->idbObjectStore());
- case IDBAny::IDBTransactionType:
- return toJS(exec, globalObject, idbAny->idbTransaction());
- case IDBAny::ScriptValueType:
- return idbAny->scriptValue().jsValue();
- case IDBAny::StringType:
- return jsStringWithCache(exec, idbAny->string());
- case IDBAny::IntegerType:
- return jsNumber(idbAny->integer());
- case IDBAny::KeyPathType:
- return toJS(exec, globalObject, idbAny->keyPath());
- }
-
- ASSERT_NOT_REACHED();
- return jsUndefined();
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(INDEXED_DATABASE)
diff --git a/Source/WebCore/bindings/js/JSIDBCursorCustom.cpp b/Source/WebCore/bindings/js/JSIDBCursorCustom.cpp
new file mode 100644
index 000000000..c74cb90da
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSIDBCursorCustom.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSIDBCursor.h"
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include "JSDOMBinding.h"
+#include "JSIDBCursorWithValue.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+void JSIDBCursor::visitAdditionalChildren(SlotVisitor& visitor)
+{
+ auto& cursor = wrapped();
+ if (auto* request = cursor.request())
+ visitor.addOpaqueRoot(request);
+}
+
+JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<IDBCursor>&& cursor)
+{
+ if (is<IDBCursorWithValue>(cursor))
+ return createWrapper<IDBCursorWithValue>(globalObject, WTFMove(cursor));
+ return createWrapper<IDBCursor>(globalObject, WTFMove(cursor));
+}
+
+JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, IDBCursor& cursor)
+{
+ return wrap(state, globalObject, cursor);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
diff --git a/Source/WebCore/bindings/js/JSRequestAnimationFrameCallbackCustom.cpp b/Source/WebCore/bindings/js/JSIDBCursorWithValueCustom.cpp
index 91785a425..abbbc78fe 100644
--- a/Source/WebCore/bindings/js/JSRequestAnimationFrameCallbackCustom.cpp
+++ b/Source/WebCore/bindings/js/JSIDBCursorWithValueCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -24,32 +24,22 @@
*/
#include "config.h"
+#include "JSIDBCursorWithValue.h"
-#if ENABLE(REQUEST_ANIMATION_FRAME)
+#if ENABLE(INDEXED_DATABASE)
-#include "JSRequestAnimationFrameCallback.h"
+#include "IDBCursorWithValue.h"
+#include <heap/HeapInlines.h>
using namespace JSC;
namespace WebCore {
-bool JSRequestAnimationFrameCallback::handleEvent(double highResNowMs)
+void JSIDBCursorWithValue::visitAdditionalChildren(SlotVisitor& visitor)
{
- if (!canInvokeCallback())
- return true;
-
- Ref<JSRequestAnimationFrameCallback> protect(*this);
-
- JSLockHolder lock(m_data->globalObject()->vm());
-
- MarkedArgumentBuffer args;
- args.append(jsNumber(highResNowMs));
-
- bool raisedException = false;
- m_data->invokeCallback(args, &raisedException);
- return !raisedException;
+ JSIDBCursor::visitAdditionalChildren(visitor);
}
-}
+} // namespace WebCore
-#endif
+#endif // ENABLE(INDEXED_DATABASE)
diff --git a/Source/WebCore/bindings/js/JSIDBDatabaseCustom.cpp b/Source/WebCore/bindings/js/JSIDBDatabaseCustom.cpp
deleted file mode 100644
index 9eae7569c..000000000
--- a/Source/WebCore/bindings/js/JSIDBDatabaseCustom.cpp
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2012 Michael Pruett <michael@68k.org>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(INDEXED_DATABASE)
-
-#include "JSIDBDatabase.h"
-
-#include "IDBBindingUtilities.h"
-#include "IDBDatabase.h"
-#include "IDBKeyPath.h"
-#include "IDBObjectStore.h"
-#include "JSIDBObjectStore.h"
-#include <runtime/Error.h>
-#include <runtime/JSString.h>
-
-using namespace JSC;
-
-namespace WebCore {
-
-JSValue JSIDBDatabase::createObjectStore(ExecState* exec)
-{
- if (exec->argumentCount() < 1)
- return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
-
- String name = exec->argument(0).toString(exec)->value(exec);
- if (exec->hadException())
- return jsUndefined();
-
- JSValue optionsValue = exec->argument(1);
- if (!optionsValue.isUndefinedOrNull() && !optionsValue.isObject())
- return throwTypeError(exec, "Not an object.");
-
- IDBKeyPath keyPath;
- bool autoIncrement = false;
- if (!optionsValue.isUndefinedOrNull()) {
- JSValue keyPathValue = optionsValue.get(exec, Identifier(exec, "keyPath"));
- if (exec->hadException())
- return jsUndefined();
-
- if (!keyPathValue.isUndefinedOrNull()) {
- keyPath = idbKeyPathFromValue(exec, keyPathValue);
- if (exec->hadException())
- return jsUndefined();
- }
-
- autoIncrement = optionsValue.get(exec, Identifier(exec, "autoIncrement")).toBoolean(exec);
- if (exec->hadException())
- return jsUndefined();
- }
-
- ExceptionCode ec = 0;
- JSValue result = toJS(exec, globalObject(), impl().createObjectStore(name, keyPath, autoIncrement, ec).get());
- setDOMException(exec, ec);
- return result;
-}
-
-}
-
-#endif
diff --git a/Source/WebCore/bindings/js/JSIDBIndexCustom.cpp b/Source/WebCore/bindings/js/JSIDBIndexCustom.cpp
new file mode 100644
index 000000000..2710090f4
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSIDBIndexCustom.cpp
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSIDBIndex.h"
+
+#if ENABLE(INDEXED_DATABASE)
+
+#include "IDBIndex.h"
+#include <heap/HeapInlines.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+void JSIDBIndex::visitAdditionalChildren(SlotVisitor& visitor)
+{
+ visitor.addOpaqueRoot(static_cast<IDBIndex&>(wrapped()).objectStoreAsOpaqueRoot());
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(INDEXED_DATABASE)
diff --git a/Source/WebCore/bindings/js/JSIDBObjectStoreCustom.cpp b/Source/WebCore/bindings/js/JSIDBObjectStoreCustom.cpp
index 74fd354b2..3fe84a71f 100644
--- a/Source/WebCore/bindings/js/JSIDBObjectStoreCustom.cpp
+++ b/Source/WebCore/bindings/js/JSIDBObjectStoreCustom.cpp
@@ -29,56 +29,16 @@
#if ENABLE(INDEXED_DATABASE)
+#include "JSDOMBinding.h"
#include "JSIDBObjectStore.h"
-#include "IDBBindingUtilities.h"
-#include "IDBKeyPath.h"
-#include "IDBObjectStore.h"
-#include "JSIDBIndex.h"
-#include <runtime/Error.h>
-#include <runtime/JSString.h>
-
using namespace JSC;
namespace WebCore {
-JSValue JSIDBObjectStore::createIndex(ExecState* exec)
+void JSIDBObjectStore::visitAdditionalChildren(SlotVisitor& visitor)
{
- ScriptExecutionContext* context = jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext();
- if (!context)
- return exec->vm().throwException(exec, createReferenceError(exec, "IDBObjectStore script execution context is unavailable"));
-
- if (exec->argumentCount() < 2)
- return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
-
- String name = exec->argument(0).toString(exec)->value(exec);
- if (exec->hadException())
- return jsUndefined();
-
- IDBKeyPath keyPath = idbKeyPathFromValue(exec, exec->argument(1));
- if (exec->hadException())
- return jsUndefined();
-
- JSValue optionsValue = exec->argument(2);
- if (!optionsValue.isUndefinedOrNull() && !optionsValue.isObject())
- return throwTypeError(exec, "Not an object.");
-
- bool unique = false;
- bool multiEntry = false;
- if (!optionsValue.isUndefinedOrNull()) {
- unique = optionsValue.get(exec, Identifier(exec, "unique")).toBoolean(exec);
- if (exec->hadException())
- return jsUndefined();
-
- multiEntry = optionsValue.get(exec, Identifier(exec, "multiEntry")).toBoolean(exec);
- if (exec->hadException())
- return jsUndefined();
- }
-
- ExceptionCode ec = 0;
- JSValue result = toJS(exec, globalObject(), impl().createIndex(context, name, keyPath, unique, multiEntry, ec).get());
- setDOMException(exec, ec);
- return result;
+ static_cast<IDBObjectStore&>(wrapped()).visitReferencedIndexes(visitor);
}
}
diff --git a/Source/WebCore/bindings/js/JSHTMLLinkElementCustom.cpp b/Source/WebCore/bindings/js/JSIDBTransactionCustom.cpp
index d3a4b543f..0e6d383e8 100644
--- a/Source/WebCore/bindings/js/JSHTMLLinkElementCustom.cpp
+++ b/Source/WebCore/bindings/js/JSIDBTransactionCustom.cpp
@@ -1,6 +1,5 @@
/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
- * Copyright (C) 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -25,25 +24,21 @@
*/
#include "config.h"
-#include "JSHTMLLinkElement.h"
+#include "JSIDBTransaction.h"
+
+#if ENABLE(INDEXED_DATABASE)
-#include "HTMLLinkElement.h"
#include "JSDOMBinding.h"
-#include "JSDOMSettableTokenList.h"
-#include <wtf/GetPtr.h>
using namespace JSC;
namespace WebCore {
-JSValue JSHTMLLinkElement::sizes(ExecState* exec) const
+void JSIDBTransaction::visitAdditionalChildren(SlotVisitor& visitor)
{
- return toJS(exec, globalObject(), impl().sizes());
+ static_cast<IDBTransaction&>(wrapped()).visitReferencedObjectStores(visitor);
}
-void JSHTMLLinkElement::setSizes(ExecState* exec, JSValue value)
-{
- impl().setSizes(valueToStringWithNullCheck(exec, value));
}
-} // namespace WebCore
+#endif
diff --git a/Source/WebCore/bindings/js/JSImageConstructor.cpp b/Source/WebCore/bindings/js/JSImageConstructor.cpp
deleted file mode 100644
index a86effd13..000000000
--- a/Source/WebCore/bindings/js/JSImageConstructor.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "config.h"
-#include "JSImageConstructor.h"
-
-#include "HTMLImageElement.h"
-#include "HTMLNames.h"
-#include "JSHTMLImageElement.h"
-#include "JSNode.h"
-#include <runtime/Error.h>
-
-using namespace JSC;
-
-namespace WebCore {
-
-STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSImageConstructor);
-
-const ClassInfo JSImageConstructor::s_info = { "ImageConstructor", &Base::s_info, 0, 0, CREATE_METHOD_TABLE(JSImageConstructor) };
-
-JSImageConstructor::JSImageConstructor(Structure* structure, JSDOMGlobalObject* globalObject)
- : DOMConstructorWithDocument(structure, globalObject)
-{
-}
-
-void JSImageConstructor::finishCreation(VM& vm, JSDOMGlobalObject* globalObject)
-{
- Base::finishCreation(globalObject);
- ASSERT(inherits(info()));
- putDirect(vm, vm.propertyNames->prototype, JSHTMLImageElementPrototype::self(vm, globalObject), None);
-}
-
-static EncodedJSValue JSC_HOST_CALL constructImage(ExecState* exec)
-{
- JSImageConstructor* jsConstructor = jsCast<JSImageConstructor*>(exec->callee());
- Document* document = jsConstructor->document();
- if (!document)
- return throwVMError(exec, createReferenceError(exec, "Image constructor associated document is unavailable"));
-
- // Calling toJS on the document causes the JS document wrapper to be
- // added to the window object. This is done to ensure that JSDocument::visit
- // will be called, which will cause the image element to be marked if necessary.
- toJS(exec, jsConstructor->globalObject(), document);
- int width;
- int height;
- int* optionalWidth = 0;
- int* optionalHeight = 0;
- if (exec->argumentCount() > 0) {
- width = exec->argument(0).toInt32(exec);
- optionalWidth = &width;
- }
- if (exec->argumentCount() > 1) {
- height = exec->argument(1).toInt32(exec);
- optionalHeight = &height;
- }
-
- return JSValue::encode(asObject(toJS(exec, jsConstructor->globalObject(),
- HTMLImageElement::createForJSConstructor(*document, optionalWidth, optionalHeight))));
-}
-
-ConstructType JSImageConstructor::getConstructData(JSCell*, ConstructData& constructData)
-{
- constructData.native.function = constructImage;
- return ConstructTypeHost;
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSImageConstructor.h b/Source/WebCore/bindings/js/JSImageConstructor.h
deleted file mode 100644
index b923215b3..000000000
--- a/Source/WebCore/bindings/js/JSImageConstructor.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 1999 Harri Porten (porten@kde.org)
- * Copyright (C) 2004, 2006, 2007, 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef JSImageConstructor_h
-#define JSImageConstructor_h
-
-#include "DOMConstructorWithDocument.h"
-#include "JSDOMBinding.h"
-#include "JSDocument.h"
-
-namespace WebCore {
-
- class JSImageConstructor : public DOMConstructorWithDocument {
- public:
- typedef DOMConstructorWithDocument Base;
-
- static JSImageConstructor* create(JSC::VM& vm, JSC::Structure* structure, JSDOMGlobalObject* globalObject)
- {
- JSImageConstructor* constructor = new (NotNull, JSC::allocateCell<JSImageConstructor>(vm.heap)) JSImageConstructor(structure, globalObject);
- constructor->finishCreation(vm, globalObject);
- return constructor;
- }
-
- static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
- {
- return JSC::Structure::create(vm, globalObject, prototype, JSC::TypeInfo(JSC::ObjectType, StructureFlags), info());
- }
-
- DECLARE_INFO;
-
- private:
- JSImageConstructor(JSC::Structure*, JSDOMGlobalObject*);
- void finishCreation(JSC::VM&, JSDOMGlobalObject*);
- static JSC::ConstructType getConstructData(JSC::JSCell*, JSC::ConstructData&);
- };
-
-} // namespace WebCore
-
-#endif // JSImageConstructor_h
diff --git a/Source/WebCore/bindings/js/JSImageDataCustom.cpp b/Source/WebCore/bindings/js/JSImageDataCustom.cpp
index 1576d5e58..518b5ef13 100644
--- a/Source/WebCore/bindings/js/JSImageDataCustom.cpp
+++ b/Source/WebCore/bindings/js/JSImageDataCustom.cpp
@@ -26,7 +26,10 @@
#include "config.h"
#include "JSImageData.h"
-#include "ImageData.h"
+#include "JSDOMConvertBufferSource.h"
+#include "JSDOMWrapperCache.h"
+#include <heap/HeapInlines.h>
+#include <runtime/IdentifierInlines.h>
#include <wtf/StdLibExtras.h>
#include <wtf/text/WTFString.h>
@@ -34,21 +37,22 @@ using namespace JSC;
namespace WebCore {
-JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, ImageData* imageData)
+JSValue toJSNewlyCreated(ExecState* state, JSDOMGlobalObject* globalObject, Ref<ImageData>&& imageData)
{
- if (!imageData)
- return jsNull();
-
- JSObject* wrapper = getCachedWrapper(currentWorld(exec), imageData);
- if (wrapper)
- return wrapper;
-
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, ImageData, imageData);
- Identifier dataName(exec, "data");
- wrapper->putDirect(exec->vm(), dataName, toJS(exec, globalObject, imageData->data()), DontDelete | ReadOnly);
- exec->heap()->reportExtraMemoryCost(imageData->data()->length());
+ auto* data = imageData->data();
+ auto* wrapper = createWrapper<ImageData>(globalObject, WTFMove(imageData));
+ Identifier dataName = Identifier::fromString(state, "data");
+ wrapper->putDirect(state->vm(), dataName, toJS(state, globalObject, data), DontDelete | ReadOnly);
+ // FIXME: Adopt reportExtraMemoryVisited, and switch to reportExtraMemoryAllocated.
+ // https://bugs.webkit.org/show_bug.cgi?id=142595
+ state->heap()->deprecatedReportExtraMemory(data->length());
return wrapper;
}
+JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, ImageData& imageData)
+{
+ return wrap(state, globalObject, imageData);
+}
+
}
diff --git a/Source/WebCore/bindings/js/JSInspectorFrontendHostCustom.cpp b/Source/WebCore/bindings/js/JSInspectorFrontendHostCustom.cpp
index 2175181d1..447dde627 100644
--- a/Source/WebCore/bindings/js/JSInspectorFrontendHostCustom.cpp
+++ b/Source/WebCore/bindings/js/JSInspectorFrontendHostCustom.cpp
@@ -31,90 +31,51 @@
*/
#include "config.h"
-
-#if ENABLE(INSPECTOR)
-
#include "JSInspectorFrontendHost.h"
#include "ContextMenuItem.h"
#include "InspectorController.h"
#include "InspectorFrontendHost.h"
+#include "JSDOMBinding.h"
#include "JSEvent.h"
#include "MouseEvent.h"
#include <runtime/JSArray.h>
#include <runtime/JSLock.h>
#include <runtime/JSObject.h>
-#include <wtf/Vector.h>
#include <wtf/text/WTFString.h>
using namespace JSC;
namespace WebCore {
-JSValue JSInspectorFrontendHost::platform(ExecState* execState)
-{
-#if PLATFORM(MAC)
- DEFINE_STATIC_LOCAL(const String, platform, (ASCIILiteral("mac")));
-#elif OS(WINDOWS)
- DEFINE_STATIC_LOCAL(const String, platform, (ASCIILiteral("windows")));
-#elif OS(LINUX)
- DEFINE_STATIC_LOCAL(const String, platform, (ASCIILiteral("linux")));
-#elif OS(FREEBSD)
- DEFINE_STATIC_LOCAL(const String, platform, (ASCIILiteral("freebsd")));
-#elif OS(OPENBSD)
- DEFINE_STATIC_LOCAL(const String, platform, (ASCIILiteral("openbsd")));
-#elif OS(SOLARIS)
- DEFINE_STATIC_LOCAL(const String, platform, (ASCIILiteral("solaris")));
-#else
- DEFINE_STATIC_LOCAL(const String, platform, (ASCIILiteral("unknown")));
-#endif
- return jsStringWithCache(execState, platform);
-}
-
-JSValue JSInspectorFrontendHost::port(ExecState* execState)
-{
-#if PLATFORM(GTK)
- DEFINE_STATIC_LOCAL(const String, port, (ASCIILiteral("gtk")));
-#elif PLATFORM(EFL)
- DEFINE_STATIC_LOCAL(const String, port, (ASCIILiteral("efl")));
-#else
- DEFINE_STATIC_LOCAL(const String, port, (ASCIILiteral("unknown")));
-#endif
- return jsStringWithCache(execState, port);
-}
-
#if ENABLE(CONTEXT_MENUS)
static void populateContextMenuItems(ExecState* exec, JSArray* array, ContextMenu& menu)
{
+ VM& vm = exec->vm();
for (size_t i = 0; i < array->length(); ++i) {
JSObject* item = asObject(array->getIndex(exec, i));
- JSValue label = item->get(exec, Identifier(exec, "label"));
- JSValue type = item->get(exec, Identifier(exec, "type"));
- JSValue id = item->get(exec, Identifier(exec, "id"));
- JSValue enabled = item->get(exec, Identifier(exec, "enabled"));
- JSValue checked = item->get(exec, Identifier(exec, "checked"));
- JSValue subItems = item->get(exec, Identifier(exec, "subItems"));
+ JSValue label = item->get(exec, Identifier::fromString(exec, "label"));
+ JSValue type = item->get(exec, Identifier::fromString(exec, "type"));
+ JSValue id = item->get(exec, Identifier::fromString(exec, "id"));
+ JSValue enabled = item->get(exec, Identifier::fromString(exec, "enabled"));
+ JSValue checked = item->get(exec, Identifier::fromString(exec, "checked"));
+ JSValue subItems = item->get(exec, Identifier::fromString(exec, "subItems"));
if (!type.isString())
continue;
- String typeString = type.toString(exec)->value(exec);
+ String typeString = asString(type)->value(exec);
if (typeString == "separator") {
- ContextMenuItem item(SeparatorType,
- ContextMenuItemCustomTagNoAction,
- String());
+ ContextMenuItem item(SeparatorType, ContextMenuItemTagNoAction, String());
menu.appendItem(item);
- } else if (typeString == "subMenu" && subItems.inherits(JSArray::info())) {
+ } else if (typeString == "subMenu" && subItems.inherits(vm, JSArray::info())) {
ContextMenu subMenu;
JSArray* subItemsArray = asArray(subItems);
populateContextMenuItems(exec, subItemsArray, subMenu);
- ContextMenuItem item(SubmenuType,
- ContextMenuItemCustomTagNoAction,
- label.toString(exec)->value(exec),
- &subMenu);
+ ContextMenuItem item(SubmenuType, ContextMenuItemTagNoAction, label.toWTFString(exec), &subMenu);
menu.appendItem(item);
} else {
ContextMenuAction typedId = static_cast<ContextMenuAction>(ContextMenuItemBaseCustomTag + id.toInt32(exec));
- ContextMenuItem menuItem((typeString == "checkbox" ? CheckableActionType : ActionType), typedId, label.toString(exec)->value(exec));
+ ContextMenuItem menuItem((typeString == "checkbox" ? CheckableActionType : ActionType), typedId, label.toWTFString(exec));
if (!enabled.isUndefined())
menuItem.setEnabled(enabled.toBoolean(exec));
if (!checked.isUndefined())
@@ -125,44 +86,23 @@ static void populateContextMenuItems(ExecState* exec, JSArray* array, ContextMen
}
#endif
-JSValue JSInspectorFrontendHost::showContextMenu(ExecState* exec)
+JSValue JSInspectorFrontendHost::showContextMenu(ExecState& state)
{
#if ENABLE(CONTEXT_MENUS)
- if (exec->argumentCount() < 2)
+ if (state.argumentCount() < 2)
return jsUndefined();
- Event* event = toEvent(exec->argument(0));
+ VM& vm = state.vm();
+ Event* event = JSEvent::toWrapped(vm, state.argument(0));
- JSArray* array = asArray(exec->argument(1));
+ JSArray* array = asArray(state.argument(1));
ContextMenu menu;
- populateContextMenuItems(exec, array, menu);
+ populateContextMenuItems(&state, array, menu);
-#if !USE(CROSS_PLATFORM_CONTEXT_MENUS)
- Vector<ContextMenuItem> items = contextMenuItemVector(menu.platformDescription());
-#else
- Vector<ContextMenuItem> items = menu.items();
-#endif
- impl().showContextMenu(event, items);
+ wrapped().showContextMenu(event, menu.items());
#else
- UNUSED_PARAM(exec);
+ UNUSED_PARAM(state);
#endif
return jsUndefined();
}
-JSValue JSInspectorFrontendHost::recordActionTaken(ExecState*)
-{
- return jsUndefined();
-}
-
-JSValue JSInspectorFrontendHost::recordPanelShown(ExecState*)
-{
- return jsUndefined();
-}
-
-JSValue JSInspectorFrontendHost::recordSettingChanged(ExecState*)
-{
- return jsUndefined();
-}
-
} // namespace WebCore
-
-#endif // ENABLE(INSPECTOR)
diff --git a/Source/WebCore/bindings/js/JSLazyEventListener.cpp b/Source/WebCore/bindings/js/JSLazyEventListener.cpp
index 01aee7fba..d270b2696 100644
--- a/Source/WebCore/bindings/js/JSLazyEventListener.cpp
+++ b/Source/WebCore/bindings/js/JSLazyEventListener.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2013 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2003-2016 Apple Inc. All Rights Reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -20,11 +20,13 @@
#include "config.h"
#include "JSLazyEventListener.h"
+#include "CachedScriptFetcher.h"
#include "ContentSecurityPolicy.h"
#include "Frame.h"
#include "JSNode.h"
#include "ScriptController.h"
#include <runtime/FunctionConstructor.h>
+#include <runtime/IdentifierInlines.h>
#include <wtf/NeverDestroyed.h>
#include <wtf/RefCountedLeakCounter.h>
#include <wtf/StdLibExtras.h>
@@ -35,13 +37,13 @@ namespace WebCore {
DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, eventListenerCounter, ("JSLazyEventListener"));
-JSLazyEventListener::JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, ContainerNode* node, const String& sourceURL, const TextPosition& position, JSObject* wrapper, DOMWrapperWorld& isolatedWorld)
+JSLazyEventListener::JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, ContainerNode* node, const String& sourceURL, const TextPosition& sourcePosition, JSObject* wrapper, DOMWrapperWorld& isolatedWorld)
: JSEventListener(0, wrapper, true, isolatedWorld)
, m_functionName(functionName)
, m_eventParameterName(eventParameterName)
, m_code(code)
, m_sourceURL(sourceURL)
- , m_position(position)
+ , m_sourcePosition(sourcePosition)
, m_originalNode(node)
{
// We don't retain the original node because we assume it
@@ -52,8 +54,8 @@ JSLazyEventListener::JSLazyEventListener(const String& functionName, const Strin
// A JSLazyEventListener can be created with a line number of zero when it is created with
// a setAttribute call from JavaScript, so make the line number 1 in that case.
- if (m_position == TextPosition::belowRangePosition())
- m_position = TextPosition::minimumPosition();
+ if (m_sourcePosition == TextPosition::belowRangePosition())
+ m_sourcePosition = TextPosition();
ASSERT(m_eventParameterName == "evt" || m_eventParameterName == "event");
@@ -71,57 +73,66 @@ JSLazyEventListener::~JSLazyEventListener()
JSObject* JSLazyEventListener::initializeJSFunction(ScriptExecutionContext* executionContext) const
{
- ASSERT(executionContext);
- ASSERT(executionContext->isDocument());
+ ASSERT(is<Document>(executionContext));
if (!executionContext)
- return 0;
+ return nullptr;
ASSERT(!m_code.isNull());
ASSERT(!m_eventParameterName.isNull());
if (m_code.isNull() || m_eventParameterName.isNull())
- return 0;
+ return nullptr;
- Document* document = toDocument(executionContext);
+ Document& document = downcast<Document>(*executionContext);
- if (!document->frame())
- return 0;
+ if (!document.frame())
+ return nullptr;
- if (!document->contentSecurityPolicy()->allowInlineEventHandlers(m_sourceURL, m_position.m_line))
- return 0;
+ if (!document.contentSecurityPolicy()->allowInlineEventHandlers(m_sourceURL, m_sourcePosition.m_line))
+ return nullptr;
- ScriptController& script = document->frame()->script();
+ ScriptController& script = document.frame()->script();
if (!script.canExecuteScripts(AboutToExecuteScript) || script.isPaused())
- return 0;
+ return nullptr;
JSDOMGlobalObject* globalObject = toJSDOMGlobalObject(executionContext, isolatedWorld());
if (!globalObject)
- return 0;
+ return nullptr;
+ VM& vm = globalObject->vm();
+ JSLockHolder lock(vm);
+ auto scope = DECLARE_CATCH_SCOPE(vm);
ExecState* exec = globalObject->globalExec();
MarkedArgumentBuffer args;
args.append(jsNontrivialString(exec, m_eventParameterName));
args.append(jsStringWithCache(exec, m_code));
- JSObject* jsFunction = constructFunctionSkippingEvalEnabledCheck(exec, exec->lexicalGlobalObject(), args, Identifier(exec, m_functionName), m_sourceURL, m_position); // FIXME: is globalExec ok?
- if (exec->hadException()) {
+ // We want all errors to refer back to the line on which our attribute was
+ // declared, regardless of any newlines in our JavaScript source text.
+ int overrideLineNumber = m_sourcePosition.m_line.oneBasedInt();
+
+ JSObject* jsFunction = constructFunctionSkippingEvalEnabledCheck(
+ exec, exec->lexicalGlobalObject(), args, Identifier::fromString(exec, m_functionName),
+ SourceOrigin { m_sourceURL, CachedScriptFetcher::create(document.charset()) }, m_sourceURL, m_sourcePosition, overrideLineNumber);
+
+ if (UNLIKELY(scope.exception())) {
reportCurrentException(exec);
- exec->clearException();
- return 0;
+ scope.clearException();
+ return nullptr;
}
JSFunction* listenerAsFunction = jsCast<JSFunction*>(jsFunction);
+
if (m_originalNode) {
if (!wrapper()) {
// Ensure that 'node' has a JavaScript wrapper to mark the event listener we're creating.
- JSLockHolder lock(exec);
// FIXME: Should pass the global object associated with the node
- setWrapper(exec->vm(), asObject(toJS(exec, globalObject, m_originalNode)));
+ setWrapper(vm, asObject(toJS(exec, globalObject, *m_originalNode)));
}
// Add the event's home element to the scope
// (and the document, and the form - see JSHTMLElement::eventHandlerScope)
- listenerAsFunction->setScope(exec->vm(), jsCast<JSNode*>(wrapper())->pushEventHandlerScope(exec, listenerAsFunction->scope()));
+ listenerAsFunction->setScope(vm, jsCast<JSNode*>(wrapper())->pushEventHandlerScope(exec, listenerAsFunction->scope()));
}
return jsFunction;
}
@@ -133,40 +144,53 @@ static const String& eventParameterName(bool isSVGEvent)
return isSVGEvent ? evtString : eventString;
}
-PassRefPtr<JSLazyEventListener> JSLazyEventListener::createForNode(ContainerNode& node, const QualifiedName& attributeName, const AtomicString& attributeValue)
+struct JSLazyEventListener::CreationArguments {
+ const QualifiedName& attributeName;
+ const AtomicString& attributeValue;
+ Document& document;
+ ContainerNode* node;
+ JSC::JSObject* wrapper;
+ bool shouldUseSVGEventName;
+};
+
+RefPtr<JSLazyEventListener> JSLazyEventListener::create(const CreationArguments& arguments)
{
- if (attributeValue.isNull())
+ if (arguments.attributeValue.isNull())
return nullptr;
- TextPosition position = TextPosition::minimumPosition();
- String sourceURL;
-
// FIXME: We should be able to provide source information for frameless documents too (e.g. for importing nodes from XMLHttpRequest.responseXML).
- if (Frame* frame = node.document().frame()) {
+ TextPosition position;
+ String sourceURL;
+ if (Frame* frame = arguments.document.frame()) {
if (!frame->script().canExecuteScripts(AboutToExecuteScript))
return nullptr;
-
position = frame->script().eventHandlerPosition();
- sourceURL = node.document().url().string();
+ sourceURL = arguments.document.url().string();
}
- return adoptRef(new JSLazyEventListener(attributeName.localName().string(),
- eventParameterName(node.isSVGElement()), attributeValue,
- &node, sourceURL, position, nullptr, mainThreadNormalWorld()));
+ return adoptRef(*new JSLazyEventListener(arguments.attributeName.localName().string(),
+ eventParameterName(arguments.shouldUseSVGEventName), arguments.attributeValue,
+ arguments.node, sourceURL, position, arguments.wrapper, mainThreadNormalWorld()));
}
-PassRefPtr<JSLazyEventListener> JSLazyEventListener::createForDOMWindow(Frame& frame, const QualifiedName& attributeName, const AtomicString& attributeValue)
+RefPtr<JSLazyEventListener> JSLazyEventListener::create(Element& element, const QualifiedName& attributeName, const AtomicString& attributeValue)
{
- if (attributeValue.isNull())
- return nullptr;
+ return create({ attributeName, attributeValue, element.document(), &element, nullptr, element.isSVGElement() });
+}
- if (!frame.script().canExecuteScripts(AboutToExecuteScript))
- return nullptr;
+RefPtr<JSLazyEventListener> JSLazyEventListener::create(Document& document, const QualifiedName& attributeName, const AtomicString& attributeValue)
+{
+ // FIXME: This always passes false for "shouldUseSVGEventName". Is that correct for events dispatched to SVG documents?
+ // This has been this way for a long time, but became more obvious when refactoring to separate the Element and Document code paths.
+ return create({ attributeName, attributeValue, document, &document, nullptr, false });
+}
- return adoptRef(new JSLazyEventListener(attributeName.localName().string(),
- eventParameterName(frame.document()->isSVGDocument()), attributeValue,
- nullptr, frame.document()->url().string(), frame.script().eventHandlerPosition(),
- toJSDOMWindow(&frame, mainThreadNormalWorld()), mainThreadNormalWorld()));
+RefPtr<JSLazyEventListener> JSLazyEventListener::create(DOMWindow& window, const QualifiedName& attributeName, const AtomicString& attributeValue)
+{
+ ASSERT(window.document());
+ auto& document = *window.document();
+ ASSERT(document.frame());
+ return create({ attributeName, attributeValue, document, nullptr, toJSDOMWindow(document.frame(), mainThreadNormalWorld()), document.isSVGDocument() });
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSLazyEventListener.h b/Source/WebCore/bindings/js/JSLazyEventListener.h
index 31900178c..9c2849ebb 100644
--- a/Source/WebCore/bindings/js/JSLazyEventListener.h
+++ b/Source/WebCore/bindings/js/JSLazyEventListener.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2003, 2008, 2009, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2003-2016 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -17,42 +17,44 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef JSLazyEventListener_h
-#define JSLazyEventListener_h
+#pragma once
#include "JSEventListener.h"
-#include <wtf/text/TextPosition.h>
-#include <wtf/text/WTFString.h>
namespace WebCore {
- class ContainerNode;
- class Frame;
- class QualifiedName;
+class ContainerNode;
+class DOMWindow;
+class Document;
+class Element;
+class QualifiedName;
- class JSLazyEventListener final : public JSEventListener {
- public:
- static PassRefPtr<JSLazyEventListener> createForNode(ContainerNode&, const QualifiedName& attributeName, const AtomicString& attributeValue);
- static PassRefPtr<JSLazyEventListener> createForDOMWindow(Frame&, const QualifiedName& attributeName, const AtomicString& attributeValue);
+class JSLazyEventListener final : public JSEventListener {
+public:
+ static RefPtr<JSLazyEventListener> create(Element&, const QualifiedName& attributeName, const AtomicString& attributeValue);
+ static RefPtr<JSLazyEventListener> create(Document&, const QualifiedName& attributeName, const AtomicString& attributeValue);
+ static RefPtr<JSLazyEventListener> create(DOMWindow&, const QualifiedName& attributeName, const AtomicString& attributeValue);
- virtual ~JSLazyEventListener();
+ virtual ~JSLazyEventListener();
- private:
- JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, ContainerNode*, const String& sourceURL, const TextPosition&, JSC::JSObject* wrapper, DOMWrapperWorld& isolatedWorld);
+ String sourceURL() const final { return m_sourceURL; }
+ TextPosition sourcePosition() const final { return m_sourcePosition; }
- virtual JSC::JSObject* initializeJSFunction(ScriptExecutionContext*) const override;
- virtual bool wasCreatedFromMarkup() const override { return true; }
+private:
+ struct CreationArguments;
+ static RefPtr<JSLazyEventListener> create(const CreationArguments&);
- static void create() = delete;
+ JSLazyEventListener(const String& functionName, const String& eventParameterName, const String& code, ContainerNode*, const String& sourceURL, const TextPosition&, JSC::JSObject* wrapper, DOMWrapperWorld& isolatedWorld);
- mutable String m_functionName;
- mutable String m_eventParameterName;
- mutable String m_code;
- mutable String m_sourceURL;
- TextPosition m_position;
- ContainerNode* m_originalNode;
- };
+ JSC::JSObject* initializeJSFunction(ScriptExecutionContext*) const override;
+ bool wasCreatedFromMarkup() const override { return true; }
-} // namespace WebCore
+ String m_functionName;
+ String m_eventParameterName;
+ String m_code;
+ String m_sourceURL;
+ TextPosition m_sourcePosition;
+ ContainerNode* m_originalNode;
+};
-#endif // JSLazyEventListener_h
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSLocationCustom.cpp b/Source/WebCore/bindings/js/JSLocationCustom.cpp
index c99f904d8..57eb752da 100644
--- a/Source/WebCore/bindings/js/JSLocationCustom.cpp
+++ b/Source/WebCore/bindings/js/JSLocationCustom.cpp
@@ -23,31 +23,23 @@
#include "config.h"
#include "JSLocation.h"
-#include "Location.h"
+#include "JSDOMBinding.h"
+#include "JSDOMBindingSecurity.h"
+#include "JSDOMExceptionHandling.h"
+#include "RuntimeApplicationChecks.h"
#include <runtime/JSFunction.h>
+#include <runtime/Lookup.h>
using namespace JSC;
namespace WebCore {
-static EncodedJSValue nonCachingStaticReplaceFunctionGetter(ExecState* exec, EncodedJSValue, EncodedJSValue, PropertyName propertyName)
+bool JSLocation::getOwnPropertySlotDelegate(ExecState* state, PropertyName propertyName, PropertySlot& slot)
{
- return JSValue::encode(JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), 1, propertyName.publicName(), jsLocationPrototypeFunctionReplace));
-}
-
-static EncodedJSValue nonCachingStaticReloadFunctionGetter(ExecState* exec, EncodedJSValue, EncodedJSValue, PropertyName propertyName)
-{
- return JSValue::encode(JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), 0, propertyName.publicName(), jsLocationPrototypeFunctionReload));
-}
+ VM& vm = state->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
-static EncodedJSValue nonCachingStaticAssignFunctionGetter(ExecState* exec, EncodedJSValue, EncodedJSValue, PropertyName propertyName)
-{
- return JSValue::encode(JSFunction::create(exec->vm(), exec->lexicalGlobalObject(), 1, propertyName.publicName(), jsLocationPrototypeFunctionAssign));
-}
-
-bool JSLocation::getOwnPropertySlotDelegate(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
-{
- Frame* frame = impl().frame();
+ Frame* frame = wrapped().frame();
if (!frame) {
slot.setUndefined();
return true;
@@ -59,56 +51,55 @@ bool JSLocation::getOwnPropertySlotDelegate(ExecState* exec, PropertyName proper
// Our custom code is only needed to implement the Window cross-domain scheme, so if access is
// allowed, return false so the normal lookup will take place.
String message;
- if (shouldAllowAccessToFrame(exec, frame, message))
+ if (BindingSecurity::shouldAllowAccessToFrame(*state, *frame, message))
return false;
- // Check for the few functions that we allow, even when called cross-domain.
- // Make these read-only / non-configurable to prevent writes via defineProperty.
- const HashEntry* entry = JSLocationPrototype::info()->propHashTable(exec)->entry(exec, propertyName);
- if (entry && (entry->attributes() & JSC::Function)) {
- if (entry->function() == jsLocationPrototypeFunctionReplace) {
- slot.setCustom(this, ReadOnly | DontDelete | DontEnum, nonCachingStaticReplaceFunctionGetter);
- return true;
- } else if (entry->function() == jsLocationPrototypeFunctionReload) {
- slot.setCustom(this, ReadOnly | DontDelete | DontEnum, nonCachingStaticReloadFunctionGetter);
- return true;
- } else if (entry->function() == jsLocationPrototypeFunctionAssign) {
- slot.setCustom(this, ReadOnly | DontDelete | DontEnum, nonCachingStaticAssignFunctionGetter);
- return true;
- }
+ // https://html.spec.whatwg.org/#crossorigingetownpropertyhelper-(-o,-p-)
+ if (propertyName == state->propertyNames().toStringTagSymbol || propertyName == state->propertyNames().hasInstanceSymbol || propertyName == state->propertyNames().isConcatSpreadableSymbol) {
+ slot.setValue(this, ReadOnly | DontEnum, jsUndefined());
+ return true;
}
- // FIXME: Other implementers of the Window cross-domain scheme (Window, History) allow toString,
- // but for now we have decided not to, partly because it seems silly to return "[Object Location]" in
- // such cases when normally the string form of Location would be the URL.
+ // We only allow access to Location.replace() cross origin.
+ if (propertyName == state->propertyNames().replace) {
+ slot.setCustom(this, ReadOnly | DontEnum, nonCachingStaticFunctionGetter<jsLocationInstanceFunctionReplace, 1>);
+ return true;
+ }
- printErrorMessageForFrame(frame, message);
+ // Getting location.href cross origin needs to throw. However, getOwnPropertyDescriptor() needs to return
+ // a descriptor that has a setter but no getter.
+ if (slot.internalMethodType() == PropertySlot::InternalMethodType::GetOwnProperty && propertyName == state->propertyNames().href) {
+ auto* entry = JSLocation::info()->staticPropHashTable->entry(propertyName);
+ CustomGetterSetter* customGetterSetter = CustomGetterSetter::create(vm, nullptr, entry->propertyPutter());
+ slot.setCustomGetterSetter(this, DontEnum | CustomAccessor, customGetterSetter);
+ return true;
+ }
+
+ throwSecurityError(*state, scope, message);
slot.setUndefined();
return true;
}
-bool JSLocation::putDelegate(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot& slot)
+bool JSLocation::putDelegate(ExecState* state, PropertyName propertyName, JSValue, PutPropertySlot&, bool& putResult)
{
- Frame* frame = impl().frame();
+ putResult = false;
+
+ Frame* frame = wrapped().frame();
if (!frame)
return true;
- if (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf)
+ // Silently block access to toString and valueOf.
+ if (propertyName == state->propertyNames().toString || propertyName == state->propertyNames().valueOf)
return true;
- bool sameDomainAccess = shouldAllowAccessToFrame(exec, frame);
-
- const HashEntry* entry = JSLocation::info()->propHashTable(exec)->entry(exec, propertyName);
- if (!entry) {
- if (sameDomainAccess)
- JSObject::put(this, exec, propertyName, value, slot);
- return true;
- }
+ // Always allow assigning to the whole location.
+ // However, alllowing assigning of pieces might inadvertently disclose parts of the original location.
+ // So fall through to the access check for those.
+ if (propertyName == state->propertyNames().href)
+ return false;
- // Cross-domain access to the location is allowed when assigning the whole location,
- // but not when assigning the individual pieces, since that might inadvertently
- // disclose other parts of the original location.
- if (entry->propertyPutter() != setJSLocationHref && !sameDomainAccess)
+ // Block access and throw if there is a security error.
+ if (!BindingSecurity::shouldAllowAccessToFrame(state, frame, ThrowSecurityError))
return true;
return false;
@@ -118,7 +109,7 @@ bool JSLocation::deleteProperty(JSCell* cell, ExecState* exec, PropertyName prop
{
JSLocation* thisObject = jsCast<JSLocation*>(cell);
// Only allow deleting by frames in the same origin.
- if (!shouldAllowAccessToFrame(exec, thisObject->impl().frame()))
+ if (!BindingSecurity::shouldAllowAccessToFrame(exec, thisObject->wrapped().frame(), ThrowSecurityError))
return false;
return Base::deleteProperty(thisObject, exec, propertyName);
}
@@ -127,128 +118,89 @@ bool JSLocation::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned p
{
JSLocation* thisObject = jsCast<JSLocation*>(cell);
// Only allow deleting by frames in the same origin.
- if (!shouldAllowAccessToFrame(exec, thisObject->impl().frame()))
+ if (!BindingSecurity::shouldAllowAccessToFrame(exec, thisObject->wrapped().frame(), ThrowSecurityError))
return false;
return Base::deletePropertyByIndex(thisObject, exec, propertyName);
}
-void JSLocation::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+// https://html.spec.whatwg.org/#crossoriginproperties-(-o-)
+static void addCrossOriginPropertyNames(ExecState& state, PropertyNameArray& propertyNames)
{
- JSLocation* thisObject = jsCast<JSLocation*>(object);
- // Only allow the location object to enumerated by frames in the same origin.
- if (!shouldAllowAccessToFrame(exec, thisObject->impl().frame()))
- return;
- Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
+ static const Identifier* const properties[] = { &state.propertyNames().href, &state.propertyNames().replace };
+ for (auto* property : properties)
+ propertyNames.add(*property);
}
-bool JSLocation::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool throwException)
+// https://html.spec.whatwg.org/#crossoriginownpropertykeys-(-o-)
+static void addCrossOriginOwnPropertyNames(ExecState& state, PropertyNameArray& propertyNames)
{
- if (descriptor.isAccessorDescriptor() && (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf))
- return false;
- return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
-}
+ addCrossOriginPropertyNames(state, propertyNames);
-void JSLocation::setHref(ExecState* exec, JSValue value)
-{
- String href = value.toString(exec)->value(exec);
- if (exec->hadException())
- return;
- impl().setHref(href, activeDOMWindow(exec), firstDOMWindow(exec));
+ propertyNames.add(state.propertyNames().toStringTagSymbol);
+ propertyNames.add(state.propertyNames().hasInstanceSymbol);
+ propertyNames.add(state.propertyNames().isConcatSpreadableSymbol);
}
-void JSLocation::setProtocol(ExecState* exec, JSValue value)
+void JSLocation::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
{
- String protocol = value.toString(exec)->value(exec);
- if (exec->hadException())
+ JSLocation* thisObject = jsCast<JSLocation*>(object);
+ if (!BindingSecurity::shouldAllowAccessToFrame(exec, thisObject->wrapped().frame(), DoNotReportSecurityError)) {
+ if (mode.includeDontEnumProperties())
+ addCrossOriginOwnPropertyNames(*exec, propertyNames);
return;
- ExceptionCode ec = 0;
- impl().setProtocol(protocol, activeDOMWindow(exec), firstDOMWindow(exec), ec);
- setDOMException(exec, ec);
+ }
+ Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
}
-void JSLocation::setHost(ExecState* exec, JSValue value)
+bool JSLocation::defineOwnProperty(JSObject* object, ExecState* exec, PropertyName propertyName, const PropertyDescriptor& descriptor, bool throwException)
{
- String host = value.toString(exec)->value(exec);
- if (exec->hadException())
- return;
- impl().setHost(host, activeDOMWindow(exec), firstDOMWindow(exec));
-}
+ JSLocation* thisObject = jsCast<JSLocation*>(object);
+ if (!BindingSecurity::shouldAllowAccessToFrame(exec, thisObject->wrapped().frame(), ThrowSecurityError))
+ return false;
-void JSLocation::setHostname(ExecState* exec, JSValue value)
-{
- String hostname = value.toString(exec)->value(exec);
- if (exec->hadException())
- return;
- impl().setHostname(hostname, activeDOMWindow(exec), firstDOMWindow(exec));
+ if (descriptor.isAccessorDescriptor() && (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf))
+ return false;
+ return Base::defineOwnProperty(object, exec, propertyName, descriptor, throwException);
}
-void JSLocation::setPort(ExecState* exec, JSValue value)
+bool JSLocation::setPrototype(JSObject*, ExecState* exec, JSValue, bool shouldThrowIfCantSet)
{
- String port = value.toWTFString(exec);
- if (exec->hadException())
- return;
- impl().setPort(port, activeDOMWindow(exec), firstDOMWindow(exec));
-}
+ auto scope = DECLARE_THROW_SCOPE(exec->vm());
-void JSLocation::setPathname(ExecState* exec, JSValue value)
-{
- String pathname = value.toString(exec)->value(exec);
- if (exec->hadException())
- return;
- impl().setPathname(pathname, activeDOMWindow(exec), firstDOMWindow(exec));
-}
+ if (shouldThrowIfCantSet)
+ throwTypeError(exec, scope, ASCIILiteral("Cannot set prototype of this object"));
-void JSLocation::setSearch(ExecState* exec, JSValue value)
-{
- String pathname = value.toString(exec)->value(exec);
- if (exec->hadException())
- return;
- impl().setSearch(pathname, activeDOMWindow(exec), firstDOMWindow(exec));
+ return false;
}
-void JSLocation::setHash(ExecState* exec, JSValue value)
+JSValue JSLocation::getPrototype(JSObject* object, ExecState* exec)
{
- String hash = value.toString(exec)->value(exec);
- if (exec->hadException())
- return;
- impl().setHash(hash, activeDOMWindow(exec), firstDOMWindow(exec));
-}
+ JSLocation* thisObject = jsCast<JSLocation*>(object);
+ if (!BindingSecurity::shouldAllowAccessToFrame(exec, thisObject->wrapped().frame(), DoNotReportSecurityError))
+ return jsNull();
-JSValue JSLocation::replace(ExecState* exec)
-{
- String urlString = exec->argument(0).toString(exec)->value(exec);
- if (exec->hadException())
- return jsUndefined();
- impl().replace(urlString, activeDOMWindow(exec), firstDOMWindow(exec));
- return jsUndefined();
+ return Base::getPrototype(object, exec);
}
-JSValue JSLocation::reload(ExecState* exec)
+bool JSLocation::preventExtensions(JSObject*, ExecState* exec)
{
- impl().reload(activeDOMWindow(exec));
- return jsUndefined();
-}
+ auto scope = DECLARE_THROW_SCOPE(exec->vm());
-JSValue JSLocation::assign(ExecState* exec)
-{
- String urlString = exec->argument(0).toString(exec)->value(exec);
- if (exec->hadException())
- return jsUndefined();
- impl().assign(urlString, activeDOMWindow(exec), firstDOMWindow(exec));
- return jsUndefined();
+ throwTypeError(exec, scope, ASCIILiteral("Cannot prevent extensions on this object"));
+ return false;
}
-JSValue JSLocation::toStringFunction(ExecState* exec)
+String JSLocation::toStringName(const JSObject* object, ExecState* exec)
{
- Frame* frame = impl().frame();
- if (!frame || !shouldAllowAccessToFrame(exec, frame))
- return jsUndefined();
-
- return jsStringWithCache(exec, impl().toString());
+ auto* thisObject = jsCast<const JSLocation*>(object);
+ if (!BindingSecurity::shouldAllowAccessToFrame(exec, thisObject->wrapped().frame(), DoNotReportSecurityError))
+ return ASCIILiteral("Object");
+ return ASCIILiteral("Location");
}
-bool JSLocationPrototype::putDelegate(ExecState* exec, PropertyName propertyName, JSValue, PutPropertySlot&)
+bool JSLocationPrototype::putDelegate(ExecState* exec, PropertyName propertyName, JSValue, PutPropertySlot&, bool& putResult)
{
+ putResult = false;
return (propertyName == exec->propertyNames().toString || propertyName == exec->propertyNames().valueOf);
}
diff --git a/Source/WebCore/bindings/js/JSMainThreadExecState.cpp b/Source/WebCore/bindings/js/JSMainThreadExecState.cpp
index 779b96ab0..f49f4a87e 100644
--- a/Source/WebCore/bindings/js/JSMainThreadExecState.cpp
+++ b/Source/WebCore/bindings/js/JSMainThreadExecState.cpp
@@ -25,11 +25,9 @@
#include "config.h"
#include "JSMainThreadExecState.h"
-#include "MutationObserver.h"
-#if ENABLE(INDEXED_DATABASE)
-#include "IDBPendingTransactionMonitor.h"
-#endif
+#include "Microtasks.h"
+#include "MutationObserver.h"
namespace WebCore {
@@ -37,27 +35,21 @@ JSC::ExecState* JSMainThreadExecState::s_mainThreadState = 0;
void JSMainThreadExecState::didLeaveScriptContext()
{
-#if ENABLE(INDEXED_DATABASE)
- // Indexed DB requires that transactions are created with an internal |active| flag
- // set to true, but the flag becomes false when control returns to the event loop.
- IDBPendingTransactionMonitor::deactivateNewTransactions();
-#endif
-
- MutationObserver::deliverAllMutations();
+ MicrotaskQueue::mainThreadQueue().performMicrotaskCheckpoint();
}
-JSC::JSValue functionCallHandlerFromAnyThread(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args)
+JSC::JSValue functionCallHandlerFromAnyThread(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args, NakedPtr<JSC::Exception>& returnedException)
{
if (isMainThread())
- return JSMainThreadExecState::call(exec, functionObject, callType, callData, thisValue, args);
- return JSC::call(exec, functionObject, callType, callData, thisValue, args);
+ return JSMainThreadExecState::call(exec, functionObject, callType, callData, thisValue, args, returnedException);
+ return JSC::call(exec, functionObject, callType, callData, thisValue, args, returnedException);
}
-JSC::JSValue evaluateHandlerFromAnyThread(JSC::ExecState* exec, const JSC::SourceCode& source, JSC::JSValue thisValue, JSC::JSValue* exception)
+JSC::JSValue evaluateHandlerFromAnyThread(JSC::ExecState* exec, const JSC::SourceCode& source, JSC::JSValue thisValue, NakedPtr<JSC::Exception>& returnedException)
{
if (isMainThread())
- return JSMainThreadExecState::evaluate(exec, source, thisValue, exception);
- return JSC::evaluate(exec, source, thisValue, exception);
+ return JSMainThreadExecState::evaluate(exec, source, thisValue, returnedException);
+ return JSC::evaluate(exec, source, thisValue, returnedException);
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSMainThreadExecState.h b/Source/WebCore/bindings/js/JSMainThreadExecState.h
index ed023dbe2..d244efe0e 100644
--- a/Source/WebCore/bindings/js/JSMainThreadExecState.h
+++ b/Source/WebCore/bindings/js/JSMainThreadExecState.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -23,11 +24,12 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSMainThreadExecState_h
-#define JSMainThreadExecState_h
+#pragma once
+#include "CustomElementReactionQueue.h"
#include "JSDOMBinding.h"
#include <runtime/Completion.h>
+#include <runtime/Microtask.h>
#include <wtf/MainThread.h>
#if PLATFORM(IOS)
@@ -49,23 +51,82 @@ public:
return s_mainThreadState;
};
- static JSC::JSValue call(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args)
+ static JSC::JSValue call(JSC::ExecState* exec, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args, NakedPtr<JSC::Exception>& returnedException)
{
JSMainThreadExecState currentState(exec);
- return JSC::call(exec, functionObject, callType, callData, thisValue, args);
+ return JSC::call(exec, functionObject, callType, callData, thisValue, args, returnedException);
};
- static JSC::JSValue evaluate(JSC::ExecState* exec, const JSC::SourceCode& source, JSC::JSValue thisValue, JSC::JSValue* exception)
+ static JSC::JSValue evaluate(JSC::ExecState* exec, const JSC::SourceCode& source, JSC::JSValue thisValue, NakedPtr<JSC::Exception>& returnedException)
{
JSMainThreadExecState currentState(exec);
- JSC::JSLockHolder lock(exec);
- return JSC::evaluate(exec, source, thisValue, exception);
+ return JSC::evaluate(exec, source, thisValue, returnedException);
};
+ static JSC::JSValue evaluate(JSC::ExecState* exec, const JSC::SourceCode& source, JSC::JSValue thisValue = JSC::JSValue())
+ {
+ NakedPtr<JSC::Exception> unused;
+ return evaluate(exec, source, thisValue, unused);
+ };
+
+ static JSC::JSValue profiledCall(JSC::ExecState* exec, JSC::ProfilingReason reason, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args, NakedPtr<JSC::Exception>& returnedException)
+ {
+ JSMainThreadExecState currentState(exec);
+ return JSC::profiledCall(exec, reason, functionObject, callType, callData, thisValue, args, returnedException);
+ }
+
+ static JSC::JSValue profiledEvaluate(JSC::ExecState* exec, JSC::ProfilingReason reason, const JSC::SourceCode& source, JSC::JSValue thisValue, NakedPtr<JSC::Exception>& returnedException)
+ {
+ JSMainThreadExecState currentState(exec);
+ return JSC::profiledEvaluate(exec, reason, source, thisValue, returnedException);
+ }
+
+ static JSC::JSValue profiledEvaluate(JSC::ExecState* exec, JSC::ProfilingReason reason, const JSC::SourceCode& source, JSC::JSValue thisValue = JSC::JSValue())
+ {
+ NakedPtr<JSC::Exception> unused;
+ return profiledEvaluate(exec, reason, source, thisValue, unused);
+ }
+
+ static void runTask(JSC::ExecState* exec, JSC::Microtask& task)
+ {
+ JSMainThreadExecState currentState(exec);
+ task.run(exec);
+ }
+
+ static JSC::JSInternalPromise& loadModule(JSC::ExecState& state, const String& moduleName, JSC::JSValue scriptFetcher)
+ {
+ JSMainThreadExecState currentState(&state);
+ return *JSC::loadModule(&state, moduleName, scriptFetcher);
+ }
+
+ static JSC::JSInternalPromise& loadModule(JSC::ExecState& state, const JSC::SourceCode& sourceCode, JSC::JSValue scriptFetcher)
+ {
+ JSMainThreadExecState currentState(&state);
+ return *JSC::loadModule(&state, sourceCode, scriptFetcher);
+ }
+
+ static JSC::JSValue linkAndEvaluateModule(JSC::ExecState& state, const JSC::Identifier& moduleKey, JSC::JSValue scriptFetcher, NakedPtr<JSC::Exception>& returnedException)
+ {
+ JSC::VM& vm = state.vm();
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+
+ JSMainThreadExecState currentState(&state);
+ auto returnValue = JSC::linkAndEvaluateModule(&state, moduleKey, scriptFetcher);
+ if (UNLIKELY(scope.exception())) {
+ returnedException = scope.exception();
+ scope.clearException();
+ return JSC::jsUndefined();
+ }
+ return returnValue;
+ }
+
static InspectorInstrumentationCookie instrumentFunctionCall(ScriptExecutionContext*, JSC::CallType, const JSC::CallData&);
+ static InspectorInstrumentationCookie instrumentFunctionConstruct(ScriptExecutionContext*, JSC::ConstructType, const JSC::ConstructData&);
+private:
explicit JSMainThreadExecState(JSC::ExecState* exec)
: m_previousState(s_mainThreadState)
+ , m_lock(exec)
{
ASSERT(isMainThread());
s_mainThreadState = exec;
@@ -73,7 +134,10 @@ public:
~JSMainThreadExecState()
{
+ JSC::VM& vm = s_mainThreadState->vm();
+ auto scope = DECLARE_CATCH_SCOPE(vm);
ASSERT(isMainThread());
+ ASSERT_UNUSED(scope, !scope.exception());
bool didExitJavaScript = s_mainThreadState && !m_previousState;
@@ -83,9 +147,11 @@ public:
didLeaveScriptContext();
}
-private:
- static JSC::ExecState* s_mainThreadState;
+ template<typename Type, Type jsType, typename DataType> static InspectorInstrumentationCookie instrumentFunctionInternal(ScriptExecutionContext*, Type, const DataType&);
+
+ WEBCORE_EXPORT static JSC::ExecState* s_mainThreadState;
JSC::ExecState* m_previousState;
+ JSC::JSLockHolder m_lock;
static void didLeaveScriptContext();
};
@@ -110,11 +176,10 @@ public:
private:
JSC::ExecState* m_previousState;
+ CustomElementReactionStack m_customElementReactionStack;
};
-JSC::JSValue functionCallHandlerFromAnyThread(JSC::ExecState*, JSC::JSValue functionObject, JSC::CallType callType, const JSC::CallData& callData, JSC::JSValue thisValue, const JSC::ArgList& args);
-JSC::JSValue evaluateHandlerFromAnyThread(JSC::ExecState*, const JSC::SourceCode&, JSC::JSValue thisValue, JSC::JSValue* exception);
+JSC::JSValue functionCallHandlerFromAnyThread(JSC::ExecState*, JSC::JSValue functionObject, JSC::CallType, const JSC::CallData&, JSC::JSValue thisValue, const JSC::ArgList& args, NakedPtr<JSC::Exception>& returnedException);
+JSC::JSValue evaluateHandlerFromAnyThread(JSC::ExecState*, const JSC::SourceCode&, JSC::JSValue thisValue, NakedPtr<JSC::Exception>& returnedException);
} // namespace WebCore
-
-#endif // JSMainThreadExecState_h
diff --git a/Source/WebCore/bindings/js/JSMainThreadExecStateInstrumentation.h b/Source/WebCore/bindings/js/JSMainThreadExecStateInstrumentation.h
index de4524696..4ad6e3201 100644
--- a/Source/WebCore/bindings/js/JSMainThreadExecStateInstrumentation.h
+++ b/Source/WebCore/bindings/js/JSMainThreadExecStateInstrumentation.h
@@ -24,29 +24,37 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSMainThreadExecStateInstrumentation_h
-#define JSMainThreadExecStateInstrumentation_h
+#pragma once
#include "InspectorInstrumentation.h"
#include "JSMainThreadExecState.h"
-#include <runtime/Executable.h>
+#include <runtime/FunctionExecutable.h>
namespace WebCore {
-inline InspectorInstrumentationCookie JSMainThreadExecState::instrumentFunctionCall(ScriptExecutionContext* context, JSC::CallType callType, const JSC::CallData& callData)
+template<typename Type, Type jsType, class DataType>
+inline InspectorInstrumentationCookie JSMainThreadExecState::instrumentFunctionInternal(ScriptExecutionContext* context, Type callType, const DataType& callData)
{
if (!InspectorInstrumentation::timelineAgentEnabled(context))
return InspectorInstrumentationCookie();
String resourceName;
int lineNumber = 1;
- if (callType == JSC::CallTypeJS) {
+ if (callType == jsType) {
resourceName = callData.js.functionExecutable->sourceURL();
- lineNumber = callData.js.functionExecutable->lineNo();
+ lineNumber = callData.js.functionExecutable->firstLine();
} else
resourceName = "undefined";
return InspectorInstrumentation::willCallFunction(context, resourceName, lineNumber);
}
-} // namespace WebCore
+inline InspectorInstrumentationCookie JSMainThreadExecState::instrumentFunctionCall(ScriptExecutionContext* context, JSC::CallType type, const JSC::CallData& data)
+{
+ return instrumentFunctionInternal<JSC::CallType, JSC::CallType::JS, JSC::CallData>(context, type, data);
+}
-#endif // JSMainThreadExecStateInstrumentation_h
+inline InspectorInstrumentationCookie JSMainThreadExecState::instrumentFunctionConstruct(ScriptExecutionContext* context, JSC::ConstructType type, const JSC::ConstructData& data)
+{
+ return instrumentFunctionInternal<JSC::ConstructType, JSC::ConstructType::JS, JSC::ConstructData>(context, type, data);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSMediaKeySessionCustom.cpp b/Source/WebCore/bindings/js/JSMediaKeySessionCustom.cpp
new file mode 100644
index 000000000..4227ccd39
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSMediaKeySessionCustom.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 Metrological Group B.V.
+ * Copyright (C) 2016 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(ENCRYPTED_MEDIA)
+
+#include "JSMediaKeySession.h"
+
+namespace WebCore {
+
+JSC::JSValue JSMediaKeySession::closed(JSC::ExecState& state) const
+{
+ if (!m_closed) {
+ auto promise = createDeferredPromise(state, domWindow());
+ m_closed.set(state.vm(), this, promise->promise());
+ wrapped().registerClosedPromise(WTFMove(promise));
+ }
+ return m_closed.get();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(ENCRYPTED_MEDIA)
diff --git a/Source/WebCore/bindings/js/JSMediaListCustom.h b/Source/WebCore/bindings/js/JSMediaListCustom.h
index 8f4ff7aeb..af934b75c 100644
--- a/Source/WebCore/bindings/js/JSMediaListCustom.h
+++ b/Source/WebCore/bindings/js/JSMediaListCustom.h
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -23,8 +23,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSMediaListCustom_h
-#define JSMediaListCustom_h
+#pragma once
#include "CSSRule.h"
#include "CSSStyleSheet.h"
@@ -44,5 +43,3 @@ inline void* root(MediaList* mediaList)
}
} // namespace WebCore
-
-#endif // JSMediaListCustom_h
diff --git a/Source/WebCore/bindings/js/JSMediaSourceStatesCustom.cpp b/Source/WebCore/bindings/js/JSMediaSourceStatesCustom.cpp
deleted file mode 100644
index 4123e08b7..000000000
--- a/Source/WebCore/bindings/js/JSMediaSourceStatesCustom.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2013 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(MEDIA_STREAM)
-
-#include "JSMediaSourceStates.h"
-
-#include "MediaSourceStates.h"
-
-using namespace JSC;
-
-namespace WebCore {
-
-JSValue JSMediaSourceStates::width(ExecState*) const
-{
- if (!impl().hasVideoSource())
- return jsUndefined();
-
- return jsNumber(impl().width());
-}
-
-JSValue JSMediaSourceStates::height(ExecState*) const
-{
- if (!impl().hasVideoSource())
- return jsUndefined();
-
- return jsNumber(impl().height());
-}
-
-JSValue JSMediaSourceStates::frameRate(ExecState*) const
-{
- if (!impl().hasVideoSource())
- return jsUndefined();
-
- return jsNumber(impl().frameRate());
-}
-
-JSValue JSMediaSourceStates::aspectRatio(ExecState*) const
-{
- if (!impl().hasVideoSource())
- return jsUndefined();
-
- return jsNumber(impl().aspectRatio());
-}
-
-JSValue JSMediaSourceStates::facingMode(ExecState* exec) const
-{
- if (!impl().hasVideoSource())
- return jsUndefined();
-
- const AtomicString& mode = impl().facingMode();
- if (mode.isEmpty())
- return jsUndefined();
-
- return jsStringWithCache(exec, impl().facingMode());
-}
-
-JSValue JSMediaSourceStates::volume(ExecState*) const
-{
- if (impl().hasVideoSource())
- return jsUndefined();
-
- return jsNumber(impl().volume());
-}
-
-} // namespace WebCore
-
-#endif
diff --git a/Source/WebCore/bindings/js/JSMediaStreamCapabilitiesCustom.cpp b/Source/WebCore/bindings/js/JSMediaStreamCapabilitiesCustom.cpp
index 9ad691de1..b2c6257b7 100644
--- a/Source/WebCore/bindings/js/JSMediaStreamCapabilitiesCustom.cpp
+++ b/Source/WebCore/bindings/js/JSMediaStreamCapabilitiesCustom.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -31,21 +31,22 @@
#include "JSAllAudioCapabilities.h"
#include "JSAllVideoCapabilities.h"
-#include "MediaStreamCapabilities.h"
+#include "JSDOMBinding.h"
using namespace JSC;
namespace WebCore {
-JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, MediaStreamCapabilities* object)
+JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<MediaStreamCapabilities>&& object)
{
- if (!object)
- return jsNull();
-
- if (object->hasVideoSource())
- return wrap<JSAllVideoCapabilities>(exec, globalObject, static_cast<AllVideoCapabilities*>(object));
+ if (object.hasVideoSource())
+ return CREATE_DOM_WRAPPER(globalObject, AllVideoCapabilities, WTFMove(object));
+ return CREATE_DOM_WRAPPER(globalObject, AllAudioCapabilities, WTFMove(object));
+}
- return wrap<JSAllAudioCapabilities>(exec, globalObject, static_cast<AllAudioCapabilities*>(object));
+JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, MediaStreamCapabilities& object)
+{
+ return wrap(state, globalObject, object);
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSMessageChannelCustom.cpp b/Source/WebCore/bindings/js/JSMessageChannelCustom.cpp
index 3b2b26189..375dd4b5f 100644
--- a/Source/WebCore/bindings/js/JSMessageChannelCustom.cpp
+++ b/Source/WebCore/bindings/js/JSMessageChannelCustom.cpp
@@ -27,27 +27,18 @@
#if ENABLE(CHANNEL_MESSAGING)
+#include "DOMWrapperWorld.h"
#include "JSMessageChannel.h"
-
-#include "MessageChannel.h"
-#include <runtime/Error.h>
-
-using namespace JSC;
+#include <heap/SlotVisitorInlines.h>
namespace WebCore {
-void JSMessageChannel::visitChildren(JSCell* cell, SlotVisitor& visitor)
+void JSMessageChannel::visitAdditionalChildren(JSC::SlotVisitor& visitor)
{
- JSMessageChannel* thisObject = jsCast<JSMessageChannel*>(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(thisObject, visitor);
-
- if (MessagePort* port = thisObject->m_impl->port1())
+ if (MessagePort* port = wrapped().port1())
visitor.addOpaqueRoot(port);
- if (MessagePort* port = thisObject->m_impl->port2())
+ if (MessagePort* port = wrapped().port2())
visitor.addOpaqueRoot(port);
}
diff --git a/Source/WebCore/bindings/js/JSMessageEventCustom.cpp b/Source/WebCore/bindings/js/JSMessageEventCustom.cpp
index c84ca0d9a..e0886ab25 100644
--- a/Source/WebCore/bindings/js/JSMessageEventCustom.cpp
+++ b/Source/WebCore/bindings/js/JSMessageEventCustom.cpp
@@ -33,9 +33,10 @@
#include "JSBlob.h"
#include "JSDOMBinding.h"
+#include "JSDOMConvert.h"
#include "JSDOMWindow.h"
#include "JSEventTarget.h"
-#include "JSMessagePortCustom.h"
+#include "JSMessagePort.h"
#include "MessageEvent.h"
#include <runtime/JSArray.h>
#include <runtime/JSArrayBuffer.h>
@@ -44,85 +45,104 @@ using namespace JSC;
namespace WebCore {
-JSValue JSMessageEvent::data(ExecState* exec) const
+JSValue JSMessageEvent::data(ExecState& state) const
{
- if (JSValue cachedValue = m_data.get())
- return cachedValue;
+ if (JSValue cachedValue = m_data.get()) {
+ // We cannot use a cached object if we are in a different world than the one it was created in.
+ if (!cachedValue.isObject() || &worldForDOMObject(cachedValue.getObject()) == &currentWorld(&state))
+ return cachedValue;
+ ASSERT_NOT_REACHED();
+ }
- MessageEvent& event = impl();
+ MessageEvent& event = wrapped();
JSValue result;
switch (event.dataType()) {
case MessageEvent::DataTypeScriptValue: {
- Deprecated::ScriptValue scriptValue = event.dataAsScriptValue();
- if (scriptValue.hasNoValue())
+ JSValue dataValue = event.dataAsScriptValue();
+ if (!dataValue)
result = jsNull();
- else
- result = scriptValue.jsValue();
+ else {
+ // We need to make sure MessageEvents do not leak objects in their state property across isolated DOM worlds.
+ // Ideally, we would check that the worlds have different privileges but that's not possible yet.
+ if (dataValue.isObject() && &worldForDOMObject(dataValue.getObject()) != &currentWorld(&state)) {
+ RefPtr<SerializedScriptValue> serializedValue = event.trySerializeData(&state);
+ if (serializedValue)
+ result = serializedValue->deserialize(state, globalObject());
+ else
+ result = jsNull();
+ } else
+ result = dataValue;
+ }
break;
}
case MessageEvent::DataTypeSerializedScriptValue:
if (RefPtr<SerializedScriptValue> serializedValue = event.dataAsSerializedScriptValue()) {
- MessagePortArray ports = impl().ports();
- result = serializedValue->deserialize(exec, globalObject(), &ports, NonThrowing);
- }
- else
+ Vector<RefPtr<MessagePort>> ports = wrapped().ports();
+ // FIXME: Why does this suppress exceptions?
+ result = serializedValue->deserialize(state, globalObject(), ports, SerializationErrorMode::NonThrowing);
+ } else
result = jsNull();
break;
case MessageEvent::DataTypeString:
- result = jsStringWithCache(exec, event.dataAsString());
+ result = jsStringWithCache(&state, event.dataAsString());
break;
case MessageEvent::DataTypeBlob:
- result = toJS(exec, globalObject(), event.dataAsBlob());
+ result = toJS(&state, globalObject(), event.dataAsBlob());
break;
case MessageEvent::DataTypeArrayBuffer:
- result = toJS(exec, globalObject(), event.dataAsArrayBuffer());
+ result = toJS(&state, globalObject(), event.dataAsArrayBuffer());
break;
}
// Save the result so we don't have to deserialize the value again.
- const_cast<JSMessageEvent*>(this)->m_data.set(exec->vm(), this, result);
+ m_data.set(state.vm(), this, result);
return result;
}
-static JSC::JSValue handleInitMessageEvent(JSMessageEvent* jsEvent, JSC::ExecState* exec)
+static JSC::JSValue handleInitMessageEvent(JSMessageEvent* jsEvent, JSC::ExecState& state)
{
- const String& typeArg = exec->argument(0).toString(exec)->value(exec);
- bool canBubbleArg = exec->argument(1).toBoolean(exec);
- bool cancelableArg = exec->argument(2).toBoolean(exec);
- const String originArg = exec->argument(4).toString(exec)->value(exec);
- const String lastEventIdArg = exec->argument(5).toString(exec)->value(exec);
- DOMWindow* sourceArg = toDOMWindow(exec->argument(6));
- OwnPtr<MessagePortArray> messagePorts;
- OwnPtr<ArrayBufferArray> arrayBuffers;
- if (!exec->argument(7).isUndefinedOrNull()) {
- messagePorts = adoptPtr(new MessagePortArray);
- arrayBuffers = adoptPtr(new ArrayBufferArray);
- fillMessagePortArray(exec, exec->argument(7), *messagePorts, *arrayBuffers);
- if (exec->hadException())
- return jsUndefined();
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ const String& typeArg = state.argument(0).toWTFString(&state);
+ RETURN_IF_EXCEPTION(scope, JSValue());
+
+ bool canBubbleArg = state.argument(1).toBoolean(&state);
+ RETURN_IF_EXCEPTION(scope, JSValue());
+
+ bool cancelableArg = state.argument(2).toBoolean(&state);
+ RETURN_IF_EXCEPTION(scope, JSValue());
+
+ JSValue dataArg = state.argument(3);
+
+ const String originArg = convert<IDLUSVString>(state, state.argument(4));
+ RETURN_IF_EXCEPTION(scope, JSValue());
+
+ const String lastEventIdArg = state.argument(5).toWTFString(&state);
+ RETURN_IF_EXCEPTION(scope, JSValue());
+
+ auto sourceArg = convert<IDLNullable<IDLUnion<IDLInterface<DOMWindow>, IDLInterface<MessagePort>>>>(state, state.argument(6));
+ RETURN_IF_EXCEPTION(scope, JSValue());
+
+ Vector<RefPtr<MessagePort>> messagePorts;
+ if (!state.argument(7).isUndefinedOrNull()) {
+ messagePorts = convert<IDLSequence<IDLInterface<MessagePort>>>(state, state.argument(7));
+ RETURN_IF_EXCEPTION(scope, JSValue());
}
- Deprecated::ScriptValue dataArg = Deprecated::ScriptValue(exec->vm(), exec->argument(3));
- if (exec->hadException())
- return jsUndefined();
- MessageEvent& event = jsEvent->impl();
- event.initMessageEvent(typeArg, canBubbleArg, cancelableArg, dataArg, originArg, lastEventIdArg, sourceArg, messagePorts.release());
- jsEvent->m_data.set(exec->vm(), jsEvent, dataArg.jsValue());
+ MessageEvent& event = jsEvent->wrapped();
+ event.initMessageEvent(state, typeArg, canBubbleArg, cancelableArg, dataArg, originArg, lastEventIdArg, WTFMove(sourceArg), WTFMove(messagePorts));
+ jsEvent->m_data.set(vm, jsEvent, dataArg);
return jsUndefined();
}
-JSC::JSValue JSMessageEvent::initMessageEvent(JSC::ExecState* exec)
-{
- return handleInitMessageEvent(this, exec);
-}
-
-JSC::JSValue JSMessageEvent::webkitInitMessageEvent(JSC::ExecState* exec)
+JSC::JSValue JSMessageEvent::webkitInitMessageEvent(JSC::ExecState& state)
{
- return handleInitMessageEvent(this, exec);
+ return handleInitMessageEvent(this, state);
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSMessagePortCustom.cpp b/Source/WebCore/bindings/js/JSMessagePortCustom.cpp
index 33ed4dc3a..b168cf22f 100644
--- a/Source/WebCore/bindings/js/JSMessagePortCustom.cpp
+++ b/Source/WebCore/bindings/js/JSMessagePortCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008-2009, 2016 Apple Inc. All Rights Reserved.
* Copyright (C) 2011 Google Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -27,87 +27,15 @@
#include "config.h"
#include "JSMessagePort.h"
-#include "Event.h"
-#include "ExceptionCode.h"
-#include "Frame.h"
-#include "JSDOMGlobalObject.h"
-#include "JSEvent.h"
-#include "JSEventListener.h"
-#include "JSMessagePortCustom.h"
-#include "MessagePort.h"
-#include <runtime/Error.h>
-#include <runtime/JSArrayBuffer.h>
-#include <wtf/text/AtomicString.h>
-
using namespace JSC;
namespace WebCore {
-void JSMessagePort::visitChildren(JSCell* cell, SlotVisitor& visitor)
+void JSMessagePort::visitAdditionalChildren(SlotVisitor& visitor)
{
- JSMessagePort* thisObject = jsCast<JSMessagePort*>(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(thisObject, visitor);
-
// If we have a locally entangled port, we can directly mark it as reachable. Ports that are remotely entangled are marked in-use by markActiveObjectsForContext().
- if (MessagePort* port = thisObject->m_impl->locallyEntangledPort())
+ if (MessagePort* port = wrapped().locallyEntangledPort())
visitor.addOpaqueRoot(port);
-
- thisObject->m_impl->visitJSEventListeners(visitor);
-}
-
-JSC::JSValue JSMessagePort::postMessage(JSC::ExecState* exec)
-{
- return handlePostMessage(exec, &impl());
-}
-
-void fillMessagePortArray(JSC::ExecState* exec, JSC::JSValue value, MessagePortArray& portArray, ArrayBufferArray& arrayBuffers)
-{
- // Convert from the passed-in JS array-like object to a MessagePortArray.
- // Also validates the elements per sections 4.1.13 and 4.1.15 of the WebIDL spec and section 8.3.3 of the HTML5 spec.
- if (value.isUndefinedOrNull()) {
- portArray.resize(0);
- arrayBuffers.resize(0);
- return;
- }
-
- // Validation of sequence types, per WebIDL spec 4.1.13.
- unsigned length = 0;
- JSObject* object = toJSSequence(exec, value, length);
- if (exec->hadException())
- return;
-
- for (unsigned i = 0 ; i < length; ++i) {
- JSValue value = object->get(exec, i);
- if (exec->hadException())
- return;
- // Validation of non-null objects, per HTML5 spec 10.3.3.
- if (value.isUndefinedOrNull()) {
- setDOMException(exec, INVALID_STATE_ERR);
- return;
- }
-
- // Validation of Objects implementing an interface, per WebIDL spec 4.1.15.
- RefPtr<MessagePort> port = toMessagePort(value);
- if (port) {
- // Check for duplicate ports.
- if (portArray.contains(port)) {
- setDOMException(exec, INVALID_STATE_ERR);
- return;
- }
- portArray.append(port.release());
- } else {
- RefPtr<ArrayBuffer> arrayBuffer = toArrayBuffer(value);
- if (arrayBuffer)
- arrayBuffers.append(arrayBuffer);
- else {
- throwTypeError(exec);
- return;
- }
- }
- }
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSMessagePortCustom.h b/Source/WebCore/bindings/js/JSMessagePortCustom.h
deleted file mode 100644
index bbd566299..000000000
--- a/Source/WebCore/bindings/js/JSMessagePortCustom.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright (C) 2009 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef JSMessagePortCustom_h
-#define JSMessagePortCustom_h
-
-#include "MessagePort.h"
-#include <runtime/JSCJSValue.h>
-#include <runtime/Operations.h>
-#include <wtf/Forward.h>
-
-namespace WebCore {
-
- typedef int ExceptionCode;
-
- // Helper function which pulls the values out of a JS sequence and into a MessagePortArray.
- // Also validates the elements per sections 4.1.13 and 4.1.15 of the WebIDL spec and section 8.3.3 of the HTML5 spec.
- // May generate an exception via the passed ExecState.
- void fillMessagePortArray(JSC::ExecState*, JSC::JSValue, MessagePortArray&, ArrayBufferArray&);
-
- // Helper function to convert from JS postMessage arguments to WebCore postMessage arguments.
- template <typename T>
- inline JSC::JSValue handlePostMessage(JSC::ExecState* exec, T* impl)
- {
- MessagePortArray portArray;
- ArrayBufferArray arrayBufferArray;
- fillMessagePortArray(exec, exec->argument(1), portArray, arrayBufferArray);
- RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(exec, exec->argument(0), &portArray, &arrayBufferArray);
- if (exec->hadException())
- return JSC::jsUndefined();
-
- ExceptionCode ec = 0;
- impl->postMessage(message.release(), &portArray, ec);
- setDOMException(exec, ec);
- return JSC::jsUndefined();
- }
-
-}
-#endif // JSMessagePortCustom_h
diff --git a/Source/WebCore/bindings/js/JSMockContentFilterSettingsCustom.cpp b/Source/WebCore/bindings/js/JSMockContentFilterSettingsCustom.cpp
new file mode 100644
index 000000000..cbce60cf5
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSMockContentFilterSettingsCustom.cpp
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSMockContentFilterSettings.h"
+
+#if ENABLE(CONTENT_FILTERING)
+
+#include "JSDOMBinding.h"
+#include "JSDOMConvert.h"
+#include "MockContentFilterSettings.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+using Decision = MockContentFilterSettings::Decision;
+using DecisionPoint = MockContentFilterSettings::DecisionPoint;
+
+JSValue JSMockContentFilterSettings::decisionPoint(ExecState&) const
+{
+ DecisionPoint decisionPoint = wrapped().decisionPoint();
+ switch (decisionPoint) {
+ case DecisionPoint::AfterWillSendRequest:
+ case DecisionPoint::AfterRedirect:
+ case DecisionPoint::AfterResponse:
+ case DecisionPoint::AfterAddData:
+ case DecisionPoint::AfterFinishedAddingData:
+ case DecisionPoint::Never:
+ return jsNumber(static_cast<uint8_t>(decisionPoint));
+ }
+
+ ASSERT_NOT_REACHED();
+ return jsUndefined();
+}
+
+void JSMockContentFilterSettings::setDecisionPoint(ExecState& state, JSValue value)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ uint8_t nativeValue { convert<IDLOctet>(state, value, IntegerConversionConfiguration::EnforceRange) };
+ RETURN_IF_EXCEPTION(scope, void());
+
+ DecisionPoint decisionPoint { static_cast<DecisionPoint>(nativeValue) };
+ switch (decisionPoint) {
+ case DecisionPoint::AfterWillSendRequest:
+ case DecisionPoint::AfterRedirect:
+ case DecisionPoint::AfterResponse:
+ case DecisionPoint::AfterAddData:
+ case DecisionPoint::AfterFinishedAddingData:
+ case DecisionPoint::Never:
+ wrapped().setDecisionPoint(decisionPoint);
+ return;
+ }
+
+ throwTypeError(&state, scope, String::format("%u is not a valid decisionPoint value.", nativeValue));
+}
+
+static inline JSValue toJSValue(Decision decision)
+{
+ switch (decision) {
+ case Decision::Allow:
+ case Decision::Block:
+ return jsNumber(static_cast<uint8_t>(decision));
+ }
+
+ ASSERT_NOT_REACHED();
+ return jsUndefined();
+}
+
+static inline Decision toDecision(ExecState& state, JSValue value)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ uint8_t nativeValue { convert<IDLOctet>(state, value, IntegerConversionConfiguration::EnforceRange) };
+ RETURN_IF_EXCEPTION(scope, Decision::Allow);
+
+ Decision decision { static_cast<Decision>(nativeValue) };
+ switch (decision) {
+ case Decision::Allow:
+ case Decision::Block:
+ return decision;
+ }
+
+ throwTypeError(&state, scope, String::format("%u is not a valid decision value.", nativeValue));
+ return Decision::Allow;
+}
+
+JSValue JSMockContentFilterSettings::decision(ExecState&) const
+{
+ return toJSValue(wrapped().decision());
+}
+
+void JSMockContentFilterSettings::setDecision(ExecState& state, JSValue value)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ Decision decision { toDecision(state, value) };
+ RETURN_IF_EXCEPTION(scope, void());
+
+ wrapped().setDecision(decision);
+}
+
+JSValue JSMockContentFilterSettings::unblockRequestDecision(ExecState&) const
+{
+ return toJSValue(wrapped().unblockRequestDecision());
+}
+
+void JSMockContentFilterSettings::setUnblockRequestDecision(ExecState& state, JSValue value)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ Decision unblockRequestDecision { toDecision(state, value) };
+ RETURN_IF_EXCEPTION(scope, void());
+
+ wrapped().setUnblockRequestDecision(unblockRequestDecision);
+}
+
+}; // namespace WebCore
+
+#endif // ENABLE(CONTENT_FILTERING)
diff --git a/Source/WebCore/bindings/js/JSMutationCallback.cpp b/Source/WebCore/bindings/js/JSMutationCallback.cpp
index adabc7eb7..afc422f36 100644
--- a/Source/WebCore/bindings/js/JSMutationCallback.cpp
+++ b/Source/WebCore/bindings/js/JSMutationCallback.cpp
@@ -51,12 +51,12 @@ JSMutationCallback::~JSMutationCallback()
{
}
-void JSMutationCallback::call(const Vector<RefPtr<MutationRecord>>& mutations, MutationObserver* observer)
+void JSMutationCallback::call(const Vector<Ref<MutationRecord>>& mutations, MutationObserver* observer)
{
if (!canInvokeCallback())
return;
- Ref<JSMutationCallback> protect(*this);
+ Ref<JSMutationCallback> protectedThis(*this);
JSLockHolder lock(m_isolatedWorld->vm());
@@ -66,7 +66,7 @@ void JSMutationCallback::call(const Vector<RefPtr<MutationRecord>>& mutations, M
JSValue callback = m_callback.get();
CallData callData;
CallType callType = getCallData(callback, callData);
- if (callType == CallTypeNone) {
+ if (callType == CallType::None) {
ASSERT_NOT_REACHED();
return;
}
@@ -82,17 +82,18 @@ void JSMutationCallback::call(const Vector<RefPtr<MutationRecord>>& mutations, M
JSValue jsObserver = toJS(exec, globalObject, observer);
MarkedArgumentBuffer args;
- args.append(jsArray(exec, globalObject, mutations));
+ args.append(toJS<IDLSequence<IDLInterface<MutationRecord>>>(*exec, *globalObject, mutations));
args.append(jsObserver);
InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(context, callType, callData);
- JSMainThreadExecState::call(exec, callback, callType, callData, jsObserver, args);
+ NakedPtr<JSC::Exception> exception;
+ JSMainThreadExecState::profiledCall(exec, JSC::ProfilingReason::Other, callback, callType, callData, jsObserver, args, exception);
- InspectorInstrumentation::didCallFunction(cookie);
+ InspectorInstrumentation::didCallFunction(cookie, context);
- if (exec->hadException())
- reportCurrentException(exec);
+ if (exception)
+ reportException(exec, exception);
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSMutationCallback.h b/Source/WebCore/bindings/js/JSMutationCallback.h
index d7bd8483b..427d6243a 100644
--- a/Source/WebCore/bindings/js/JSMutationCallback.h
+++ b/Source/WebCore/bindings/js/JSMutationCallback.h
@@ -23,8 +23,7 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSMutationCallback_h
-#define JSMutationCallback_h
+#pragma once
#include "ActiveDOMCallback.h"
#include "DOMWrapperWorld.h"
@@ -37,18 +36,17 @@ namespace WebCore {
class JSDOMGlobalObject;
-class JSMutationCallback : public MutationCallback, public ActiveDOMCallback {
+class JSMutationCallback final : public MutationCallback, public ActiveDOMCallback {
public:
- static PassRefPtr<JSMutationCallback> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)
+ static Ref<JSMutationCallback> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)
{
- return adoptRef(new JSMutationCallback(callback, globalObject));
+ return adoptRef(*new JSMutationCallback(callback, globalObject));
}
virtual ~JSMutationCallback();
- virtual void call(const Vector<RefPtr<MutationRecord>>&, MutationObserver*) override;
-
- virtual ScriptExecutionContext* scriptExecutionContext() const override { return ContextDestructionObserver::scriptExecutionContext(); }
+ void call(const Vector<Ref<MutationRecord>>&, MutationObserver*) override;
+ bool canInvokeCallback() const override { return ActiveDOMCallback::canInvokeCallback(); }
private:
JSMutationCallback(JSC::JSObject* callback, JSDOMGlobalObject*);
@@ -58,5 +56,3 @@ private:
};
} // namespace WebCore
-
-#endif
diff --git a/Source/WebCore/bindings/js/JSMutationObserverCustom.cpp b/Source/WebCore/bindings/js/JSMutationObserverCustom.cpp
index 09760945e..33c5509ae 100644
--- a/Source/WebCore/bindings/js/JSMutationObserverCustom.cpp
+++ b/Source/WebCore/bindings/js/JSMutationObserverCustom.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2011 Google Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
@@ -29,10 +30,10 @@
*/
#include "config.h"
-
#include "JSMutationObserver.h"
#include "ExceptionCode.h"
+#include "JSDOMConstructorBase.h"
#include "JSMutationCallback.h"
#include "JSNodeCustom.h"
#include "MutationObserver.h"
@@ -43,30 +44,31 @@ using namespace JSC;
namespace WebCore {
-EncodedJSValue JSC_HOST_CALL JSMutationObserverConstructor::constructJSMutationObserver(ExecState* exec)
+EncodedJSValue JSC_HOST_CALL constructJSMutationObserver(ExecState& exec)
{
- if (exec->argumentCount() < 1)
- return throwVMError(exec, createNotEnoughArgumentsError(exec));
+ VM& vm = exec.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (exec.argumentCount() < 1)
+ return throwVMError(&exec, scope, createNotEnoughArgumentsError(&exec));
- JSObject* object = exec->argument(0).getObject();
+ JSObject* object = exec.uncheckedArgument(0).getObject();
CallData callData;
- if (!object || object->methodTable()->getCallData(object, callData) == CallTypeNone)
- return throwVMError(exec, createTypeError(exec, "Callback argument must be a function"));
+ if (!object || object->methodTable()->getCallData(object, callData) == CallType::None)
+ return throwArgumentTypeError(exec, scope, 0, "callback", "MutationObserver", nullptr, "MutationCallback");
- JSMutationObserverConstructor* jsConstructor = jsCast<JSMutationObserverConstructor*>(exec->callee());
- RefPtr<JSMutationCallback> callback = JSMutationCallback::create(object, jsConstructor->globalObject());
- JSObject* jsObserver = asObject(toJS(exec, jsConstructor->globalObject(), MutationObserver::create(callback.release())));
+ auto* jsConstructor = jsCast<JSDOMConstructorBase*>(exec.jsCallee());
+ auto callback = JSMutationCallback::create(object, jsConstructor->globalObject());
+ JSObject* jsObserver = asObject(toJSNewlyCreated(&exec, jsConstructor->globalObject(), MutationObserver::create(WTFMove(callback))));
PrivateName propertyName;
- jsObserver->putDirect(jsConstructor->globalObject()->vm(), propertyName, object);
+ jsObserver->putDirect(vm, propertyName, object);
return JSValue::encode(jsObserver);
}
bool JSMutationObserverOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
{
- MutationObserver& observer = jsCast<JSMutationObserver*>(handle.get().asCell())->impl();
- auto observedNodes = observer.getObservedNodes();
- for (auto it = observedNodes.begin(), end = observedNodes.end(); it != end; ++it) {
- if (visitor.containsOpaqueRoot(root(*it)))
+ for (auto* node : jsCast<JSMutationObserver*>(handle.slot()->asCell())->wrapped().observedNodes()) {
+ if (visitor.containsOpaqueRoot(root(node)))
return true;
}
return false;
diff --git a/Source/WebCore/bindings/js/JSNamedNodeMapCustom.cpp b/Source/WebCore/bindings/js/JSNamedNodeMapCustom.cpp
deleted file mode 100644
index 5e3c898fb..000000000
--- a/Source/WebCore/bindings/js/JSNamedNodeMapCustom.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2007, 2008, 2009, 2013 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "JSNamedNodeMap.h"
-
-#include "JSNode.h"
-
-#include "Element.h"
-#include "NamedNodeMap.h"
-
-using namespace JSC;
-
-namespace WebCore {
-
-bool JSNamedNodeMap::canGetItemsForName(ExecState*, NamedNodeMap* impl, PropertyName propertyName)
-{
- return impl->getNamedItem(propertyNameToAtomicString(propertyName));
-}
-
-EncodedJSValue JSNamedNodeMap::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName)
-{
- JSNamedNodeMap* thisObj = jsCast<JSNamedNodeMap*>(JSValue::decode(slotBase));
- return JSValue::encode(toJS(exec, thisObj->globalObject(), thisObj->impl().getNamedItem(propertyNameToAtomicString(propertyName))));
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSNodeCustom.cpp b/Source/WebCore/bindings/js/JSNodeCustom.cpp
index 3c2468cd8..32548720c 100644
--- a/Source/WebCore/bindings/js/JSNodeCustom.cpp
+++ b/Source/WebCore/bindings/js/JSNodeCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2007, 2009-2010, 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -32,8 +32,6 @@
#include "Document.h"
#include "DocumentFragment.h"
#include "DocumentType.h"
-#include "Entity.h"
-#include "EntityReference.h"
#include "ExceptionCode.h"
#include "HTMLAudioElement.h"
#include "HTMLCanvasElement.h"
@@ -51,29 +49,22 @@
#include "JSDocument.h"
#include "JSDocumentFragment.h"
#include "JSDocumentType.h"
-#include "JSEntity.h"
-#include "JSEntityReference.h"
#include "JSEventListener.h"
#include "JSHTMLElement.h"
#include "JSHTMLElementWrapperFactory.h"
-#include "JSNotation.h"
#include "JSProcessingInstruction.h"
+#include "JSSVGElementWrapperFactory.h"
+#include "JSShadowRoot.h"
#include "JSText.h"
#include "Node.h"
-#include "Notation.h"
#include "ProcessingInstruction.h"
#include "RegisteredEventListener.h"
+#include "SVGElement.h"
+#include "ScriptState.h"
#include "ShadowRoot.h"
#include "StyleSheet.h"
#include "StyledElement.h"
#include "Text.h"
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefPtr.h>
-
-#if ENABLE(SVG)
-#include "JSSVGElementWrapperFactory.h"
-#include "SVGElement.h"
-#endif
using namespace JSC;
@@ -81,40 +72,28 @@ namespace WebCore {
using namespace HTMLNames;
-static inline bool isObservable(JSNode* jsNode, Node* node)
+static inline bool isReachableFromDOM(Node* node, SlotVisitor& visitor)
{
- // The root node keeps the tree intact.
- if (!node->parentNode())
- return true;
-
- if (jsNode->hasCustomProperties())
- return true;
-
- // A node's JS wrapper is responsible for marking its JS event listeners.
- if (node->hasEventListeners())
- return true;
-
- return false;
-}
+ if (!node->isConnected()) {
+ if (is<Element>(*node)) {
+ auto& element = downcast<Element>(*node);
-static inline bool isReachableFromDOM(JSNode* jsNode, Node* node, SlotVisitor& visitor)
-{
- if (!node->inDocument()) {
- // If a wrapper is the last reference to an image element
- // that is loading but not in the document, the wrapper is observable
- // because it is the only thing keeping the image element alive, and if
- // the element is destroyed, its load event will not fire.
- // FIXME: The DOM should manage this issue without the help of JavaScript wrappers.
- if (isHTMLImageElement(node)) {
- if (toHTMLImageElement(node)->hasPendingActivity())
- return true;
- }
- #if ENABLE(VIDEO)
- else if (isHTMLAudioElement(node)) {
- if (!toHTMLAudioElement(node)->paused())
- return true;
+ // If a wrapper is the last reference to an image element
+ // that is loading but not in the document, the wrapper is observable
+ // because it is the only thing keeping the image element alive, and if
+ // the element is destroyed, its load event will not fire.
+ // FIXME: The DOM should manage this issue without the help of JavaScript wrappers.
+ if (is<HTMLImageElement>(element)) {
+ if (downcast<HTMLImageElement>(element).hasPendingActivity())
+ return true;
+ }
+#if ENABLE(VIDEO)
+ else if (is<HTMLAudioElement>(element)) {
+ if (!downcast<HTMLAudioElement>(element).paused())
+ return true;
+ }
+#endif
}
- #endif
// If a node is firing event listeners, its wrapper is observable because
// its wrapper is responsible for marking those event listeners.
@@ -122,144 +101,155 @@ static inline bool isReachableFromDOM(JSNode* jsNode, Node* node, SlotVisitor& v
return true;
}
- return isObservable(jsNode, node) && visitor.containsOpaqueRoot(root(node));
+ return visitor.containsOpaqueRoot(root(node));
}
bool JSNodeOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
{
- JSNode* jsNode = jsCast<JSNode*>(handle.get().asCell());
- return isReachableFromDOM(jsNode, &jsNode->impl(), visitor);
+ JSNode* jsNode = jsCast<JSNode*>(handle.slot()->asCell());
+ return isReachableFromDOM(&jsNode->wrapped(), visitor);
}
-JSValue JSNode::insertBefore(ExecState* exec)
+JSValue JSNode::insertBefore(ExecState& state)
{
- ExceptionCode ec = 0;
- bool ok = impl().insertBefore(toNode(exec->argument(0)), toNode(exec->argument(1)), ec);
- setDOMException(exec, ec);
- if (ok)
- return exec->argument(0);
- return jsNull();
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (UNLIKELY(state.argumentCount() < 2))
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+
+ JSValue newChildValue = state.uncheckedArgument(0);
+ auto* newChild = JSNode::toWrapped(vm, newChildValue);
+ if (UNLIKELY(!newChild))
+ return JSValue::decode(throwArgumentTypeError(state, scope, 0, "node", "Node", "insertBefore", "Node"));
+
+ propagateException(state, scope, wrapped().insertBefore(*newChild, JSNode::toWrapped(vm, state.uncheckedArgument(1))));
+ return newChildValue;
}
-JSValue JSNode::replaceChild(ExecState* exec)
+JSValue JSNode::replaceChild(ExecState& state)
{
- ExceptionCode ec = 0;
- bool ok = impl().replaceChild(toNode(exec->argument(0)), toNode(exec->argument(1)), ec);
- setDOMException(exec, ec);
- if (ok)
- return exec->argument(1);
- return jsNull();
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (UNLIKELY(state.argumentCount() < 2))
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+
+ auto* newChild = JSNode::toWrapped(vm, state.uncheckedArgument(0));
+ JSValue oldChildValue = state.uncheckedArgument(1);
+ auto* oldChild = JSNode::toWrapped(vm, oldChildValue);
+ if (UNLIKELY(!newChild || !oldChild)) {
+ if (!newChild)
+ return JSValue::decode(throwArgumentTypeError(state, scope, 0, "node", "Node", "replaceChild", "Node"));
+ return JSValue::decode(throwArgumentTypeError(state, scope, 1, "child", "Node", "replaceChild", "Node"));
+ }
+
+ propagateException(state, scope, wrapped().replaceChild(*newChild, *oldChild));
+ return oldChildValue;
}
-JSValue JSNode::removeChild(ExecState* exec)
+JSValue JSNode::removeChild(ExecState& state)
{
- ExceptionCode ec = 0;
- bool ok = impl().removeChild(toNode(exec->argument(0)), ec);
- setDOMException(exec, ec);
- if (ok)
- return exec->argument(0);
- return jsNull();
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ JSValue childValue = state.argument(0);
+ auto* child = JSNode::toWrapped(vm, childValue);
+ if (UNLIKELY(!child))
+ return JSValue::decode(throwArgumentTypeError(state, scope, 0, "child", "Node", "removeChild", "Node"));
+
+ propagateException(state, scope, wrapped().removeChild(*child));
+ return childValue;
}
-JSValue JSNode::appendChild(ExecState* exec)
+JSValue JSNode::appendChild(ExecState& state)
{
- ExceptionCode ec = 0;
- bool ok = impl().appendChild(toNode(exec->argument(0)), ec);
- setDOMException(exec, ec);
- if (ok)
- return exec->argument(0);
- return jsNull();
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ JSValue newChildValue = state.argument(0);
+ auto newChild = JSNode::toWrapped(vm, newChildValue);
+ if (UNLIKELY(!newChild))
+ return JSValue::decode(throwArgumentTypeError(state, scope, 0, "node", "Node", "appendChild", "Node"));
+
+ propagateException(state, scope, wrapped().appendChild(*newChild));
+ return newChildValue;
}
JSScope* JSNode::pushEventHandlerScope(ExecState* exec, JSScope* node) const
{
- if (inherits(JSHTMLElement::info()))
+ if (inherits(exec->vm(), JSHTMLElement::info()))
return jsCast<const JSHTMLElement*>(this)->pushEventHandlerScope(exec, node);
return node;
}
-void JSNode::visitChildren(JSCell* cell, SlotVisitor& visitor)
+void JSNode::visitAdditionalChildren(SlotVisitor& visitor)
{
- JSNode* thisObject = jsCast<JSNode*>(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(thisObject, visitor);
-
- Node& node = thisObject->impl();
- node.visitJSEventListeners(visitor);
-
- visitor.addOpaqueRoot(root(node));
+ visitor.addOpaqueRoot(root(wrapped()));
}
-static ALWAYS_INLINE JSValue createWrapperInline(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node)
+static ALWAYS_INLINE JSValue createWrapperInline(ExecState* exec, JSDOMGlobalObject* globalObject, Ref<Node>&& node)
{
- ASSERT(node);
- ASSERT(!getCachedWrapper(currentWorld(exec), node));
+ ASSERT(!getCachedWrapper(globalObject->world(), node));
- JSDOMWrapper* wrapper;
+ JSDOMObject* wrapper;
switch (node->nodeType()) {
case Node::ELEMENT_NODE:
- if (node->isHTMLElement())
- wrapper = createJSHTMLWrapper(exec, globalObject, toHTMLElement(node));
-#if ENABLE(SVG)
- else if (node->isSVGElement())
- wrapper = createJSSVGWrapper(exec, globalObject, toSVGElement(node));
-#endif
+ if (is<HTMLElement>(node.get()))
+ wrapper = createJSHTMLWrapper(globalObject, static_reference_cast<HTMLElement>(WTFMove(node)));
+ else if (is<SVGElement>(node.get()))
+ wrapper = createJSSVGWrapper(globalObject, static_reference_cast<SVGElement>(WTFMove(node)));
else
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, Element, node);
+ wrapper = createWrapper<Element>(globalObject, WTFMove(node));
break;
case Node::ATTRIBUTE_NODE:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, Attr, node);
+ wrapper = createWrapper<Attr>(globalObject, WTFMove(node));
break;
case Node::TEXT_NODE:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, Text, node);
+ wrapper = createWrapper<Text>(globalObject, WTFMove(node));
break;
case Node::CDATA_SECTION_NODE:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CDATASection, node);
- break;
- case Node::ENTITY_NODE:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, Entity, node);
+ wrapper = createWrapper<CDATASection>(globalObject, WTFMove(node));
break;
case Node::PROCESSING_INSTRUCTION_NODE:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, ProcessingInstruction, node);
+ wrapper = createWrapper<ProcessingInstruction>(globalObject, WTFMove(node));
break;
case Node::COMMENT_NODE:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, Comment, node);
+ wrapper = createWrapper<Comment>(globalObject, WTFMove(node));
break;
case Node::DOCUMENT_NODE:
// we don't want to cache the document itself in the per-document dictionary
- return toJS(exec, globalObject, toDocument(node));
+ return toJS(exec, globalObject, downcast<Document>(node.get()));
case Node::DOCUMENT_TYPE_NODE:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, DocumentType, node);
- break;
- case Node::NOTATION_NODE:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, Notation, node);
+ wrapper = createWrapper<DocumentType>(globalObject, WTFMove(node));
break;
case Node::DOCUMENT_FRAGMENT_NODE:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, DocumentFragment, node);
- break;
- case Node::ENTITY_REFERENCE_NODE:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, EntityReference, node);
+ if (node->isShadowRoot())
+ wrapper = createWrapper<ShadowRoot>(globalObject, WTFMove(node));
+ else
+ wrapper = createWrapper<DocumentFragment>(globalObject, WTFMove(node));
break;
default:
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, Node, node);
+ wrapper = createWrapper<Node>(globalObject, WTFMove(node));
}
- return wrapper;
+ return wrapper;
}
-JSValue createWrapper(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node)
+JSValue createWrapper(ExecState* exec, JSDOMGlobalObject* globalObject, Ref<Node>&& node)
{
- return createWrapperInline(exec, globalObject, node);
+ return createWrapperInline(exec, globalObject, WTFMove(node));
}
-JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, Node* node)
+JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, Ref<Node>&& node)
{
- if (!node)
- return jsNull();
-
- return createWrapperInline(exec, globalObject, node);
+ return createWrapperInline(exec, globalObject, WTFMove(node));
+}
+
+JSC::JSObject* getOutOfLineCachedWrapper(JSDOMGlobalObject* globalObject, Node& node)
+{
+ ASSERT(!globalObject->world().isNormal());
+ return globalObject->world().m_wrappers.get(&node);
}
void willCreatePossiblyOrphanedTreeByRemovalSlowCase(Node* root)
@@ -269,7 +259,7 @@ void willCreatePossiblyOrphanedTreeByRemovalSlowCase(Node* root)
return;
JSLockHolder lock(scriptState);
- toJS(scriptState, static_cast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject()), root);
+ toJS(scriptState, static_cast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject()), *root);
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSNodeCustom.h b/Source/WebCore/bindings/js/JSNodeCustom.h
index 2880274ed..6779dad32 100644
--- a/Source/WebCore/bindings/js/JSNodeCustom.h
+++ b/Source/WebCore/bindings/js/JSNodeCustom.h
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -23,26 +23,26 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSNodeCustom_h
-#define JSNodeCustom_h
+#pragma once
#include "JSDOMBinding.h"
#include "JSNode.h"
-#include "ScriptState.h"
#include "ShadowRoot.h"
namespace WebCore {
-JSC::JSValue createWrapper(JSC::ExecState*, JSDOMGlobalObject*, Node*);
+WEBCORE_EXPORT JSC::JSValue createWrapper(JSC::ExecState*, JSDOMGlobalObject*, Ref<Node>&&);
+WEBCORE_EXPORT JSC::JSObject* getOutOfLineCachedWrapper(JSDOMGlobalObject*, Node&);
-inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, Node* node)
+inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, Node& node)
{
- if (!node)
- return JSC::jsNull();
-
- JSNode* wrapper = JSC::jsCast<JSNode*>(getCachedWrapper(currentWorld(exec), node));
- if (wrapper)
- return wrapper;
+ if (LIKELY(globalObject->worldIsNormal())) {
+ if (auto* wrapper = node.wrapper())
+ return wrapper;
+ } else {
+ if (auto* wrapper = getOutOfLineCachedWrapper(globalObject, node))
+ return wrapper;
+ }
return createWrapper(exec, globalObject, node);
}
@@ -65,12 +65,7 @@ inline void willCreatePossiblyOrphanedTreeByRemoval(Node* root)
inline void* root(Node* node)
{
- if (node->inDocument())
- return &node->document();
-
- while (node->parentOrShadowHostNode())
- node = node->parentOrShadowHostNode();
- return node;
+ return node->opaqueRoot();
}
inline void* root(Node& node)
@@ -78,6 +73,15 @@ inline void* root(Node& node)
return root(&node);
}
-} // namespace WebCore
+template<typename From>
+ALWAYS_INLINE JSDynamicCastResult<JSNode, From> jsNodeCast(From* value)
+{
+ return value->type() >= JSNodeType ? JSC::jsCast<JSDynamicCastResult<JSNode, From>>(value) : nullptr;
+}
-#endif // JSDOMNodeCustom_h
+ALWAYS_INLINE JSC::JSValue JSNode::nodeType(JSC::ExecState&) const
+{
+ return JSC::jsNumber(static_cast<uint8_t>(type()) & JSNodeTypeMask);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSNodeFilterCondition.cpp b/Source/WebCore/bindings/js/JSNodeFilterCondition.cpp
deleted file mode 100644
index d1b472135..000000000
--- a/Source/WebCore/bindings/js/JSNodeFilterCondition.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "config.h"
-#include "JSNodeFilterCondition.h"
-
-#include "JSMainThreadExecState.h"
-#include "JSNode.h"
-#include "JSNodeFilter.h"
-#include "NodeFilter.h"
-#include <runtime/Error.h>
-#include <runtime/JSLock.h>
-
-namespace WebCore {
-
-using namespace JSC;
-
-JSNodeFilterCondition::JSNodeFilterCondition(VM&, NodeFilter* owner, JSValue filter)
- : m_filter(filter.isObject() ? Weak<JSObject>(jsCast<JSObject*>(filter), &m_weakOwner, owner) : nullptr)
-{
-}
-
-short JSNodeFilterCondition::acceptNode(JSC::ExecState* exec, Node* filterNode) const
-{
- JSLockHolder lock(exec);
-
- if (!m_filter)
- return NodeFilter::FILTER_ACCEPT;
-
- // Exec is null if we've been called from a non-JavaScript language and the document
- // is no longer able to run JavaScript (e.g., it's disconnected from its frame).
- if (!exec)
- return NodeFilter::FILTER_REJECT;
-
- JSValue filter = m_filter.get();
- CallData callData;
- CallType callType = getCallData(filter, callData);
- if (callType == CallTypeNone) {
- filter = filter.get(exec, Identifier(exec, "acceptNode"));
- callType = getCallData(filter, callData);
- if (callType == CallTypeNone) {
- exec->vm().throwException(exec, createTypeError(exec, "NodeFilter object does not have an acceptNode function"));
- return NodeFilter::FILTER_REJECT;
- }
- }
-
- MarkedArgumentBuffer args;
- // FIXME: The node should have the prototype chain that came from its document, not
- // whatever prototype chain might be on the window this filter came from. Bug 27662
- args.append(toJS(exec, deprecatedGlobalObjectForPrototype(exec), filterNode));
- if (exec->hadException())
- return NodeFilter::FILTER_REJECT;
-
- JSValue result = JSMainThreadExecState::call(exec, filter, callType, callData, m_filter.get(), args);
- if (exec->hadException())
- return NodeFilter::FILTER_REJECT;
-
- int intResult = result.toInt32(exec);
- if (exec->hadException())
- return NodeFilter::FILTER_REJECT;
-
- return intResult;
-}
-
-bool JSNodeFilterCondition::WeakOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, SlotVisitor& visitor)
-{
- return visitor.containsOpaqueRoot(context);
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSNodeFilterCondition.h b/Source/WebCore/bindings/js/JSNodeFilterCondition.h
deleted file mode 100644
index 3b175815a..000000000
--- a/Source/WebCore/bindings/js/JSNodeFilterCondition.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef JSNodeFilterCondition_h
-#define JSNodeFilterCondition_h
-
-#include "NodeFilterCondition.h"
-#include <heap/Weak.h>
-#include <heap/WeakInlines.h>
-#include <runtime/JSCJSValue.h>
-#include <runtime/Operations.h>
-#include <wtf/PassRefPtr.h>
-
-namespace WebCore {
-
- class Node;
- class NodeFilter;
-
- class JSNodeFilterCondition : public NodeFilterCondition {
- public:
- static PassRefPtr<JSNodeFilterCondition> create(JSC::VM& vm, NodeFilter* owner, JSC::JSValue filter)
- {
- return adoptRef(new JSNodeFilterCondition(vm, owner, filter));
- }
-
- private:
- JSNodeFilterCondition(JSC::VM&, NodeFilter* owner, JSC::JSValue filter);
-
- virtual short acceptNode(JSC::ExecState*, Node*) const;
-
- class WeakOwner : public JSC::WeakHandleOwner {
- virtual bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::SlotVisitor&);
- };
- WeakOwner m_weakOwner;
- mutable JSC::Weak<JSC::JSObject> m_filter;
- };
-
-} // namespace WebCore
-
-#endif // JSNodeFilterCondition_h
diff --git a/Source/WebCore/bindings/js/JSNodeFilterCustom.cpp b/Source/WebCore/bindings/js/JSNodeFilterCustom.cpp
index 877c98543..fd3089b53 100644
--- a/Source/WebCore/bindings/js/JSNodeFilterCustom.cpp
+++ b/Source/WebCore/bindings/js/JSNodeFilterCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,50 +10,61 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "JSNodeFilter.h"
-#include "JSDOMWindowBase.h"
+#include "JSCallbackData.h"
+#include "JSDOMConvert.h"
#include "JSNode.h"
-#include "JSNodeFilterCondition.h"
#include "NodeFilter.h"
-#include "JSDOMBinding.h"
-
-using namespace JSC;
namespace WebCore {
-void JSNodeFilter::visitChildren(JSCell* cell, SlotVisitor& visitor)
-{
- JSNodeFilter* thisObject = jsCast<JSNodeFilter*>(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(thisObject, visitor);
- visitor.addOpaqueRoot(&thisObject->impl());
-}
+using namespace JSC;
-PassRefPtr<NodeFilter> toNodeFilter(VM& vm, JSValue value)
+// FIXME: The bindings generator is currently not able to generate
+// callback function calls if they return something other than a
+// boolean.
+uint16_t JSNodeFilter::acceptNode(Node* node)
{
- if (value.inherits(JSNodeFilter::info()))
- return &jsCast<JSNodeFilter*>(asObject(value))->impl();
+ Ref<JSNodeFilter> protectedThis(*this);
+
+ VM& vm = m_data->globalObject()->vm();
+ JSLockHolder lock(vm);
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ ExecState* state = m_data->globalObject()->globalExec();
+ MarkedArgumentBuffer args;
+ args.append(toJS(state, m_data->globalObject(), node));
+ RETURN_IF_EXCEPTION(scope, NodeFilter::FILTER_REJECT);
+
+ NakedPtr<JSC::Exception> returnedException;
+ JSValue value = m_data->invokeCallback(args, JSCallbackData::CallbackType::FunctionOrObject, Identifier::fromString(state, "acceptNode"), returnedException);
+ ASSERT(!scope.exception() || returnedException);
+ if (returnedException) {
+ // Rethrow exception.
+ throwException(state, scope, returnedException);
+
+ return NodeFilter::FILTER_REJECT;
+ }
+
+ auto result = convert<IDLUnsignedShort>(*state, value, IntegerConversionConfiguration::Normal);
+ RETURN_IF_EXCEPTION(scope, NodeFilter::FILTER_REJECT);
- RefPtr<NodeFilter> result = NodeFilter::create();
- result->setCondition(JSNodeFilterCondition::create(vm, result.get(), value));
- return result.release();
+ return result;
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSNodeIteratorCustom.cpp b/Source/WebCore/bindings/js/JSNodeIteratorCustom.cpp
index 49cde01cc..b3f036139 100644
--- a/Source/WebCore/bindings/js/JSNodeIteratorCustom.cpp
+++ b/Source/WebCore/bindings/js/JSNodeIteratorCustom.cpp
@@ -20,24 +20,14 @@
#include "config.h"
#include "JSNodeIterator.h"
-#include "JSNode.h"
#include "Node.h"
-#include "NodeFilter.h"
-#include "NodeIterator.h"
-
-using namespace JSC;
+#include <heap/SlotVisitorInlines.h>
namespace WebCore {
-void JSNodeIterator::visitChildren(JSCell* cell, SlotVisitor& visitor)
+void JSNodeIterator::visitAdditionalChildren(JSC::SlotVisitor& visitor)
{
- JSNodeIterator* thisObject = jsCast<JSNodeIterator*>(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(thisObject, visitor);
-
- if (NodeFilter* filter = thisObject->m_impl->filter())
+ if (NodeFilter* filter = wrapped().filter())
visitor.addOpaqueRoot(filter);
}
diff --git a/Source/WebCore/bindings/js/JSNodeListCustom.cpp b/Source/WebCore/bindings/js/JSNodeListCustom.cpp
index a58d980ef..513bbdfda 100644
--- a/Source/WebCore/bindings/js/JSNodeListCustom.cpp
+++ b/Source/WebCore/bindings/js/JSNodeListCustom.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -39,25 +39,29 @@ namespace WebCore {
bool JSNodeListOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
{
- JSNodeList* jsNodeList = jsCast<JSNodeList*>(handle.get().asCell());
+ JSNodeList* jsNodeList = jsCast<JSNodeList*>(handle.slot()->asCell());
if (!jsNodeList->hasCustomProperties())
return false;
- if (jsNodeList->impl().isLiveNodeList())
- return visitor.containsOpaqueRoot(root(static_cast<LiveNodeList&>(jsNodeList->impl()).ownerNode()));
- if (jsNodeList->impl().isChildNodeList())
- return visitor.containsOpaqueRoot(root(static_cast<ChildNodeList&>(jsNodeList->impl()).ownerNode()));
- if (jsNodeList->impl().isEmptyNodeList())
- return visitor.containsOpaqueRoot(root(static_cast<EmptyNodeList&>(jsNodeList->impl()).ownerNode()));
+ if (jsNodeList->wrapped().isLiveNodeList())
+ return visitor.containsOpaqueRoot(root(static_cast<LiveNodeList&>(jsNodeList->wrapped()).ownerNode()));
+ if (jsNodeList->wrapped().isChildNodeList())
+ return visitor.containsOpaqueRoot(root(static_cast<ChildNodeList&>(jsNodeList->wrapped()).ownerNode()));
+ if (jsNodeList->wrapped().isEmptyNodeList())
+ return visitor.containsOpaqueRoot(root(static_cast<EmptyNodeList&>(jsNodeList->wrapped()).ownerNode()));
return false;
}
-bool JSNodeList::getOwnPropertySlotDelegate(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
+JSC::JSValue createWrapper(JSDOMGlobalObject& globalObject, Ref<NodeList>&& nodeList)
{
- if (Node* item = impl().namedItem(propertyNameToAtomicString(propertyName))) {
- slot.setValue(this, ReadOnly | DontDelete | DontEnum, toJS(exec, globalObject(), item));
- return true;
- }
- return false;
+ // FIXME: Adopt reportExtraMemoryVisited, and switch to reportExtraMemoryAllocated.
+ // https://bugs.webkit.org/show_bug.cgi?id=142595
+ globalObject.vm().heap.deprecatedReportExtraMemory(nodeList->memoryCost());
+ return createWrapper<NodeList>(&globalObject, WTFMove(nodeList));
+}
+
+JSC::JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<NodeList>&& nodeList)
+{
+ return createWrapper(*globalObject, WTFMove(nodeList));
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSNodeListCustom.h b/Source/WebCore/bindings/js/JSNodeListCustom.h
new file mode 100644
index 000000000..845bb409a
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSNodeListCustom.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "JSDOMBinding.h"
+#include "JSNodeList.h"
+
+namespace WebCore {
+
+WEBCORE_EXPORT JSC::JSValue createWrapper(JSDOMGlobalObject&, Ref<NodeList>&&);
+
+ALWAYS_INLINE JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject* globalObject, NodeList& nodeList)
+{
+ if (auto wrapper = getCachedWrapper(globalObject->world(), nodeList))
+ return wrapper;
+ return createWrapper(*globalObject, nodeList);
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSOscillatorNodeCustom.cpp b/Source/WebCore/bindings/js/JSOscillatorNodeCustom.cpp
deleted file mode 100644
index f44625c0f..000000000
--- a/Source/WebCore/bindings/js/JSOscillatorNodeCustom.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (C) 2012, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(WEB_AUDIO)
-
-#include "JSOscillatorNode.h"
-
-#include "ExceptionCode.h"
-#include "OscillatorNode.h"
-#include <runtime/Error.h>
-
-using namespace JSC;
-
-namespace WebCore {
-
-void JSOscillatorNode::setType(ExecState* exec, JSValue value)
-{
- OscillatorNode& imp = impl();
-
-#if ENABLE(LEGACY_WEB_AUDIO)
- if (value.isNumber()) {
- uint32_t type = value.toUInt32(exec);
- if (!imp.setType(type))
- exec->vm().throwException(exec, createTypeError(exec, "Illegal OscillatorNode type"));
- return;
- }
-#endif
-
- if (value.isString()) {
- String type = value.toString(exec)->value(exec);
- if (type == "sine" || type == "square" || type == "sawtooth" || type == "triangle") {
- imp.setType(type);
- return;
- }
- }
-
- exec->vm().throwException(exec, createTypeError(exec, "Illegal OscillatorNode type"));
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/bindings/js/JSPannerNodeCustom.cpp b/Source/WebCore/bindings/js/JSPannerNodeCustom.cpp
deleted file mode 100644
index f28978520..000000000
--- a/Source/WebCore/bindings/js/JSPannerNodeCustom.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2012, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(WEB_AUDIO)
-
-#include "JSPannerNode.h"
-
-#include "ExceptionCode.h"
-#include "PannerNode.h"
-#include <runtime/Error.h>
-
-using namespace JSC;
-
-namespace WebCore {
-
-void JSPannerNode::setPanningModel(ExecState* exec, JSValue value)
-{
- PannerNode& imp = impl();
-
-#if ENABLE(LEGACY_WEB_AUDIO)
- if (value.isNumber()) {
- uint32_t model = value.toUInt32(exec);
- if (!imp.setPanningModel(model))
- exec->vm().throwException(exec, createTypeError(exec, "Illegal panningModel"));
- return;
- }
-#endif
-
- if (value.isString()) {
- String model = value.toString(exec)->value(exec);
- if (model == "equalpower" || model == "HRTF" || model == "soundfield") {
- imp.setPanningModel(model);
- return;
- }
- }
-
- exec->vm().throwException(exec, createTypeError(exec, "Illegal panningModel"));
-}
-
-void JSPannerNode::setDistanceModel(ExecState* exec, JSValue value)
-{
- PannerNode& imp = impl();
-
-#if ENABLE(LEGACY_WEB_AUDIO)
- if (value.isNumber()) {
- uint32_t model = value.toUInt32(exec);
- if (!imp.setDistanceModel(model))
- exec->vm().throwException(exec, createTypeError(exec, "Illegal distanceModel"));
- return;
- }
-#endif
-
- if (value.isString()) {
- String model = value.toString(exec)->value(exec);
- if (model == "linear" || model == "inverse" || model == "exponential") {
- imp.setDistanceModel(model);
- return;
- }
- }
-
- exec->vm().throwException(exec, createTypeError(exec, "Illegal distanceModel"));
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(WEB_AUDIO)
diff --git a/Source/WebCore/bindings/js/JSPerformanceEntryCustom.cpp b/Source/WebCore/bindings/js/JSPerformanceEntryCustom.cpp
index 0b6f98ce1..471897834 100644
--- a/Source/WebCore/bindings/js/JSPerformanceEntryCustom.cpp
+++ b/Source/WebCore/bindings/js/JSPerformanceEntryCustom.cpp
@@ -30,7 +30,7 @@
#include "config.h"
-#if ENABLE(PERFORMANCE_TIMELINE)
+#if ENABLE(WEB_TIMING)
#include "JSPerformanceEntry.h"
@@ -46,27 +46,25 @@ using namespace JSC;
namespace WebCore {
-JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, PerformanceEntry* entry)
+JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<PerformanceEntry>&& entry)
{
- if (!entry)
- return jsNull();
+ if (is<PerformanceResourceTiming>(entry))
+ return createWrapper<PerformanceResourceTiming>(globalObject, WTFMove(entry));
-#if ENABLE(RESOURCE_TIMING)
- if (entry->isResource())
- return wrap<JSPerformanceResourceTiming>(exec, globalObject, static_cast<PerformanceResourceTiming*>(entry));
-#endif
+ if (is<PerformanceMark>(entry))
+ return createWrapper<PerformanceMark>(globalObject, WTFMove(entry));
-#if ENABLE(USER_TIMING)
- if (entry->isMark())
- return wrap<JSPerformanceMark>(exec, globalObject, static_cast<PerformanceMark*>(entry));
+ if (is<PerformanceMeasure>(entry))
+ return createWrapper<PerformanceMeasure>(globalObject, WTFMove(entry));
- if (entry->isMeasure())
- return wrap<JSPerformanceMeasure>(exec, globalObject, static_cast<PerformanceMeasure*>(entry));
-#endif
+ return createWrapper<PerformanceEntry>(globalObject, WTFMove(entry));
+}
- return wrap<JSPerformanceEntry>(exec, globalObject, entry);
+JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, PerformanceEntry& entry)
+{
+ return wrap(state, globalObject, entry);
}
} // namespace WebCore
-#endif // ENABLE(PERFORMANCE_TIMELINE)
+#endif // ENABLE(WEB_TIMING)
diff --git a/Source/WebCore/bindings/js/JSPluginElementFunctions.cpp b/Source/WebCore/bindings/js/JSPluginElementFunctions.cpp
index 7f62aa2a7..88b5b123a 100644
--- a/Source/WebCore/bindings/js/JSPluginElementFunctions.cpp
+++ b/Source/WebCore/bindings/js/JSPluginElementFunctions.cpp
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999-2000 Harri Porten (porten@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2004-2017 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -35,77 +35,73 @@ using namespace HTMLNames;
// JavaScript access to plug-in-exported properties for JSHTMLAppletElement, JSHTMLEmbedElement and JSHTMLObjectElement.
-static inline bool isPluginElement(HTMLElement& element)
-{
- return element.hasTagName(objectTag) || element.hasTagName(embedTag) || element.hasTagName(appletTag);
-}
-
Instance* pluginInstance(HTMLElement& element)
{
// The plugin element holds an owning reference, so we don't have to.
- if (!isPluginElement(element))
- return 0;
- Instance* instance = toHTMLPlugInElement(element).getInstance().get();
+ if (!is<HTMLPlugInElement>(element))
+ return nullptr;
+ auto* instance = downcast<HTMLPlugInElement>(element).bindingsInstance();
if (!instance || !instance->rootObject())
- return 0;
+ return nullptr;
return instance;
}
static JSObject* pluginScriptObjectFromPluginViewBase(HTMLPlugInElement& pluginElement, JSGlobalObject* globalObject)
{
Widget* pluginWidget = pluginElement.pluginWidget();
- if (!pluginWidget)
- return 0;
-
- if (!pluginWidget->isPluginViewBase())
- return 0;
+ if (!is<PluginViewBase>(pluginWidget))
+ return nullptr;
- PluginViewBase* pluginViewBase = toPluginViewBase(pluginWidget);
- return pluginViewBase->scriptObject(globalObject);
+ return downcast<PluginViewBase>(*pluginWidget).scriptObject(globalObject);
}
static JSObject* pluginScriptObjectFromPluginViewBase(JSHTMLElement* jsHTMLElement)
{
- HTMLElement& element = jsHTMLElement->impl();
- if (!isPluginElement(element))
- return 0;
+ HTMLElement& element = jsHTMLElement->wrapped();
+ if (!is<HTMLPlugInElement>(element))
+ return nullptr;
- HTMLPlugInElement& pluginElement = toHTMLPlugInElement(element);
+ HTMLPlugInElement& pluginElement = downcast<HTMLPlugInElement>(element);
return pluginScriptObjectFromPluginViewBase(pluginElement, jsHTMLElement->globalObject());
}
JSObject* pluginScriptObject(ExecState* exec, JSHTMLElement* jsHTMLElement)
{
- HTMLElement& element = jsHTMLElement->impl();
- if (!isPluginElement(element))
- return 0;
+ HTMLElement& element = jsHTMLElement->wrapped();
+ if (!is<HTMLPlugInElement>(element))
+ return nullptr;
+
+ auto& pluginElement = downcast<HTMLPlugInElement>(element);
- HTMLPlugInElement& pluginElement = toHTMLPlugInElement(element);
+ // Choke point for script/plugin interaction; notify DOMTimer of the event.
+ DOMTimer::scriptDidInteractWithPlugin(pluginElement);
// First, see if the element has a plug-in replacement with a script.
- if (JSObject* scriptObject = pluginElement.scriptObjectForPluginReplacement())
+ if (auto* scriptObject = pluginElement.scriptObjectForPluginReplacement())
return scriptObject;
// Next, see if we can ask the plug-in view for its script object.
- if (JSObject* scriptObject = pluginScriptObjectFromPluginViewBase(pluginElement, jsHTMLElement->globalObject()))
+ if (auto* scriptObject = pluginScriptObjectFromPluginViewBase(pluginElement, jsHTMLElement->globalObject()))
return scriptObject;
// Otherwise, fall back to getting the object from the instance.
// The plugin element holds an owning reference, so we don't have to.
- Instance* instance = pluginElement.getInstance().get();
+ auto* instance = pluginElement.bindingsInstance();
if (!instance || !instance->rootObject())
- return 0;
+ return nullptr;
return instance->createRuntimeObject(exec);
}
-EncodedJSValue pluginElementPropertyGetter(ExecState* exec, EncodedJSValue, EncodedJSValue thisValue, PropertyName propertyName)
+EncodedJSValue pluginElementPropertyGetter(ExecState* exec, EncodedJSValue thisValue, PropertyName propertyName)
{
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
- JSHTMLElement* thisObject = jsDynamicCast<JSHTMLElement*>(JSValue::decode(thisValue));
+ JSHTMLElement* thisObject = jsDynamicDowncast<JSHTMLElement*>(vm, JSValue::decode(thisValue));
if (!thisObject)
- return throwVMTypeError(exec);
+ return throwVMTypeError(exec, scope);
JSObject* scriptObject = pluginScriptObject(exec, thisObject);
if (!scriptObject)
return JSValue::encode(jsUndefined());
@@ -125,20 +121,20 @@ bool pluginElementCustomGetOwnPropertySlot(ExecState* exec, PropertyName propert
return true;
}
-bool pluginElementCustomPut(ExecState* exec, PropertyName propertyName, JSValue value, JSHTMLElement* element, PutPropertySlot& slot)
+bool pluginElementCustomPut(ExecState* exec, PropertyName propertyName, JSValue value, JSHTMLElement* element, PutPropertySlot& slot, bool& putResult)
{
JSObject* scriptObject = pluginScriptObject(exec, element);
if (!scriptObject)
- return 0;
+ return false;
if (!scriptObject->hasProperty(exec, propertyName))
return false;
- scriptObject->methodTable()->put(scriptObject, exec, propertyName, value, slot);
+ putResult = scriptObject->methodTable()->put(scriptObject, exec, propertyName, value, slot);
return true;
}
static EncodedJSValue JSC_HOST_CALL callPlugin(ExecState* exec)
{
- JSHTMLElement* element = jsCast<JSHTMLElement*>(exec->callee());
+ JSHTMLElement* element = jsCast<JSHTMLElement*>(exec->jsCallee());
// Get the plug-in script object.
JSObject* scriptObject = pluginScriptObject(exec, element);
@@ -151,10 +147,10 @@ static EncodedJSValue JSC_HOST_CALL callPlugin(ExecState* exec)
CallData callData;
CallType callType = getCallData(scriptObject, callData);
- ASSERT(callType == CallTypeHost);
+ ASSERT(callType == CallType::Host);
// Call the object.
- JSValue result = call(exec, scriptObject, callType, callData, exec->hostThisValue(), argumentList);
+ JSValue result = call(exec, scriptObject, callType, callData, exec->thisValue(), argumentList);
return JSValue::encode(result);
}
@@ -164,18 +160,18 @@ CallType pluginElementGetCallData(JSHTMLElement* element, CallData& callData)
if (JSObject* scriptObject = pluginScriptObjectFromPluginViewBase(element)) {
CallData scriptObjectCallData;
- if (scriptObject->methodTable()->getCallData(scriptObject, scriptObjectCallData) == CallTypeNone)
- return CallTypeNone;
+ if (scriptObject->methodTable()->getCallData(scriptObject, scriptObjectCallData) == CallType::None)
+ return CallType::None;
callData.native.function = callPlugin;
- return CallTypeHost;
+ return CallType::Host;
}
- Instance* instance = pluginInstance(element->impl());
+ Instance* instance = pluginInstance(element->wrapped());
if (!instance || !instance->supportsInvokeDefaultMethod())
- return CallTypeNone;
+ return CallType::None;
callData.native.function = callPlugin;
- return CallTypeHost;
+ return CallType::Host;
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSPluginElementFunctions.h b/Source/WebCore/bindings/js/JSPluginElementFunctions.h
index 8a2e99d59..f4f5f4ca9 100644
--- a/Source/WebCore/bindings/js/JSPluginElementFunctions.h
+++ b/Source/WebCore/bindings/js/JSPluginElementFunctions.h
@@ -17,8 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef JSPluginElementFunctions_h
-#define JSPluginElementFunctions_h
+#pragma once
#include "JSDOMBinding.h"
@@ -36,27 +35,22 @@ namespace WebCore {
// JavaScript access to plug-in-exported properties for JSHTMLAppletElement, JSHTMLEmbedElement and JSHTMLObjectElement.
JSC::Bindings::Instance* pluginInstance(HTMLElement&);
- JSC::JSObject* pluginScriptObject(JSC::ExecState*, JSHTMLElement*);
+ WEBCORE_EXPORT JSC::JSObject* pluginScriptObject(JSC::ExecState*, JSHTMLElement*);
- JSC::EncodedJSValue pluginElementPropertyGetter(JSC::ExecState*, JSC::EncodedJSValue, JSC::EncodedJSValue, JSC::PropertyName);
+ JSC::EncodedJSValue pluginElementPropertyGetter(JSC::ExecState*, JSC::EncodedJSValue, JSC::PropertyName);
bool pluginElementCustomGetOwnPropertySlot(JSC::ExecState*, JSC::PropertyName, JSC::PropertySlot&, JSHTMLElement*);
- bool pluginElementCustomPut(JSC::ExecState*, JSC::PropertyName, JSC::JSValue, JSHTMLElement*, JSC::PutPropertySlot&);
+ bool pluginElementCustomPut(JSC::ExecState*, JSC::PropertyName, JSC::JSValue, JSHTMLElement*, JSC::PutPropertySlot&, bool& putResult);
JSC::CallType pluginElementGetCallData(JSHTMLElement*, JSC::CallData&);
template <class Type, class Base> bool pluginElementCustomGetOwnPropertySlot(JSC::ExecState* exec, JSC::PropertyName propertyName, JSC::PropertySlot& slot, Type* element)
{
if (!element->globalObject()->world().isNormal()) {
- if (JSC::getStaticValueSlot<Type, Base>(exec, *Type::info()->staticPropHashTable, element, propertyName, slot))
- return true;
-
- JSC::JSValue proto = element->prototype();
+ JSC::JSValue proto = element->getPrototypeDirect();
if (proto.isObject() && JSC::jsCast<JSC::JSObject*>(asObject(proto))->hasProperty(exec, propertyName))
return false;
}
-
+
return pluginElementCustomGetOwnPropertySlot(exec, propertyName, slot, element);
}
} // namespace WebCore
-
-#endif // JSPluginElementFunctions_h
diff --git a/Source/WebCore/bindings/js/JSPopStateEventCustom.cpp b/Source/WebCore/bindings/js/JSPopStateEventCustom.cpp
index e4d46f792..aadb860a3 100644
--- a/Source/WebCore/bindings/js/JSPopStateEventCustom.cpp
+++ b/Source/WebCore/bindings/js/JSPopStateEventCustom.cpp
@@ -29,36 +29,51 @@
*/
#include "config.h"
+#include "JSPopStateEvent.h"
-#include "History.h"
+#include "DOMWrapperWorld.h"
#include "JSHistory.h"
-#include "JSPopStateEvent.h"
+#include <heap/HeapInlines.h>
+#include <runtime/JSCJSValueInlines.h>
using namespace JSC;
namespace WebCore {
// Save the state value to the m_state member of a JSPopStateEvent, and return it, for convenience.
-static const JSValue& cacheState(ExecState* exec, JSPopStateEvent* event, const JSValue& state)
+static const JSValue& cacheState(ExecState& state, const JSPopStateEvent* event, const JSValue& eventState)
{
- event->m_state.set(exec->vm(), event, state);
- return state;
+ event->m_state.set(state.vm(), event, eventState);
+ return eventState;
}
-JSValue JSPopStateEvent::state(ExecState* exec) const
+JSValue JSPopStateEvent::state(ExecState& state) const
{
JSValue cachedValue = m_state.get();
- if (!cachedValue.isEmpty())
- return cachedValue;
-
- PopStateEvent& event = impl();
+ if (!cachedValue.isEmpty()) {
+ // We cannot use a cached object if we are in a different world than the one it was created in.
+ if (!cachedValue.isObject() || &worldForDOMObject(cachedValue.getObject()) == &currentWorld(&state))
+ return cachedValue;
+ ASSERT_NOT_REACHED();
+ }
- if (!event.state().hasNoValue())
- return cacheState(exec, const_cast<JSPopStateEvent*>(this), event.state().jsValue());
+ PopStateEvent& event = wrapped();
+ if (auto eventState = event.state()) {
+ // We need to make sure a PopStateEvent does not leak objects in its state property across isolated DOM worlds.
+ // Ideally, we would check that the worlds have different privileges but that's not possible yet.
+ if (eventState.isObject() && &worldForDOMObject(eventState.getObject()) != &currentWorld(&state)) {
+ if (auto serializedValue = event.trySerializeState(state))
+ eventState = serializedValue->deserialize(state, globalObject());
+ else
+ eventState = jsNull();
+ }
+ return cacheState(state, this, eventState);
+ }
+
History* history = event.history();
if (!history || !event.serializedState())
- return cacheState(exec, const_cast<JSPopStateEvent*>(this), jsNull());
+ return cacheState(state, this, jsNull());
// There's no cached value from a previous invocation, nor a state value was provided by the
// event, but there is a history object, so first we need to see if the state object has been
@@ -66,16 +81,16 @@ JSValue JSPopStateEvent::state(ExecState* exec) const
// The current history state object might've changed in the meantime, so we need to take care
// of using the correct one, and always share the same deserialization with history.state.
- bool isSameState = history->isSameAsCurrentState(event.serializedState().get());
+ bool isSameState = history->isSameAsCurrentState(event.serializedState());
JSValue result;
if (isSameState) {
- JSHistory* jsHistory = jsCast<JSHistory*>(toJS(exec, globalObject(), history).asCell());
- result = jsHistory->state(exec);
+ JSHistory* jsHistory = jsCast<JSHistory*>(toJS(&state, globalObject(), *history).asCell());
+ result = jsHistory->state(state);
} else
- result = event.serializedState()->deserialize(exec, globalObject(), 0);
+ result = event.serializedState()->deserialize(state, globalObject());
- return cacheState(exec, const_cast<JSPopStateEvent*>(this), result);
+ return cacheState(state, this, result);
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSRTCIceCandidateCustom.cpp b/Source/WebCore/bindings/js/JSRTCIceCandidateCustom.cpp
deleted file mode 100644
index 148ff1154..000000000
--- a/Source/WebCore/bindings/js/JSRTCIceCandidateCustom.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(MEDIA_STREAM)
-
-#include "JSRTCIceCandidate.h"
-
-#include "Dictionary.h"
-#include "ExceptionCode.h"
-
-using namespace JSC;
-
-namespace WebCore {
-
-EncodedJSValue JSC_HOST_CALL JSRTCIceCandidateConstructor::constructJSRTCIceCandidate(ExecState* exec)
-{
- ExceptionCode ec = 0;
- Dictionary sessionInit;
- if (exec->argumentCount() > 0) {
- sessionInit = Dictionary(exec, exec->argument(0));
- if (!sessionInit.isObject())
- return throwVMError(exec, createTypeError(exec, "Optional RTCIceCandidate constructor argument must be a valid Dictionary"));
-
- if (exec->hadException())
- return JSValue::encode(jsUndefined());
- }
-
- JSRTCIceCandidateConstructor* jsConstructor = jsCast<JSRTCIceCandidateConstructor*>(exec->callee());
- RefPtr<RTCIceCandidate> iceCandidate = RTCIceCandidate::create(sessionInit, ec);
- if (ec == TYPE_MISMATCH_ERR) {
- setDOMException(exec, ec);
- return throwVMError(exec, createTypeError(exec, "Invalid RTCIceCandidate constructor arguments"));
- }
-
- if (ec) {
- setDOMException(exec, ec);
- return throwVMError(exec, createTypeError(exec, "Error creating RTCIceCandidate"));
- }
-
- return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), RTCIceCandidate, iceCandidate.get()));
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(MEDIA_STREAM)
-
diff --git a/Source/WebCore/bindings/js/JSRTCPeerConnectionCustom.cpp b/Source/WebCore/bindings/js/JSRTCPeerConnectionCustom.cpp
deleted file mode 100644
index f24bec22a..000000000
--- a/Source/WebCore/bindings/js/JSRTCPeerConnectionCustom.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(MEDIA_STREAM)
-
-#include "JSRTCPeerConnection.h"
-
-#include "ExceptionCode.h"
-
-using namespace JSC;
-
-namespace WebCore {
-
-EncodedJSValue JSC_HOST_CALL JSRTCPeerConnectionConstructor::constructJSRTCPeerConnection(ExecState* exec)
-{
- // Spec says that we must have at least one arument, the RTCConfiguration.
- if (exec->argumentCount() < 1)
- return throwVMError(exec, createNotEnoughArgumentsError(exec));
-
- ExceptionCode ec = 0;
- Dictionary rtcConfiguration(exec, exec->argument(0));
- if (exec->hadException())
- return JSValue::encode(jsUndefined());
-
- if (!rtcConfiguration.isObject())
- return throwVMError(exec, createTypeError(exec, "First argument of RTCPeerConnection must be a valid Dictionary"));
-
- Dictionary mediaConstraints;
- if (exec->argumentCount() > 1) {
- mediaConstraints = Dictionary(exec, exec->argument(1));
- if (!mediaConstraints.isObject())
- return throwVMError(exec, createTypeError(exec, "Optional constraints argument of RTCPeerConnection must be a valid Dictionary"));
-
- if (exec->hadException())
- return JSValue::encode(jsUndefined());
- }
-
- JSRTCPeerConnectionConstructor* jsConstructor = jsCast<JSRTCPeerConnectionConstructor*>(exec->callee());
- ScriptExecutionContext* scriptExecutionContext = jsConstructor->scriptExecutionContext();
- if (!scriptExecutionContext)
- return throwVMError(exec, createReferenceError(exec, "RTCPeerConnection constructor associated document is unavailable"));
-
- RefPtr<RTCPeerConnection> peerConnection = RTCPeerConnection::create(*scriptExecutionContext, rtcConfiguration, mediaConstraints, ec);
- if (ec == TYPE_MISMATCH_ERR) {
- setDOMException(exec, ec);
- return throwVMError(exec, createTypeError(exec, "Invalid RTCPeerConnection constructor arguments"));
- }
-
- if (ec) {
- setDOMException(exec, ec);
- return throwVMError(exec, createTypeError(exec, "Error creating RTCPeerConnection"));
- }
-
- return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), RTCPeerConnection, peerConnection.get()));
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(MEDIA_STREAM)
diff --git a/Source/WebCore/bindings/js/JSRTCSessionDescriptionCustom.cpp b/Source/WebCore/bindings/js/JSRTCSessionDescriptionCustom.cpp
deleted file mode 100644
index ddf03f3e7..000000000
--- a/Source/WebCore/bindings/js/JSRTCSessionDescriptionCustom.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2013 Nokia Corporation and/or its subsidiary(-ies).
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(MEDIA_STREAM)
-
-#include "JSRTCSessionDescription.h"
-
-#include "Dictionary.h"
-#include "ExceptionCode.h"
-
-using namespace JSC;
-
-namespace WebCore {
-
-EncodedJSValue JSC_HOST_CALL JSRTCSessionDescriptionConstructor::constructJSRTCSessionDescription(ExecState* exec)
-{
- ExceptionCode ec = 0;
- Dictionary sessionInit;
- if (exec->argumentCount() > 0) {
- sessionInit = Dictionary(exec, exec->argument(0));
- if (!sessionInit.isObject())
- return throwVMError(exec, createTypeError(exec, "Optional RTCSessionDescription constructor argument must be a valid Dictionary"));
-
- if (exec->hadException())
- return JSValue::encode(jsUndefined());
- }
-
- JSRTCSessionDescriptionConstructor* jsConstructor = jsCast<JSRTCSessionDescriptionConstructor*>(exec->callee());
- RefPtr<RTCSessionDescription> sessionDescription = RTCSessionDescription::create(sessionInit, ec);
- if (ec == TYPE_MISMATCH_ERR) {
- setDOMException(exec, ec);
- return throwVMError(exec, createTypeError(exec, "Invalid RTCSessionDescription constructor arguments"));
- }
-
- if (ec) {
- setDOMException(exec, ec);
- return throwVMError(exec, createTypeError(exec, "Error creating RTCSessionDescription"));
- }
-
- return JSValue::encode(CREATE_DOM_WRAPPER(exec, jsConstructor->globalObject(), RTCSessionDescription, sessionDescription.get()));
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(MEDIA_STREAM)
-
diff --git a/Source/WebCore/bindings/js/JSReadableStreamPrivateConstructors.cpp b/Source/WebCore/bindings/js/JSReadableStreamPrivateConstructors.cpp
new file mode 100644
index 000000000..984cfc315
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSReadableStreamPrivateConstructors.cpp
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2015 Canon Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+#include "JSReadableStreamPrivateConstructors.h"
+
+#if ENABLE(READABLE_STREAM_API)
+
+#include "JSDOMBuiltinConstructor.h"
+#include "JSReadableByteStreamController.h"
+#include "JSReadableStream.h"
+#include "JSReadableStreamDefaultController.h"
+#include "JSReadableStreamDefaultReader.h"
+#include "ReadableByteStreamInternalsBuiltins.h"
+#include "ReadableStreamInternalsBuiltins.h"
+#include "WebCoreJSClientData.h"
+#include <runtime/JSCInlines.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+// Public JS ReadableStreamReader and ReadableStreamDefaultController constructor callbacks.
+EncodedJSValue JSC_HOST_CALL constructJSReadableStreamDefaultController(ExecState& exec)
+{
+ VM& vm = exec.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ return throwVMTypeError(&exec, scope, ASCIILiteral("ReadableStreamDefaultController constructor should not be called directly"));
+}
+
+#if ENABLE(READABLE_BYTE_STREAM_API)
+// Public JS ReadableByteStreamController constructor callback.
+EncodedJSValue JSC_HOST_CALL constructJSReadableByteStreamController(ExecState& exec)
+{
+ VM& vm = exec.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ return throwVMTypeError(&exec, scope, ASCIILiteral("ReadableByteStreamController constructor should not be called directly"));
+}
+#endif
+
+EncodedJSValue JSC_HOST_CALL constructJSReadableStreamDefaultReader(ExecState& exec)
+{
+ VM& vm = exec.vm();
+ JSVMClientData& clientData = *static_cast<JSVMClientData*>(vm.clientData);
+ JSDOMGlobalObject& globalObject = *static_cast<JSDOMGlobalObject*>(exec.lexicalGlobalObject());
+
+ JSC::JSObject* constructor = JSC::asObject(globalObject.get(&exec, clientData.builtinNames().ReadableStreamDefaultReaderPrivateName()));
+ ConstructData constructData;
+ ConstructType constructType = constructor->methodTable(vm)->getConstructData(constructor, constructData);
+ ASSERT(constructType != ConstructType::None);
+
+ MarkedArgumentBuffer args;
+ args.append(exec.argument(0));
+ return JSValue::encode(JSC::construct(&exec, constructor, constructType, constructData, args));
+}
+
+// Private JS ReadableStreamDefaultReader and ReadableStreamDefaultController constructors.
+using JSBuiltinReadableStreamDefaultReaderPrivateConstructor = JSDOMBuiltinConstructor<JSReadableStreamDefaultReader>;
+using JSBuiltinReadableStreamDefaultControllerPrivateConstructor = JSDOMBuiltinConstructor<JSReadableStreamDefaultController>;
+#if ENABLE(READABLE_BYTE_STREAM_API)
+// Private JS ReadableByteStreamController constructor.
+using JSBuiltinReadableByteStreamControllerPrivateConstructor = JSDOMBuiltinConstructor<JSReadableByteStreamController>;
+#endif
+
+STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSBuiltinReadableStreamDefaultReaderPrivateConstructor);
+STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSBuiltinReadableStreamDefaultControllerPrivateConstructor);
+#if ENABLE(READABLE_BYTE_STREAM_API)
+STATIC_ASSERT_IS_TRIVIALLY_DESTRUCTIBLE(JSBuiltinReadableByteStreamControllerPrivateConstructor);
+#endif
+
+template<> const ClassInfo JSBuiltinReadableStreamDefaultReaderPrivateConstructor::s_info = { "ReadableStreamDefaultReaderPrivateConstructor", &Base::s_info, 0, CREATE_METHOD_TABLE(JSBuiltinReadableStreamDefaultReaderPrivateConstructor) };
+template<> const ClassInfo JSBuiltinReadableStreamDefaultControllerPrivateConstructor::s_info = { "ReadableStreamDefaultControllerPrivateConstructor", &Base::s_info, 0, CREATE_METHOD_TABLE(JSBuiltinReadableStreamDefaultControllerPrivateConstructor) };
+#if ENABLE(READABLE_BYTE_STREAM_API)
+template<> const ClassInfo JSBuiltinReadableByteStreamControllerPrivateConstructor::s_info = { "ReadableByteStreamControllerPrivateConstructor", &Base::s_info, 0, CREATE_METHOD_TABLE(JSBuiltinReadableByteStreamControllerPrivateConstructor) };
+#endif
+
+template<> FunctionExecutable* JSBuiltinReadableStreamDefaultReaderPrivateConstructor::initializeExecutable(JSC::VM& vm)
+{
+ return readableStreamInternalsPrivateInitializeReadableStreamDefaultReaderCodeGenerator(vm);
+}
+
+template<> FunctionExecutable* JSBuiltinReadableStreamDefaultControllerPrivateConstructor::initializeExecutable(JSC::VM& vm)
+{
+ return readableStreamInternalsPrivateInitializeReadableStreamDefaultControllerCodeGenerator(vm);
+}
+
+#if ENABLE(READABLE_BYTE_STREAM_API)
+template<> FunctionExecutable* JSBuiltinReadableByteStreamControllerPrivateConstructor::initializeExecutable(JSC::VM& vm)
+{
+ return readableByteStreamInternalsPrivateInitializeReadableByteStreamControllerCodeGenerator(vm);
+}
+#endif
+
+JSObject* createReadableStreamDefaultReaderPrivateConstructor(VM& vm, JSDOMGlobalObject& globalObject)
+{
+ return JSBuiltinReadableStreamDefaultReaderPrivateConstructor::create(vm, JSBuiltinReadableStreamDefaultReaderPrivateConstructor::createStructure(vm, globalObject, globalObject.objectPrototype()), globalObject);
+}
+
+JSObject* createReadableStreamDefaultControllerPrivateConstructor(VM& vm, JSDOMGlobalObject& globalObject)
+{
+ return JSBuiltinReadableStreamDefaultControllerPrivateConstructor::create(vm, JSBuiltinReadableStreamDefaultControllerPrivateConstructor::createStructure(vm, globalObject, globalObject.objectPrototype()), globalObject);
+}
+
+#if ENABLE(READABLE_BYTE_STREAM_API)
+JSObject* createReadableByteStreamControllerPrivateConstructor(VM& vm, JSDOMGlobalObject& globalObject)
+{
+ return JSBuiltinReadableByteStreamControllerPrivateConstructor::create(vm, JSBuiltinReadableByteStreamControllerPrivateConstructor::createStructure(vm, globalObject, globalObject.objectPrototype()), globalObject);
+}
+#endif
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/bindings/js/JSDOMStringListCustom.cpp b/Source/WebCore/bindings/js/JSReadableStreamPrivateConstructors.h
index b73378d37..ac16afdef 100644
--- a/Source/WebCore/bindings/js/JSDOMStringListCustom.cpp
+++ b/Source/WebCore/bindings/js/JSReadableStreamPrivateConstructors.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012 Research In Motion Inc. All rights reserved.
+ * Copyright (C) 2015 Canon Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -16,27 +16,26 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "config.h"
-#include "JSDOMStringList.h"
+#pragma once
-using namespace JSC;
+#if ENABLE(READABLE_STREAM_API)
+
+namespace JSC {
+class JSObject;
+class VM;
+}
namespace WebCore {
-PassRefPtr<DOMStringList> toDOMStringList(ExecState* exec, JSValue value)
-{
- if (value.inherits(JSDOMStringList::info()))
- return &jsCast<JSDOMStringList*>(asObject(value))->impl();
+class JSDOMGlobalObject;
- if (!isJSArray(value))
- return 0;
+JSC::JSObject* createReadableStreamDefaultReaderPrivateConstructor(JSC::VM&, JSDOMGlobalObject&);
+JSC::JSObject* createReadableStreamDefaultControllerPrivateConstructor(JSC::VM&, JSDOMGlobalObject&);
- JSArray* array = asArray(value);
- RefPtr<DOMStringList> stringList = DOMStringList::create();
- for (unsigned i = 0; i < array->length(); ++i)
- stringList->append(array->getIndex(exec, i).toString(exec)->value(exec));
-
- return stringList.release();
-}
+#if ENABLE(READABLE_BYTE_STREAM_API)
+JSC::JSObject* createReadableByteStreamControllerPrivateConstructor(JSC::VM&, JSDOMGlobalObject&);
+#endif
} // namespace WebCore
+
+#endif // ENABLE(READABLE_STREAM_API)
diff --git a/Source/WebCore/bindings/js/JSReadableStreamSourceCustom.cpp b/Source/WebCore/bindings/js/JSReadableStreamSourceCustom.cpp
new file mode 100644
index 000000000..5cf0a8478
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSReadableStreamSourceCustom.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2016 Canon Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted, provided that the following conditions
+ * are required to be met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Canon Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSReadableStreamSource.h"
+
+#if ENABLE(READABLE_STREAM_API)
+
+using namespace JSC;
+
+namespace WebCore {
+
+static void startReadableStream(JSC::ExecState& state, Ref<DeferredPromise>&& promise)
+{
+ VM& vm = state.vm();
+ JSReadableStreamSource* source = jsDynamicDowncast<JSReadableStreamSource*>(vm, state.thisValue());
+ ASSERT(source);
+
+ ASSERT(state.argumentCount());
+ JSReadableStreamDefaultController* controller = jsDynamicDowncast<JSReadableStreamDefaultController*>(vm, state.uncheckedArgument(0));
+ ASSERT(controller);
+
+ source->wrapped().start(ReadableStreamDefaultController(controller), WTFMove(promise));
+}
+
+JSValue JSReadableStreamSource::start(ExecState& state)
+{
+ VM& vm = state.vm();
+ ASSERT(state.argumentCount());
+ JSReadableStreamDefaultController* controller = jsDynamicDowncast<JSReadableStreamDefaultController*>(vm, state.uncheckedArgument(0));
+ ASSERT(controller);
+
+ m_controller.set(vm, this, controller);
+
+ return callPromiseFunction<startReadableStream, PromiseExecutionScope::WindowOrWorker>(state);
+}
+
+static void pullReadableStream(JSC::ExecState& state, Ref<DeferredPromise>&& promise)
+{
+ VM& vm = state.vm();
+ JSReadableStreamSource* source = jsDynamicDowncast<JSReadableStreamSource*>(vm, state.thisValue());
+ ASSERT(source);
+
+ source->wrapped().pull(WTFMove(promise));
+}
+
+JSValue JSReadableStreamSource::pull(ExecState& state)
+{
+ return callPromiseFunction<pullReadableStream, PromiseExecutionScope::WindowOrWorker>(state);
+}
+
+JSValue JSReadableStreamSource::controller(ExecState&) const
+{
+ ASSERT_NOT_REACHED();
+ return jsUndefined();
+}
+
+}
+
+#endif // ENABLE(READABLE_STREAM_API)
diff --git a/Source/WebCore/bindings/js/JSSQLResultSetRowListCustom.cpp b/Source/WebCore/bindings/js/JSSQLResultSetRowListCustom.cpp
deleted file mode 100644
index c0b240d11..000000000
--- a/Source/WebCore/bindings/js/JSSQLResultSetRowListCustom.cpp
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(SQL_DATABASE)
-
-#include "JSSQLResultSetRowList.h"
-
-#include "ExceptionCode.h"
-#include "SQLValue.h"
-#include "SQLResultSetRowList.h"
-#include <runtime/ObjectConstructor.h>
-
-using namespace JSC;
-
-namespace WebCore {
-
-JSValue JSSQLResultSetRowList::item(ExecState* exec)
-{
- bool indexOk;
- int index = finiteInt32Value(exec->argument(0), exec, indexOk);
- if (!indexOk) {
- setDOMException(exec, TYPE_MISMATCH_ERR);
- return jsUndefined();
- }
- if (index < 0 || (unsigned)index >= m_impl->length()) {
- setDOMException(exec, INDEX_SIZE_ERR);
- return jsUndefined();
- }
-
- JSObject* object = constructEmptyObject(exec);
-
- unsigned numColumns = m_impl->columnNames().size();
- unsigned valuesIndex = index * numColumns;
- for (unsigned i = 0; i < numColumns; i++) {
- const SQLValue& value = m_impl->values()[valuesIndex + i];
- JSValue jsValue;
-
- switch (value.type()) {
- case SQLValue::StringValue:
- jsValue = jsStringWithCache(exec, value.string());
- break;
- case SQLValue::NullValue:
- jsValue = jsNull();
- break;
- case SQLValue::NumberValue:
- jsValue = jsNumber(value.number());
- break;
- default:
- ASSERT_NOT_REACHED();
- }
-
- object->putDirect(exec->vm(), Identifier(exec, m_impl->columnNames()[i]), jsValue, DontDelete | ReadOnly);
- }
-
- return object;
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(SQL_DATABASE)
diff --git a/Source/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp b/Source/WebCore/bindings/js/JSSQLStatementErrorCallbackCustom.cpp
index b4e315e6e..0030f0178 100644
--- a/Source/WebCore/bindings/js/JSCustomSQLStatementErrorCallback.cpp
+++ b/Source/WebCore/bindings/js/JSSQLStatementErrorCallbackCustom.cpp
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -27,14 +27,13 @@
*/
#include "config.h"
-
-#if ENABLE(SQL_DATABASE)
-
#include "JSSQLStatementErrorCallback.h"
+#include "JSDOMExceptionHandling.h"
#include "JSSQLError.h"
#include "JSSQLTransaction.h"
#include "ScriptExecutionContext.h"
+#include <runtime/Exception.h>
#include <runtime/JSLock.h>
#include <wtf/Ref.h>
@@ -47,7 +46,7 @@ bool JSSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, SQLEr
if (!m_data || !m_data->globalObject() || !canInvokeCallback())
return true;
- Ref<JSSQLStatementErrorCallback> protect(*this);
+ Ref<JSSQLStatementErrorCallback> protectedThis(*this);
JSC::JSLockHolder lock(m_data->globalObject()->vm());
@@ -56,9 +55,11 @@ bool JSSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, SQLEr
args.append(toJS(exec, m_data->globalObject(), transaction));
args.append(toJS(exec, m_data->globalObject(), error));
- bool raisedException = false;
- JSValue result = m_data->invokeCallback(args, &raisedException);
- if (raisedException) {
+ NakedPtr<JSC::Exception> returnedException;
+ JSValue result = m_data->invokeCallback(args, JSCallbackData::CallbackType::Function, Identifier(), returnedException);
+ if (returnedException) {
+ reportException(exec, returnedException);
+
// The spec says:
// "If the error callback returns false, then move on to the next statement..."
// "Otherwise, the error callback did not return false, or there was no error callback"
@@ -69,5 +70,3 @@ bool JSSQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, SQLEr
}
}
-
-#endif // ENABLE(SQL_DATABASE)
diff --git a/Source/WebCore/bindings/js/JSSQLTransactionCustom.cpp b/Source/WebCore/bindings/js/JSSQLTransactionCustom.cpp
deleted file mode 100644
index 7a90c43bf..000000000
--- a/Source/WebCore/bindings/js/JSSQLTransactionCustom.cpp
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(SQL_DATABASE)
-
-#include "JSSQLTransaction.h"
-
-#include "DOMWindow.h"
-#include "ExceptionCode.h"
-#include "JSSQLStatementCallback.h"
-#include "JSSQLStatementErrorCallback.h"
-#include "JSDOMWindowCustom.h"
-#include "SQLTransaction.h"
-
-using namespace JSC;
-
-namespace WebCore {
-
-JSValue JSSQLTransaction::executeSql(ExecState* exec)
-{
- if (!exec->argumentCount()) {
- setDOMException(exec, SYNTAX_ERR);
- return jsUndefined();
- }
-
- String sqlStatement = exec->argument(0).toString(exec)->value(exec);
- if (exec->hadException())
- return jsUndefined();
-
- // Now assemble the list of SQL arguments
- Vector<SQLValue> sqlValues;
- if (!exec->argument(1).isUndefinedOrNull()) {
- JSObject* object = exec->argument(1).getObject();
- if (!object) {
- setDOMException(exec, TYPE_MISMATCH_ERR);
- return jsUndefined();
- }
-
- JSValue lengthValue = object->get(exec, exec->propertyNames().length);
- if (exec->hadException())
- return jsUndefined();
- unsigned length = lengthValue.toUInt32(exec);
- if (exec->hadException())
- return jsUndefined();
-
- for (unsigned i = 0 ; i < length; ++i) {
- JSValue value = object->get(exec, i);
- if (exec->hadException())
- return jsUndefined();
-
- if (value.isUndefinedOrNull())
- sqlValues.append(SQLValue());
- else if (value.isNumber())
- sqlValues.append(value.asNumber());
- else {
- // Convert the argument to a string and append it
- sqlValues.append(value.toString(exec)->value(exec));
- if (exec->hadException())
- return jsUndefined();
- }
- }
- }
-
- RefPtr<SQLStatementCallback> callback;
- if (!exec->argument(2).isUndefinedOrNull()) {
- JSObject* object = exec->argument(2).getObject();
- if (!object) {
- setDOMException(exec, TYPE_MISMATCH_ERR);
- return jsUndefined();
- }
-
- callback = JSSQLStatementCallback::create(object, jsCast<JSDOMGlobalObject*>(globalObject()));
- }
-
- RefPtr<SQLStatementErrorCallback> errorCallback;
- if (!exec->argument(3).isUndefinedOrNull()) {
- JSObject* object = exec->argument(3).getObject();
- if (!object) {
- setDOMException(exec, TYPE_MISMATCH_ERR);
- return jsUndefined();
- }
-
- errorCallback = JSSQLStatementErrorCallback::create(object, jsCast<JSDOMGlobalObject*>(globalObject()));
- }
-
- ExceptionCode ec = 0;
- m_impl->executeSQL(sqlStatement, sqlValues, callback.release(), errorCallback.release(), ec);
- setDOMException(exec, ec);
-
- return jsUndefined();
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(SQL_DATABASE)
diff --git a/Source/WebCore/bindings/js/JSSQLTransactionSyncCustom.cpp b/Source/WebCore/bindings/js/JSSQLTransactionSyncCustom.cpp
deleted file mode 100644
index b682c451d..000000000
--- a/Source/WebCore/bindings/js/JSSQLTransactionSyncCustom.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(SQL_DATABASE)
-
-#include "JSSQLTransactionSync.h"
-
-#include "ExceptionCode.h"
-#include "JSSQLResultSet.h"
-#include "SQLResultSet.h"
-#include "SQLTransactionSync.h"
-#include "SQLValue.h"
-
-using namespace JSC;
-
-namespace WebCore {
-
-JSValue JSSQLTransactionSync::executeSql(ExecState* exec)
-{
- if (!exec->argumentCount()) {
- setDOMException(exec, SYNTAX_ERR);
- return jsUndefined();
- }
-
- String sqlStatement = exec->uncheckedArgument(0).toString(exec)->value(exec);
- if (exec->hadException())
- return jsUndefined();
-
- // Now assemble the list of SQL arguments
- Vector<SQLValue> sqlValues;
- if (!exec->argument(1).isUndefinedOrNull()) {
- JSObject* object = exec->argument(1).getObject();
- if (!object) {
- setDOMException(exec, TYPE_MISMATCH_ERR);
- return jsUndefined();
- }
-
- JSValue lengthValue = object->get(exec, exec->propertyNames().length);
- if (exec->hadException())
- return jsUndefined();
- unsigned length = lengthValue.toUInt32(exec);
- if (exec->hadException())
- return jsUndefined();
-
- for (unsigned i = 0 ; i < length; ++i) {
- JSValue value = object->get(exec, i);
- if (exec->hadException())
- return jsUndefined();
-
- if (value.isUndefinedOrNull())
- sqlValues.append(SQLValue());
- else if (value.isNumber())
- sqlValues.append(value.asNumber());
- else {
- // Convert the argument to a string and append it
- sqlValues.append(value.toString(exec)->value(exec));
- if (exec->hadException())
- return jsUndefined();
- }
- }
- }
-
- ExceptionCode ec = 0;
- JSValue result = toJS(exec, globalObject(), WTF::getPtr(m_impl->executeSQL(sqlStatement, sqlValues, ec)));
- setDOMException(exec, ec);
-
- return result;
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(SQL_DATABASE)
diff --git a/Source/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp b/Source/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp
deleted file mode 100644
index b28e7cf59..000000000
--- a/Source/WebCore/bindings/js/JSSVGElementInstanceCustom.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org>
- * Copyright (C) 2009 Apple, Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(SVG)
-
-#include "JSSVGElementInstance.h"
-
-#include "JSEventTarget.h"
-#include "JSNodeCustom.h"
-
-namespace WebCore {
-
-void JSSVGElementInstance::visitChildren(JSC::JSCell* cell, JSC::SlotVisitor& visitor)
-{
- JSSVGElementInstance* thisObject = JSC::jsCast<JSSVGElementInstance*>(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- COMPILE_ASSERT(StructureFlags & JSC::OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
- // Skip JSEventTarget::visitChildren because event listener registration is
- // forwarded to the corresponding element.
- JSEventTarget::Base::visitChildren(thisObject, visitor);
- visitor.addOpaqueRoot(root(thisObject->impl().correspondingElement()));
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/bindings/js/JSSVGLengthCustom.cpp b/Source/WebCore/bindings/js/JSSVGLengthCustom.cpp
deleted file mode 100644
index cf78a03ad..000000000
--- a/Source/WebCore/bindings/js/JSSVGLengthCustom.cpp
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- Copyright (C) 2008 Nikolas Zimmermann <zimmermann@kde.org>
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Library General Public
- License as published by the Free Software Foundation; either
- version 2 of the License, or (at your option) any later version.
-
- This library is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- Library General Public License for more details.
-
- You should have received a copy of the GNU Library General Public License
- along with this library; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- Boston, MA 02110-1301, USA.
-*/
-
-#include "config.h"
-
-#if ENABLE(SVG)
-#include "JSSVGLength.h"
-
-#include "ExceptionCode.h"
-#include "SVGAnimatedProperty.h"
-#include "SVGException.h"
-#include "SVGLengthContext.h"
-#include <runtime/Error.h>
-
-using namespace JSC;
-
-namespace WebCore {
-
-JSValue JSSVGLength::value(ExecState* exec) const
-{
- SVGLength& podImp = impl().propertyReference();
- ExceptionCode ec = 0;
- SVGLengthContext lengthContext(impl().contextElement());
- float value = podImp.value(lengthContext, ec);
- if (ec) {
- setDOMException(exec, ec);
- return jsUndefined();
- }
-
- return jsNumber(value);
-}
-
-void JSSVGLength::setValue(ExecState* exec, JSValue value)
-{
- if (impl().isReadOnly()) {
- setDOMException(exec, NO_MODIFICATION_ALLOWED_ERR);
- return;
- }
-
- if (!value.isUndefinedOrNull() && !value.isNumber() && !value.isBoolean()) {
- throwVMTypeError(exec);
- return;
- }
-
- SVGLength& podImp = impl().propertyReference();
-
- ExceptionCode ec = 0;
- SVGLengthContext lengthContext(impl().contextElement());
- podImp.setValue(value.toFloat(exec), lengthContext, ec);
- if (ec) {
- setDOMException(exec, ec);
- return;
- }
-
- impl().commitChange();
-}
-
-JSValue JSSVGLength::convertToSpecifiedUnits(ExecState* exec)
-{
- if (impl().isReadOnly()) {
- setDOMException(exec, NO_MODIFICATION_ALLOWED_ERR);
- return jsUndefined();
- }
-
- SVGLength& podImp = impl().propertyReference();
-
- if (exec->argumentCount() < 1)
- return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
-
- unsigned short unitType = exec->uncheckedArgument(0).toUInt32(exec);
- if (exec->hadException())
- return jsUndefined();
-
- ExceptionCode ec = 0;
- SVGLengthContext lengthContext(impl().contextElement());
- podImp.convertToSpecifiedUnits(unitType, lengthContext, ec);
- if (ec) {
- setDOMException(exec, ec);
- return jsUndefined();
- }
-
- impl().commitChange();
- return jsUndefined();
-}
-
-}
-
-#endif // ENABLE(SVG)
diff --git a/Source/WebCore/bindings/js/JSSVGPathSegCustom.cpp b/Source/WebCore/bindings/js/JSSVGPathSegCustom.cpp
index 9d6bf2d39..b4747184a 100644
--- a/Source/WebCore/bindings/js/JSSVGPathSegCustom.cpp
+++ b/Source/WebCore/bindings/js/JSSVGPathSegCustom.cpp
@@ -18,8 +18,6 @@
*/
#include "config.h"
-
-#if ENABLE(SVG)
#include "JSSVGPathSeg.h"
#include "JSDOMBinding.h"
@@ -61,59 +59,56 @@ using namespace JSC;
namespace WebCore {
-JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, SVGPathSeg* object)
+JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<SVGPathSeg>&& object)
{
- if (!object)
- return jsNull();
-
- if (JSObject* wrapper = getCachedWrapper(currentWorld(exec), object))
- return wrapper;
-
switch (object->pathSegType()) {
case SVGPathSeg::PATHSEG_CLOSEPATH:
- return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegClosePath, object);
+ return createWrapper<SVGPathSegClosePath>(globalObject, WTFMove(object));
case SVGPathSeg::PATHSEG_MOVETO_ABS:
- return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegMovetoAbs, object);
+ return createWrapper<SVGPathSegMovetoAbs>(globalObject, WTFMove(object));
case SVGPathSeg::PATHSEG_MOVETO_REL:
- return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegMovetoRel, object);
+ return createWrapper<SVGPathSegMovetoRel>(globalObject, WTFMove(object));
case SVGPathSeg::PATHSEG_LINETO_ABS:
- return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegLinetoAbs, object);
+ return createWrapper<SVGPathSegLinetoAbs>(globalObject, WTFMove(object));
case SVGPathSeg::PATHSEG_LINETO_REL:
- return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegLinetoRel, object);
+ return createWrapper<SVGPathSegLinetoRel>(globalObject, WTFMove(object));
case SVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS:
- return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegCurvetoCubicAbs, object);
+ return createWrapper<SVGPathSegCurvetoCubicAbs>(globalObject, WTFMove(object));
case SVGPathSeg::PATHSEG_CURVETO_CUBIC_REL:
- return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegCurvetoCubicRel, object);
+ return createWrapper<SVGPathSegCurvetoCubicRel>(globalObject, WTFMove(object));
case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_ABS:
- return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegCurvetoQuadraticAbs, object);
+ return createWrapper<SVGPathSegCurvetoQuadraticAbs>(globalObject, WTFMove(object));
case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_REL:
- return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegCurvetoQuadraticRel, object);
+ return createWrapper<SVGPathSegCurvetoQuadraticRel>(globalObject, WTFMove(object));
case SVGPathSeg::PATHSEG_ARC_ABS:
- return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegArcAbs, object);
+ return createWrapper<SVGPathSegArcAbs>(globalObject, WTFMove(object));
case SVGPathSeg::PATHSEG_ARC_REL:
- return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegArcRel, object);
+ return createWrapper<SVGPathSegArcRel>(globalObject, WTFMove(object));
case SVGPathSeg::PATHSEG_LINETO_HORIZONTAL_ABS:
- return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegLinetoHorizontalAbs, object);
+ return createWrapper<SVGPathSegLinetoHorizontalAbs>(globalObject, WTFMove(object));
case SVGPathSeg::PATHSEG_LINETO_HORIZONTAL_REL:
- return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegLinetoHorizontalRel, object);
+ return createWrapper<SVGPathSegLinetoHorizontalRel>(globalObject, WTFMove(object));
case SVGPathSeg::PATHSEG_LINETO_VERTICAL_ABS:
- return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegLinetoVerticalAbs, object);
+ return createWrapper<SVGPathSegLinetoVerticalAbs>(globalObject, WTFMove(object));
case SVGPathSeg::PATHSEG_LINETO_VERTICAL_REL:
- return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegLinetoVerticalRel, object);
+ return createWrapper<SVGPathSegLinetoVerticalRel>(globalObject, WTFMove(object));
case SVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_ABS:
- return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegCurvetoCubicSmoothAbs, object);
+ return createWrapper<SVGPathSegCurvetoCubicSmoothAbs>(globalObject, WTFMove(object));
case SVGPathSeg::PATHSEG_CURVETO_CUBIC_SMOOTH_REL:
- return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegCurvetoCubicSmoothRel, object);
+ return createWrapper<SVGPathSegCurvetoCubicSmoothRel>(globalObject, WTFMove(object));
case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS:
- return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegCurvetoQuadraticSmoothAbs, object);
+ return createWrapper<SVGPathSegCurvetoQuadraticSmoothAbs>(globalObject, WTFMove(object));
case SVGPathSeg::PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL:
- return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSegCurvetoQuadraticSmoothRel, object);
+ return createWrapper<SVGPathSegCurvetoQuadraticSmoothRel>(globalObject, WTFMove(object));
case SVGPathSeg::PATHSEG_UNKNOWN:
default:
- return CREATE_DOM_WRAPPER(exec, globalObject, SVGPathSeg, object);
+ return createWrapper<SVGPathSeg>(globalObject, WTFMove(object));
}
}
+JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, SVGPathSeg& object)
+{
+ return wrap(state, globalObject, object);
}
-#endif // ENABLE(SVG)
+}
diff --git a/Source/WebCore/bindings/js/JSSharedWorkerCustom.cpp b/Source/WebCore/bindings/js/JSSharedWorkerCustom.cpp
deleted file mode 100644
index 2c2786417..000000000
--- a/Source/WebCore/bindings/js/JSSharedWorkerCustom.cpp
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * Copyright (C) 2009 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(SHARED_WORKERS)
-
-#include "JSSharedWorker.h"
-
-#include "Document.h"
-#include "JSDOMGlobalObject.h"
-#include "JSDOMWindowCustom.h"
-#include "SharedWorker.h"
-#include <runtime/Error.h>
-
-using namespace JSC;
-
-namespace WebCore {
-
-void JSSharedWorker::visitChildren(JSCell* cell, SlotVisitor& visitor)
-{
- JSSharedWorker* thisObject = jsCast<JSSharedWorker*>(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(thisObject, visitor);
-
- if (MessagePort* port = thisObject->impl().port())
- visitor.addOpaqueRoot(port);
-}
-
-EncodedJSValue JSC_HOST_CALL JSSharedWorkerConstructor::constructJSSharedWorker(ExecState* exec)
-{
- JSSharedWorkerConstructor* jsConstructor = jsCast<JSSharedWorkerConstructor*>(exec->callee());
-
- if (exec->argumentCount() < 1)
- return throwVMError(exec, createNotEnoughArgumentsError(exec));
-
- String scriptURL = exec->uncheckedArgument(0).toString(exec)->value(exec);
- String name;
- if (exec->argumentCount() > 1)
- name = exec->uncheckedArgument(1).toString(exec)->value(exec);
-
- if (exec->hadException())
- return JSValue::encode(JSValue());
-
- // FIXME: We need to use both the dynamic scope and the lexical scope (dynamic scope for resolving the worker URL)
- DOMWindow& window = asJSDOMWindow(exec->lexicalGlobalObject())->impl();
- ExceptionCode ec = 0;
- ASSERT(window.document());
- RefPtr<SharedWorker> worker = SharedWorker::create(*window.document(), scriptURL, name, ec);
- if (ec) {
- setDOMException(exec, ec);
- return JSValue::encode(JSValue());
- }
-
- return JSValue::encode(asObject(toJS(exec, jsConstructor->globalObject(), worker.release())));
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(SHARED_WORKERS)
diff --git a/Source/WebCore/bindings/js/JSStorageCustom.cpp b/Source/WebCore/bindings/js/JSStorageCustom.cpp
index f2e22a3b6..044044361 100644
--- a/Source/WebCore/bindings/js/JSStorageCustom.cpp
+++ b/Source/WebCore/bindings/js/JSStorageCustom.cpp
@@ -26,7 +26,9 @@
#include "config.h"
#include "JSStorage.h"
-#include "Storage.h"
+#include "JSDOMConvertStrings.h"
+#include "JSDOMExceptionHandling.h"
+#include <runtime/JSCInlines.h>
#include <runtime/PropertyNameArray.h>
#include <wtf/text/WTFString.h>
@@ -34,45 +36,25 @@ using namespace JSC;
namespace WebCore {
-bool JSStorage::canGetItemsForName(ExecState* exec, Storage* impl, PropertyName propertyName)
+bool JSStorage::deleteProperty(JSCell* cell, ExecState* state, PropertyName propertyName)
{
- ExceptionCode ec = 0;
- bool result = impl->contains(propertyNameToString(propertyName), ec);
- setDOMException(exec, ec);
- return result;
-}
-
-EncodedJSValue JSStorage::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName)
-{
- JSStorage* thisObj = jsCast<JSStorage*>(JSValue::decode(slotBase));
-
- JSValue prototype = asObject(JSValue::decode(slotBase))->prototype();
- if (prototype.isObject() && asObject(prototype)->hasProperty(exec, propertyName))
- return JSValue::encode(asObject(prototype)->get(exec, propertyName));
-
- ExceptionCode ec = 0;
- JSValue result = jsStringOrNull(exec, thisObj->impl().getItem(propertyNameToString(propertyName), ec));
- setDOMException(exec, ec);
- return JSValue::encode(result);
-}
+ auto& thisObject = *jsCast<JSStorage*>(cell);
-bool JSStorage::deleteProperty(JSCell* cell, ExecState* exec, PropertyName propertyName)
-{
- JSStorage* thisObject = jsCast<JSStorage*>(cell);
// Only perform the custom delete if the object doesn't have a native property by this name.
// Since hasProperty() would end up calling canGetItemsForName() and be fooled, we need to check
// the native property slots manually.
- PropertySlot slot(thisObject);
- if (getStaticValueSlot<JSStorage, Base>(exec, *s_info.propHashTable(exec), thisObject, propertyName, slot))
- return false;
-
- JSValue prototype = thisObject->prototype();
- if (prototype.isObject() && asObject(prototype)->hasProperty(exec, propertyName))
- return false;
+ PropertySlot slot(&thisObject, PropertySlot::InternalMethodType::GetOwnProperty);
+
+ JSValue prototype = thisObject.getPrototypeDirect();
+ if (prototype.isObject() && asObject(prototype)->getPropertySlot(state, propertyName, slot))
+ return Base::deleteProperty(&thisObject, state, propertyName);
- ExceptionCode ec = 0;
- thisObject->m_impl->removeItem(propertyNameToString(propertyName), ec);
- setDOMException(exec, ec);
+ if (propertyName.isSymbol())
+ return Base::deleteProperty(&thisObject, state, propertyName);
+
+ VM& vm = state->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ propagateException(*state, scope, thisObject.wrapped().removeItem(propertyNameToString(propertyName)));
return true;
}
@@ -81,45 +63,57 @@ bool JSStorage::deletePropertyByIndex(JSCell* cell, ExecState* exec, unsigned pr
return deleteProperty(cell, exec, Identifier::from(exec, propertyName));
}
-void JSStorage::getOwnPropertyNames(JSObject* object, ExecState* exec, PropertyNameArray& propertyNames, EnumerationMode mode)
+void JSStorage::getOwnPropertyNames(JSObject* object, ExecState* state, PropertyNameArray& propertyNames, EnumerationMode mode)
{
- JSStorage* thisObject = jsCast<JSStorage*>(object);
- ExceptionCode ec = 0;
- unsigned length = thisObject->m_impl->length(ec);
- setDOMException(exec, ec);
- if (exec->hadException())
+ VM& vm = state->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto& thisObject = *jsCast<JSStorage*>(object);
+ auto lengthResult = thisObject.wrapped().length();
+ if (lengthResult.hasException()) {
+ propagateException(*state, scope, lengthResult.releaseException());
return;
+ }
+ unsigned length = lengthResult.releaseReturnValue();
for (unsigned i = 0; i < length; ++i) {
- propertyNames.add(Identifier(exec, thisObject->m_impl->key(i, ec)));
- setDOMException(exec, ec);
- if (exec->hadException())
+ auto keyResult = thisObject.wrapped().key(i);
+ if (keyResult.hasException()) {
+ propagateException(*state, scope, lengthResult.releaseException());
return;
+ }
+ propertyNames.add(Identifier::fromString(state, keyResult.releaseReturnValue()));
}
- Base::getOwnPropertyNames(thisObject, exec, propertyNames, mode);
+ Base::getOwnPropertyNames(&thisObject, state, propertyNames, mode);
}
-bool JSStorage::putDelegate(ExecState* exec, PropertyName propertyName, JSValue value, PutPropertySlot&)
+bool JSStorage::putDelegate(ExecState* state, PropertyName propertyName, JSValue value, PutPropertySlot&, bool& putResult)
{
+ VM& vm = state->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
// Only perform the custom put if the object doesn't have a native property by this name.
// Since hasProperty() would end up calling canGetItemsForName() and be fooled, we need to check
// the native property slots manually.
- PropertySlot slot(this);
- if (getStaticValueSlot<JSStorage, Base>(exec, *s_info.propHashTable(exec), this, propertyName, slot))
+ PropertySlot slot { this, PropertySlot::InternalMethodType::GetOwnProperty };
+
+ JSValue prototype = this->getPrototypeDirect();
+ if (prototype.isObject() && asObject(prototype)->getPropertySlot(state, propertyName, slot))
return false;
-
- JSValue prototype = this->prototype();
- if (prototype.isObject() && asObject(prototype)->hasProperty(exec, propertyName))
+
+ if (propertyName.isSymbol())
return false;
-
- String stringValue = value.toString(exec)->value(exec);
- if (exec->hadException())
+
+ String stringValue = value.toWTFString(state);
+ RETURN_IF_EXCEPTION(scope, true);
+
+ auto setItemResult = wrapped().setItem(propertyNameToString(propertyName), stringValue);
+ if (setItemResult.hasException()) {
+ propagateException(*state, scope, setItemResult.releaseException());
return true;
-
- ExceptionCode ec = 0;
- impl().setItem(propertyNameToString(propertyName), stringValue, ec);
- setDOMException(exec, ec);
+ }
+ putResult = true;
return true;
}
diff --git a/Source/WebCore/bindings/js/JSStyleSheetCustom.cpp b/Source/WebCore/bindings/js/JSStyleSheetCustom.cpp
index f7063061f..5c3b82f13 100644
--- a/Source/WebCore/bindings/js/JSStyleSheetCustom.cpp
+++ b/Source/WebCore/bindings/js/JSStyleSheetCustom.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -26,40 +26,25 @@
#include "config.h"
#include "JSStyleSheet.h"
-#include "CSSStyleSheet.h"
-#include "Node.h"
#include "JSCSSStyleSheet.h"
-#include "JSNode.h"
-
-using namespace JSC;
namespace WebCore {
-void JSStyleSheet::visitChildren(JSCell* cell, SlotVisitor& visitor)
+void JSStyleSheet::visitAdditionalChildren(JSC::SlotVisitor& visitor)
{
- JSStyleSheet* thisObject = jsCast<JSStyleSheet*>(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(thisObject, visitor);
- visitor.addOpaqueRoot(root(&thisObject->impl()));
+ visitor.addOpaqueRoot(root(&wrapped()));
}
-JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, StyleSheet* styleSheet)
+JSC::JSValue toJSNewlyCreated(JSC::ExecState*, JSDOMGlobalObject* globalObject, Ref<StyleSheet>&& styleSheet)
{
- if (!styleSheet)
- return jsNull();
-
- JSObject* wrapper = getCachedWrapper(currentWorld(exec), styleSheet);
- if (wrapper)
- return wrapper;
-
if (styleSheet->isCSSStyleSheet())
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, CSSStyleSheet, styleSheet);
- else
- wrapper = CREATE_DOM_WRAPPER(exec, globalObject, StyleSheet, styleSheet);
+ return createWrapper<CSSStyleSheet>(globalObject, WTFMove(styleSheet));
+ return createWrapper<StyleSheet>(globalObject, WTFMove(styleSheet));
+}
- return wrapper;
+JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, StyleSheet& stylesheet)
+{
+ return wrap(state, globalObject, stylesheet);
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSStyleSheetCustom.h b/Source/WebCore/bindings/js/JSStyleSheetCustom.h
index 8c9c18756..95777fc53 100644
--- a/Source/WebCore/bindings/js/JSStyleSheetCustom.h
+++ b/Source/WebCore/bindings/js/JSStyleSheetCustom.h
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -23,8 +23,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSStyleSheetCustom_h
-#define JSStyleSheetCustom_h
+#pragma once
#include "CSSImportRule.h"
#include "CSSStyleSheet.h"
@@ -43,5 +42,3 @@ inline void* root(StyleSheet* styleSheet)
}
} // namespace WebCore
-
-#endif // JSStyleSheetCustom_h
diff --git a/Source/WebCore/bindings/js/JSStyleSheetListCustom.cpp b/Source/WebCore/bindings/js/JSStyleSheetListCustom.cpp
deleted file mode 100644
index a5b4eef85..000000000
--- a/Source/WebCore/bindings/js/JSStyleSheetListCustom.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2007, 2009 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "JSStyleSheetList.h"
-
-#include "HTMLStyleElement.h"
-#include "JSStyleSheet.h"
-#include "StyleSheet.h"
-#include "StyleSheetList.h"
-
-using namespace JSC;
-
-namespace WebCore {
-
-bool JSStyleSheetList::canGetItemsForName(ExecState*, StyleSheetList* styleSheetList, PropertyName propertyName)
-{
- return styleSheetList->getNamedItem(propertyNameToString(propertyName));
-}
-
-EncodedJSValue JSStyleSheetList::nameGetter(ExecState* exec, EncodedJSValue slotBase, EncodedJSValue, PropertyName propertyName)
-{
- JSStyleSheetList* thisObj = jsCast<JSStyleSheetList*>(JSValue::decode(slotBase));
- HTMLStyleElement* element = thisObj->impl().getNamedItem(propertyNameToString(propertyName));
- ASSERT(element);
- return JSValue::encode(toJS(exec, thisObj->globalObject(), element->sheet()));
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSSubtleCryptoCustom.cpp b/Source/WebCore/bindings/js/JSSubtleCryptoCustom.cpp
new file mode 100644
index 000000000..86b95d71a
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSSubtleCryptoCustom.cpp
@@ -0,0 +1,1113 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSSubtleCrypto.h"
+
+#if ENABLE(SUBTLE_CRYPTO)
+
+#include "CryptoAlgorithm.h"
+#include "CryptoAlgorithmRegistry.h"
+#include "JSAesCbcParams.h"
+#include "JSAesKeyGenParams.h"
+#include "JSCryptoAlgorithmParameters.h"
+#include "JSCryptoKey.h"
+#include "JSCryptoKeyPair.h"
+#include "JSDOMPromise.h"
+#include "JSDOMWrapper.h"
+#include "JSHmacKeyParams.h"
+#include "JSJsonWebKey.h"
+#include "JSRsaHashedImportParams.h"
+#include "JSRsaHashedKeyGenParams.h"
+#include "JSRsaKeyGenParams.h"
+#include "JSRsaOaepParams.h"
+#include "ScriptState.h"
+#include <runtime/Error.h>
+#include <runtime/JSArray.h>
+#include <runtime/JSONObject.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+enum class Operations {
+ Encrypt,
+ Decrypt,
+ Sign,
+ Verify,
+ Digest,
+ DeriveKey,
+ DeriveBits,
+ GenerateKey,
+ ImportKey,
+ WrapKey,
+ UnwrapKey
+};
+
+static std::unique_ptr<CryptoAlgorithmParameters> normalizeCryptoAlgorithmParameters(ExecState&, JSValue, Operations);
+
+static CryptoAlgorithmIdentifier toHashIdentifier(ExecState& state, JSValue value)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto digestParams = normalizeCryptoAlgorithmParameters(state, value, Operations::Digest);
+ RETURN_IF_EXCEPTION(scope, { });
+ return digestParams->identifier;
+}
+
+static std::unique_ptr<CryptoAlgorithmParameters> normalizeCryptoAlgorithmParameters(ExecState& state, JSValue value, Operations operation)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (value.isString()) {
+ JSObject* newParams = constructEmptyObject(&state);
+ newParams->putDirect(vm, Identifier::fromString(&vm, "name"), value);
+ return normalizeCryptoAlgorithmParameters(state, newParams, operation);
+ }
+
+ if (value.isObject()) {
+ auto params = convertDictionary<CryptoAlgorithmParameters>(state, value);
+ RETURN_IF_EXCEPTION(scope, nullptr);
+
+ auto identifier = CryptoAlgorithmRegistry::singleton().identifier(params.name);
+ if (UNLIKELY(!identifier)) {
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ }
+
+ std::unique_ptr<CryptoAlgorithmParameters> result;
+ switch (operation) {
+ case Operations::Encrypt:
+ case Operations::Decrypt:
+ switch (*identifier) {
+ case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
+ result = std::make_unique<CryptoAlgorithmParameters>(params);
+ break;
+ case CryptoAlgorithmIdentifier::RSA_OAEP: {
+ auto params = convertDictionary<CryptoAlgorithmRsaOaepParams>(state, value);
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ result = std::make_unique<CryptoAlgorithmRsaOaepParams>(params);
+ break;
+ }
+ case CryptoAlgorithmIdentifier::AES_CBC: {
+ auto params = convertDictionary<CryptoAlgorithmAesCbcParams>(state, value);
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ result = std::make_unique<CryptoAlgorithmAesCbcParams>(params);
+ break;
+ }
+ default:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ }
+ break;
+ case Operations::Sign:
+ case Operations::Verify:
+ switch (*identifier) {
+ case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
+ case CryptoAlgorithmIdentifier::HMAC:
+ result = std::make_unique<CryptoAlgorithmParameters>(params);
+ break;
+ default:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ }
+ break;
+ case Operations::Digest:
+ switch (*identifier) {
+ case CryptoAlgorithmIdentifier::SHA_1:
+ case CryptoAlgorithmIdentifier::SHA_224:
+ case CryptoAlgorithmIdentifier::SHA_256:
+ case CryptoAlgorithmIdentifier::SHA_384:
+ case CryptoAlgorithmIdentifier::SHA_512:
+ result = std::make_unique<CryptoAlgorithmParameters>(params);
+ break;
+ default:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ }
+ break;
+ case Operations::DeriveKey:
+ case Operations::DeriveBits:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ case Operations::GenerateKey:
+ switch (*identifier) {
+ case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5: {
+ auto params = convertDictionary<CryptoAlgorithmRsaKeyGenParams>(state, value);
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ result = std::make_unique<CryptoAlgorithmRsaKeyGenParams>(params);
+ break;
+ }
+ case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
+ case CryptoAlgorithmIdentifier::RSA_PSS:
+ case CryptoAlgorithmIdentifier::RSA_OAEP: {
+ auto params = convertDictionary<CryptoAlgorithmRsaHashedKeyGenParams>(state, value);
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ params.hashIdentifier = toHashIdentifier(state, params.hash);
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ result = std::make_unique<CryptoAlgorithmRsaHashedKeyGenParams>(params);
+ break;
+ }
+ case CryptoAlgorithmIdentifier::AES_CTR:
+ case CryptoAlgorithmIdentifier::AES_CBC:
+ case CryptoAlgorithmIdentifier::AES_CMAC:
+ case CryptoAlgorithmIdentifier::AES_GCM:
+ case CryptoAlgorithmIdentifier::AES_CFB:
+ case CryptoAlgorithmIdentifier::AES_KW: {
+ auto params = convertDictionary<CryptoAlgorithmAesKeyGenParams>(state, value);
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ result = std::make_unique<CryptoAlgorithmAesKeyGenParams>(params);
+ break;
+ }
+ case CryptoAlgorithmIdentifier::HMAC: {
+ auto params = convertDictionary<CryptoAlgorithmHmacKeyParams>(state, value);
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ params.hashIdentifier = toHashIdentifier(state, params.hash);
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ result = std::make_unique<CryptoAlgorithmHmacKeyParams>(params);
+ break;
+ }
+ default:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ }
+ break;
+ case Operations::ImportKey:
+ switch (*identifier) {
+ case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
+ result = std::make_unique<CryptoAlgorithmParameters>(params);
+ break;
+ case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
+ case CryptoAlgorithmIdentifier::RSA_PSS:
+ case CryptoAlgorithmIdentifier::RSA_OAEP: {
+ auto params = convertDictionary<CryptoAlgorithmRsaHashedImportParams>(state, value);
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ params.hashIdentifier = toHashIdentifier(state, params.hash);
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ result = std::make_unique<CryptoAlgorithmRsaHashedImportParams>(params);
+ break;
+ }
+ case CryptoAlgorithmIdentifier::AES_CTR:
+ case CryptoAlgorithmIdentifier::AES_CBC:
+ case CryptoAlgorithmIdentifier::AES_CMAC:
+ case CryptoAlgorithmIdentifier::AES_GCM:
+ case CryptoAlgorithmIdentifier::AES_CFB:
+ case CryptoAlgorithmIdentifier::AES_KW:
+ result = std::make_unique<CryptoAlgorithmParameters>(params);
+ break;
+ case CryptoAlgorithmIdentifier::HMAC: {
+ auto params = convertDictionary<CryptoAlgorithmHmacKeyParams>(state, value);
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ params.hashIdentifier = toHashIdentifier(state, params.hash);
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ result = std::make_unique<CryptoAlgorithmHmacKeyParams>(params);
+ break;
+ }
+ default:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ }
+ break;
+ case Operations::WrapKey:
+ case Operations::UnwrapKey:
+ switch (*identifier) {
+ case CryptoAlgorithmIdentifier::AES_KW:
+ result = std::make_unique<CryptoAlgorithmParameters>(params);
+ break;
+ default:
+ throwNotSupportedError(state, scope);
+ return nullptr;
+ }
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ return nullptr;
+ }
+
+ result->identifier = *identifier;
+ return result;
+ }
+
+ throwTypeError(&state, scope, ASCIILiteral("Invalid AlgorithmIdentifier"));
+ return nullptr;
+}
+
+static CryptoKeyUsageBitmap toCryptoKeyUsageBitmap(CryptoKeyUsage usage)
+{
+ switch (usage) {
+ case CryptoKeyUsage::Encrypt:
+ return CryptoKeyUsageEncrypt;
+ case CryptoKeyUsage::Decrypt:
+ return CryptoKeyUsageDecrypt;
+ case CryptoKeyUsage::Sign:
+ return CryptoKeyUsageSign;
+ case CryptoKeyUsage::Verify:
+ return CryptoKeyUsageVerify;
+ case CryptoKeyUsage::DeriveKey:
+ return CryptoKeyUsageDeriveKey;
+ case CryptoKeyUsage::DeriveBits:
+ return CryptoKeyUsageDeriveBits;
+ case CryptoKeyUsage::WrapKey:
+ return CryptoKeyUsageWrapKey;
+ case CryptoKeyUsage::UnwrapKey:
+ return CryptoKeyUsageUnwrapKey;
+ }
+
+ ASSERT_NOT_REACHED();
+ return 0;
+}
+
+static CryptoKeyUsageBitmap cryptoKeyUsageBitmapFromJSValue(ExecState& state, JSValue value)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ CryptoKeyUsageBitmap result = 0;
+ auto usages = convert<IDLSequence<IDLEnumeration<CryptoKeyUsage>>>(state, value);
+ RETURN_IF_EXCEPTION(scope, 0);
+ // Maybe we shouldn't silently bypass duplicated usages?
+ for (auto usage : usages)
+ result |= toCryptoKeyUsageBitmap(usage);
+
+ return result;
+}
+
+// Maybe we want more specific error messages?
+static void rejectWithException(Ref<DeferredPromise>&& passedPromise, ExceptionCode ec)
+{
+ switch (ec) {
+ case NOT_SUPPORTED_ERR:
+ passedPromise->reject(ec, ASCIILiteral("The algorithm is not supported"));
+ return;
+ case SYNTAX_ERR:
+ passedPromise->reject(ec, ASCIILiteral("A required parameter was missing or out-of-range"));
+ return;
+ case INVALID_STATE_ERR:
+ passedPromise->reject(ec, ASCIILiteral("The requested operation is not valid for the current state of the provided key"));
+ return;
+ case INVALID_ACCESS_ERR:
+ passedPromise->reject(ec, ASCIILiteral("The requested operation is not valid for the provided key"));
+ return;
+ case UnknownError:
+ passedPromise->reject(ec, ASCIILiteral("The operation failed for an unknown transient reason (e.g. out of memory)"));
+ return;
+ case DataError:
+ passedPromise->reject(ec, ASCIILiteral("Data provided to an operation does not meet requirements"));
+ return;
+ case OperationError:
+ passedPromise->reject(ec, ASCIILiteral("The operation failed for an operation-specific reason"));
+ return;
+ }
+ ASSERT_NOT_REACHED();
+}
+
+static KeyData toKeyData(ExecState& state, SubtleCrypto::KeyFormat format, JSValue value)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ KeyData result;
+ switch (format) {
+ case SubtleCrypto::KeyFormat::Spki:
+ case SubtleCrypto::KeyFormat::Pkcs8:
+ case SubtleCrypto::KeyFormat::Raw: {
+ BufferSource bufferSource = convert<IDLBufferSource>(state, value);
+ RETURN_IF_EXCEPTION(scope, result);
+ Vector<uint8_t> vector;
+ vector.append(bufferSource.data(), bufferSource.length());
+ result = WTFMove(vector);
+ return result;
+ }
+ case SubtleCrypto::KeyFormat::Jwk: {
+ result = convertDictionary<JsonWebKey>(state, value);
+ RETURN_IF_EXCEPTION(scope, result);
+ CryptoKeyUsageBitmap usages = 0;
+ if (WTF::get<JsonWebKey>(result).key_ops) {
+ // Maybe we shouldn't silently bypass duplicated usages?
+ for (auto usage : WTF::get<JsonWebKey>(result).key_ops.value())
+ usages |= toCryptoKeyUsageBitmap(usage);
+ }
+ WTF::get<JsonWebKey>(result).usages = usages;
+ return result;
+ }
+ }
+ ASSERT_NOT_REACHED();
+ return result;
+}
+
+static RefPtr<CryptoKey> toCryptoKey(ExecState& state, JSValue value)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ RefPtr<CryptoKey> result = JSCryptoKey::toWrapped(vm, value);
+ if (!result) {
+ throwTypeError(&state, scope, ASCIILiteral("Invalid CryptoKey"));
+ return nullptr;
+ }
+ return result;
+}
+
+static Vector<uint8_t> toVector(ExecState& state, JSValue value)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ BufferSource data = convert<IDLBufferSource>(state, value);
+ RETURN_IF_EXCEPTION(scope, { });
+ Vector<uint8_t> dataVector;
+ dataVector.append(data.data(), data.length());
+
+ return dataVector;
+}
+
+static void supportExportKeyThrow(ExecState& state, ThrowScope& scope, CryptoAlgorithmIdentifier identifier)
+{
+ switch (identifier) {
+ case CryptoAlgorithmIdentifier::RSAES_PKCS1_v1_5:
+ case CryptoAlgorithmIdentifier::RSASSA_PKCS1_v1_5:
+ case CryptoAlgorithmIdentifier::RSA_PSS:
+ case CryptoAlgorithmIdentifier::RSA_OAEP:
+ case CryptoAlgorithmIdentifier::AES_CTR:
+ case CryptoAlgorithmIdentifier::AES_CBC:
+ case CryptoAlgorithmIdentifier::AES_CMAC:
+ case CryptoAlgorithmIdentifier::AES_GCM:
+ case CryptoAlgorithmIdentifier::AES_CFB:
+ case CryptoAlgorithmIdentifier::AES_KW:
+ case CryptoAlgorithmIdentifier::HMAC:
+ return;
+ default:
+ throwNotSupportedError(state, scope);
+ }
+}
+
+static void jsSubtleCryptoFunctionEncryptPromise(ExecState& state, Ref<DeferredPromise>&& promise)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (UNLIKELY(state.argumentCount() < 3)) {
+ promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
+ return;
+ }
+
+ auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::Encrypt);
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto key = toCryptoKey(state, state.uncheckedArgument(1));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto data = toVector(state, state.uncheckedArgument(2));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ if (params->identifier != key->algorithmIdentifier()) {
+ promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't match AlgorithmIdentifier"));
+ return;
+ }
+
+ if (!key->allows(CryptoKeyUsageEncrypt)) {
+ promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't support encryption"));
+ return;
+ }
+
+ auto algorithm = CryptoAlgorithmRegistry::singleton().create(key->algorithmIdentifier());
+ if (UNLIKELY(!algorithm)) {
+ throwNotSupportedError(state, scope);
+ return;
+ }
+
+ auto callback = [capturedPromise = promise.copyRef()](const Vector<uint8_t>& cipherText) mutable {
+ fulfillPromiseWithArrayBuffer(WTFMove(capturedPromise), cipherText.data(), cipherText.size());
+ return;
+ };
+ auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
+ rejectWithException(WTFMove(capturedPromise), ec);
+ };
+
+ auto subtle = jsDynamicDowncast<JSSubtleCrypto*>(vm, state.thisValue());
+ ASSERT(subtle);
+ algorithm->encrypt(WTFMove(params), key.releaseNonNull(), WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state), subtle->wrapped().workQueue());
+}
+
+static void jsSubtleCryptoFunctionDecryptPromise(ExecState& state, Ref<DeferredPromise>&& promise)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (UNLIKELY(state.argumentCount() < 3)) {
+ promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
+ return;
+ }
+
+ auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::Decrypt);
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto key = toCryptoKey(state, state.uncheckedArgument(1));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto data = toVector(state, state.uncheckedArgument(2));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ if (params->identifier != key->algorithmIdentifier()) {
+ promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't match AlgorithmIdentifier"));
+ return;
+ }
+
+ if (!key->allows(CryptoKeyUsageDecrypt)) {
+ promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't support decryption"));
+ return;
+ }
+
+ auto algorithm = CryptoAlgorithmRegistry::singleton().create(key->algorithmIdentifier());
+ if (UNLIKELY(!algorithm)) {
+ throwNotSupportedError(state, scope);
+ return;
+ }
+
+ auto callback = [capturedPromise = promise.copyRef()](const Vector<uint8_t>& plainText) mutable {
+ fulfillPromiseWithArrayBuffer(WTFMove(capturedPromise), plainText.data(), plainText.size());
+ return;
+ };
+ auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
+ rejectWithException(WTFMove(capturedPromise), ec);
+ };
+
+ auto subtle = jsDynamicDowncast<JSSubtleCrypto*>(vm, state.thisValue());
+ ASSERT(subtle);
+ algorithm->decrypt(WTFMove(params), key.releaseNonNull(), WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state), subtle->wrapped().workQueue());
+}
+
+static void jsSubtleCryptoFunctionSignPromise(ExecState& state, Ref<DeferredPromise>&& promise)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (UNLIKELY(state.argumentCount() < 3)) {
+ promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
+ return;
+ }
+
+ auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::Sign);
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto key = toCryptoKey(state, state.uncheckedArgument(1));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto data = toVector(state, state.uncheckedArgument(2));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ if (params->identifier != key->algorithmIdentifier()) {
+ promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't match AlgorithmIdentifier"));
+ return;
+ }
+
+ if (!key->allows(CryptoKeyUsageSign)) {
+ promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't support signing"));
+ return;
+ }
+
+ auto algorithm = CryptoAlgorithmRegistry::singleton().create(key->algorithmIdentifier());
+ if (UNLIKELY(!algorithm)) {
+ throwNotSupportedError(state, scope);
+ return;
+ }
+
+ auto callback = [capturedPromise = promise.copyRef()](const Vector<uint8_t>& signature) mutable {
+ fulfillPromiseWithArrayBuffer(WTFMove(capturedPromise), signature.data(), signature.size());
+ return;
+ };
+ auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
+ rejectWithException(WTFMove(capturedPromise), ec);
+ };
+
+ JSSubtleCrypto* subtle = jsDynamicDowncast<JSSubtleCrypto*>(vm, state.thisValue());
+ ASSERT(subtle);
+ algorithm->sign(key.releaseNonNull(), WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state), subtle->wrapped().workQueue());
+}
+
+static void jsSubtleCryptoFunctionVerifyPromise(ExecState& state, Ref<DeferredPromise>&& promise)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (UNLIKELY(state.argumentCount() < 4)) {
+ promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
+ return;
+ }
+
+ auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::Verify);
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto key = toCryptoKey(state, state.uncheckedArgument(1));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto signature = toVector(state, state.uncheckedArgument(2));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto data = toVector(state, state.uncheckedArgument(3));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ if (params->identifier != key->algorithmIdentifier()) {
+ promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't match AlgorithmIdentifier"));
+ return;
+ }
+
+ if (!key->allows(CryptoKeyUsageVerify)) {
+ promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("CryptoKey doesn't support verification"));
+ return;
+ }
+
+ auto algorithm = CryptoAlgorithmRegistry::singleton().create(key->algorithmIdentifier());
+ if (UNLIKELY(!algorithm)) {
+ throwNotSupportedError(state, scope);
+ return;
+ }
+
+ auto callback = [capturedPromise = promise.copyRef()](bool result) mutable {
+ capturedPromise->resolve<IDLBoolean>(result);
+ return;
+ };
+ auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
+ rejectWithException(WTFMove(capturedPromise), ec);
+ };
+
+ auto subtle = jsDynamicDowncast<JSSubtleCrypto*>(vm, state.thisValue());
+ ASSERT(subtle);
+ algorithm->verify(key.releaseNonNull(), WTFMove(signature), WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state), subtle->wrapped().workQueue());
+}
+
+static void jsSubtleCryptoFunctionDigestPromise(ExecState& state, Ref<DeferredPromise>&& promise)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (UNLIKELY(state.argumentCount() < 2)) {
+ promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
+ return;
+ }
+
+ auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::Digest);
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto data = toVector(state, state.uncheckedArgument(1));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto algorithm = CryptoAlgorithmRegistry::singleton().create(params->identifier);
+ if (UNLIKELY(!algorithm)) {
+ throwNotSupportedError(state, scope);
+ return;
+ }
+
+ auto callback = [capturedPromise = promise.copyRef()](const Vector<uint8_t>& digest) mutable {
+ fulfillPromiseWithArrayBuffer(WTFMove(capturedPromise), digest.data(), digest.size());
+ return;
+ };
+ auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
+ rejectWithException(WTFMove(capturedPromise), ec);
+ };
+
+ auto subtle = jsDynamicDowncast<JSSubtleCrypto*>(vm, state.thisValue());
+ ASSERT(subtle);
+ algorithm->digest(WTFMove(data), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state), subtle->wrapped().workQueue());
+}
+
+static void jsSubtleCryptoFunctionDeriveKeyPromise(ExecState& state, Ref<DeferredPromise>&& promise)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (UNLIKELY(state.argumentCount() < 5)) {
+ promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
+ return;
+ }
+
+ auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::DeriveKey);
+ RETURN_IF_EXCEPTION(scope, void());
+
+ // We should always return a NOT_SUPPORTED_ERR since we currently don't support any algorithms that has deriveKey operation.
+ ASSERT_NOT_REACHED();
+}
+
+static void jsSubtleCryptoFunctionDeriveBitsPromise(ExecState& state, Ref<DeferredPromise>&& promise)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (UNLIKELY(state.argumentCount() < 3)) {
+ promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
+ return;
+ }
+
+ auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::DeriveBits);
+ RETURN_IF_EXCEPTION(scope, void());
+
+ // We should always return a NOT_SUPPORTED_ERR since we currently don't support any algorithms that has deriveBits operation.
+ ASSERT_NOT_REACHED();
+}
+
+static void jsSubtleCryptoFunctionGenerateKeyPromise(ExecState& state, Ref<DeferredPromise>&& promise)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (UNLIKELY(state.argumentCount() < 3)) {
+ promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
+ return;
+ }
+
+ auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(0), Operations::GenerateKey);
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto extractable = state.uncheckedArgument(1).toBoolean(&state);
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto keyUsages = cryptoKeyUsageBitmapFromJSValue(state, state.uncheckedArgument(2));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto algorithm = CryptoAlgorithmRegistry::singleton().create(params->identifier);
+ if (UNLIKELY(!algorithm)) {
+ throwNotSupportedError(state, scope);
+ return;
+ }
+
+ auto callback = [capturedPromise = promise.copyRef()](KeyOrKeyPair&& keyOrKeyPair) mutable {
+ WTF::switchOn(keyOrKeyPair,
+ [&capturedPromise] (RefPtr<CryptoKey>& key) {
+ if ((key->type() == CryptoKeyType::Private || key->type() == CryptoKeyType::Secret) && !key->usagesBitmap()) {
+ rejectWithException(WTFMove(capturedPromise), SYNTAX_ERR);
+ return;
+ }
+ capturedPromise->resolve<IDLInterface<CryptoKey>>(*key);
+ },
+ [&capturedPromise] (CryptoKeyPair& keyPair) {
+ if (!keyPair.privateKey->usagesBitmap()) {
+ rejectWithException(WTFMove(capturedPromise), SYNTAX_ERR);
+ return;
+ }
+ capturedPromise->resolve<IDLDictionary<CryptoKeyPair>>(keyPair);
+ }
+ );
+ };
+ auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
+ rejectWithException(WTFMove(capturedPromise), ec);
+ };
+
+ // The 11 December 2014 version of the specification suggests we should perform the following task asynchronously
+ // regardless what kind of keys it produces: https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-generateKey
+ // That's simply not efficient for AES and HMAC keys. Therefore, we perform it as an async task conditionally.
+ algorithm->generateKey(*params, extractable, keyUsages, WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state));
+}
+
+static void jsSubtleCryptoFunctionImportKeyPromise(ExecState& state, Ref<DeferredPromise>&& promise)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (UNLIKELY(state.argumentCount() < 5)) {
+ promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
+ return;
+ }
+
+ auto format = convertEnumeration<SubtleCrypto::KeyFormat>(state, state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto keyData = toKeyData(state, format, state.uncheckedArgument(1));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto params = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(2), Operations::ImportKey);
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto extractable = state.uncheckedArgument(3).toBoolean(&state);
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto keyUsages = cryptoKeyUsageBitmapFromJSValue(state, state.uncheckedArgument(4));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto algorithm = CryptoAlgorithmRegistry::singleton().create(params->identifier);
+ if (UNLIKELY(!algorithm)) {
+ throwNotSupportedError(state, scope);
+ return;
+ }
+
+ auto callback = [capturedPromise = promise.copyRef()](CryptoKey& key) mutable {
+ if ((key.type() == CryptoKeyType::Private || key.type() == CryptoKeyType::Secret) && !key.usagesBitmap()) {
+ rejectWithException(WTFMove(capturedPromise), SYNTAX_ERR);
+ return;
+ }
+ capturedPromise->resolve<IDLInterface<CryptoKey>>(key);
+ };
+ auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
+ rejectWithException(WTFMove(capturedPromise), ec);
+ };
+
+ // The 11 December 2014 version of the specification suggests we should perform the following task asynchronously:
+ // https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-importKey
+ // It is not beneficial for less time consuming operations. Therefore, we perform it synchronously.
+ algorithm->importKey(format, WTFMove(keyData), WTFMove(params), extractable, keyUsages, WTFMove(callback), WTFMove(exceptionCallback));
+}
+
+static void jsSubtleCryptoFunctionExportKeyPromise(ExecState& state, Ref<DeferredPromise>&& promise)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (UNLIKELY(state.argumentCount() < 2)) {
+ promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
+ return;
+ }
+
+ auto format = convertEnumeration<SubtleCrypto::KeyFormat>(state, state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto key = toCryptoKey(state, state.uncheckedArgument(1));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ supportExportKeyThrow(state, scope, key->algorithmIdentifier());
+ RETURN_IF_EXCEPTION(scope, void());
+
+ if (!key->extractable()) {
+ promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("The CryptoKey is nonextractable"));
+ return;
+ }
+
+ auto algorithm = CryptoAlgorithmRegistry::singleton().create(key->algorithmIdentifier());
+ if (UNLIKELY(!algorithm)) {
+ throwNotSupportedError(state, scope);
+ return;
+ }
+
+ auto callback = [capturedPromise = promise.copyRef()](SubtleCrypto::KeyFormat format, KeyData&& key) mutable {
+ switch (format) {
+ case SubtleCrypto::KeyFormat::Spki:
+ case SubtleCrypto::KeyFormat::Pkcs8:
+ case SubtleCrypto::KeyFormat::Raw: {
+ Vector<uint8_t>& rawKey = WTF::get<Vector<uint8_t>>(key);
+ fulfillPromiseWithArrayBuffer(WTFMove(capturedPromise), rawKey.data(), rawKey.size());
+ return;
+ }
+ case SubtleCrypto::KeyFormat::Jwk:
+ capturedPromise->resolve<IDLDictionary<JsonWebKey>>(WTFMove(WTF::get<JsonWebKey>(key)));
+ return;
+ }
+ ASSERT_NOT_REACHED();
+ };
+ auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
+ rejectWithException(WTFMove(capturedPromise), ec);
+ };
+
+ // The 11 December 2014 version of the specification suggests we should perform the following task asynchronously:
+ // https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-exportKey
+ // It is not beneficial for less time consuming operations. Therefore, we perform it synchronously.
+ algorithm->exportKey(format, key.releaseNonNull(), WTFMove(callback), WTFMove(exceptionCallback));
+}
+
+static void jsSubtleCryptoFunctionWrapKeyPromise(ExecState& state, Ref<DeferredPromise>&& promise)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (UNLIKELY(state.argumentCount() < 4)) {
+ promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
+ return;
+ }
+
+ auto format = convertEnumeration<SubtleCrypto::KeyFormat>(state, state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto key = toCryptoKey(state, state.uncheckedArgument(1));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto wrappingKey = toCryptoKey(state, state.uncheckedArgument(2));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto catchScope = DECLARE_CATCH_SCOPE(vm);
+ bool isEncryption = false;
+ auto wrapParams = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(3), Operations::WrapKey);
+ if (catchScope.exception()) {
+ catchScope.clearException();
+ wrapParams = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(3), Operations::Encrypt);
+ RETURN_IF_EXCEPTION(scope, void());
+ isEncryption = true;
+ }
+
+ if (wrapParams->identifier != wrappingKey->algorithmIdentifier()) {
+ promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("Wrapping CryptoKey doesn't match AlgorithmIdentifier"));
+ return;
+ }
+
+ if (!wrappingKey->allows(CryptoKeyUsageWrapKey)) {
+ promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("Wrapping CryptoKey doesn't support wrapKey operation"));
+ return;
+ }
+
+ supportExportKeyThrow(state, scope, key->algorithmIdentifier());
+ RETURN_IF_EXCEPTION(scope, void());
+
+ if (!key->extractable()) {
+ promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("The CryptoKey is nonextractable"));
+ return;
+ }
+
+ auto exportAlgorithm = CryptoAlgorithmRegistry::singleton().create(key->algorithmIdentifier());
+ if (UNLIKELY(!exportAlgorithm)) {
+ throwNotSupportedError(state, scope);
+ return;
+ }
+
+ auto wrapAlgorithm = CryptoAlgorithmRegistry::singleton().create(wrappingKey->algorithmIdentifier());
+ if (UNLIKELY(!wrapAlgorithm)) {
+ throwNotSupportedError(state, scope);
+ return;
+ }
+
+ auto context = scriptExecutionContextFromExecState(&state);
+
+ auto subtle = jsDynamicDowncast<JSSubtleCrypto*>(vm, state.thisValue());
+ ASSERT(subtle);
+ auto& workQueue = subtle->wrapped().workQueue();
+
+ auto callback = [promise = promise.copyRef(), wrapAlgorithm, wrappingKey = WTFMove(wrappingKey), wrapParams = WTFMove(wrapParams), isEncryption, context, &workQueue](SubtleCrypto::KeyFormat format, KeyData&& key) mutable {
+ Vector<uint8_t> bytes;
+ switch (format) {
+ case SubtleCrypto::KeyFormat::Spki:
+ case SubtleCrypto::KeyFormat::Pkcs8:
+ case SubtleCrypto::KeyFormat::Raw:
+ bytes = WTF::get<Vector<uint8_t>>(key);
+ break;
+ case SubtleCrypto::KeyFormat::Jwk: {
+ auto jwk = toJS<IDLDictionary<JsonWebKey>>(*(promise->globalObject()->globalExec()), *(promise->globalObject()), WTFMove(WTF::get<JsonWebKey>(key)));
+ String jwkString = JSONStringify(promise->globalObject()->globalExec(), jwk, 0);
+ CString jwkUtf8String = jwkString.utf8(StrictConversion);
+ bytes.append(jwkUtf8String.data(), jwkUtf8String.length());
+ }
+ }
+
+ auto callback = [promise = promise.copyRef()](const Vector<uint8_t>& wrappedKey) mutable {
+ fulfillPromiseWithArrayBuffer(WTFMove(promise), wrappedKey.data(), wrappedKey.size());
+ return;
+ };
+ auto exceptionCallback = [promise = WTFMove(promise)](ExceptionCode ec) mutable {
+ rejectWithException(WTFMove(promise), ec);
+ };
+
+ if (!isEncryption) {
+ // The 11 December 2014 version of the specification suggests we should perform the following task asynchronously:
+ // https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-wrapKey
+ // It is not beneficial for less time consuming operations. Therefore, we perform it synchronously.
+ wrapAlgorithm->wrapKey(wrappingKey.releaseNonNull(), WTFMove(bytes), WTFMove(callback), WTFMove(exceptionCallback));
+ return;
+ }
+ // The following operation should be performed asynchronously.
+ wrapAlgorithm->encrypt(WTFMove(wrapParams), wrappingKey.releaseNonNull(), WTFMove(bytes), WTFMove(callback), WTFMove(exceptionCallback), *context, workQueue);
+ };
+ auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
+ rejectWithException(WTFMove(capturedPromise), ec);
+ };
+
+ // The following operation should be performed synchronously.
+ exportAlgorithm->exportKey(format, key.releaseNonNull(), WTFMove(callback), WTFMove(exceptionCallback));
+}
+
+static void jsSubtleCryptoFunctionUnwrapKeyPromise(ExecState& state, Ref<DeferredPromise>&& promise)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (UNLIKELY(state.argumentCount() < 7)) {
+ promise->reject<IDLAny>(createNotEnoughArgumentsError(&state));
+ return;
+ }
+
+ auto format = convertEnumeration<SubtleCrypto::KeyFormat>(state, state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto wrappedKey = toVector(state, state.uncheckedArgument(1));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto unwrappingKey = toCryptoKey(state, state.uncheckedArgument(2));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto catchScope = DECLARE_CATCH_SCOPE(vm);
+ bool isDecryption = false;
+ auto unwrapParams = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(3), Operations::UnwrapKey);
+ if (catchScope.exception()) {
+ catchScope.clearException();
+ unwrapParams = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(3), Operations::Decrypt);
+ RETURN_IF_EXCEPTION(scope, void());
+ isDecryption = true;
+ }
+
+ auto unwrappedKeyAlgorithm = normalizeCryptoAlgorithmParameters(state, state.uncheckedArgument(4), Operations::ImportKey);
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto extractable = state.uncheckedArgument(5).toBoolean(&state);
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto keyUsages = cryptoKeyUsageBitmapFromJSValue(state, state.uncheckedArgument(6));
+ RETURN_IF_EXCEPTION(scope, void());
+
+ if (unwrapParams->identifier != unwrappingKey->algorithmIdentifier()) {
+ promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("Unwrapping CryptoKey doesn't match unwrap AlgorithmIdentifier"));
+ return;
+ }
+
+ if (!unwrappingKey->allows(CryptoKeyUsageUnwrapKey)) {
+ promise->reject(INVALID_ACCESS_ERR, ASCIILiteral("Unwrapping CryptoKey doesn't support unwrapKey operation"));
+ return;
+ }
+
+ auto importAlgorithm = CryptoAlgorithmRegistry::singleton().create(unwrappedKeyAlgorithm->identifier);
+ if (UNLIKELY(!importAlgorithm)) {
+ throwNotSupportedError(state, scope);
+ return;
+ }
+
+ auto unwrapAlgorithm = CryptoAlgorithmRegistry::singleton().create(unwrappingKey->algorithmIdentifier());
+ if (UNLIKELY(!unwrapAlgorithm)) {
+ throwNotSupportedError(state, scope);
+ return;
+ }
+
+ auto callback = [promise = promise.copyRef(), format, importAlgorithm, unwrappedKeyAlgorithm = WTFMove(unwrappedKeyAlgorithm), extractable, keyUsages](const Vector<uint8_t>& bytes) mutable {
+ ExecState& state = *(promise->globalObject()->globalExec());
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ KeyData keyData;
+ switch (format) {
+ case SubtleCrypto::KeyFormat::Spki:
+ case SubtleCrypto::KeyFormat::Pkcs8:
+ case SubtleCrypto::KeyFormat::Raw:
+ keyData = bytes;
+ break;
+ case SubtleCrypto::KeyFormat::Jwk: {
+ String jwkString(reinterpret_cast_ptr<const char*>(bytes.data()), bytes.size());
+ JSC::JSLockHolder locker(vm);
+ auto jwk = JSONParse(&state, jwkString);
+ if (!jwk) {
+ promise->reject(DataError, ASCIILiteral("WrappedKey cannot be converted to a JSON object"));
+ return;
+ }
+ keyData = toKeyData(state, format, jwk);
+ RETURN_IF_EXCEPTION(scope, void());
+ }
+ }
+
+ auto callback = [promise = promise.copyRef()](CryptoKey& key) mutable {
+ if ((key.type() == CryptoKeyType::Private || key.type() == CryptoKeyType::Secret) && !key.usagesBitmap()) {
+ rejectWithException(WTFMove(promise), SYNTAX_ERR);
+ return;
+ }
+ promise->resolve<IDLInterface<CryptoKey>>(key);
+ };
+ auto exceptionCallback = [promise = WTFMove(promise)](ExceptionCode ec) mutable {
+ rejectWithException(WTFMove(promise), ec);
+ };
+
+ // The following operation should be performed synchronously.
+ importAlgorithm->importKey(format, WTFMove(keyData), WTFMove(unwrappedKeyAlgorithm), extractable, keyUsages, WTFMove(callback), WTFMove(exceptionCallback));
+ };
+ auto exceptionCallback = [capturedPromise = WTFMove(promise)](ExceptionCode ec) mutable {
+ rejectWithException(WTFMove(capturedPromise), ec);
+ };
+
+ if (!isDecryption) {
+ // The 11 December 2014 version of the specification suggests we should perform the following task asynchronously:
+ // https://www.w3.org/TR/WebCryptoAPI/#SubtleCrypto-method-unwrapKey
+ // It is not beneficial for less time consuming operations. Therefore, we perform it synchronously.
+ unwrapAlgorithm->unwrapKey(unwrappingKey.releaseNonNull(), WTFMove(wrappedKey), WTFMove(callback), WTFMove(exceptionCallback));
+ return;
+ }
+ auto subtle = jsDynamicDowncast<JSSubtleCrypto*>(vm, state.thisValue());
+ ASSERT(subtle);
+ // The following operation should be performed asynchronously.
+ unwrapAlgorithm->decrypt(WTFMove(unwrapParams), unwrappingKey.releaseNonNull(), WTFMove(wrappedKey), WTFMove(callback), WTFMove(exceptionCallback), *scriptExecutionContextFromExecState(&state), subtle->wrapped().workQueue());
+}
+
+JSValue JSSubtleCrypto::encrypt(ExecState& state)
+{
+ return callPromiseFunction<jsSubtleCryptoFunctionEncryptPromise, PromiseExecutionScope::WindowOrWorker>(state);
+}
+
+JSValue JSSubtleCrypto::decrypt(ExecState& state)
+{
+ return callPromiseFunction<jsSubtleCryptoFunctionDecryptPromise, PromiseExecutionScope::WindowOrWorker>(state);
+}
+
+JSValue JSSubtleCrypto::sign(ExecState& state)
+{
+ return callPromiseFunction<jsSubtleCryptoFunctionSignPromise, PromiseExecutionScope::WindowOrWorker>(state);
+}
+
+JSValue JSSubtleCrypto::verify(ExecState& state)
+{
+ return callPromiseFunction<jsSubtleCryptoFunctionVerifyPromise, PromiseExecutionScope::WindowOrWorker>(state);
+}
+
+JSValue JSSubtleCrypto::digest(ExecState& state)
+{
+ return callPromiseFunction<jsSubtleCryptoFunctionDigestPromise, PromiseExecutionScope::WindowOrWorker>(state);
+}
+
+JSValue JSSubtleCrypto::deriveKey(ExecState& state)
+{
+ return callPromiseFunction<jsSubtleCryptoFunctionDeriveKeyPromise, PromiseExecutionScope::WindowOrWorker>(state);
+}
+
+JSValue JSSubtleCrypto::deriveBits(ExecState& state)
+{
+ return callPromiseFunction<jsSubtleCryptoFunctionDeriveBitsPromise, PromiseExecutionScope::WindowOrWorker>(state);
+}
+
+JSValue JSSubtleCrypto::generateKey(ExecState& state)
+{
+ return callPromiseFunction<jsSubtleCryptoFunctionGenerateKeyPromise, PromiseExecutionScope::WindowOrWorker>(state);
+}
+
+JSValue JSSubtleCrypto::importKey(ExecState& state)
+{
+ return callPromiseFunction<jsSubtleCryptoFunctionImportKeyPromise, PromiseExecutionScope::WindowOrWorker>(state);
+}
+
+JSValue JSSubtleCrypto::exportKey(ExecState& state)
+{
+ return callPromiseFunction<jsSubtleCryptoFunctionExportKeyPromise, PromiseExecutionScope::WindowOrWorker>(state);
+}
+
+JSValue JSSubtleCrypto::wrapKey(ExecState& state)
+{
+ return callPromiseFunction<jsSubtleCryptoFunctionWrapKeyPromise, PromiseExecutionScope::WindowOrWorker>(state);
+}
+
+JSValue JSSubtleCrypto::unwrapKey(ExecState& state)
+{
+ return callPromiseFunction<jsSubtleCryptoFunctionUnwrapKeyPromise, PromiseExecutionScope::WindowOrWorker>(state);
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/bindings/js/JSTextCustom.cpp b/Source/WebCore/bindings/js/JSTextCustom.cpp
index 4b6e52965..8343e5043 100644
--- a/Source/WebCore/bindings/js/JSTextCustom.cpp
+++ b/Source/WebCore/bindings/js/JSTextCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,34 +10,38 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include "JSText.h"
-#include "Text.h"
+#include "JSCDATASection.h"
+
+namespace WebCore {
using namespace JSC;
-namespace WebCore {
+JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<Text>&& text)
+{
+ if (is<CDATASection>(text.get()))
+ return createWrapper<CDATASection>(globalObject, WTFMove(text));
+ return createWrapper<Text>(globalObject, WTFMove(text));
+}
-JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, Text* text)
+JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, Text& text)
{
- if (!text)
- return jsNull();
-
- return CREATE_DOM_WRAPPER(exec, globalObject, Text, text);
+ return wrap(state, globalObject, text);
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSTextTrackCueCustom.cpp b/Source/WebCore/bindings/js/JSTextTrackCueCustom.cpp
index 1605ab3e3..a297e8df2 100644
--- a/Source/WebCore/bindings/js/JSTextTrackCueCustom.cpp
+++ b/Source/WebCore/bindings/js/JSTextTrackCueCustom.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -28,7 +28,10 @@
#if ENABLE(VIDEO_TRACK)
#include "JSTextTrackCue.h"
+
+#include "JSDataCue.h"
#include "JSTrackCustom.h"
+#include "JSVTTCue.h"
#include "TextTrack.h"
using namespace JSC;
@@ -37,18 +40,14 @@ namespace WebCore {
bool JSTextTrackCueOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
{
- JSTextTrackCue* jsTextTrackCue = jsCast<JSTextTrackCue*>(handle.get().asCell());
- TextTrackCue& textTrackCue = jsTextTrackCue->impl();
+ JSTextTrackCue* jsTextTrackCue = jsCast<JSTextTrackCue*>(handle.slot()->asCell());
+ TextTrackCue& textTrackCue = jsTextTrackCue->wrapped();
// If the cue is firing event listeners, its wrapper is reachable because
// the wrapper is responsible for marking those event listeners.
if (textTrackCue.isFiringEventListeners())
return true;
- // If the cue has no event listeners and has no custom properties, it is not reachable.
- if (!textTrackCue.hasEventListeners() && !jsTextTrackCue->hasCustomProperties())
- return false;
-
// If the cue is not associated with a track, it is not reachable.
if (!textTrackCue.track())
return false;
@@ -56,20 +55,29 @@ bool JSTextTrackCueOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> h
return visitor.containsOpaqueRoot(root(textTrackCue.track()));
}
-void JSTextTrackCue::visitChildren(JSCell* cell, SlotVisitor& visitor)
+JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<TextTrackCue>&& cue)
+{
+ switch (cue->cueType()) {
+ case TextTrackCue::Data:
+ return createWrapper<DataCue>(globalObject, WTFMove(cue));
+ case TextTrackCue::WebVTT:
+ case TextTrackCue::Generic:
+ return createWrapper<VTTCue>(globalObject, WTFMove(cue));
+ default:
+ ASSERT_NOT_REACHED();
+ return jsNull();
+ }
+}
+
+JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, TextTrackCue& cue)
+{
+ return wrap(state, globalObject, cue);
+}
+
+void JSTextTrackCue::visitAdditionalChildren(SlotVisitor& visitor)
{
- JSTextTrackCue* jsTextTrackCue = jsCast<JSTextTrackCue*>(cell);
- ASSERT_GC_OBJECT_INHERITS(jsTextTrackCue, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(jsTextTrackCue->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(jsTextTrackCue, visitor);
-
- // Mark the cue's track root if it has one.
- TextTrackCue& textTrackCue = jsTextTrackCue->impl();
- if (TextTrack* textTrack = textTrackCue.track())
+ if (TextTrack* textTrack = wrapped().track())
visitor.addOpaqueRoot(root(textTrack));
-
- textTrackCue.visitJSEventListeners(visitor);
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSTextTrackCustom.cpp b/Source/WebCore/bindings/js/JSTextTrackCustom.cpp
index 078f6f256..793b6eadf 100644
--- a/Source/WebCore/bindings/js/JSTextTrackCustom.cpp
+++ b/Source/WebCore/bindings/js/JSTextTrackCustom.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -26,7 +26,9 @@
#include "config.h"
#if ENABLE(VIDEO_TRACK)
+
#include "JSTextTrack.h"
+
#include "JSTextTrackCueList.h"
#include "JSTrackCustom.h"
@@ -34,45 +36,23 @@ using namespace JSC;
namespace WebCore {
-void JSTextTrack::visitChildren(JSCell* cell, SlotVisitor& visitor)
+void JSTextTrack::visitAdditionalChildren(SlotVisitor& visitor)
{
- JSTextTrack* jsTextTrack = jsCast<JSTextTrack*>(cell);
- ASSERT_GC_OBJECT_INHERITS(jsTextTrack, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(jsTextTrack->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(jsTextTrack, visitor);
-
- TextTrack& textTrack = jsTextTrack->impl();
- visitor.addOpaqueRoot(root(&textTrack));
-
- textTrack.visitJSEventListeners(visitor);
+ visitor.addOpaqueRoot(root(&wrapped()));
}
-void JSTextTrack::setKind(ExecState* exec, JSValue value)
+void JSTextTrack::setLanguage(ExecState& state, JSValue value)
{
- UNUSED_PARAM(exec);
#if ENABLE(MEDIA_SOURCE)
- const String& nativeValue(value.isEmpty() ? String() : value.toString(exec)->value(exec));
- if (exec->hadException())
- return;
- impl().setKind(nativeValue);
-#else
- UNUSED_PARAM(value);
- return;
-#endif
-}
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
-void JSTextTrack::setLanguage(ExecState* exec, JSValue value)
-{
- UNUSED_PARAM(exec);
-#if ENABLE(MEDIA_SOURCE)
- const String& nativeValue(value.isEmpty() ? String() : value.toString(exec)->value(exec));
- if (exec->hadException())
- return;
- impl().setLanguage(nativeValue);
+ auto string = value.toWTFString(&state);
+ RETURN_IF_EXCEPTION(scope, void());
+ wrapped().setLanguage(string);
#else
+ UNUSED_PARAM(state);
UNUSED_PARAM(value);
- return;
#endif
}
diff --git a/Source/WebCore/bindings/js/JSTextTrackListCustom.cpp b/Source/WebCore/bindings/js/JSTextTrackListCustom.cpp
index 8be5ef40c..3f46f4331 100644
--- a/Source/WebCore/bindings/js/JSTextTrackListCustom.cpp
+++ b/Source/WebCore/bindings/js/JSTextTrackListCustom.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -26,6 +26,7 @@
#include "config.h"
#if ENABLE(VIDEO_TRACK)
+
#include "JSTextTrackList.h"
#include "Element.h"
@@ -35,17 +36,9 @@ using namespace JSC;
namespace WebCore {
-void JSTextTrackList::visitChildren(JSCell* cell, SlotVisitor& visitor)
+void JSTextTrackList::visitAdditionalChildren(JSC::SlotVisitor& visitor)
{
- JSTextTrackList* jsTextTrackList = jsCast<JSTextTrackList*>(cell);
- ASSERT_GC_OBJECT_INHERITS(jsTextTrackList, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(jsTextTrackList->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(jsTextTrackList, visitor);
-
- TextTrackList& textTrackList = jsTextTrackList->impl();
- visitor.addOpaqueRoot(root(textTrackList.element()));
- textTrackList.visitJSEventListeners(visitor);
+ visitor.addOpaqueRoot(root(wrapped().element()));
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSTouchCustom.cpp b/Source/WebCore/bindings/js/JSTouchCustom.cpp
deleted file mode 100644
index d9434c0f2..000000000
--- a/Source/WebCore/bindings/js/JSTouchCustom.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if !PLATFORM(IOS)
-#if ENABLE(TOUCH_EVENTS)
-
-#include "JSTouch.h"
-
-#include "Touch.h"
-
-using namespace JSC;
-
-namespace WebCore {
-
-JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, Touch* touch)
-{
- if (!touch)
- return jsNull();
-
- return CREATE_DOM_WRAPPER(exec, globalObject, Touch, touch);
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(TOUCH_EVENTS)
-#endif // !PLATFORM(IOS)
diff --git a/Source/WebCore/bindings/js/JSTouchListCustom.cpp b/Source/WebCore/bindings/js/JSTouchListCustom.cpp
deleted file mode 100644
index 11318c005..000000000
--- a/Source/WebCore/bindings/js/JSTouchListCustom.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright 2010, The Android Open Source Project
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if !PLATFORM(IOS)
-#if ENABLE(TOUCH_EVENTS)
-
-#include "JSTouchList.h"
-
-#include "TouchList.h"
-
-using namespace JSC;
-
-namespace WebCore {
-
-JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, TouchList* touchList)
-{
- if (!touchList)
- return jsNull();
-
- return CREATE_DOM_WRAPPER(exec, globalObject, TouchList, touchList);
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(TOUCH_EVENTS)
-#endif // !PLATFORM(IOS)
diff --git a/Source/WebCore/bindings/js/JSTrackCustom.cpp b/Source/WebCore/bindings/js/JSTrackCustom.cpp
index 0ad233618..57bb6b2c5 100644
--- a/Source/WebCore/bindings/js/JSTrackCustom.cpp
+++ b/Source/WebCore/bindings/js/JSTrackCustom.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -37,49 +37,22 @@ using namespace JSC;
namespace WebCore {
-TrackBase* toTrack(JSValue value)
+JSC::JSValue toJS(JSC::ExecState* state, JSDOMGlobalObject* globalObject, TrackBase& track)
{
- if (!value.isObject())
- return 0;
-
- JSObject* object = asObject(value);
- if (object->inherits(JSTextTrack::info()))
- return &jsCast<JSTextTrack*>(object)->impl();
-
- // FIXME: Fill in additional tests and casts here for VideoTrack and AudioTrack when
- // they have been added to WebCore.
-
- return 0;
-}
-
-JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, TrackBase* track)
-{
- if (!track)
- return jsNull();
-
- JSObject* wrapper = getCachedWrapper(currentWorld(exec), track);
- if (wrapper)
- return wrapper;
-
- switch (track->type()) {
+ switch (track.type()) {
case TrackBase::BaseTrack:
// This should never happen.
ASSERT_NOT_REACHED();
break;
-
- case TrackBase::AudioTrack:
- return CREATE_DOM_WRAPPER(exec, globalObject, AudioTrack, track);
- break;
+ case TrackBase::AudioTrack:
+ return wrap(state, globalObject, downcast<AudioTrack>(track));
case TrackBase::VideoTrack:
- return CREATE_DOM_WRAPPER(exec, globalObject, VideoTrack, track);
- break;
-
+ return wrap(state, globalObject, downcast<VideoTrack>(track));
case TrackBase::TextTrack:
- return CREATE_DOM_WRAPPER(exec, globalObject, TextTrack, track);
- break;
+ return wrap(state, globalObject, downcast<TextTrack>(track));
}
-
+
return jsNull();
}
diff --git a/Source/WebCore/bindings/js/JSTrackCustom.h b/Source/WebCore/bindings/js/JSTrackCustom.h
index 6e24a0915..30dd99066 100644
--- a/Source/WebCore/bindings/js/JSTrackCustom.h
+++ b/Source/WebCore/bindings/js/JSTrackCustom.h
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -23,8 +23,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef JSTrackCustom_h
-#define JSTrackCustom_h
+#pragma once
#if ENABLE(VIDEO_TRACK)
@@ -35,8 +34,7 @@
namespace WebCore {
-TrackBase* toTrack(JSC::JSValue);
-JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, TrackBase*);
+JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, TrackBase&);
inline void* root(TrackBase* track)
{
@@ -45,7 +43,6 @@ inline void* root(TrackBase* track)
return track;
}
-}
+} // namespace WebCore
-#endif
-#endif
+#endif // ENABLE(VIDEO_TRACK)
diff --git a/Source/WebCore/bindings/js/JSTreeWalkerCustom.cpp b/Source/WebCore/bindings/js/JSTreeWalkerCustom.cpp
index 9f01659f9..2be08a991 100644
--- a/Source/WebCore/bindings/js/JSTreeWalkerCustom.cpp
+++ b/Source/WebCore/bindings/js/JSTreeWalkerCustom.cpp
@@ -20,24 +20,14 @@
#include "config.h"
#include "JSTreeWalker.h"
-#include "JSNode.h"
#include "Node.h"
-#include "NodeFilter.h"
-#include "TreeWalker.h"
-
-using namespace JSC;
+#include <heap/SlotVisitorInlines.h>
namespace WebCore {
-void JSTreeWalker::visitChildren(JSCell* cell, SlotVisitor& visitor)
+void JSTreeWalker::visitAdditionalChildren(JSC::SlotVisitor& visitor)
{
- JSTreeWalker* thisObject = jsCast<JSTreeWalker*>(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(thisObject, visitor);
-
- if (NodeFilter* filter = thisObject->m_impl->filter())
+ if (NodeFilter* filter = wrapped().filter())
visitor.addOpaqueRoot(filter);
}
diff --git a/Source/WebCore/bindings/js/JSUserMessageHandlersNamespaceCustom.cpp b/Source/WebCore/bindings/js/JSUserMessageHandlersNamespaceCustom.cpp
new file mode 100644
index 000000000..1dd42d4fd
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSUserMessageHandlersNamespaceCustom.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2014 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSUserMessageHandlersNamespace.h"
+
+#if ENABLE(USER_MESSAGE_HANDLERS)
+
+#include "JSDOMConvertInterface.h"
+#include "JSDOMConvertStrings.h"
+#include "JSUserMessageHandler.h"
+#include <runtime/JSCInlines.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+bool JSUserMessageHandlersNamespace::getOwnPropertySlotDelegate(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
+{
+ if (auto* handler = wrapped().handler(propertyNameToAtomicString(propertyName), globalObject()->world())) {
+ slot.setValue(this, ReadOnly | DontDelete | DontEnum, toJS<IDLInterface<UserMessageHandler>>(*exec, *globalObject(), *handler));
+ return true;
+ }
+ return false;
+}
+
+}
+
+#endif // ENABLE(USER_MESSAGE_HANDLERS)
diff --git a/Source/WebCore/bindings/js/JSVideoTrackCustom.cpp b/Source/WebCore/bindings/js/JSVideoTrackCustom.cpp
index a82e7b8bc..f79a3341f 100644
--- a/Source/WebCore/bindings/js/JSVideoTrackCustom.cpp
+++ b/Source/WebCore/bindings/js/JSVideoTrackCustom.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -35,43 +35,38 @@ using namespace JSC;
namespace WebCore {
-void JSVideoTrack::visitChildren(JSCell* cell, SlotVisitor& visitor)
+void JSVideoTrack::visitAdditionalChildren(SlotVisitor& visitor)
{
- JSVideoTrack* jsVideoTrack = jsCast<JSVideoTrack*>(cell);
- ASSERT_GC_OBJECT_INHERITS(jsVideoTrack, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(jsVideoTrack->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(jsVideoTrack, visitor);
-
- VideoTrack& videoTrack = jsVideoTrack->impl();
- visitor.addOpaqueRoot(root(&videoTrack));
+ visitor.addOpaqueRoot(root(&wrapped()));
}
-void JSVideoTrack::setKind(ExecState* exec, JSValue value)
+void JSVideoTrack::setKind(ExecState& state, JSValue value)
{
- UNUSED_PARAM(exec);
#if ENABLE(MEDIA_SOURCE)
- const String& nativeValue(value.isEmpty() ? String() : value.toString(exec)->value(exec));
- if (exec->hadException())
- return;
- impl().setKind(nativeValue);
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto string = value.toWTFString(&state);
+ RETURN_IF_EXCEPTION(scope, void());
+ wrapped().setKind(string);
#else
+ UNUSED_PARAM(state);
UNUSED_PARAM(value);
- return;
#endif
}
-void JSVideoTrack::setLanguage(ExecState* exec, JSValue value)
+void JSVideoTrack::setLanguage(ExecState& state, JSValue value)
{
- UNUSED_PARAM(exec);
#if ENABLE(MEDIA_SOURCE)
- const String& nativeValue(value.isEmpty() ? String() : value.toString(exec)->value(exec));
- if (exec->hadException())
- return;
- impl().setLanguage(nativeValue);
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto string = value.toWTFString(&state);
+ RETURN_IF_EXCEPTION(scope, void());
+ wrapped().setLanguage(string);
#else
+ UNUSED_PARAM(state);
UNUSED_PARAM(value);
- return;
#endif
}
diff --git a/Source/WebCore/bindings/js/JSVideoTrackListCustom.cpp b/Source/WebCore/bindings/js/JSVideoTrackListCustom.cpp
index 0a669d3e3..a2a36184a 100644
--- a/Source/WebCore/bindings/js/JSVideoTrackListCustom.cpp
+++ b/Source/WebCore/bindings/js/JSVideoTrackListCustom.cpp
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -26,26 +26,18 @@
#include "config.h"
#if ENABLE(VIDEO_TRACK)
+
#include "JSVideoTrackList.h"
-#include "Element.h"
#include "JSNodeCustom.h"
using namespace JSC;
namespace WebCore {
-void JSVideoTrackList::visitChildren(JSCell* cell, SlotVisitor& visitor)
+void JSVideoTrackList::visitAdditionalChildren(SlotVisitor& visitor)
{
- JSVideoTrackList* jsVideoTrackList = jsCast<JSVideoTrackList*>(cell);
- ASSERT_GC_OBJECT_INHERITS(jsVideoTrackList, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(jsVideoTrackList->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(jsVideoTrackList, visitor);
-
- VideoTrackList& videoTrackList = jsVideoTrackList->impl();
- visitor.addOpaqueRoot(root(videoTrackList.element()));
- videoTrackList.visitJSEventListeners(visitor);
+ visitor.addOpaqueRoot(root(wrapped().element()));
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSCDATASectionCustom.cpp b/Source/WebCore/bindings/js/JSWebGL2RenderingContextCustom.cpp
index de655c129..9cefb0ea3 100644
--- a/Source/WebCore/bindings/js/JSCDATASectionCustom.cpp
+++ b/Source/WebCore/bindings/js/JSWebGL2RenderingContextCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -20,24 +20,25 @@
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
-#include "JSCDATASection.h"
-#include "CDATASection.h"
+#if ENABLE(WEBGL) && ENABLE(WEBGL2)
+
+#include "JSWebGL2RenderingContext.h"
+#include <heap/HeapInlines.h>
using namespace JSC;
namespace WebCore {
-JSValue toJSNewlyCreated(ExecState* exec, JSDOMGlobalObject* globalObject, CDATASection* section)
+void JSWebGL2RenderingContext::visitAdditionalChildren(SlotVisitor& visitor)
{
- if (!section)
- return jsNull();
-
- return CREATE_DOM_WRAPPER(exec, globalObject, CDATASection, section);
+ visitor.addOpaqueRoot(&wrapped());
}
} // namespace WebCore
+
+#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/bindings/js/JSWebGLRenderingContextBaseCustom.cpp b/Source/WebCore/bindings/js/JSWebGLRenderingContextBaseCustom.cpp
new file mode 100644
index 000000000..66d7ebd04
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSWebGLRenderingContextBaseCustom.cpp
@@ -0,0 +1,206 @@
+/*
+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(WEBGL)
+
+#include "EXTBlendMinMax.h"
+#include "EXTFragDepth.h"
+#include "EXTShaderTextureLOD.h"
+#include "EXTTextureFilterAnisotropic.h"
+#include "EXTsRGB.h"
+#include "ExceptionCode.h"
+#include "JSANGLEInstancedArrays.h"
+#include "JSEXTBlendMinMax.h"
+#include "JSEXTFragDepth.h"
+#include "JSEXTShaderTextureLOD.h"
+#include "JSEXTTextureFilterAnisotropic.h"
+#include "JSEXTsRGB.h"
+#include "JSHTMLCanvasElement.h"
+#include "JSHTMLImageElement.h"
+#include "JSImageData.h"
+#include "JSOESElementIndexUint.h"
+#include "JSOESStandardDerivatives.h"
+#include "JSOESTextureFloat.h"
+#include "JSOESTextureFloatLinear.h"
+#include "JSOESTextureHalfFloat.h"
+#include "JSOESTextureHalfFloatLinear.h"
+#include "JSOESVertexArrayObject.h"
+#include "JSWebGLBuffer.h"
+#include "JSWebGLCompressedTextureATC.h"
+#include "JSWebGLCompressedTexturePVRTC.h"
+#include "JSWebGLCompressedTextureS3TC.h"
+#include "JSWebGLDebugRendererInfo.h"
+#include "JSWebGLDebugShaders.h"
+#include "JSWebGLDepthTexture.h"
+#include "JSWebGLDrawBuffers.h"
+#include "JSWebGLFramebuffer.h"
+#include "JSWebGLLoseContext.h"
+#include "JSWebGLProgram.h"
+#include "JSWebGLRenderbuffer.h"
+#include "JSWebGLRenderingContext.h"
+#include "JSWebGLShader.h"
+#include "JSWebGLTexture.h"
+#include "JSWebGLUniformLocation.h"
+#include "JSWebGLVertexArrayObject.h"
+#include "JSWebGLVertexArrayObjectOES.h"
+#include "JSWebKitCSSMatrix.h"
+#include "OESElementIndexUint.h"
+#include "OESStandardDerivatives.h"
+#include "OESTextureFloat.h"
+#include "OESTextureFloatLinear.h"
+#include "OESTextureHalfFloat.h"
+#include "OESTextureHalfFloatLinear.h"
+#include "OESVertexArrayObject.h"
+#include "WebGLBuffer.h"
+#include "WebGLCompressedTextureATC.h"
+#include "WebGLCompressedTexturePVRTC.h"
+#include "WebGLCompressedTextureS3TC.h"
+#include "WebGLDebugRendererInfo.h"
+#include "WebGLDebugShaders.h"
+#include "WebGLDepthTexture.h"
+#include "WebGLDrawBuffers.h"
+#include "WebGLExtension.h"
+#include "WebGLFramebuffer.h"
+#include "WebGLLoseContext.h"
+#include "WebGLProgram.h"
+#include "WebGLRenderingContextBase.h"
+#include "WebGLVertexArrayObject.h"
+#include "WebGLVertexArrayObjectOES.h"
+#include <runtime/Error.h>
+#include <runtime/JSObjectInlines.h>
+#include <runtime/JSTypedArrays.h>
+#include <runtime/TypedArrayInlines.h>
+#include <runtime/TypedArrays.h>
+#include <wtf/FastMalloc.h>
+
+#if ENABLE(VIDEO)
+#include "JSHTMLVideoElement.h"
+#endif
+
+#if ENABLE(WEBGL2)
+#include "JSWebGL2RenderingContext.h"
+#endif
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSValue toJSNewlyCreated(ExecState*, JSDOMGlobalObject* globalObject, Ref<WebGLRenderingContextBase>&& object)
+{
+#if ENABLE(WEBGL2)
+ if (is<WebGL2RenderingContext>(object))
+ return createWrapper<WebGL2RenderingContext>(globalObject, WTFMove(object));
+#endif
+ return createWrapper<WebGLRenderingContext>(globalObject, WTFMove(object));
+}
+
+JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, WebGLRenderingContextBase& object)
+{
+ return wrap(state, globalObject, object);
+}
+
+static JSValue toJS(ExecState& state, JSDOMGlobalObject& globalObject, WebGLExtension* extension)
+{
+ if (!extension)
+ return jsNull();
+ switch (extension->getName()) {
+ case WebGLExtension::WebGLLoseContextName:
+ return toJS(&state, &globalObject, static_cast<WebGLLoseContext*>(extension));
+ case WebGLExtension::EXTShaderTextureLODName:
+ return toJS(&state, &globalObject, static_cast<EXTShaderTextureLOD*>(extension));
+ case WebGLExtension::EXTTextureFilterAnisotropicName:
+ return toJS(&state, &globalObject, static_cast<EXTTextureFilterAnisotropic*>(extension));
+ case WebGLExtension::EXTsRGBName:
+ return toJS(&state, &globalObject, static_cast<EXTsRGB*>(extension));
+ case WebGLExtension::EXTFragDepthName:
+ return toJS(&state, &globalObject, static_cast<EXTFragDepth*>(extension));
+ case WebGLExtension::EXTBlendMinMaxName:
+ return toJS(&state, &globalObject, static_cast<EXTBlendMinMax*>(extension));
+ case WebGLExtension::OESStandardDerivativesName:
+ return toJS(&state, &globalObject, static_cast<OESStandardDerivatives*>(extension));
+ case WebGLExtension::OESTextureFloatName:
+ return toJS(&state, &globalObject, static_cast<OESTextureFloat*>(extension));
+ case WebGLExtension::OESTextureFloatLinearName:
+ return toJS(&state, &globalObject, static_cast<OESTextureFloatLinear*>(extension));
+ case WebGLExtension::OESTextureHalfFloatName:
+ return toJS(&state, &globalObject, static_cast<OESTextureHalfFloat*>(extension));
+ case WebGLExtension::OESTextureHalfFloatLinearName:
+ return toJS(&state, &globalObject, static_cast<OESTextureHalfFloatLinear*>(extension));
+ case WebGLExtension::OESVertexArrayObjectName:
+ return toJS(&state, &globalObject, static_cast<OESVertexArrayObject*>(extension));
+ case WebGLExtension::OESElementIndexUintName:
+ return toJS(&state, &globalObject, static_cast<OESElementIndexUint*>(extension));
+ case WebGLExtension::WebGLDebugRendererInfoName:
+ return toJS(&state, &globalObject, static_cast<WebGLDebugRendererInfo*>(extension));
+ case WebGLExtension::WebGLDebugShadersName:
+ return toJS(&state, &globalObject, static_cast<WebGLDebugShaders*>(extension));
+ case WebGLExtension::WebGLCompressedTextureATCName:
+ return toJS(&state, &globalObject, static_cast<WebGLCompressedTextureATC*>(extension));
+ case WebGLExtension::WebGLCompressedTexturePVRTCName:
+ return toJS(&state, &globalObject, static_cast<WebGLCompressedTexturePVRTC*>(extension));
+ case WebGLExtension::WebGLCompressedTextureS3TCName:
+ return toJS(&state, &globalObject, static_cast<WebGLCompressedTextureS3TC*>(extension));
+ case WebGLExtension::WebGLDepthTextureName:
+ return toJS(&state, &globalObject, static_cast<WebGLDepthTexture*>(extension));
+ case WebGLExtension::WebGLDrawBuffersName:
+ return toJS(&state, &globalObject, static_cast<WebGLDrawBuffers*>(extension));
+ case WebGLExtension::ANGLEInstancedArraysName:
+ return toJS(&state, &globalObject, static_cast<ANGLEInstancedArrays*>(extension));
+ }
+ ASSERT_NOT_REACHED();
+ return jsNull();
+}
+
+bool JSWebGLRenderingContextBaseOwner::isReachableFromOpaqueRoots(Handle<JSC::Unknown> handle, void*, SlotVisitor& visitor)
+{
+ JSWebGLRenderingContextBase* jsWebGLRenderingContext = jsCast<JSWebGLRenderingContextBase*>(handle.slot()->asCell());
+ void* root = WebCore::root(jsWebGLRenderingContext->wrapped().canvas());
+ return visitor.containsOpaqueRoot(root);
+}
+
+void JSWebGLRenderingContextBase::visitAdditionalChildren(SlotVisitor& visitor)
+{
+ visitor.addOpaqueRoot(&wrapped());
+ visitor.addOpaqueRoot(root(wrapped().canvas()));
+}
+
+JSValue JSWebGLRenderingContextBase::getExtension(ExecState& state)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (state.argumentCount() < 1)
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+
+ auto name = state.uncheckedArgument(0).toWTFString(&state);
+ RETURN_IF_EXCEPTION(scope, { });
+ return toJS(state, *globalObject(), wrapped().getExtension(name));
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(WEBGL)
diff --git a/Source/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp b/Source/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp
index 9e390fc23..65abcdd1f 100644
--- a/Source/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp
+++ b/Source/WebCore/bindings/js/JSWebGLRenderingContextCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -26,727 +26,20 @@
#include "config.h"
#if ENABLE(WEBGL)
-
#include "JSWebGLRenderingContext.h"
-
-#include "ANGLEInstancedArrays.h"
-#include "EXTDrawBuffers.h"
-#include "EXTTextureFilterAnisotropic.h"
-#include "ExceptionCode.h"
-#include "HTMLCanvasElement.h"
-#include "HTMLImageElement.h"
-#include "JSANGLEInstancedArrays.h"
-#include "JSEXTDrawBuffers.h"
-#include "JSEXTTextureFilterAnisotropic.h"
-#include "JSHTMLCanvasElement.h"
-#include "JSHTMLImageElement.h"
-#include "JSImageData.h"
-#include "JSOESElementIndexUint.h"
-#include "JSOESStandardDerivatives.h"
-#include "JSOESTextureFloat.h"
-#include "JSOESTextureFloatLinear.h"
-#include "JSOESTextureHalfFloat.h"
-#include "JSOESTextureHalfFloatLinear.h"
-#include "JSOESVertexArrayObject.h"
-#include "JSWebGLBuffer.h"
-#include "JSWebGLCompressedTextureATC.h"
-#include "JSWebGLCompressedTexturePVRTC.h"
-#include "JSWebGLCompressedTextureS3TC.h"
-#include "JSWebGLDebugRendererInfo.h"
-#include "JSWebGLDebugShaders.h"
-#include "JSWebGLDepthTexture.h"
-#include "JSWebGLFramebuffer.h"
-#include "JSWebGLLoseContext.h"
-#include "JSWebGLProgram.h"
-#include "JSWebGLRenderbuffer.h"
-#include "JSWebGLShader.h"
-#include "JSWebGLTexture.h"
-#include "JSWebGLUniformLocation.h"
-#include "JSWebGLVertexArrayObjectOES.h"
-#include "JSWebKitCSSMatrix.h"
-#include "NotImplemented.h"
-#include "OESElementIndexUint.h"
-#include "OESStandardDerivatives.h"
-#include "OESTextureFloat.h"
-#include "OESTextureFloatLinear.h"
-#include "OESTextureHalfFloat.h"
-#include "OESTextureHalfFloatLinear.h"
-#include "OESVertexArrayObject.h"
-#include "WebGLBuffer.h"
-#include "WebGLCompressedTextureATC.h"
-#include "WebGLCompressedTexturePVRTC.h"
-#include "WebGLCompressedTextureS3TC.h"
-#include "WebGLDebugRendererInfo.h"
-#include "WebGLDebugShaders.h"
-#include "WebGLDepthTexture.h"
-#include "WebGLExtension.h"
-#include "WebGLFramebuffer.h"
-#include "WebGLGetInfo.h"
-#include "WebGLLoseContext.h"
-#include "WebGLProgram.h"
-#include "WebGLRenderingContext.h"
-#include "WebGLVertexArrayObjectOES.h"
-#include <runtime/Error.h>
-#include <runtime/JSTypedArrays.h>
-#include <runtime/TypedArrayInlines.h>
-#include <runtime/TypedArrays.h>
-#include <wtf/FastMalloc.h>
-
-#if ENABLE(VIDEO)
-#include "HTMLVideoElement.h"
-#include "JSHTMLVideoElement.h"
-#endif
+#include "DOMWrapperWorld.h"
+#include <JavaScriptCore/JSCellInlines.h>
+#include <JavaScriptCore/StructureInlines.h>
+#include <heap/HeapInlines.h>
+#include <heap/SlotVisitorInlines.h>
using namespace JSC;
namespace WebCore {
-static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, const WebGLGetInfo& info)
-{
- switch (info.getType()) {
- case WebGLGetInfo::kTypeBool:
- return jsBoolean(info.getBool());
- case WebGLGetInfo::kTypeBoolArray: {
- MarkedArgumentBuffer list;
- const Vector<bool>& value = info.getBoolArray();
- for (size_t ii = 0; ii < value.size(); ++ii)
- list.append(jsBoolean(value[ii]));
- return constructArray(exec, 0, globalObject, list);
- }
- case WebGLGetInfo::kTypeFloat:
- return jsNumber(info.getFloat());
- case WebGLGetInfo::kTypeInt:
- return jsNumber(info.getInt());
- case WebGLGetInfo::kTypeNull:
- return jsNull();
- case WebGLGetInfo::kTypeString:
- return jsStringWithCache(exec, info.getString());
- case WebGLGetInfo::kTypeUnsignedInt:
- return jsNumber(info.getUnsignedInt());
- case WebGLGetInfo::kTypeWebGLBuffer:
- return toJS(exec, globalObject, info.getWebGLBuffer());
- case WebGLGetInfo::kTypeWebGLFloatArray:
- return toJS(exec, globalObject, info.getWebGLFloatArray());
- case WebGLGetInfo::kTypeWebGLFramebuffer:
- return toJS(exec, globalObject, info.getWebGLFramebuffer());
- case WebGLGetInfo::kTypeWebGLIntArray:
- return toJS(exec, globalObject, info.getWebGLIntArray());
- // FIXME: implement WebGLObjectArray
- // case WebGLGetInfo::kTypeWebGLObjectArray:
- case WebGLGetInfo::kTypeWebGLProgram:
- return toJS(exec, globalObject, info.getWebGLProgram());
- case WebGLGetInfo::kTypeWebGLRenderbuffer:
- return toJS(exec, globalObject, info.getWebGLRenderbuffer());
- case WebGLGetInfo::kTypeWebGLTexture:
- return toJS(exec, globalObject, info.getWebGLTexture());
- case WebGLGetInfo::kTypeWebGLUnsignedByteArray:
- return toJS(exec, globalObject, info.getWebGLUnsignedByteArray());
- case WebGLGetInfo::kTypeWebGLUnsignedIntArray:
- return toJS(exec, globalObject, info.getWebGLUnsignedIntArray());
- case WebGLGetInfo::kTypeWebGLVertexArrayObjectOES:
- return toJS(exec, globalObject, info.getWebGLVertexArrayObjectOES());
- default:
- notImplemented();
- return jsUndefined();
- }
-}
-
-enum ObjectType {
- kBuffer, kRenderbuffer, kTexture, kVertexAttrib
-};
-
-static JSValue getObjectParameter(JSWebGLRenderingContext* obj, ExecState* exec, ObjectType objectType)
-{
- if (exec->argumentCount() != 2)
- return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
-
- ExceptionCode ec = 0;
- WebGLRenderingContext& context = obj->impl();
- unsigned target = exec->uncheckedArgument(0).toInt32(exec);
- if (exec->hadException())
- return jsUndefined();
- unsigned pname = exec->uncheckedArgument(1).toInt32(exec);
- if (exec->hadException())
- return jsUndefined();
- WebGLGetInfo info;
- switch (objectType) {
- case kBuffer:
- info = context.getBufferParameter(target, pname, ec);
- break;
- case kRenderbuffer:
- info = context.getRenderbufferParameter(target, pname, ec);
- break;
- case kTexture:
- info = context.getTexParameter(target, pname, ec);
- break;
- case kVertexAttrib:
- // target => index
- info = context.getVertexAttrib(target, pname, ec);
- break;
- default:
- notImplemented();
- break;
- }
- if (ec) {
- setDOMException(exec, ec);
- return jsUndefined();
- }
- return toJS(exec, obj->globalObject(), info);
-}
-
-enum WhichProgramCall {
- kProgramParameter, kUniform
-};
-
-static JSValue toJS(ExecState* exec, JSDOMGlobalObject* globalObject, WebGLExtension* extension)
-{
- if (!extension)
- return jsNull();
- switch (extension->getName()) {
- case WebGLExtension::WebGLLoseContextName:
- return toJS(exec, globalObject, static_cast<WebGLLoseContext*>(extension));
- case WebGLExtension::EXTDrawBuffersName:
- return toJS(exec, globalObject, static_cast<EXTDrawBuffers*>(extension));
- case WebGLExtension::EXTTextureFilterAnisotropicName:
- return toJS(exec, globalObject, static_cast<EXTTextureFilterAnisotropic*>(extension));
- case WebGLExtension::OESStandardDerivativesName:
- return toJS(exec, globalObject, static_cast<OESStandardDerivatives*>(extension));
- case WebGLExtension::OESTextureFloatName:
- return toJS(exec, globalObject, static_cast<OESTextureFloat*>(extension));
- case WebGLExtension::OESTextureFloatLinearName:
- return toJS(exec, globalObject, static_cast<OESTextureFloatLinear*>(extension));
- case WebGLExtension::OESTextureHalfFloatName:
- return toJS(exec, globalObject, static_cast<OESTextureHalfFloat*>(extension));
- case WebGLExtension::OESTextureHalfFloatLinearName:
- return toJS(exec, globalObject, static_cast<OESTextureHalfFloatLinear*>(extension));
- case WebGLExtension::OESVertexArrayObjectName:
- return toJS(exec, globalObject, static_cast<OESVertexArrayObject*>(extension));
- case WebGLExtension::OESElementIndexUintName:
- return toJS(exec, globalObject, static_cast<OESElementIndexUint*>(extension));
- case WebGLExtension::WebGLDebugRendererInfoName:
- return toJS(exec, globalObject, static_cast<WebGLDebugRendererInfo*>(extension));
- case WebGLExtension::WebGLDebugShadersName:
- return toJS(exec, globalObject, static_cast<WebGLDebugShaders*>(extension));
- case WebGLExtension::WebGLCompressedTextureATCName:
- return toJS(exec, globalObject, static_cast<WebGLCompressedTextureATC*>(extension));
- case WebGLExtension::WebGLCompressedTexturePVRTCName:
- return toJS(exec, globalObject, static_cast<WebGLCompressedTexturePVRTC*>(extension));
- case WebGLExtension::WebGLCompressedTextureS3TCName:
- return toJS(exec, globalObject, static_cast<WebGLCompressedTextureS3TC*>(extension));
- case WebGLExtension::WebGLDepthTextureName:
- return toJS(exec, globalObject, static_cast<WebGLDepthTexture*>(extension));
- case WebGLExtension::ANGLEInstancedArraysName:
- return toJS(exec, globalObject, static_cast<ANGLEInstancedArrays*>(extension));
- }
- ASSERT_NOT_REACHED();
- return jsNull();
-}
-
-void JSWebGLRenderingContext::visitChildren(JSCell* cell, SlotVisitor& visitor)
-{
- JSWebGLRenderingContext* thisObject = jsCast<JSWebGLRenderingContext*>(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(thisObject, visitor);
- visitor.addOpaqueRoot(&thisObject->impl());
-}
-
-JSValue JSWebGLRenderingContext::getAttachedShaders(ExecState* exec)
-{
- if (exec->argumentCount() < 1)
- return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
- ExceptionCode ec = 0;
- WebGLRenderingContext& context = impl();
- WebGLProgram* program = toWebGLProgram(exec->uncheckedArgument(0));
- if (!program && !exec->uncheckedArgument(0).isUndefinedOrNull())
- return throwTypeError(exec);
- Vector<RefPtr<WebGLShader>> shaders;
- bool succeed = context.getAttachedShaders(program, shaders, ec);
- if (ec) {
- setDOMException(exec, ec);
- return jsNull();
- }
- if (!succeed)
- return jsNull();
- MarkedArgumentBuffer list;
- for (size_t ii = 0; ii < shaders.size(); ++ii)
- list.append(toJS(exec, globalObject(), shaders[ii].get()));
- return constructArray(exec, 0, globalObject(), list);
-}
-
-JSValue JSWebGLRenderingContext::getExtension(ExecState* exec)
-{
- if (exec->argumentCount() < 1)
- return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
-
- WebGLRenderingContext& context = impl();
- const String name = exec->uncheckedArgument(0).toString(exec)->value(exec);
- if (exec->hadException())
- return jsUndefined();
- WebGLExtension* extension = context.getExtension(name);
- return toJS(exec, globalObject(), extension);
-}
-
-JSValue JSWebGLRenderingContext::getBufferParameter(ExecState* exec)
-{
- return getObjectParameter(this, exec, kBuffer);
-}
-
-JSValue JSWebGLRenderingContext::getFramebufferAttachmentParameter(ExecState* exec)
-{
- if (exec->argumentCount() != 3)
- return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
-
- ExceptionCode ec = 0;
- WebGLRenderingContext& context = impl();
- unsigned target = exec->uncheckedArgument(0).toInt32(exec);
- if (exec->hadException())
- return jsUndefined();
- unsigned attachment = exec->uncheckedArgument(1).toInt32(exec);
- if (exec->hadException())
- return jsUndefined();
- unsigned pname = exec->uncheckedArgument(2).toInt32(exec);
- if (exec->hadException())
- return jsUndefined();
- WebGLGetInfo info = context.getFramebufferAttachmentParameter(target, attachment, pname, ec);
- if (ec) {
- setDOMException(exec, ec);
- return jsUndefined();
- }
- return toJS(exec, globalObject(), info);
-}
-
-JSValue JSWebGLRenderingContext::getParameter(ExecState* exec)
-{
- if (exec->argumentCount() != 1)
- return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
-
- ExceptionCode ec = 0;
- WebGLRenderingContext& context = impl();
- unsigned pname = exec->uncheckedArgument(0).toInt32(exec);
- if (exec->hadException())
- return jsUndefined();
- WebGLGetInfo info = context.getParameter(pname, ec);
- if (ec) {
- setDOMException(exec, ec);
- return jsUndefined();
- }
- return toJS(exec, globalObject(), info);
-}
-
-JSValue JSWebGLRenderingContext::getProgramParameter(ExecState* exec)
-{
- if (exec->argumentCount() != 2)
- return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
-
- ExceptionCode ec = 0;
- WebGLRenderingContext& context = impl();
- WebGLProgram* program = toWebGLProgram(exec->uncheckedArgument(0));
- if (!program && !exec->uncheckedArgument(0).isUndefinedOrNull())
- return throwTypeError(exec);
- unsigned pname = exec->uncheckedArgument(1).toInt32(exec);
- if (exec->hadException())
- return jsUndefined();
- WebGLGetInfo info = context.getProgramParameter(program, pname, ec);
- if (ec) {
- setDOMException(exec, ec);
- return jsUndefined();
- }
- return toJS(exec, globalObject(), info);
-}
-
-JSValue JSWebGLRenderingContext::getRenderbufferParameter(ExecState* exec)
-{
- return getObjectParameter(this, exec, kRenderbuffer);
-}
-
-JSValue JSWebGLRenderingContext::getShaderParameter(ExecState* exec)
-{
- if (exec->argumentCount() != 2)
- return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
-
- ExceptionCode ec = 0;
- WebGLRenderingContext& context = impl();
- if (!exec->uncheckedArgument(0).isUndefinedOrNull() && !exec->uncheckedArgument(0).inherits(JSWebGLShader::info()))
- return throwTypeError(exec);
- WebGLShader* shader = toWebGLShader(exec->uncheckedArgument(0));
- unsigned pname = exec->uncheckedArgument(1).toInt32(exec);
- if (exec->hadException())
- return jsUndefined();
- WebGLGetInfo info = context.getShaderParameter(shader, pname, ec);
- if (ec) {
- setDOMException(exec, ec);
- return jsUndefined();
- }
- return toJS(exec, globalObject(), info);
-}
-
-JSValue JSWebGLRenderingContext::getSupportedExtensions(ExecState* exec)
-{
- WebGLRenderingContext& context = impl();
- if (context.isContextLost())
- return jsNull();
- Vector<String> value = context.getSupportedExtensions();
- MarkedArgumentBuffer list;
- for (size_t ii = 0; ii < value.size(); ++ii)
- list.append(jsStringWithCache(exec, value[ii]));
- return constructArray(exec, 0, globalObject(), list);
-}
-
-JSValue JSWebGLRenderingContext::getTexParameter(ExecState* exec)
-{
- return getObjectParameter(this, exec, kTexture);
-}
-
-JSValue JSWebGLRenderingContext::getUniform(ExecState* exec)
-{
- if (exec->argumentCount() != 2)
- return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
-
- ExceptionCode ec = 0;
- WebGLRenderingContext& context = impl();
- WebGLProgram* program = toWebGLProgram(exec->uncheckedArgument(0));
- if (!program && !exec->uncheckedArgument(0).isUndefinedOrNull())
- return throwTypeError(exec);
- WebGLUniformLocation* location = toWebGLUniformLocation(exec->uncheckedArgument(1));
- if (!location && !exec->uncheckedArgument(1).isUndefinedOrNull())
- return throwTypeError(exec);
- WebGLGetInfo info = context.getUniform(program, location, ec);
- if (ec) {
- setDOMException(exec, ec);
- return jsUndefined();
- }
- return toJS(exec, globalObject(), info);
-}
-
-JSValue JSWebGLRenderingContext::getVertexAttrib(ExecState* exec)
-{
- return getObjectParameter(this, exec, kVertexAttrib);
-}
-
-template<typename T, size_t inlineCapacity>
-bool toVector(JSC::ExecState* exec, JSC::JSValue value, Vector<T, inlineCapacity>& vector)
-{
- if (!value.isObject())
- return false;
-
- JSC::JSObject* object = asObject(value);
- int32_t length = object->get(exec, exec->vm().propertyNames->length).toInt32(exec);
-
- if (!vector.tryReserveCapacity(length))
- return false;
- vector.resize(length);
-
- for (int32_t i = 0; i < length; ++i) {
- JSC::JSValue v = object->get(exec, i);
- if (exec->hadException())
- return false;
- vector[i] = static_cast<T>(v.toNumber(exec));
- }
-
- return true;
-}
-
-enum DataFunctionToCall {
- f_uniform1v, f_uniform2v, f_uniform3v, f_uniform4v,
- f_vertexAttrib1v, f_vertexAttrib2v, f_vertexAttrib3v, f_vertexAttrib4v
-};
-
-enum DataFunctionMatrixToCall {
- f_uniformMatrix2fv, f_uniformMatrix3fv, f_uniformMatrix4fv
-};
-
-static bool functionForUniform(DataFunctionToCall f)
-{
- switch (f) {
- case f_uniform1v:
- case f_uniform2v:
- case f_uniform3v:
- case f_uniform4v:
- return true;
- break;
- default: break;
- }
- return false;
-}
-
-static JSC::JSValue dataFunctionf(DataFunctionToCall f, JSC::ExecState* exec, WebGLRenderingContext& context)
-{
- if (exec->argumentCount() != 2)
- return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
-
- WebGLUniformLocation* location = 0;
- long index = -1;
-
- if (functionForUniform(f)) {
- location = toWebGLUniformLocation(exec->uncheckedArgument(0));
- if (!location && !exec->uncheckedArgument(0).isUndefinedOrNull())
- return throwTypeError(exec);
- } else
- index = exec->uncheckedArgument(0).toInt32(exec);
-
- if (exec->hadException())
- return jsUndefined();
-
- RefPtr<Float32Array> webGLArray = toFloat32Array(exec->uncheckedArgument(1));
- if (exec->hadException())
- return jsUndefined();
-
- ExceptionCode ec = 0;
- if (webGLArray) {
- switch (f) {
- case f_uniform1v:
- context.uniform1fv(location, webGLArray.get(), ec);
- break;
- case f_uniform2v:
- context.uniform2fv(location, webGLArray.get(), ec);
- break;
- case f_uniform3v:
- context.uniform3fv(location, webGLArray.get(), ec);
- break;
- case f_uniform4v:
- context.uniform4fv(location, webGLArray.get(), ec);
- break;
- case f_vertexAttrib1v:
- context.vertexAttrib1fv(index, webGLArray.get());
- break;
- case f_vertexAttrib2v:
- context.vertexAttrib2fv(index, webGLArray.get());
- break;
- case f_vertexAttrib3v:
- context.vertexAttrib3fv(index, webGLArray.get());
- break;
- case f_vertexAttrib4v:
- context.vertexAttrib4fv(index, webGLArray.get());
- break;
- }
-
- setDOMException(exec, ec);
- return jsUndefined();
- }
-
- Vector<float, 64> array;
- if (!toVector(exec, exec->uncheckedArgument(1), array))
- return throwTypeError(exec);
-
- switch (f) {
- case f_uniform1v:
- context.uniform1fv(location, array.data(), array.size(), ec);
- break;
- case f_uniform2v:
- context.uniform2fv(location, array.data(), array.size(), ec);
- break;
- case f_uniform3v:
- context.uniform3fv(location, array.data(), array.size(), ec);
- break;
- case f_uniform4v:
- context.uniform4fv(location, array.data(), array.size(), ec);
- break;
- case f_vertexAttrib1v:
- context.vertexAttrib1fv(index, array.data(), array.size());
- break;
- case f_vertexAttrib2v:
- context.vertexAttrib2fv(index, array.data(), array.size());
- break;
- case f_vertexAttrib3v:
- context.vertexAttrib3fv(index, array.data(), array.size());
- break;
- case f_vertexAttrib4v:
- context.vertexAttrib4fv(index, array.data(), array.size());
- break;
- }
-
- setDOMException(exec, ec);
- return jsUndefined();
-}
-
-static JSC::JSValue dataFunctioni(DataFunctionToCall f, JSC::ExecState* exec, WebGLRenderingContext& context)
-{
- if (exec->argumentCount() != 2)
- return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
-
- WebGLUniformLocation* location = toWebGLUniformLocation(exec->uncheckedArgument(0));
- if (!location && !exec->uncheckedArgument(0).isUndefinedOrNull())
- return throwTypeError(exec);
-
- RefPtr<Int32Array> webGLArray = toInt32Array(exec->uncheckedArgument(1));
-
- ExceptionCode ec = 0;
- if (webGLArray) {
- switch (f) {
- case f_uniform1v:
- context.uniform1iv(location, webGLArray.get(), ec);
- break;
- case f_uniform2v:
- context.uniform2iv(location, webGLArray.get(), ec);
- break;
- case f_uniform3v:
- context.uniform3iv(location, webGLArray.get(), ec);
- break;
- case f_uniform4v:
- context.uniform4iv(location, webGLArray.get(), ec);
- break;
- default:
- break;
- }
-
- setDOMException(exec, ec);
- return jsUndefined();
- }
-
-
- Vector<int, 64> array;
- if (!toVector(exec, exec->uncheckedArgument(1), array))
- return throwTypeError(exec);
-
- switch (f) {
- case f_uniform1v:
- context.uniform1iv(location, array.data(), array.size(), ec);
- break;
- case f_uniform2v:
- context.uniform2iv(location, array.data(), array.size(), ec);
- break;
- case f_uniform3v:
- context.uniform3iv(location, array.data(), array.size(), ec);
- break;
- case f_uniform4v:
- context.uniform4iv(location, array.data(), array.size(), ec);
- break;
- default:
- break;
- }
-
- setDOMException(exec, ec);
- return jsUndefined();
-}
-
-static JSC::JSValue dataFunctionMatrix(DataFunctionMatrixToCall f, JSC::ExecState* exec, WebGLRenderingContext& context)
-{
- if (exec->argumentCount() != 3)
- return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
-
- WebGLUniformLocation* location = toWebGLUniformLocation(exec->uncheckedArgument(0));
- if (!location && !exec->uncheckedArgument(0).isUndefinedOrNull())
- return throwTypeError(exec);
-
- bool transpose = exec->uncheckedArgument(1).toBoolean(exec);
- if (exec->hadException())
- return jsUndefined();
-
- RefPtr<Float32Array> webGLArray = toFloat32Array(exec->uncheckedArgument(2));
-
- ExceptionCode ec = 0;
- if (webGLArray) {
- switch (f) {
- case f_uniformMatrix2fv:
- context.uniformMatrix2fv(location, transpose, webGLArray.get(), ec);
- break;
- case f_uniformMatrix3fv:
- context.uniformMatrix3fv(location, transpose, webGLArray.get(), ec);
- break;
- case f_uniformMatrix4fv:
- context.uniformMatrix4fv(location, transpose, webGLArray.get(), ec);
- break;
- }
-
- setDOMException(exec, ec);
- return jsUndefined();
- }
-
- Vector<float, 64> array;
- if (!toVector(exec, exec->uncheckedArgument(2), array))
- return throwTypeError(exec);
-
- switch (f) {
- case f_uniformMatrix2fv:
- context.uniformMatrix2fv(location, transpose, array.data(), array.size(), ec);
- break;
- case f_uniformMatrix3fv:
- context.uniformMatrix3fv(location, transpose, array.data(), array.size(), ec);
- break;
- case f_uniformMatrix4fv:
- context.uniformMatrix4fv(location, transpose, array.data(), array.size(), ec);
- break;
- }
-
- setDOMException(exec, ec);
- return jsUndefined();
-}
-
-JSC::JSValue JSWebGLRenderingContext::uniform1fv(JSC::ExecState* exec)
-{
- return dataFunctionf(f_uniform1v, exec, impl());
-}
-
-JSC::JSValue JSWebGLRenderingContext::uniform1iv(JSC::ExecState* exec)
-{
- return dataFunctioni(f_uniform1v, exec, impl());
-}
-
-JSC::JSValue JSWebGLRenderingContext::uniform2fv(JSC::ExecState* exec)
-{
- return dataFunctionf(f_uniform2v, exec, impl());
-}
-
-JSC::JSValue JSWebGLRenderingContext::uniform2iv(JSC::ExecState* exec)
-{
- return dataFunctioni(f_uniform2v, exec, impl());
-}
-
-JSC::JSValue JSWebGLRenderingContext::uniform3fv(JSC::ExecState* exec)
-{
- return dataFunctionf(f_uniform3v, exec, impl());
-}
-
-JSC::JSValue JSWebGLRenderingContext::uniform3iv(JSC::ExecState* exec)
-{
- return dataFunctioni(f_uniform3v, exec, impl());
-}
-
-JSC::JSValue JSWebGLRenderingContext::uniform4fv(JSC::ExecState* exec)
-{
- return dataFunctionf(f_uniform4v, exec, impl());
-}
-
-JSC::JSValue JSWebGLRenderingContext::uniform4iv(JSC::ExecState* exec)
-{
- return dataFunctioni(f_uniform4v, exec, impl());
-}
-
-JSC::JSValue JSWebGLRenderingContext::uniformMatrix2fv(JSC::ExecState* exec)
-{
- return dataFunctionMatrix(f_uniformMatrix2fv, exec, impl());
-}
-
-JSC::JSValue JSWebGLRenderingContext::uniformMatrix3fv(JSC::ExecState* exec)
-{
- return dataFunctionMatrix(f_uniformMatrix3fv, exec, impl());
-}
-
-JSC::JSValue JSWebGLRenderingContext::uniformMatrix4fv(JSC::ExecState* exec)
-{
- return dataFunctionMatrix(f_uniformMatrix4fv, exec, impl());
-}
-
-JSC::JSValue JSWebGLRenderingContext::vertexAttrib1fv(JSC::ExecState* exec)
-{
- return dataFunctionf(f_vertexAttrib1v, exec, impl());
-}
-
-JSC::JSValue JSWebGLRenderingContext::vertexAttrib2fv(JSC::ExecState* exec)
-{
- return dataFunctionf(f_vertexAttrib2v, exec, impl());
-}
-
-JSC::JSValue JSWebGLRenderingContext::vertexAttrib3fv(JSC::ExecState* exec)
-{
- return dataFunctionf(f_vertexAttrib3v, exec, impl());
-}
-
-JSC::JSValue JSWebGLRenderingContext::vertexAttrib4fv(JSC::ExecState* exec)
+void JSWebGLRenderingContext::visitAdditionalChildren(SlotVisitor& visitor)
{
- return dataFunctionf(f_vertexAttrib4v, exec, impl());
+ visitor.addOpaqueRoot(&wrapped());
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSWebKitPointCustom.cpp b/Source/WebCore/bindings/js/JSWebKitPointCustom.cpp
deleted file mode 100644
index 7ef129103..000000000
--- a/Source/WebCore/bindings/js/JSWebKitPointCustom.cpp
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "JSWebKitPoint.h"
-
-#include "WebKitPoint.h"
-
-using namespace JSC;
-
-namespace WebCore {
-
-EncodedJSValue JSC_HOST_CALL JSWebKitPointConstructor::constructJSWebKitPoint(ExecState* exec)
-{
- JSWebKitPointConstructor* jsConstructor = jsCast<JSWebKitPointConstructor*>(exec->callee());
-
- float x = 0;
- float y = 0;
- if (exec->argumentCount() >= 2) {
- x = static_cast<float>(exec->argument(0).toNumber(exec));
- y = static_cast<float>(exec->argument(1).toNumber(exec));
- if (std::isnan(x))
- x = 0;
- if (std::isnan(y))
- y = 0;
- }
- return JSValue::encode(asObject(toJS(exec, jsConstructor->globalObject(), WebKitPoint::create(x, y))));
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSWebKitSubtleCryptoCustom.cpp b/Source/WebCore/bindings/js/JSWebKitSubtleCryptoCustom.cpp
new file mode 100644
index 000000000..638b37e4a
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSWebKitSubtleCryptoCustom.cpp
@@ -0,0 +1,705 @@
+/*
+ * Copyright (C) 2013, 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSWebKitSubtleCrypto.h"
+
+#if ENABLE(SUBTLE_CRYPTO)
+
+#include "CryptoAlgorithm.h"
+#include "CryptoAlgorithmParametersDeprecated.h"
+#include "CryptoAlgorithmRegistry.h"
+#include "CryptoKeyData.h"
+#include "CryptoKeySerializationRaw.h"
+#include "Document.h"
+#include "ExceptionCode.h"
+#include "JSCryptoAlgorithmDictionary.h"
+#include "JSCryptoKey.h"
+#include "JSCryptoKeyPair.h"
+#include "JSCryptoKeySerializationJWK.h"
+#include "JSCryptoOperationData.h"
+#include "JSDOMPromise.h"
+#include "ScriptState.h"
+#include <runtime/Error.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+enum class CryptoKeyFormat {
+ // An unformatted sequence of bytes. Intended for secret keys.
+ Raw,
+
+ // The DER encoding of the PrivateKeyInfo structure from RFC 5208.
+ PKCS8,
+
+ // The DER encoding of the SubjectPublicKeyInfo structure from RFC 5280.
+ SPKI,
+
+ // The key is represented as JSON according to the JSON Web Key format.
+ JWK
+};
+
+static RefPtr<CryptoAlgorithm> createAlgorithmFromJSValue(ExecState& state, ThrowScope& scope, JSValue value)
+{
+ auto algorithmIdentifier = JSCryptoAlgorithmDictionary::parseAlgorithmIdentifier(state, scope, value);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ auto result = CryptoAlgorithmRegistry::singleton().create(algorithmIdentifier);
+ if (!result)
+ throwNotSupportedError(state, scope);
+
+ return result;
+}
+
+static CryptoKeyFormat cryptoKeyFormatFromJSValue(ExecState& state, ThrowScope& scope, JSValue value)
+{
+ auto keyFormatString = value.toWTFString(&state);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ if (keyFormatString == "raw")
+ return CryptoKeyFormat::Raw;
+ if (keyFormatString == "pkcs8")
+ return CryptoKeyFormat::PKCS8;
+ if (keyFormatString == "spki")
+ return CryptoKeyFormat::SPKI;
+ if (keyFormatString == "jwk")
+ return CryptoKeyFormat::JWK;
+
+ throwTypeError(&state, scope, ASCIILiteral("Unknown key format"));
+ return { };
+}
+
+static CryptoKeyUsageBitmap cryptoKeyUsagesFromJSValue(ExecState& state, ThrowScope& scope, JSValue value)
+{
+ if (!isJSArray(value)) {
+ throwTypeError(&state, scope);
+ return { };
+ }
+
+ CryptoKeyUsageBitmap result = 0;
+ JSArray* array = asArray(value);
+ for (unsigned i = 0; i < array->length(); ++i) {
+ auto usageString = array->getIndex(&state, i).toWTFString(&state);
+ RETURN_IF_EXCEPTION(scope, { });
+ if (usageString == "encrypt")
+ result |= CryptoKeyUsageEncrypt;
+ else if (usageString == "decrypt")
+ result |= CryptoKeyUsageDecrypt;
+ else if (usageString == "sign")
+ result |= CryptoKeyUsageSign;
+ else if (usageString == "verify")
+ result |= CryptoKeyUsageVerify;
+ else if (usageString == "deriveKey")
+ result |= CryptoKeyUsageDeriveKey;
+ else if (usageString == "deriveBits")
+ result |= CryptoKeyUsageDeriveBits;
+ else if (usageString == "wrapKey")
+ result |= CryptoKeyUsageWrapKey;
+ else if (usageString == "unwrapKey")
+ result |= CryptoKeyUsageUnwrapKey;
+ }
+ return result;
+}
+
+JSValue JSWebKitSubtleCrypto::encrypt(ExecState& state)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (state.argumentCount() < 3)
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+
+ auto algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ auto parameters = JSCryptoAlgorithmDictionary::createParametersForEncrypt(state, scope, algorithm->identifier(), state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(1));
+ if (!key)
+ return throwTypeError(&state, scope);
+
+ if (!key->allows(CryptoKeyUsageEncrypt)) {
+ wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'encrypt'"));
+ throwNotSupportedError(state, scope);
+ return jsUndefined();
+ }
+
+ auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(2));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow());
+ auto promise = wrapper->promise();
+ auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable {
+ fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), result.data(), result.size());
+ };
+ auto failureCallback = [wrapper]() mutable {
+ wrapper->reject(); // FIXME: This should reject with an Exception.
+ };
+
+ auto result = algorithm->encrypt(*parameters, *key, data, WTFMove(successCallback), WTFMove(failureCallback));
+ if (result.hasException()) {
+ propagateException(state, scope, result.releaseException());
+ return { };
+ }
+
+ return promise;
+}
+
+JSValue JSWebKitSubtleCrypto::decrypt(ExecState& state)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (state.argumentCount() < 3)
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+
+ auto algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ auto parameters = JSCryptoAlgorithmDictionary::createParametersForDecrypt(state, scope, algorithm->identifier(), state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(1));
+ if (!key)
+ return throwTypeError(&state, scope);
+
+ if (!key->allows(CryptoKeyUsageDecrypt)) {
+ wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'decrypt'"));
+ throwNotSupportedError(state, scope);
+ return jsUndefined();
+ }
+
+ auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(2));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow());
+ auto promise = wrapper->promise();
+ auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable {
+ fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), result.data(), result.size());
+ };
+ auto failureCallback = [wrapper]() mutable {
+ wrapper->reject(); // FIXME: This should reject with an Exception.
+ };
+
+ auto result = algorithm->decrypt(*parameters, *key, data, WTFMove(successCallback), WTFMove(failureCallback));
+ if (result.hasException()) {
+ propagateException(state, scope, result.releaseException());
+ return { };
+ }
+
+ return promise;
+}
+
+JSValue JSWebKitSubtleCrypto::sign(ExecState& state)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (state.argumentCount() < 3)
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+
+ auto algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ auto parameters = JSCryptoAlgorithmDictionary::createParametersForSign(state, scope, algorithm->identifier(), state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(1));
+ if (!key)
+ return throwTypeError(&state, scope);
+
+ if (!key->allows(CryptoKeyUsageSign)) {
+ wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'sign'"));
+ throwNotSupportedError(state, scope);
+ return jsUndefined();
+ }
+
+ auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(2));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow());
+ auto promise = wrapper->promise();
+ auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable {
+ fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), result.data(), result.size());
+ };
+ auto failureCallback = [wrapper]() mutable {
+ wrapper->reject(); // FIXME: This should reject with an Exception.
+ };
+
+ auto result = algorithm->sign(*parameters, *key, data, WTFMove(successCallback), WTFMove(failureCallback));
+ if (result.hasException()) {
+ propagateException(state, scope, result.releaseException());
+ return { };
+ }
+
+ return promise;
+}
+
+JSValue JSWebKitSubtleCrypto::verify(ExecState& state)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (state.argumentCount() < 4)
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+
+ auto algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ auto parameters = JSCryptoAlgorithmDictionary::createParametersForVerify(state, scope, algorithm->identifier(), state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(1));
+ if (!key)
+ return throwTypeError(&state, scope);
+
+ if (!key->allows(CryptoKeyUsageVerify)) {
+ wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'verify'"));
+ throwNotSupportedError(state, scope);
+ return jsUndefined();
+ }
+
+ auto signature = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(2));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(3));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow());
+ auto promise = wrapper->promise();
+ auto successCallback = [wrapper](bool result) mutable {
+ wrapper->resolve<IDLBoolean>(result);
+ };
+ auto failureCallback = [wrapper]() mutable {
+ wrapper->reject(); // FIXME: This should reject with an Exception.
+ };
+
+ auto result = algorithm->verify(*parameters, *key, signature, data, WTFMove(successCallback), WTFMove(failureCallback));
+ if (result.hasException()) {
+ propagateException(state, scope, result.releaseException());
+ return { };
+ }
+
+ return promise;
+}
+
+JSValue JSWebKitSubtleCrypto::digest(ExecState& state)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (state.argumentCount() < 2)
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+
+ auto algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ auto parameters = JSCryptoAlgorithmDictionary::createParametersForDigest(state, scope, algorithm->identifier(), state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(1));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow());
+ auto promise = wrapper->promise();
+ auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable {
+ fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), result.data(), result.size());
+ };
+ auto failureCallback = [wrapper]() mutable {
+ wrapper->reject(); // FIXME: This should reject with an Exception.
+ };
+
+ auto result = algorithm->digest(*parameters, data, WTFMove(successCallback), WTFMove(failureCallback));
+ if (result.hasException()) {
+ propagateException(state, scope, result.releaseException());
+ return { };
+ }
+
+ return promise;
+}
+
+JSValue JSWebKitSubtleCrypto::generateKey(ExecState& state)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (state.argumentCount() < 1)
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+
+ auto algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ auto parameters = JSCryptoAlgorithmDictionary::createParametersForGenerateKey(state, scope, algorithm->identifier(), state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ bool extractable = state.argument(1).toBoolean(&state);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ CryptoKeyUsageBitmap keyUsages = 0;
+ if (state.argumentCount() >= 3) {
+ keyUsages = cryptoKeyUsagesFromJSValue(state, scope, state.uncheckedArgument(2));
+ RETURN_IF_EXCEPTION(scope, { });
+ }
+
+ RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow());
+ auto promise = wrapper->promise();
+ auto successCallback = [wrapper](KeyOrKeyPair&& keyOrKeyPair) mutable {
+ WTF::switchOn(keyOrKeyPair,
+ [&wrapper] (RefPtr<CryptoKey>& key) {
+ wrapper->resolve<IDLInterface<CryptoKey>>(*key);
+ },
+ [&wrapper] (CryptoKeyPair& keyPair) {
+ wrapper->resolve<IDLDictionary<CryptoKeyPair>>(keyPair);
+ }
+ );
+ };
+ auto failureCallback = [wrapper]() mutable {
+ wrapper->reject(); // FIXME: This should reject with an Exception.
+ };
+
+ auto result = algorithm->generateKey(*parameters, extractable, keyUsages, WTFMove(successCallback), WTFMove(failureCallback), *scriptExecutionContextFromExecState(&state));
+ if (result.hasException()) {
+ propagateException(state, scope, result.releaseException());
+ return { };
+ }
+
+ return promise;
+}
+
+static void importKey(ExecState& state, CryptoKeyFormat keyFormat, CryptoOperationData data, RefPtr<CryptoAlgorithm> algorithm, RefPtr<CryptoAlgorithmParametersDeprecated> parameters, bool extractable, CryptoKeyUsageBitmap keyUsages, CryptoAlgorithm::KeyCallback callback, CryptoAlgorithm::VoidCallback failureCallback)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ std::unique_ptr<CryptoKeySerialization> keySerialization;
+ switch (keyFormat) {
+ case CryptoKeyFormat::Raw:
+ keySerialization = CryptoKeySerializationRaw::create(data);
+ break;
+ case CryptoKeyFormat::JWK: {
+ String jwkString = String::fromUTF8(data.first, data.second);
+ if (jwkString.isNull()) {
+ throwTypeError(&state, scope, ASCIILiteral("JWK JSON serialization is not valid UTF-8"));
+ return;
+ }
+ keySerialization = std::make_unique<JSCryptoKeySerializationJWK>(&state, jwkString);
+ RETURN_IF_EXCEPTION(scope, void());
+ break;
+ }
+ default:
+ throwTypeError(&state, scope, ASCIILiteral("Unsupported key format for import"));
+ return;
+ }
+
+ ASSERT(keySerialization);
+
+ std::optional<CryptoAlgorithmPair> reconciledResult = keySerialization->reconcileAlgorithm(algorithm.get(), parameters.get());
+ if (!reconciledResult) {
+ if (!scope.exception())
+ throwTypeError(&state, scope, ASCIILiteral("Algorithm specified in key is not compatible with one passed to importKey as argument"));
+ return;
+ }
+ RETURN_IF_EXCEPTION(scope, void());
+
+ algorithm = reconciledResult->algorithm;
+ parameters = reconciledResult->parameters;
+ if (!algorithm) {
+ throwTypeError(&state, scope, ASCIILiteral("Neither key nor function argument has crypto algorithm specified"));
+ return;
+ }
+ ASSERT(parameters);
+
+ keySerialization->reconcileExtractable(extractable);
+ RETURN_IF_EXCEPTION(scope, void());
+
+ keySerialization->reconcileUsages(keyUsages);
+ RETURN_IF_EXCEPTION(scope, void());
+
+ auto keyData = keySerialization->keyData();
+ RETURN_IF_EXCEPTION(scope, void());
+
+ propagateException(state, scope, algorithm->importKey(*parameters, *keyData, extractable, keyUsages, WTFMove(callback), WTFMove(failureCallback)));
+}
+
+JSValue JSWebKitSubtleCrypto::importKey(ExecState& state)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (state.argumentCount() < 3)
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+
+ auto keyFormat = cryptoKeyFormatFromJSValue(state, scope, state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ auto data = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(1));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ RefPtr<CryptoAlgorithm> algorithm;
+ RefPtr<CryptoAlgorithmParametersDeprecated> parameters;
+ if (!state.uncheckedArgument(2).isNull()) {
+ algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(2));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ parameters = JSCryptoAlgorithmDictionary::createParametersForImportKey(state, scope, algorithm->identifier(), state.uncheckedArgument(2));
+ RETURN_IF_EXCEPTION(scope, { });
+ }
+
+ bool extractable = state.argument(3).toBoolean(&state);
+ RETURN_IF_EXCEPTION(scope, JSValue());
+
+ CryptoKeyUsageBitmap keyUsages = 0;
+ if (state.argumentCount() >= 5) {
+ keyUsages = cryptoKeyUsagesFromJSValue(state, scope, state.uncheckedArgument(4));
+ RETURN_IF_EXCEPTION(scope, { });
+ }
+
+ RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow());
+ auto promise = wrapper->promise();
+ auto successCallback = [wrapper](CryptoKey& result) mutable {
+ wrapper->resolve<IDLInterface<CryptoKey>>(result);
+ };
+ auto failureCallback = [wrapper]() mutable {
+ wrapper->reject(); // FIXME: This should reject with an Exception.
+ };
+
+ WebCore::importKey(state, keyFormat, data, WTFMove(algorithm), WTFMove(parameters), extractable, keyUsages, WTFMove(successCallback), WTFMove(failureCallback));
+ RETURN_IF_EXCEPTION(scope, JSValue());
+
+ return promise;
+}
+
+static void exportKey(ExecState& state, CryptoKeyFormat keyFormat, const CryptoKey& key, CryptoAlgorithm::VectorCallback callback, CryptoAlgorithm::VoidCallback failureCallback)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (!key.extractable()) {
+ throwTypeError(&state, scope, ASCIILiteral("Key is not extractable"));
+ return;
+ }
+
+ switch (keyFormat) {
+ case CryptoKeyFormat::Raw: {
+ Vector<uint8_t> result;
+ if (CryptoKeySerializationRaw::serialize(key, result))
+ callback(result);
+ else
+ failureCallback();
+ break;
+ }
+ case CryptoKeyFormat::JWK: {
+ String result = JSCryptoKeySerializationJWK::serialize(&state, key);
+ RETURN_IF_EXCEPTION(scope, void());
+ CString utf8String = result.utf8(StrictConversion);
+ Vector<uint8_t> resultBuffer;
+ resultBuffer.append(utf8String.data(), utf8String.length());
+ callback(resultBuffer);
+ break;
+ }
+ default:
+ throwTypeError(&state, scope, ASCIILiteral("Unsupported key format for export"));
+ break;
+ }
+}
+
+JSValue JSWebKitSubtleCrypto::exportKey(ExecState& state)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (state.argumentCount() < 2)
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+
+ auto keyFormat = cryptoKeyFormatFromJSValue(state, scope, state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(1));
+ if (!key)
+ return throwTypeError(&state, scope);
+
+ RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow());
+ auto promise = wrapper->promise();
+ auto successCallback = [wrapper](const Vector<uint8_t>& result) mutable {
+ fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), result.data(), result.size());
+ };
+ auto failureCallback = [wrapper]() mutable {
+ wrapper->reject(); // FIXME: This should reject with an Exception.
+ };
+
+ WebCore::exportKey(state, keyFormat, *key, WTFMove(successCallback), WTFMove(failureCallback));
+ RETURN_IF_EXCEPTION(scope, JSValue());
+
+ return promise;
+}
+
+JSValue JSWebKitSubtleCrypto::wrapKey(ExecState& state)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (state.argumentCount() < 4)
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+
+ auto keyFormat = cryptoKeyFormatFromJSValue(state, scope, state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ RefPtr<CryptoKey> key = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(1));
+ if (!key)
+ return throwTypeError(&state, scope);
+
+ RefPtr<CryptoKey> wrappingKey = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(2));
+ if (!key)
+ return throwTypeError(&state, scope);
+
+ if (!wrappingKey->allows(CryptoKeyUsageWrapKey)) {
+ wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'wrapKey'"));
+ throwNotSupportedError(state, scope);
+ return jsUndefined();
+ }
+
+ auto algorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(3));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ auto parameters = JSCryptoAlgorithmDictionary::createParametersForEncrypt(state, scope, algorithm->identifier(), state.uncheckedArgument(3));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow());
+ auto promise = wrapper->promise();
+
+ auto exportSuccessCallback = [keyFormat, algorithm, parameters, wrappingKey, wrapper](const Vector<uint8_t>& exportedKeyData) mutable {
+ auto encryptSuccessCallback = [wrapper](const Vector<uint8_t>& encryptedData) mutable {
+ fulfillPromiseWithArrayBuffer(wrapper.releaseNonNull(), encryptedData.data(), encryptedData.size());
+ };
+ auto encryptFailureCallback = [wrapper]() mutable {
+ wrapper->reject(); // FIXME: This should reject with an Exception.
+ };
+ auto result = algorithm->encryptForWrapKey(*parameters, *wrappingKey, std::make_pair(exportedKeyData.data(), exportedKeyData.size()), WTFMove(encryptSuccessCallback), WTFMove(encryptFailureCallback));
+ if (result.hasException()) {
+ // FIXME: Report failure details to console, and possibly to calling script once there is a standardized way to pass errors to WebCrypto promise reject functions.
+ wrapper->reject(); // FIXME: This should reject with an Exception.
+ }
+ };
+
+ auto exportFailureCallback = [wrapper]() mutable {
+ wrapper->reject(); // FIXME: This should reject with an Exception.
+ };
+
+ WebCore::exportKey(state, keyFormat, *key, WTFMove(exportSuccessCallback), WTFMove(exportFailureCallback));
+
+ return promise;
+}
+
+JSValue JSWebKitSubtleCrypto::unwrapKey(ExecState& state)
+{
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (state.argumentCount() < 5)
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+
+ auto keyFormat = cryptoKeyFormatFromJSValue(state, scope, state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ auto wrappedKeyData = cryptoOperationDataFromJSValue(state, scope, state.uncheckedArgument(1));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ RefPtr<CryptoKey> unwrappingKey = JSCryptoKey::toWrapped(vm, state.uncheckedArgument(2));
+ if (!unwrappingKey)
+ return throwTypeError(&state, scope);
+
+ if (!unwrappingKey->allows(CryptoKeyUsageUnwrapKey)) {
+ wrapped().document()->addConsoleMessage(MessageSource::JS, MessageLevel::Error, ASCIILiteral("Key usages do not include 'unwrapKey'"));
+ throwNotSupportedError(state, scope);
+ return jsUndefined();
+ }
+
+ auto unwrapAlgorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(3));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ auto unwrapAlgorithmParameters = JSCryptoAlgorithmDictionary::createParametersForDecrypt(state, scope, unwrapAlgorithm->identifier(), state.uncheckedArgument(3));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ RefPtr<CryptoAlgorithm> unwrappedKeyAlgorithm;
+ RefPtr<CryptoAlgorithmParametersDeprecated> unwrappedKeyAlgorithmParameters;
+ if (!state.uncheckedArgument(4).isNull()) {
+ unwrappedKeyAlgorithm = createAlgorithmFromJSValue(state, scope, state.uncheckedArgument(4));
+ RETURN_IF_EXCEPTION(scope, { });
+
+ unwrappedKeyAlgorithmParameters = JSCryptoAlgorithmDictionary::createParametersForImportKey(state, scope, unwrappedKeyAlgorithm->identifier(), state.uncheckedArgument(4));
+ RETURN_IF_EXCEPTION(scope, { });
+ }
+
+ bool extractable = state.argument(5).toBoolean(&state);
+ RETURN_IF_EXCEPTION(scope, { });
+
+ CryptoKeyUsageBitmap keyUsages = 0;
+ if (state.argumentCount() >= 7) {
+ keyUsages = cryptoKeyUsagesFromJSValue(state, scope, state.uncheckedArgument(6));
+ RETURN_IF_EXCEPTION(scope, { });
+ }
+
+ RefPtr<DeferredPromise> wrapper = createDeferredPromise(state, domWindow());
+ auto promise = wrapper->promise();
+ Strong<JSDOMGlobalObject> domGlobalObject(state.vm(), globalObject());
+
+ auto decryptSuccessCallback = [domGlobalObject, keyFormat, unwrappedKeyAlgorithm, unwrappedKeyAlgorithmParameters, extractable, keyUsages, wrapper](const Vector<uint8_t>& result) mutable {
+ auto importSuccessCallback = [wrapper](CryptoKey& key) mutable {
+ wrapper->resolve<IDLInterface<CryptoKey>>(key);
+ };
+ auto importFailureCallback = [wrapper]() mutable {
+ wrapper->reject(); // FIXME: This should reject with an Exception.
+ };
+
+ VM& vm = domGlobalObject->vm();
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+
+ ExecState& state = *domGlobalObject->globalExec();
+ WebCore::importKey(state, keyFormat, std::make_pair(result.data(), result.size()), unwrappedKeyAlgorithm, unwrappedKeyAlgorithmParameters, extractable, keyUsages, WTFMove(importSuccessCallback), WTFMove(importFailureCallback));
+ if (UNLIKELY(scope.exception())) {
+ // FIXME: Report exception details to console, and possibly to calling script once there is a standardized way to pass errors to WebCrypto promise reject functions.
+ scope.clearException();
+ wrapper->reject(); // FIXME: This should reject with an Exception.
+ }
+ };
+
+ auto decryptFailureCallback = [wrapper]() mutable {
+ wrapper->reject(); // FIXME: This should reject with an Exception.
+ };
+
+ auto result = unwrapAlgorithm->decryptForUnwrapKey(*unwrapAlgorithmParameters, *unwrappingKey, wrappedKeyData, WTFMove(decryptSuccessCallback), WTFMove(decryptFailureCallback));
+ if (result.hasException()) {
+ propagateException(state, scope, result.releaseException());
+ return { };
+ }
+
+ return promise;
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/WebCore/bindings/js/JSWorkerCustom.cpp b/Source/WebCore/bindings/js/JSWorkerCustom.cpp
index caa5318f1..84e07fe05 100644
--- a/Source/WebCore/bindings/js/JSWorkerCustom.cpp
+++ b/Source/WebCore/bindings/js/JSWorkerCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008-2009, 2016 Apple Inc. All Rights Reserved.
* Copyright (C) 2011 Google Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,48 +25,41 @@
*/
#include "config.h"
-
#include "JSWorker.h"
#include "Document.h"
+#include "JSDOMConstructorBase.h"
+#include "JSDOMConvertStrings.h"
+#include "JSDOMExceptionHandling.h"
#include "JSDOMGlobalObject.h"
-#include "JSMessagePortCustom.h"
-#include "Worker.h"
#include "JSDOMWindowCustom.h"
+#include "Worker.h"
#include <runtime/Error.h>
using namespace JSC;
namespace WebCore {
-JSC::JSValue JSWorker::postMessage(JSC::ExecState* exec)
+EncodedJSValue JSC_HOST_CALL constructJSWorker(ExecState& state)
{
- return handlePostMessage(exec, &impl());
-}
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
-EncodedJSValue JSC_HOST_CALL JSWorkerConstructor::constructJSWorker(ExecState* exec)
-{
- JSWorkerConstructor* jsConstructor = jsCast<JSWorkerConstructor*>(exec->callee());
+ ASSERT(jsCast<JSDOMConstructorBase*>(state.jsCallee()));
+ ASSERT(jsCast<JSDOMConstructorBase*>(state.jsCallee())->globalObject());
+ auto& globalObject = *jsCast<JSDOMConstructorBase*>(state.jsCallee())->globalObject();
- if (!exec->argumentCount())
- return throwVMError(exec, createNotEnoughArgumentsError(exec));
+ if (!state.argumentCount())
+ return throwVMError(&state, scope, createNotEnoughArgumentsError(&state));
- String scriptURL = exec->argument(0).toString(exec)->value(exec);
- if (exec->hadException())
- return JSValue::encode(JSValue());
+ auto scriptURL = convert<IDLDOMString>(state, state.uncheckedArgument(0));
+ RETURN_IF_EXCEPTION(scope, encodedJSValue());
- // See section 4.8.2 step 14 of WebWorkers for why this is the lexicalGlobalObject.
- DOMWindow& window = asJSDOMWindow(exec->lexicalGlobalObject())->impl();
+ // See section 4.8.2 step 14 of WebWorkers for why this is the lexicalGlobalObject.
+ auto& window = asJSDOMWindow(state.lexicalGlobalObject())->wrapped();
- ExceptionCode ec = 0;
ASSERT(window.document());
- RefPtr<Worker> worker = Worker::create(*window.document(), scriptURL, ec);
- if (ec) {
- setDOMException(exec, ec);
- return JSValue::encode(JSValue());
- }
-
- return JSValue::encode(asObject(toJS(exec, jsConstructor->globalObject(), worker.release())));
+ return JSValue::encode(toJSNewlyCreated<IDLInterface<Worker>>(state, globalObject, scope, Worker::create(*window.document(), scriptURL, globalObject.runtimeFlags())));
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp b/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp
index bc42aba4c..f1e6d8ed4 100644
--- a/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp
+++ b/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009, 2016 Apple Inc. All rights reserved.
* Copyright (C) 2009 Google Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -11,10 +11,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -26,58 +26,70 @@
*/
#include "config.h"
-
#include "JSWorkerGlobalScopeBase.h"
#include "DOMWrapperWorld.h"
#include "JSDOMGlobalObjectTask.h"
#include "JSDedicatedWorkerGlobalScope.h"
+#include "JSDynamicDowncast.h"
#include "JSWorkerGlobalScope.h"
+#include "Language.h"
#include "WorkerGlobalScope.h"
+#include "WorkerThread.h"
+#include <runtime/JSCInlines.h>
+#include <runtime/JSCJSValueInlines.h>
#include <runtime/Microtask.h>
-#if ENABLE(SHARED_WORKERS)
-#include "JSSharedWorkerGlobalScope.h"
-#endif
-
using namespace JSC;
namespace WebCore {
-const ClassInfo JSWorkerGlobalScopeBase::s_info = { "WorkerGlobalScope", &JSDOMGlobalObject::s_info, 0, 0, CREATE_METHOD_TABLE(JSWorkerGlobalScopeBase) };
+const ClassInfo JSWorkerGlobalScopeBase::s_info = { "WorkerGlobalScope", &JSDOMGlobalObject::s_info, 0, CREATE_METHOD_TABLE(JSWorkerGlobalScopeBase) };
-const GlobalObjectMethodTable JSWorkerGlobalScopeBase::s_globalObjectMethodTable = { &allowsAccessFrom, &supportsProfiling, &supportsRichSourceInfo, &shouldInterruptScript, &javaScriptExperimentsEnabled, &queueTaskToEventLoop, &shouldInterruptScriptBeforeTimeout };
+const GlobalObjectMethodTable JSWorkerGlobalScopeBase::s_globalObjectMethodTable = {
+ &supportsRichSourceInfo,
+ &shouldInterruptScript,
+ &javaScriptRuntimeFlags,
+ &queueTaskToEventLoop,
+ &shouldInterruptScriptBeforeTimeout,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ &defaultLanguage
+};
-JSWorkerGlobalScopeBase::JSWorkerGlobalScopeBase(JSC::VM& vm, JSC::Structure* structure, PassRefPtr<WorkerGlobalScope> impl)
- : JSDOMGlobalObject(vm, structure, &normalWorld(vm), &s_globalObjectMethodTable)
- , m_impl(impl)
+JSWorkerGlobalScopeBase::JSWorkerGlobalScopeBase(JSC::VM& vm, JSC::Structure* structure, RefPtr<WorkerGlobalScope>&& impl)
+ : JSDOMGlobalObject(vm, structure, normalWorld(vm), &s_globalObjectMethodTable)
+ , m_wrapped(WTFMove(impl))
{
}
-void JSWorkerGlobalScopeBase::finishCreation(VM& vm)
+void JSWorkerGlobalScopeBase::finishCreation(VM& vm, JSProxy* proxy)
{
- Base::finishCreation(vm);
- ASSERT(inherits(info()));
-}
+ m_proxy.set(vm, this, proxy);
-void JSWorkerGlobalScopeBase::destroy(JSCell* cell)
-{
- static_cast<JSWorkerGlobalScopeBase*>(cell)->JSWorkerGlobalScopeBase::~JSWorkerGlobalScopeBase();
+ Base::finishCreation(vm, m_proxy.get());
+ ASSERT(inherits(vm, info()));
}
-ScriptExecutionContext* JSWorkerGlobalScopeBase::scriptExecutionContext() const
+void JSWorkerGlobalScopeBase::visitChildren(JSCell* cell, SlotVisitor& visitor)
{
- return m_impl.get();
+ JSWorkerGlobalScopeBase* thisObject = jsCast<JSWorkerGlobalScopeBase*>(cell);
+ ASSERT_GC_OBJECT_INHERITS(thisObject, info());
+ Base::visitChildren(thisObject, visitor);
+ visitor.append(thisObject->m_proxy);
}
-bool JSWorkerGlobalScopeBase::allowsAccessFrom(const JSGlobalObject* object, ExecState* exec)
+void JSWorkerGlobalScopeBase::destroy(JSCell* cell)
{
- return JSGlobalObject::allowsAccessFrom(object, exec);
+ static_cast<JSWorkerGlobalScopeBase*>(cell)->JSWorkerGlobalScopeBase::~JSWorkerGlobalScopeBase();
}
-bool JSWorkerGlobalScopeBase::supportsProfiling(const JSGlobalObject* object)
+ScriptExecutionContext* JSWorkerGlobalScopeBase::scriptExecutionContext() const
{
- return JSGlobalObject::supportsProfiling(object);
+ return m_wrapped.get();
}
bool JSWorkerGlobalScopeBase::supportsRichSourceInfo(const JSGlobalObject* object)
@@ -95,64 +107,49 @@ bool JSWorkerGlobalScopeBase::shouldInterruptScriptBeforeTimeout(const JSGlobalO
return JSGlobalObject::shouldInterruptScriptBeforeTimeout(object);
}
-bool JSWorkerGlobalScopeBase::javaScriptExperimentsEnabled(const JSGlobalObject* object)
+RuntimeFlags JSWorkerGlobalScopeBase::javaScriptRuntimeFlags(const JSGlobalObject* object)
{
- return JSGlobalObject::javaScriptExperimentsEnabled(object);
+ const JSWorkerGlobalScopeBase *thisObject = jsCast<const JSWorkerGlobalScopeBase*>(object);
+ return thisObject->m_wrapped->thread().runtimeFlags();
}
-void JSWorkerGlobalScopeBase::queueTaskToEventLoop(const JSGlobalObject* object, PassRefPtr<Microtask> task)
+void JSWorkerGlobalScopeBase::queueTaskToEventLoop(const JSGlobalObject* object, Ref<JSC::Microtask>&& task)
{
const JSWorkerGlobalScopeBase* thisObject = static_cast<const JSWorkerGlobalScopeBase*>(object);
- thisObject->scriptExecutionContext()->postTask(JSGlobalObjectTask::create((JSDOMGlobalObject*)thisObject, task));
+ thisObject->scriptExecutionContext()->postTask(JSGlobalObjectTask((JSDOMGlobalObject*)thisObject, WTFMove(task)));
}
-JSValue toJS(ExecState* exec, JSDOMGlobalObject*, WorkerGlobalScope* workerGlobalScope)
+JSValue toJS(ExecState* exec, JSDOMGlobalObject*, WorkerGlobalScope& workerGlobalScope)
{
return toJS(exec, workerGlobalScope);
}
-JSValue toJS(ExecState*, WorkerGlobalScope* workerGlobalScope)
+JSValue toJS(ExecState*, WorkerGlobalScope& workerGlobalScope)
{
- if (!workerGlobalScope)
- return jsNull();
- WorkerScriptController* script = workerGlobalScope->script();
+ WorkerScriptController* script = workerGlobalScope.script();
if (!script)
return jsNull();
JSWorkerGlobalScope* contextWrapper = script->workerGlobalScopeWrapper();
ASSERT(contextWrapper);
- return contextWrapper;
+ return contextWrapper->proxy();
}
-JSDedicatedWorkerGlobalScope* toJSDedicatedWorkerGlobalScope(JSValue value)
+JSDedicatedWorkerGlobalScope* toJSDedicatedWorkerGlobalScope(VM& vm, JSValue value)
{
if (!value.isObject())
return 0;
- const ClassInfo* classInfo = asObject(value)->classInfo();
+ const ClassInfo* classInfo = asObject(value)->classInfo(vm);
if (classInfo == JSDedicatedWorkerGlobalScope::info())
return jsCast<JSDedicatedWorkerGlobalScope*>(asObject(value));
+ if (classInfo == JSProxy::info())
+ return jsDynamicDowncast<JSDedicatedWorkerGlobalScope*>(vm, jsCast<JSProxy*>(asObject(value))->target());
return 0;
}
-#if ENABLE(SHARED_WORKERS)
-JSSharedWorkerGlobalScope* toJSSharedWorkerGlobalScope(JSValue value)
-{
- if (!value.isObject())
- return 0;
- const ClassInfo* classInfo = asObject(value)->classInfo();
- if (classInfo == JSSharedWorkerGlobalScope::info())
- return jsCast<JSSharedWorkerGlobalScope*>(asObject(value));
- return 0;
-}
-#endif
-JSWorkerGlobalScope* toJSWorkerGlobalScope(JSValue value)
+JSWorkerGlobalScope* toJSWorkerGlobalScope(VM& vm, JSValue value)
{
- JSWorkerGlobalScope* context = toJSDedicatedWorkerGlobalScope(value);
-#if ENABLE(SHARED_WORKERS)
- if (!context)
- context = toJSSharedWorkerGlobalScope(value);
-#endif
- return context;
+ return toJSDedicatedWorkerGlobalScope(vm, value);
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.h b/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.h
index e2e93e14e..b0b36f9be 100644
--- a/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.h
+++ b/Source/WebCore/bindings/js/JSWorkerGlobalScopeBase.h
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -24,15 +24,14 @@
*
*/
-#ifndef JSWorkerGlobalScopeBase_h
-#define JSWorkerGlobalScopeBase_h
+#pragma once
#include "JSDOMGlobalObject.h"
+#include "JSDOMWrapper.h"
namespace WebCore {
class JSDedicatedWorkerGlobalScope;
- class JSSharedWorkerGlobalScope;
class JSWorkerGlobalScope;
class WorkerGlobalScope;
@@ -43,7 +42,8 @@ namespace WebCore {
DECLARE_INFO;
- WorkerGlobalScope& impl() const { return *m_impl; }
+ WorkerGlobalScope& wrapped() const { return *m_wrapped; }
+ JSC::JSProxy* proxy() const { ASSERT(m_proxy); return m_proxy.get(); }
ScriptExecutionContext* scriptExecutionContext() const;
static JSC::Structure* createStructure(JSC::VM& vm, JSC::JSGlobalObject* globalObject, JSC::JSValue prototype)
@@ -53,34 +53,31 @@ namespace WebCore {
static const JSC::GlobalObjectMethodTable s_globalObjectMethodTable;
- static bool allowsAccessFrom(const JSC::JSGlobalObject*, JSC::ExecState*);
- static bool supportsProfiling(const JSC::JSGlobalObject*);
static bool supportsRichSourceInfo(const JSC::JSGlobalObject*);
static bool shouldInterruptScript(const JSC::JSGlobalObject*);
static bool shouldInterruptScriptBeforeTimeout(const JSC::JSGlobalObject*);
- static bool javaScriptExperimentsEnabled(const JSC::JSGlobalObject*);
- static void queueTaskToEventLoop(const JSC::JSGlobalObject*, PassRefPtr<JSC::Microtask>);
+ static JSC::RuntimeFlags javaScriptRuntimeFlags(const JSC::JSGlobalObject*);
+ static void queueTaskToEventLoop(const JSC::JSGlobalObject*, Ref<JSC::Microtask>&&);
protected:
- JSWorkerGlobalScopeBase(JSC::VM&, JSC::Structure*, PassRefPtr<WorkerGlobalScope>);
- void finishCreation(JSC::VM&);
+ JSWorkerGlobalScopeBase(JSC::VM&, JSC::Structure*, RefPtr<WorkerGlobalScope>&&);
+ void finishCreation(JSC::VM&, JSC::JSProxy*);
+
+ static void visitChildren(JSC::JSCell*, JSC::SlotVisitor&);
private:
- RefPtr<WorkerGlobalScope> m_impl;
+ RefPtr<WorkerGlobalScope> m_wrapped;
+ JSC::WriteBarrier<JSC::JSProxy> m_proxy;
};
// Returns a JSWorkerGlobalScope or jsNull()
// Always ignores the execState and passed globalObject, WorkerGlobalScope is itself a globalObject and will always use its own prototype chain.
- JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, WorkerGlobalScope*);
- JSC::JSValue toJS(JSC::ExecState*, WorkerGlobalScope*);
-
- JSDedicatedWorkerGlobalScope* toJSDedicatedWorkerGlobalScope(JSC::JSValue);
- JSWorkerGlobalScope* toJSWorkerGlobalScope(JSC::JSValue);
+ JSC::JSValue toJS(JSC::ExecState*, JSDOMGlobalObject*, WorkerGlobalScope&);
+ inline JSC::JSValue toJS(JSC::ExecState* exec, JSDOMGlobalObject* globalObject, WorkerGlobalScope* scope) { return scope ? toJS(exec, globalObject, *scope) : JSC::jsNull(); }
+ JSC::JSValue toJS(JSC::ExecState*, WorkerGlobalScope&);
+ inline JSC::JSValue toJS(JSC::ExecState* exec, WorkerGlobalScope* scope) { return scope ? toJS(exec, *scope) : JSC::jsNull(); }
-#if ENABLE(SHARED_WORKERS)
- JSSharedWorkerGlobalScope* toJSSharedWorkerGlobalScope(JSC::JSValue);
-#endif
+ JSDedicatedWorkerGlobalScope* toJSDedicatedWorkerGlobalScope(JSC::VM&, JSC::JSValue);
+ JSWorkerGlobalScope* toJSWorkerGlobalScope(JSC::VM&, JSC::JSValue);
} // namespace WebCore
-
-#endif // JSWorkerGlobalScopeBase_h
diff --git a/Source/WebCore/bindings/js/JSWorkerGlobalScopeCustom.cpp b/Source/WebCore/bindings/js/JSWorkerGlobalScopeCustom.cpp
index d12d98e84..6663dfb7b 100644
--- a/Source/WebCore/bindings/js/JSWorkerGlobalScopeCustom.cpp
+++ b/Source/WebCore/bindings/js/JSWorkerGlobalScopeCustom.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008, 2009, 2011 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008-2009, 2011, 2016 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -24,95 +24,61 @@
*/
#include "config.h"
-
#include "JSWorkerGlobalScope.h"
-#include "ExceptionCode.h"
-#include "JSDOMBinding.h"
-#include "JSDOMGlobalObject.h"
-#include "JSEventListener.h"
-#include "JSEventSource.h"
-#include "JSMessageChannel.h"
-#include "JSMessagePort.h"
-#include "JSWorkerLocation.h"
-#include "JSWorkerNavigator.h"
-#include "JSXMLHttpRequest.h"
+#include "JSDOMConvert.h"
#include "ScheduledAction.h"
#include "WorkerGlobalScope.h"
-#include "WorkerLocation.h"
-#include "WorkerNavigator.h"
-#include <interpreter/Interpreter.h>
-
-#if ENABLE(WEB_SOCKETS)
-#include "JSWebSocket.h"
-#endif
using namespace JSC;
namespace WebCore {
-void JSWorkerGlobalScope::visitChildren(JSCell* cell, SlotVisitor& visitor)
+void JSWorkerGlobalScope::visitAdditionalChildren(SlotVisitor& visitor)
{
- JSWorkerGlobalScope* thisObject = jsCast<JSWorkerGlobalScope*>(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(thisObject, visitor);
-
- if (WorkerLocation* location = thisObject->impl().optionalLocation())
+ if (auto* location = wrapped().optionalLocation())
visitor.addOpaqueRoot(location);
- if (WorkerNavigator* navigator = thisObject->impl().optionalNavigator())
+ if (auto* navigator = wrapped().optionalNavigator())
visitor.addOpaqueRoot(navigator);
-
- thisObject->impl().visitJSEventListeners(visitor);
-}
-
-bool JSWorkerGlobalScope::getOwnPropertySlotDelegate(ExecState* exec, PropertyName propertyName, PropertySlot& slot)
-{
- // Look for overrides before looking at any of our own properties.
- if (JSGlobalObject::getOwnPropertySlot(this, exec, propertyName, slot))
- return true;
- return false;
+ ScriptExecutionContext& context = wrapped();
+ visitor.addOpaqueRoot(&context);
+
+ // Normally JSEventTargetCustom.cpp's JSEventTarget::visitAdditionalChildren() would call this. But
+ // even though WorkerGlobalScope is an EventTarget, JSWorkerGlobalScope does not subclass
+ // JSEventTarget, so we need to do this here.
+ wrapped().visitJSEventListeners(visitor);
}
-JSValue JSWorkerGlobalScope::importScripts(ExecState* exec)
+JSValue JSWorkerGlobalScope::setTimeout(ExecState& state)
{
- if (!exec->argumentCount())
- return jsUndefined();
-
- Vector<String> urls;
- for (unsigned i = 0; i < exec->argumentCount(); i++) {
- urls.append(exec->uncheckedArgument(i).toString(exec)->value(exec));
- if (exec->hadException())
- return jsUndefined();
- }
- ExceptionCode ec = 0;
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
- impl().importScripts(urls, ec);
- setDOMException(exec, ec);
- return jsUndefined();
-}
+ if (UNLIKELY(state.argumentCount() < 1))
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
-JSValue JSWorkerGlobalScope::setTimeout(ExecState* exec)
-{
- OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, currentWorld(exec), impl().contentSecurityPolicy());
- if (exec->hadException())
- return jsUndefined();
+ std::unique_ptr<ScheduledAction> action = ScheduledAction::create(&state, globalObject()->world(), wrapped().contentSecurityPolicy());
+ RETURN_IF_EXCEPTION(scope, JSValue());
if (!action)
return jsNumber(0);
- int delay = exec->argument(1).toInt32(exec);
- return jsNumber(impl().setTimeout(action.release(), delay));
+ int delay = state.argument(1).toInt32(&state);
+ return jsNumber(wrapped().setTimeout(WTFMove(action), delay));
}
-JSValue JSWorkerGlobalScope::setInterval(ExecState* exec)
+JSValue JSWorkerGlobalScope::setInterval(ExecState& state)
{
- OwnPtr<ScheduledAction> action = ScheduledAction::create(exec, currentWorld(exec), impl().contentSecurityPolicy());
- if (exec->hadException())
- return jsUndefined();
+ VM& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ if (UNLIKELY(state.argumentCount() < 1))
+ return throwException(&state, scope, createNotEnoughArgumentsError(&state));
+
+ std::unique_ptr<ScheduledAction> action = ScheduledAction::create(&state, globalObject()->world(), wrapped().contentSecurityPolicy());
+ RETURN_IF_EXCEPTION(scope, JSValue());
if (!action)
return jsNumber(0);
- int delay = exec->argument(1).toInt32(exec);
- return jsNumber(impl().setInterval(action.release(), delay));
+ int delay = state.argument(1).toInt32(&state);
+ return jsNumber(wrapped().setInterval(WTFMove(action), delay));
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSXMLDocumentCustom.cpp b/Source/WebCore/bindings/js/JSXMLDocumentCustom.cpp
new file mode 100644
index 000000000..9c82c500b
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSXMLDocumentCustom.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSXMLDocument.h"
+
+#include "JSDOMWindow.h"
+#include "JSDocumentCustom.h"
+#include "JSSVGDocument.h"
+#include "NodeTraversal.h"
+
+namespace WebCore {
+
+using namespace JSC;
+
+JSValue toJSNewlyCreated(ExecState* state, JSDOMGlobalObject* globalObject, Ref<XMLDocument>&& document)
+{
+ reportMemoryForDocumentIfFrameless(*state, document.get());
+
+ return createWrapper<XMLDocument>(globalObject, WTFMove(document));
+}
+
+JSValue toJS(ExecState* state, JSDOMGlobalObject* globalObject, XMLDocument& document)
+{
+ if (auto* wrapper = cachedDocumentWrapper(*state, *globalObject, document))
+ return wrapper;
+ return toJSNewlyCreated(state, globalObject, Ref<XMLDocument>(document));
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp b/Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp
index 7ea887833..7d584d74c 100644
--- a/Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp
+++ b/Source/WebCore/bindings/js/JSXMLHttpRequestCustom.cpp
@@ -10,7 +10,7 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * 3. Neither the name of Apple Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
@@ -39,13 +39,13 @@
#include "HTMLDocument.h"
#include "InspectorInstrumentation.h"
#include "JSBlob.h"
+#include "JSDOMConvert.h"
#include "JSDOMFormData.h"
#include "JSDOMWindowCustom.h"
#include "JSDocument.h"
#include "JSEvent.h"
#include "JSEventListener.h"
#include "XMLHttpRequest.h"
-#include <interpreter/StackVisitor.h>
#include <runtime/ArrayBuffer.h>
#include <runtime/Error.h>
#include <runtime/JSArrayBuffer.h>
@@ -56,184 +56,81 @@ using namespace JSC;
namespace WebCore {
-void JSXMLHttpRequest::visitChildren(JSCell* cell, SlotVisitor& visitor)
+void JSXMLHttpRequest::visitAdditionalChildren(SlotVisitor& visitor)
{
- JSXMLHttpRequest* thisObject = jsCast<JSXMLHttpRequest*>(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(thisObject, visitor);
-
- if (XMLHttpRequestUpload* upload = thisObject->m_impl->optionalUpload())
+ if (XMLHttpRequestUpload* upload = wrapped().optionalUpload())
visitor.addOpaqueRoot(upload);
- if (Document* responseDocument = thisObject->m_impl->optionalResponseXML())
+ if (Document* responseDocument = wrapped().optionalResponseXML())
visitor.addOpaqueRoot(responseDocument);
-
- if (ArrayBuffer* responseArrayBuffer = thisObject->m_impl->optionalResponseArrayBuffer())
- visitor.addOpaqueRoot(responseArrayBuffer);
-
- if (Blob* responseBlob = thisObject->m_impl->optionalResponseBlob())
- visitor.addOpaqueRoot(responseBlob);
-
- if (thisObject->m_response)
- visitor.append(&thisObject->m_response);
-
- thisObject->m_impl->visitJSEventListeners(visitor);
}
-// Custom functions
-JSValue JSXMLHttpRequest::open(ExecState* exec)
+JSValue JSXMLHttpRequest::responseText(ExecState& state) const
{
- if (exec->argumentCount() < 2)
- return exec->vm().throwException(exec, createNotEnoughArgumentsError(exec));
-
- const URL& url = impl().scriptExecutionContext()->completeURL(exec->uncheckedArgument(1).toString(exec)->value(exec));
- String method = exec->uncheckedArgument(0).toString(exec)->value(exec);
-
- ExceptionCode ec = 0;
- if (exec->argumentCount() >= 3) {
- bool async = exec->uncheckedArgument(2).toBoolean(exec);
- if (!exec->argument(3).isUndefined()) {
- String user = valueToStringWithNullCheck(exec, exec->uncheckedArgument(3));
-
- if (!exec->argument(4).isUndefined()) {
- String password = valueToStringWithNullCheck(exec, exec->uncheckedArgument(4));
- impl().open(method, url, async, user, password, ec);
- } else
- impl().open(method, url, async, user, ec);
- } else
- impl().open(method, url, async, ec);
- } else
- impl().open(method, url, ec);
-
- setDOMException(exec, ec);
- return jsUndefined();
-}
-
-class SendFunctor {
-public:
- SendFunctor()
- : m_hasSkippedFirstFrame(false)
- , m_line(0)
- , m_column(0)
- {
- }
+ auto result = wrapped().responseText();
- unsigned line() const { return m_line; }
- unsigned column() const { return m_column; }
- String url() const { return m_url; }
-
- StackVisitor::Status operator()(StackVisitor& visitor)
- {
- if (!m_hasSkippedFirstFrame) {
- m_hasSkippedFirstFrame = true;
- return StackVisitor::Continue;
- }
-
- unsigned line = 0;
- unsigned column = 0;
- visitor->computeLineAndColumn(line, column);
- m_line = line;
- m_column = column;
- m_url = visitor->sourceURL();
- return StackVisitor::Done;
+ if (UNLIKELY(result.hasException())) {
+ auto& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ propagateException(state, scope, result.releaseException());
+ return { };
}
-private:
- bool m_hasSkippedFirstFrame;
- unsigned m_line;
- unsigned m_column;
- String m_url;
-};
+ auto resultValue = result.releaseReturnValue();
+ if (resultValue.isNull())
+ return jsNull();
-JSValue JSXMLHttpRequest::send(ExecState* exec)
-{
- InspectorInstrumentation::willSendXMLHttpRequest(impl().scriptExecutionContext(), impl().url());
-
- ExceptionCode ec = 0;
- JSValue val = exec->argument(0);
- if (val.isUndefinedOrNull())
- impl().send(ec);
- else if (val.inherits(JSDocument::info()))
- impl().send(toDocument(val), ec);
- else if (val.inherits(JSBlob::info()))
- impl().send(toBlob(val), ec);
- else if (val.inherits(JSDOMFormData::info()))
- impl().send(toDOMFormData(val), ec);
- else if (val.inherits(JSArrayBuffer::info()))
- impl().send(toArrayBuffer(val), ec);
- else if (val.inherits(JSArrayBufferView::info())) {
- RefPtr<ArrayBufferView> view = toArrayBufferView(val);
- impl().send(view.get(), ec);
- } else
- impl().send(val.toString(exec)->value(exec), ec);
-
- SendFunctor functor;
- exec->iterate(functor);
- impl().setLastSendLineAndColumnNumber(functor.line(), functor.column());
- impl().setLastSendURL(functor.url());
- setDOMException(exec, ec);
- return jsUndefined();
+ // See JavaScriptCore for explanation: Should be used for any string that is already owned by another
+ // object, to let the engine know that collecting the JSString wrapper is unlikely to save memory.
+ return jsOwnedString(&state, resultValue);
}
-JSValue JSXMLHttpRequest::responseText(ExecState* exec) const
+JSValue JSXMLHttpRequest::retrieveResponse(ExecState& state)
{
- ExceptionCode ec = 0;
- String text = impl().responseText(ec);
- if (ec) {
- setDOMException(exec, ec);
+ auto type = wrapped().responseType();
+
+ switch (type) {
+ case XMLHttpRequest::ResponseType::EmptyString:
+ case XMLHttpRequest::ResponseType::Text:
+ return responseText(state);
+ default:
+ break;
+ }
+
+ if (!wrapped().doneWithoutErrors())
+ return jsNull();
+
+ JSValue value;
+ switch (type) {
+ case XMLHttpRequest::ResponseType::EmptyString:
+ case XMLHttpRequest::ResponseType::Text:
+ ASSERT_NOT_REACHED();
return jsUndefined();
+
+ case XMLHttpRequest::ResponseType::Json:
+ value = JSONParse(&state, wrapped().responseTextIgnoringResponseType());
+ if (!value)
+ value = jsNull();
+ break;
+
+ case XMLHttpRequest::ResponseType::Document: {
+ auto document = wrapped().responseXML();
+ ASSERT(!document.hasException());
+ value = toJS<IDLInterface<Document>>(state, *globalObject(), document.releaseReturnValue());
+ break;
}
- return jsOwnedStringOrNull(exec, text);
-}
-JSValue JSXMLHttpRequest::response(ExecState* exec) const
-{
- switch (impl().responseTypeCode()) {
- case XMLHttpRequest::ResponseTypeDefault:
- case XMLHttpRequest::ResponseTypeText:
- return responseText(exec);
-
- case XMLHttpRequest::ResponseTypeJSON:
- {
- // FIXME: Use CachedAttribute for other types as well.
- if (m_response && impl().responseCacheIsValid())
- return m_response.get();
-
- if (!impl().doneWithoutErrors())
- return jsNull();
-
- JSValue value = JSONParse(exec, impl().responseTextIgnoringResponseType());
- if (!value)
- value = jsNull();
- JSXMLHttpRequest* jsRequest = const_cast<JSXMLHttpRequest*>(this);
- jsRequest->m_response.set(exec->vm(), jsRequest, value);
-
- impl().didCacheResponseJSON();
-
- return value;
- }
-
- case XMLHttpRequest::ResponseTypeDocument:
- {
- ExceptionCode ec = 0;
- Document* document = impl().responseXML(ec);
- if (ec) {
- setDOMException(exec, ec);
- return jsUndefined();
- }
- return toJS(exec, globalObject(), document);
- }
-
- case XMLHttpRequest::ResponseTypeBlob:
- return toJS(exec, globalObject(), impl().responseBlob());
-
- case XMLHttpRequest::ResponseTypeArrayBuffer:
- return toJS(exec, globalObject(), impl().responseArrayBuffer());
+ case XMLHttpRequest::ResponseType::Blob:
+ value = toJSNewlyCreated<IDLInterface<Blob>>(state, *globalObject(), wrapped().createResponseBlob());
+ break;
+
+ case XMLHttpRequest::ResponseType::Arraybuffer:
+ value = toJS<IDLInterface<ArrayBuffer>>(state, *globalObject(), wrapped().createResponseArrayBuffer());
+ break;
}
- return jsUndefined();
+ wrapped().didCacheResponse();
+ return value;
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSXPathNSResolverCustom.cpp b/Source/WebCore/bindings/js/JSXPathNSResolverCustom.cpp
new file mode 100644
index 000000000..8c1761ccb
--- /dev/null
+++ b/Source/WebCore/bindings/js/JSXPathNSResolverCustom.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "JSXPathNSResolver.h"
+
+#include "JSCustomXPathNSResolver.h"
+#include "JSDOMExceptionHandling.h"
+
+using namespace JSC;
+
+namespace WebCore {
+
+RefPtr<XPathNSResolver> JSXPathNSResolver::toWrapped(VM& vm, ExecState& state, JSValue value)
+{
+ if (value.inherits(vm, JSXPathNSResolver::info()))
+ return &jsCast<JSXPathNSResolver*>(asObject(value))->wrapped();
+
+ auto result = JSCustomXPathNSResolver::create(state, value);
+ if (UNLIKELY(result.hasException())) {
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ propagateException(state, scope, result.releaseException());
+ return nullptr;
+ }
+ return result.releaseReturnValue();
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSXPathResultCustom.cpp b/Source/WebCore/bindings/js/JSXPathResultCustom.cpp
index 35ba89231..d4fbbef6f 100644
--- a/Source/WebCore/bindings/js/JSXPathResultCustom.cpp
+++ b/Source/WebCore/bindings/js/JSXPathResultCustom.cpp
@@ -26,30 +26,18 @@
#include "config.h"
#include "JSXPathResult.h"
-#include "JSDOMBinding.h"
#include "JSNodeCustom.h"
-#include "XPathResult.h"
#include "XPathValue.h"
-using namespace JSC;
-
namespace WebCore {
-void JSXPathResult::visitChildren(JSCell* cell, SlotVisitor& visitor)
+void JSXPathResult::visitAdditionalChildren(JSC::SlotVisitor& visitor)
{
- JSXPathResult* thisObject = jsCast<JSXPathResult*>(cell);
- ASSERT_GC_OBJECT_INHERITS(thisObject, info());
- COMPILE_ASSERT(StructureFlags & OverridesVisitChildren, OverridesVisitChildrenWithoutSettingFlag);
- ASSERT(thisObject->structure()->typeInfo().overridesVisitChildren());
- Base::visitChildren(thisObject, visitor);
-
- const XPath::Value& xpathValue = thisObject->impl().value();
- if (xpathValue.isNodeSet()) {
- const XPath::NodeSet& nodesToMark = xpathValue.toNodeSet();
- for (size_t i = 0; i < nodesToMark.size(); ++i) {
- Node* node = nodesToMark[i];
- visitor.addOpaqueRoot(root(node));
- }
+ auto& value = wrapped().value();
+ if (value.isNodeSet()) {
+ // FIXME: This looks like it might race, but I'm not sure.
+ for (auto& node : value.toNodeSet())
+ visitor.addOpaqueRoot(root(node.get()));
}
}
diff --git a/Source/WebCore/bindings/js/JSXSLTProcessorCustom.cpp b/Source/WebCore/bindings/js/JSXSLTProcessorCustom.cpp
deleted file mode 100644
index 1086de270..000000000
--- a/Source/WebCore/bindings/js/JSXSLTProcessorCustom.cpp
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
- * its contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#if ENABLE(XSLT)
-
-#include "JSXSLTProcessor.h"
-
-#include "Document.h"
-#include "DocumentFragment.h"
-#include "JSDocument.h"
-#include "JSDocumentFragment.h"
-#include "JSNode.h"
-#include "Node.h"
-#include "XSLTProcessor.h"
-#include "JSDOMBinding.h"
-#include <wtf/text/WTFString.h>
-
-using namespace JSC;
-
-namespace WebCore {
-
-JSValue JSXSLTProcessor::setParameter(ExecState* exec)
-{
- if (exec->argument(1).isUndefinedOrNull() || exec->argument(2).isUndefinedOrNull())
- return jsUndefined(); // Throw exception?
- String namespaceURI = exec->uncheckedArgument(0).toString(exec)->value(exec);
- String localName = exec->uncheckedArgument(1).toString(exec)->value(exec);
- String value = exec->uncheckedArgument(2).toString(exec)->value(exec);
- impl().setParameter(namespaceURI, localName, value);
- return jsUndefined();
-}
-
-JSValue JSXSLTProcessor::getParameter(ExecState* exec)
-{
- if (exec->argument(1).isUndefinedOrNull())
- return jsUndefined();
- String namespaceURI = exec->uncheckedArgument(0).toString(exec)->value(exec);
- String localName = exec->uncheckedArgument(1).toString(exec)->value(exec);
- String value = impl().getParameter(namespaceURI, localName);
- return jsStringOrUndefined(exec, value);
-}
-
-JSValue JSXSLTProcessor::removeParameter(ExecState* exec)
-{
- if (exec->argument(1).isUndefinedOrNull())
- return jsUndefined();
- String namespaceURI = exec->uncheckedArgument(0).toString(exec)->value(exec);
- String localName = exec->uncheckedArgument(1).toString(exec)->value(exec);
- impl().removeParameter(namespaceURI, localName);
- return jsUndefined();
-}
-
-} // namespace WebCore
-
-#endif // ENABLE(XSLT)
diff --git a/Source/WebCore/bindings/js/ModuleFetchFailureKind.h b/Source/WebCore/bindings/js/ModuleFetchFailureKind.h
new file mode 100644
index 000000000..259ef1ed6
--- /dev/null
+++ b/Source/WebCore/bindings/js/ModuleFetchFailureKind.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+namespace WebCore {
+
+enum class ModuleFetchFailureKind {
+ WasErrored,
+ WasCanceled,
+};
+
+} // namespace WebCore
+
diff --git a/Source/WebCore/bindings/js/PageScriptDebugServer.cpp b/Source/WebCore/bindings/js/PageScriptDebugServer.cpp
deleted file mode 100644
index e938d8900..000000000
--- a/Source/WebCore/bindings/js/PageScriptDebugServer.cpp
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * Copyright (c) 2011 Google Inc. All rights reserved.
- * Copyright (C) 2013 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "PageScriptDebugServer.h"
-
-#include "Document.h"
-#include "EventLoop.h"
-#include "FrameView.h"
-#include "JSDOMWindowCustom.h"
-#include "MainFrame.h"
-#include "Page.h"
-#include "PageGroup.h"
-#include "PluginView.h"
-#include "ScriptController.h"
-#include "Timer.h"
-#include "Widget.h"
-#include <runtime/JSLock.h>
-#include <wtf/MainThread.h>
-#include <wtf/OwnPtr.h>
-#include <wtf/PassOwnPtr.h>
-#include <wtf/StdLibExtras.h>
-
-#if PLATFORM(IOS)
-#include "JSDOMWindowBase.h"
-#include "WebCoreThreadInternal.h"
-#endif
-
-using namespace JSC;
-using namespace Inspector;
-
-namespace WebCore {
-
-static Page* toPage(JSGlobalObject* globalObject)
-{
- ASSERT_ARG(globalObject, globalObject);
-
- JSDOMWindow* window = asJSDOMWindow(globalObject);
- Frame* frame = window->impl().frame();
- return frame ? frame->page() : 0;
-}
-
-PageScriptDebugServer& PageScriptDebugServer::shared()
-{
- DEFINE_STATIC_LOCAL(PageScriptDebugServer, server, ());
- return server;
-}
-
-PageScriptDebugServer::PageScriptDebugServer()
- : ScriptDebugServer()
- , m_pausedPage(0)
-{
-}
-
-PageScriptDebugServer::~PageScriptDebugServer()
-{
-}
-
-void PageScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page)
-{
- ASSERT_ARG(listener, listener);
- ASSERT_ARG(page, page);
-
- OwnPtr<ListenerSet>& listeners = m_pageListenersMap.add(page, nullptr).iterator->value;
- if (!listeners)
- listeners = adoptPtr(new ListenerSet);
-
- bool wasEmpty = listeners->isEmpty();
- listeners->add(listener);
-
- if (wasEmpty)
- didAddFirstListener(page);
-}
-
-void PageScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* page, bool skipRecompile)
-{
- ASSERT_ARG(listener, listener);
- ASSERT_ARG(page, page);
-
- PageListenersMap::iterator it = m_pageListenersMap.find(page);
- if (it == m_pageListenersMap.end())
- return;
-
- ListenerSet* listeners = it->value.get();
- listeners->remove(listener);
-
- if (listeners->isEmpty()) {
- m_pageListenersMap.remove(it);
- didRemoveLastListener(page, skipRecompile);
- }
-}
-
-void PageScriptDebugServer::recompileAllJSFunctions()
-{
- JSLockHolder lock(JSDOMWindow::commonVM());
- Debugger::recompileAllJSFunctions(JSDOMWindow::commonVM());
-}
-
-ScriptDebugServer::ListenerSet* PageScriptDebugServer::getListenersForGlobalObject(JSGlobalObject* globalObject)
-{
- Page* page = toPage(globalObject);
- if (!page)
- return 0;
- return m_pageListenersMap.get(page);
-}
-
-void PageScriptDebugServer::didPause(JSC::JSGlobalObject* globalObject)
-{
- ASSERT(!m_pausedPage);
-
- Page* page = toPage(globalObject);
- ASSERT(page);
- if (!page)
- return;
-
- m_pausedPage = page;
-
- setJavaScriptPaused(page->group(), true);
-}
-
-void PageScriptDebugServer::didContinue(JSC::JSGlobalObject* globalObject)
-{
- // Page can be null if we are continuing because the Page closed.
- Page* page = toPage(globalObject);
- ASSERT(!page || page == m_pausedPage);
-
- m_pausedPage = 0;
-
- if (page)
- setJavaScriptPaused(page->group(), false);
-}
-
-void PageScriptDebugServer::didAddFirstListener(Page* page)
-{
- // Set debugger before recompiling to get sourceParsed callbacks.
- page->setDebugger(this);
- recompileAllJSFunctions();
-}
-
-void PageScriptDebugServer::didRemoveLastListener(Page* page, bool skipRecompile)
-{
- ASSERT(page);
-
- if (m_pausedPage == page)
- m_doneProcessingDebuggerEvents = true;
-
- // Clear debugger before recompiling because we do not need sourceParsed callbacks.
- page->setDebugger(nullptr);
-
- if (!skipRecompile)
- recompileAllJSFunctions();
-}
-
-void PageScriptDebugServer::runEventLoopWhilePaused()
-{
-#if PLATFORM(IOS)
- // On iOS, running an EventLoop causes us to run a nested WebRunLoop.
- // Since the WebThread is autoreleased at the end of run loop iterations
- // we need to gracefully handle releasing and reacquiring the lock.
- ASSERT(WebThreadIsLockedOrDisabled());
- {
- if (WebThreadIsEnabled())
- JSC::JSLock::DropAllLocks dropAllLocks(WebCore::JSDOMWindowBase::commonVM(), JSC::JSLock::DropAllLocks::AlwaysDropLocks);
- WebRunLoopEnableNested();
-#endif
-
- TimerBase::fireTimersInNestedEventLoop();
-
- EventLoop loop;
- while (!m_doneProcessingDebuggerEvents && !loop.ended())
- loop.cycle();
-
-#if PLATFORM(IOS)
- WebRunLoopDisableNested();
- }
- ASSERT(WebThreadIsLockedOrDisabled());
-#endif
-}
-
-bool PageScriptDebugServer::isContentScript(ExecState* exec) const
-{
- return &currentWorld(exec) != &mainThreadNormalWorld();
-}
-
-void PageScriptDebugServer::reportException(ExecState* exec, JSValue exception) const
-{
- WebCore::reportException(exec, exception);
-}
-
-void PageScriptDebugServer::setJavaScriptPaused(const PageGroup& pageGroup, bool paused)
-{
- setMainThreadCallbacksPaused(paused);
-
- const HashSet<Page*>& pages = pageGroup.pages();
-
- HashSet<Page*>::const_iterator end = pages.end();
- for (HashSet<Page*>::const_iterator it = pages.begin(); it != end; ++it)
- setJavaScriptPaused(*it, paused);
-}
-
-void PageScriptDebugServer::setJavaScriptPaused(Page* page, bool paused)
-{
- ASSERT_ARG(page, page);
-
- page->setDefersLoading(paused);
-
- for (Frame* frame = &page->mainFrame(); frame; frame = frame->tree().traverseNext())
- setJavaScriptPaused(frame, paused);
-}
-
-void PageScriptDebugServer::setJavaScriptPaused(Frame* frame, bool paused)
-{
- ASSERT_ARG(frame, frame);
-
- if (!frame->script().canExecuteScripts(NotAboutToExecuteScript))
- return;
-
- frame->script().setPaused(paused);
-
- Document* document = frame->document();
- if (paused) {
- document->suspendScriptedAnimationControllerCallbacks();
- document->suspendActiveDOMObjects(ActiveDOMObject::JavaScriptDebuggerPaused);
- } else {
- document->resumeActiveDOMObjects(ActiveDOMObject::JavaScriptDebuggerPaused);
- document->resumeScriptedAnimationControllerCallbacks();
- }
-
- setJavaScriptPaused(frame->view(), paused);
-}
-
-void PageScriptDebugServer::setJavaScriptPaused(FrameView* view, bool paused)
-{
- if (!view)
- return;
-
- for (auto it = view->children().begin(), end = view->children().end(); it != end; ++it) {
- Widget* widget = (*it).get();
- if (!widget->isPluginView())
- continue;
- toPluginView(widget)->setJavaScriptPaused(paused);
- }
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/PageScriptDebugServer.h b/Source/WebCore/bindings/js/PageScriptDebugServer.h
deleted file mode 100644
index 75db77a1c..000000000
--- a/Source/WebCore/bindings/js/PageScriptDebugServer.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef PageScriptDebugServer_h
-#define PageScriptDebugServer_h
-
-#include <inspector/ScriptDebugServer.h>
-#include <wtf/Forward.h>
-
-namespace WebCore {
-
-class Frame;
-class FrameView;
-class Page;
-class PageGroup;
-
-class PageScriptDebugServer : public Inspector::ScriptDebugServer {
- WTF_MAKE_NONCOPYABLE(PageScriptDebugServer);
-public:
- static PageScriptDebugServer& shared();
-
- void addListener(Inspector::ScriptDebugListener*, Page*);
- void removeListener(Inspector::ScriptDebugListener*, Page*, bool skipRecompile);
-
- virtual void recompileAllJSFunctions() override;
-
-private:
- typedef HashMap<Page*, OwnPtr<ListenerSet>> PageListenersMap;
-
- PageScriptDebugServer();
- virtual ~PageScriptDebugServer();
-
- virtual ListenerSet* getListenersForGlobalObject(JSC::JSGlobalObject*);
- virtual void didPause(JSC::JSGlobalObject*);
- virtual void didContinue(JSC::JSGlobalObject*);
- virtual void runEventLoopWhilePaused();
- virtual bool isContentScript(JSC::ExecState*) const override;
- virtual void reportException(JSC::ExecState*, JSC::JSValue) const override;
-
-
- void didAddFirstListener(Page*);
- void didRemoveLastListener(Page*, bool skipRecompile);
-
- void setJavaScriptPaused(const PageGroup&, bool paused);
- void setJavaScriptPaused(Page*, bool paused);
- void setJavaScriptPaused(Frame*, bool paused);
- void setJavaScriptPaused(FrameView*, bool paused);
-
- PageListenersMap m_pageListenersMap;
- Page* m_pausedPage;
-};
-
-} // namespace WebCore
-
-#endif // PageScriptDebugServer_h
diff --git a/Source/WebCore/bindings/js/ReadableStreamDefaultController.cpp b/Source/WebCore/bindings/js/ReadableStreamDefaultController.cpp
new file mode 100644
index 000000000..080cf7013
--- /dev/null
+++ b/Source/WebCore/bindings/js/ReadableStreamDefaultController.cpp
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2016 Canon Inc.
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted, provided that the following conditions
+ * are required to be met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Canon Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+
+#include "config.h"
+#include "ReadableStreamDefaultController.h"
+
+#if ENABLE(READABLE_STREAM_API)
+
+#include "WebCoreJSClientData.h"
+#include <heap/HeapInlines.h>
+#include <runtime/IdentifierInlines.h>
+#include <runtime/JSObjectInlines.h>
+
+namespace WebCore {
+
+static inline JSC::JSValue callFunction(JSC::ExecState& state, JSC::JSValue jsFunction, JSC::JSValue thisValue, const JSC::ArgList& arguments)
+{
+ JSC::CallData callData;
+ auto callType = JSC::getCallData(jsFunction, callData);
+ return call(&state, jsFunction, callType, callData, thisValue, arguments);
+}
+
+JSC::JSValue ReadableStreamDefaultController::invoke(JSC::ExecState& state, JSC::JSObject& object, const char* propertyName, JSC::JSValue parameter)
+{
+ JSC::VM& vm = state.vm();
+ JSC::JSLockHolder lock(vm);
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ auto function = object.get(&state, JSC::Identifier::fromString(&state, propertyName));
+ RETURN_IF_EXCEPTION(scope, JSC::JSValue());
+
+ if (!function.isFunction()) {
+ if (!function.isUndefined())
+ throwTypeError(&state, scope, ASCIILiteral("ReadableStream trying to call a property that is not callable"));
+ return JSC::jsUndefined();
+ }
+
+ JSC::MarkedArgumentBuffer arguments;
+ arguments.append(parameter);
+
+ return callFunction(state, function, &object, arguments);
+}
+
+bool ReadableStreamDefaultController::isControlledReadableStreamLocked() const
+{
+ auto& globalObject = this->globalObject();
+ JSC::VM& vm = globalObject.vm();
+ JSC::JSLockHolder lock(vm);
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+ auto& state = globalExec();
+
+ auto& clientData = *static_cast<JSVMClientData*>(vm.clientData);
+ auto readableStream = m_jsController->get(&state, clientData.builtinNames().controlledReadableStreamPrivateName());
+ ASSERT_UNUSED(scope, !scope.exception());
+
+ auto* isLocked = globalObject.builtinInternalFunctions().readableStreamInternals().m_isReadableStreamLockedFunction.get();
+ ASSERT(isLocked);
+
+ JSC::MarkedArgumentBuffer arguments;
+ arguments.append(readableStream);
+ auto result = callFunction(state, isLocked, JSC::jsUndefined(), arguments);
+ ASSERT(!scope.exception());
+
+ return result.isTrue();
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(READABLE_STREAM_API)
diff --git a/Source/WebCore/bindings/js/ReadableStreamDefaultController.h b/Source/WebCore/bindings/js/ReadableStreamDefaultController.h
new file mode 100644
index 000000000..c3500b14a
--- /dev/null
+++ b/Source/WebCore/bindings/js/ReadableStreamDefaultController.h
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2016 Canon Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted, provided that the following conditions
+ * are required to be met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Canon Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#if ENABLE(READABLE_STREAM_API)
+
+#include "JSDOMConvertBufferSource.h"
+#include "JSReadableStreamDefaultController.h"
+#include <runtime/JSCJSValue.h>
+#include <runtime/JSCJSValueInlines.h>
+#include <runtime/TypedArrays.h>
+
+namespace WebCore {
+
+class ReadableStreamSource;
+
+class ReadableStreamDefaultController {
+public:
+ explicit ReadableStreamDefaultController(JSReadableStreamDefaultController* controller) : m_jsController(controller) { }
+
+ static JSC::JSValue invoke(JSC::ExecState&, JSC::JSObject&, const char*, JSC::JSValue);
+
+ bool enqueue(RefPtr<JSC::ArrayBuffer>&&);
+
+ template<class ResolveResultType>
+ void error(const ResolveResultType&);
+
+ void close() { invoke(*globalObject().globalExec(), jsController(), "close", JSC::jsUndefined()); }
+
+ bool isControlledReadableStreamLocked() const;
+
+private:
+ void error(JSC::ExecState& state, JSC::JSValue value) { invoke(state, jsController(), "error", value); }
+ void enqueue(JSC::ExecState& state, JSC::JSValue value) { invoke(state, jsController(), "enqueue", value); }
+ JSReadableStreamDefaultController& jsController() const;
+
+ JSDOMGlobalObject& globalObject() const;
+ JSC::ExecState& globalExec() const;
+
+ // The owner of ReadableStreamDefaultController is responsible to keep uncollected the JSReadableStreamDefaultController.
+ JSReadableStreamDefaultController* m_jsController { nullptr };
+};
+
+inline JSReadableStreamDefaultController& ReadableStreamDefaultController::jsController() const
+{
+ ASSERT(m_jsController);
+ return *m_jsController;
+}
+
+inline JSDOMGlobalObject& ReadableStreamDefaultController::globalObject() const
+{
+ ASSERT(m_jsController);
+ ASSERT(m_jsController->globalObject());
+ return *static_cast<JSDOMGlobalObject*>(m_jsController->globalObject());
+}
+
+inline JSC::ExecState& ReadableStreamDefaultController::globalExec() const
+{
+ ASSERT(globalObject().globalExec());
+ return *globalObject().globalExec();
+}
+
+inline bool ReadableStreamDefaultController::enqueue(RefPtr<JSC::ArrayBuffer>&& buffer)
+{
+ auto& globalObject = this->globalObject();
+ JSC::VM& vm = globalObject.vm();
+ JSC::JSLockHolder locker(vm);
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ JSC::ExecState& state = globalExec();
+
+ if (!buffer) {
+ error(state, createOutOfMemoryError(&state));
+ return false;
+ }
+ auto length = buffer->byteLength();
+ auto chunk = JSC::Uint8Array::create(WTFMove(buffer), 0, length);
+ ASSERT(chunk);
+ enqueue(state, toJS(&state, &globalObject, chunk.get()));
+ ASSERT_UNUSED(scope, !scope.exception());
+ return true;
+}
+
+template<>
+inline void ReadableStreamDefaultController::error<String>(const String& errorMessage)
+{
+ JSC::ExecState& state = globalExec();
+ JSC::JSLockHolder locker(&state);
+ error(state, JSC::createTypeError(&state, errorMessage));
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(READABLE_STREAM_API)
diff --git a/Source/WebCore/bindings/js/ScheduledAction.cpp b/Source/WebCore/bindings/js/ScheduledAction.cpp
index 9173edd49..93332666b 100644
--- a/Source/WebCore/bindings/js/ScheduledAction.cpp
+++ b/Source/WebCore/bindings/js/ScheduledAction.cpp
@@ -29,7 +29,7 @@
#include "Document.h"
#include "Frame.h"
#include "FrameLoader.h"
-#include "JSDOMBinding.h"
+#include "JSDOMExceptionHandling.h"
#include "JSDOMWindow.h"
#include "JSMainThreadExecState.h"
#include "JSMainThreadExecStateInstrumentation.h"
@@ -39,27 +39,28 @@
#include "ScriptSourceCode.h"
#include "WorkerGlobalScope.h"
#include "WorkerThread.h"
-#include <bindings/ScriptValue.h>
#include <runtime/JSLock.h>
using namespace JSC;
namespace WebCore {
-PassOwnPtr<ScheduledAction> ScheduledAction::create(ExecState* exec, DOMWrapperWorld& isolatedWorld, ContentSecurityPolicy* policy)
+std::unique_ptr<ScheduledAction> ScheduledAction::create(ExecState* exec, DOMWrapperWorld& isolatedWorld, ContentSecurityPolicy* policy)
{
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
JSValue v = exec->argument(0);
CallData callData;
- if (getCallData(v, callData) == CallTypeNone) {
+ if (getCallData(v, callData) == CallType::None) {
if (policy && !policy->allowEval(exec))
return nullptr;
- String string = v.toString(exec)->value(exec);
- if (exec->hadException())
- return nullptr;
- return adoptPtr(new ScheduledAction(string, isolatedWorld));
+ String string = v.toWTFString(exec);
+ RETURN_IF_EXCEPTION(scope, nullptr);
+ return std::unique_ptr<ScheduledAction>(new ScheduledAction(string, isolatedWorld));
}
- return adoptPtr(new ScheduledAction(exec, v, isolatedWorld));
+ return std::unique_ptr<ScheduledAction>(new ScheduledAction(exec, v, isolatedWorld));
}
ScheduledAction::ScheduledAction(ExecState* exec, JSValue function, DOMWrapperWorld& isolatedWorld)
@@ -72,24 +73,22 @@ ScheduledAction::ScheduledAction(ExecState* exec, JSValue function, DOMWrapperWo
m_args.append(Strong<JSC::Unknown>(exec->vm(), exec->uncheckedArgument(i)));
}
-void ScheduledAction::execute(ScriptExecutionContext* context)
+void ScheduledAction::execute(ScriptExecutionContext& context)
{
- if (context->isDocument())
- execute(toDocument(context));
- else {
- ASSERT_WITH_SECURITY_IMPLICATION(context->isWorkerGlobalScope());
- execute(static_cast<WorkerGlobalScope*>(context));
- }
+ if (is<Document>(context))
+ execute(downcast<Document>(context));
+ else
+ execute(downcast<WorkerGlobalScope>(context));
}
-void ScheduledAction::executeFunctionInContext(JSGlobalObject* globalObject, JSValue thisValue, ScriptExecutionContext* context)
+void ScheduledAction::executeFunctionInContext(JSGlobalObject* globalObject, JSValue thisValue, ScriptExecutionContext& context)
{
ASSERT(m_function);
- JSLockHolder lock(context->vm());
+ JSLockHolder lock(context.vm());
CallData callData;
CallType callType = getCallData(m_function.get(), callData);
- if (callType == CallTypeNone)
+ if (callType == CallType::None)
return;
ExecState* exec = globalObject->globalExec();
@@ -99,26 +98,27 @@ void ScheduledAction::executeFunctionInContext(JSGlobalObject* globalObject, JSV
for (size_t i = 0; i < size; ++i)
args.append(m_args[i].get());
- InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(context, callType, callData);
+ InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(&context, callType, callData);
- if (context->isDocument())
- JSMainThreadExecState::call(exec, m_function.get(), callType, callData, thisValue, args);
+ NakedPtr<JSC::Exception> exception;
+ if (is<Document>(context))
+ JSMainThreadExecState::profiledCall(exec, JSC::ProfilingReason::Other, m_function.get(), callType, callData, thisValue, args, exception);
else
- JSC::call(exec, m_function.get(), callType, callData, thisValue, args);
+ JSC::profiledCall(exec, JSC::ProfilingReason::Other, m_function.get(), callType, callData, thisValue, args, exception);
- InspectorInstrumentation::didCallFunction(cookie);
+ InspectorInstrumentation::didCallFunction(cookie, &context);
- if (exec->hadException())
- reportCurrentException(exec);
+ if (exception)
+ reportException(exec, exception);
}
-void ScheduledAction::execute(Document* document)
+void ScheduledAction::execute(Document& document)
{
- JSDOMWindow* window = toJSDOMWindow(document->frame(), *m_isolatedWorld);
+ JSDOMWindow* window = toJSDOMWindow(document.frame(), *m_isolatedWorld);
if (!window)
return;
- RefPtr<Frame> frame = window->impl().frame();
+ RefPtr<Frame> frame = window->wrapped().frame();
if (!frame || !frame->script().canExecuteScripts(AboutToExecuteScript))
return;
@@ -128,18 +128,18 @@ void ScheduledAction::execute(Document* document)
frame->script().executeScriptInWorld(*m_isolatedWorld, m_code);
}
-void ScheduledAction::execute(WorkerGlobalScope* workerGlobalScope)
+void ScheduledAction::execute(WorkerGlobalScope& workerGlobalScope)
{
// In a Worker, the execution should always happen on a worker thread.
- ASSERT(workerGlobalScope->thread()->threadID() == currentThread());
+ ASSERT(workerGlobalScope.thread().threadID() == currentThread());
- WorkerScriptController* scriptController = workerGlobalScope->script();
+ WorkerScriptController* scriptController = workerGlobalScope.script();
if (m_function) {
JSWorkerGlobalScope* contextWrapper = scriptController->workerGlobalScopeWrapper();
executeFunctionInContext(contextWrapper, contextWrapper, workerGlobalScope);
} else {
- ScriptSourceCode code(m_code, workerGlobalScope->url());
+ ScriptSourceCode code(m_code, workerGlobalScope.url());
scriptController->evaluate(code);
}
}
diff --git a/Source/WebCore/bindings/js/ScheduledAction.h b/Source/WebCore/bindings/js/ScheduledAction.h
index 19add3fe8..dac8579ea 100644
--- a/Source/WebCore/bindings/js/ScheduledAction.h
+++ b/Source/WebCore/bindings/js/ScheduledAction.h
@@ -17,14 +17,13 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef ScheduledAction_h
-#define ScheduledAction_h
+#pragma once
#include "JSDOMBinding.h"
#include <heap/Strong.h>
#include <heap/StrongInlines.h>
+#include <memory>
#include <runtime/JSCell.h>
-#include <wtf/PassOwnPtr.h>
#include <wtf/Vector.h>
#include <wtf/text/WTFString.h>
@@ -46,22 +45,22 @@ namespace WebCore {
class ScheduledAction {
WTF_MAKE_NONCOPYABLE(ScheduledAction); WTF_MAKE_FAST_ALLOCATED;
public:
- static PassOwnPtr<ScheduledAction> create(JSC::ExecState*, DOMWrapperWorld& isolatedWorld, ContentSecurityPolicy*);
+ static std::unique_ptr<ScheduledAction> create(JSC::ExecState*, DOMWrapperWorld& isolatedWorld, ContentSecurityPolicy*);
- void execute(ScriptExecutionContext*);
+ void execute(ScriptExecutionContext&);
private:
ScheduledAction(JSC::ExecState*, JSC::JSValue function, DOMWrapperWorld& isolatedWorld);
ScheduledAction(const String& code, DOMWrapperWorld& isolatedWorld)
- : m_function(*isolatedWorld.vm())
+ : m_function(isolatedWorld.vm())
, m_code(code)
, m_isolatedWorld(&isolatedWorld)
{
}
- void executeFunctionInContext(JSC::JSGlobalObject*, JSC::JSValue thisValue, ScriptExecutionContext*);
- void execute(Document*);
- void execute(WorkerGlobalScope*);
+ void executeFunctionInContext(JSC::JSGlobalObject*, JSC::JSValue thisValue, ScriptExecutionContext&);
+ void execute(Document&);
+ void execute(WorkerGlobalScope&);
JSC::Strong<JSC::Unknown> m_function;
Vector<JSC::Strong<JSC::Unknown>> m_args;
@@ -70,5 +69,3 @@ namespace WebCore {
};
} // namespace WebCore
-
-#endif // ScheduledAction_h
diff --git a/Source/WebCore/bindings/js/ScriptCachedFrameData.cpp b/Source/WebCore/bindings/js/ScriptCachedFrameData.cpp
index c4e12f942..1196db791 100644
--- a/Source/WebCore/bindings/js/ScriptCachedFrameData.cpp
+++ b/Source/WebCore/bindings/js/ScriptCachedFrameData.cpp
@@ -1,11 +1,11 @@
/*
* Copyright (c) 2008, Google Inc. All rights reserved.
* Copyright (C) 2008 Apple Inc. All Rights Reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
- *
+ *
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
@@ -15,7 +15,7 @@
* * Neither the name of Google Inc. nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -32,14 +32,17 @@
#include "config.h"
#include "ScriptCachedFrameData.h"
+#include "CommonVM.h"
#include "Document.h"
#include "Frame.h"
#include "GCController.h"
#include "Page.h"
+#include "PageConsoleClient.h"
#include "PageGroup.h"
+#include "ScriptController.h"
#include <heap/StrongInlines.h>
#include <runtime/JSLock.h>
-#include "ScriptController.h"
+#include <runtime/WeakGCMapInlines.h>
using namespace JSC;
@@ -47,18 +50,19 @@ namespace WebCore {
ScriptCachedFrameData::ScriptCachedFrameData(Frame& frame)
{
- JSLockHolder lock(JSDOMWindowBase::commonVM());
+ JSLockHolder lock(commonVM());
ScriptController& scriptController = frame.script();
- ScriptController::ShellMap& windowShells = scriptController.m_windowShells;
+ Vector<JSC::Strong<JSDOMWindowShell>> windowShells = scriptController.windowShells();
- ScriptController::ShellMap::iterator windowShellsEnd = windowShells.end();
- for (ScriptController::ShellMap::iterator iter = windowShells.begin(); iter != windowShellsEnd; ++iter) {
- JSDOMWindow* window = iter->value->window();
- m_windows.add(iter->key.get(), Strong<JSDOMWindow>(window->vm(), window));
+ for (size_t i = 0; i < windowShells.size(); ++i) {
+ JSDOMWindowShell* windowShell = windowShells[i].get();
+ JSDOMWindow* window = windowShell->window();
+ m_windows.add(&windowShell->world(), Strong<JSDOMWindow>(window->vm(), window));
+ window->setConsoleClient(nullptr);
}
- scriptController.attachDebugger(0);
+ scriptController.attachDebugger(nullptr);
}
ScriptCachedFrameData::~ScriptCachedFrameData()
@@ -68,29 +72,33 @@ ScriptCachedFrameData::~ScriptCachedFrameData()
void ScriptCachedFrameData::restore(Frame& frame)
{
- JSLockHolder lock(JSDOMWindowBase::commonVM());
+ JSLockHolder lock(commonVM());
+ Page* page = frame.page();
ScriptController& scriptController = frame.script();
- ScriptController::ShellMap& windowShells = scriptController.m_windowShells;
+ Vector<JSC::Strong<JSDOMWindowShell>> windowShells = scriptController.windowShells();
- for (auto it = windowShells.begin(), end = windowShells.end(); it != end; ++it) {
- DOMWrapperWorld* world = it->key.get();
- JSDOMWindowShell* windowShell = it->value.get();
+ for (size_t i = 0; i < windowShells.size(); ++i) {
+ JSDOMWindowShell* windowShell = windowShells[i].get();
+ DOMWrapperWorld* world = &windowShell->world();
if (JSDOMWindow* window = m_windows.get(world).get())
windowShell->setWindow(window->vm(), window);
else {
DOMWindow* domWindow = frame.document()->domWindow();
- if (&windowShell->window()->impl() == domWindow)
+ if (&windowShell->window()->wrapped() == domWindow)
continue;
windowShell->setWindow(domWindow);
- if (Page* page = frame.page()) {
+ if (page) {
scriptController.attachDebugger(windowShell, page->debugger());
windowShell->window()->setProfileGroup(page->group().identifier());
}
}
+
+ if (page)
+ windowShell->window()->setConsoleClient(&page->console());
}
}
@@ -99,9 +107,9 @@ void ScriptCachedFrameData::clear()
if (m_windows.isEmpty())
return;
- JSLockHolder lock(JSDOMWindowBase::commonVM());
+ JSLockHolder lock(commonVM());
m_windows.clear();
- gcController().garbageCollectSoon();
+ GCController::singleton().garbageCollectSoon();
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/ScriptCachedFrameData.h b/Source/WebCore/bindings/js/ScriptCachedFrameData.h
index 55b98e3be..eff5e3802 100644
--- a/Source/WebCore/bindings/js/ScriptCachedFrameData.h
+++ b/Source/WebCore/bindings/js/ScriptCachedFrameData.h
@@ -29,8 +29,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ScriptCachedFrameData_h
-#define ScriptCachedFrameData_h
+#pragma once
#include <heap/Strong.h>
#include <wtf/HashMap.h>
@@ -56,5 +55,3 @@ private:
};
} // namespace WebCore
-
-#endif // ScriptCachedFrameData_h
diff --git a/Source/WebCore/bindings/js/ScriptCallStackFactory.cpp b/Source/WebCore/bindings/js/ScriptCallStackFactory.cpp
deleted file mode 100644
index 7d695a444..000000000
--- a/Source/WebCore/bindings/js/ScriptCallStackFactory.cpp
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * Copyright (c) 2010 Google Inc. All rights reserved.
- * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "ScriptCallStackFactory.h"
-
-#include "InspectorInstrumentation.h"
-#include "JSDOMBinding.h"
-#include "JSMainThreadExecState.h"
-#include "ScriptArguments.h"
-#include "ScriptCallFrame.h"
-#include "ScriptCallStack.h"
-#include <bindings/ScriptValue.h>
-#include <interpreter/CallFrame.h>
-#include <interpreter/CallFrameInlines.h>
-#include <interpreter/StackVisitor.h>
-#include <runtime/ArgList.h>
-#include <runtime/JSCJSValue.h>
-#include <runtime/JSFunction.h>
-#include <runtime/VM.h>
-#include <wtf/text/WTFString.h>
-
-using namespace JSC;
-
-namespace WebCore {
-
-class ScriptExecutionContext;
-
-class CreateScriptCallStackFunctor {
-public:
- CreateScriptCallStackFunctor(Vector<ScriptCallFrame>& frames, size_t remainingCapacity)
- : m_frames(frames)
- , m_remainingCapacityForFrameCapture(remainingCapacity)
- {
- }
-
- StackVisitor::Status operator()(StackVisitor& visitor)
- {
- if (m_remainingCapacityForFrameCapture) {
- unsigned line;
- unsigned column;
- visitor->computeLineAndColumn(line, column);
- m_frames.append(ScriptCallFrame(visitor->functionName(), visitor->sourceURL(), line, column));
-
- m_remainingCapacityForFrameCapture--;
- return StackVisitor::Continue;
- }
- return StackVisitor::Done;
- }
-
-private:
- Vector<ScriptCallFrame>& m_frames;
- size_t m_remainingCapacityForFrameCapture;
-};
-
-PassRefPtr<ScriptCallStack> createScriptCallStack(size_t maxStackSize, bool emptyIsAllowed)
-{
- Vector<ScriptCallFrame> frames;
- if (JSC::ExecState* exec = JSMainThreadExecState::currentState()) {
- CallFrame* frame = exec->vm().topCallFrame;
- CreateScriptCallStackFunctor functor(frames, maxStackSize);
- frame->iterate(functor);
- }
- if (frames.isEmpty() && !emptyIsAllowed) {
- // No frames found. It may happen in the case where
- // a bound function is called from native code for example.
- // Fallback to setting lineNumber to 0, and source and function name to "undefined".
- frames.append(ScriptCallFrame("undefined", "undefined", 0, 0));
- }
- return ScriptCallStack::create(frames);
-}
-
-class CreateScriptCallStackForConsoleFunctor {
-public:
- CreateScriptCallStackForConsoleFunctor(bool needToSkipAFrame, size_t remainingCapacity, Vector<ScriptCallFrame>& frames)
- : m_needToSkipAFrame(needToSkipAFrame)
- , m_remainingCapacityForFrameCapture(remainingCapacity)
- , m_frames(frames)
- {
- }
-
- StackVisitor::Status operator()(StackVisitor& visitor)
- {
- if (m_needToSkipAFrame) {
- m_needToSkipAFrame = false;
- return StackVisitor::Continue;
- }
-
- if (m_remainingCapacityForFrameCapture) {
- // This early exit is necessary to maintain our old behaviour
- // but the stack trace we produce now is complete and handles all
- // ways in which code may be running
- if (!visitor->callee() && m_frames.size())
- return StackVisitor::Done;
-
- unsigned line;
- unsigned column;
- visitor->computeLineAndColumn(line, column);
- m_frames.append(ScriptCallFrame(visitor->functionName(), visitor->sourceURL(), line, column));
-
- m_remainingCapacityForFrameCapture--;
- return StackVisitor::Continue;
- }
- return StackVisitor::Done;
- }
-
-private:
- bool m_needToSkipAFrame;
- size_t m_remainingCapacityForFrameCapture;
- Vector<ScriptCallFrame>& m_frames;
-};
-
-PassRefPtr<ScriptCallStack> createScriptCallStack(JSC::ExecState* exec, size_t maxStackSize)
-{
- Vector<ScriptCallFrame> frames;
- ASSERT(exec);
- CallFrame* frame = exec->vm().topCallFrame;
- CreateScriptCallStackForConsoleFunctor functor(true, maxStackSize, frames);
- frame->iterate(functor);
- if (frames.isEmpty()) {
- CreateScriptCallStackForConsoleFunctor functor(false, maxStackSize, frames);
- frame->iterate(functor);
- }
- return ScriptCallStack::create(frames);
-}
-
-PassRefPtr<ScriptCallStack> createScriptCallStackFromException(JSC::ExecState* exec, JSC::JSValue& exception, size_t maxStackSize)
-{
- Vector<ScriptCallFrame> frames;
- RefCountedArray<StackFrame> stackTrace = exec->vm().exceptionStack();
- for (size_t i = 0; i < stackTrace.size() && i < maxStackSize; i++) {
- if (!stackTrace[i].callee && frames.size())
- break;
-
- String functionName = stackTrace[i].friendlyFunctionName(exec);
- unsigned line;
- unsigned column;
- stackTrace[i].computeLineAndColumn(line, column);
- frames.append(ScriptCallFrame(functionName, stackTrace[i].sourceURL, line, column));
- }
-
- // FIXME: <http://webkit.org/b/115087> Web Inspector: WebCore::reportException should not evaluate JavaScript handling exceptions
- // Fallback to getting at least the line and sourceURL from the exception if it has values and the exceptionStack doesn't.
- if (frames.size() > 0) {
- const ScriptCallFrame& firstCallFrame = frames.first();
- JSObject* exceptionObject = exception.toObject(exec);
- if (exception.isObject() && firstCallFrame.sourceURL().isEmpty()) {
- JSValue lineValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "line"));
- int lineNumber = lineValue && lineValue.isNumber() ? int(lineValue.toNumber(exec)) : 0;
- JSValue columnValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "column"));
- int columnNumber = columnValue && columnValue.isNumber() ? int(columnValue.toNumber(exec)) : 0;
- JSValue sourceURLValue = exceptionObject->getDirect(exec->vm(), Identifier(exec, "sourceURL"));
- String exceptionSourceURL = sourceURLValue && sourceURLValue.isString() ? sourceURLValue.toString(exec)->value(exec) : ASCIILiteral("undefined");
- frames[0] = ScriptCallFrame(firstCallFrame.functionName(), exceptionSourceURL, lineNumber, columnNumber);
- }
- }
-
- return ScriptCallStack::create(frames);
-}
-
-PassRefPtr<ScriptCallStack> createScriptCallStackForConsole(JSC::ExecState* exec)
-{
- size_t maxStackSize = 1;
- if (InspectorInstrumentation::hasFrontends()) {
- ScriptExecutionContext* scriptExecutionContext = jsCast<JSDOMGlobalObject*>(exec->lexicalGlobalObject())->scriptExecutionContext();
- if (InspectorInstrumentation::consoleAgentEnabled(scriptExecutionContext))
- maxStackSize = ScriptCallStack::maxCallStackSizeToCapture;
- }
- return createScriptCallStack(exec, maxStackSize);
-}
-
-PassRefPtr<ScriptArguments> createScriptArguments(JSC::ExecState* exec, unsigned skipArgumentCount)
-{
- Vector<Deprecated::ScriptValue> arguments;
- size_t argumentCount = exec->argumentCount();
- for (size_t i = skipArgumentCount; i < argumentCount; ++i)
- arguments.append(Deprecated::ScriptValue(exec->vm(), exec->uncheckedArgument(i)));
- return ScriptArguments::create(exec, arguments);
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/ScriptCallStackFactory.h b/Source/WebCore/bindings/js/ScriptCallStackFactory.h
deleted file mode 100644
index 298bbbd40..000000000
--- a/Source/WebCore/bindings/js/ScriptCallStackFactory.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Copyright (c) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef ScriptCallStackFactory_h
-#define ScriptCallStackFactory_h
-
-#include <wtf/Forward.h>
-#include <wtf/RefCountedArray.h>
-
-namespace JSC {
-class ExecState;
-class JSValue;
-struct StackFrame;
-}
-
-namespace WebCore {
-
-class ScriptArguments;
-class ScriptCallStack;
-
-PassRefPtr<ScriptCallStack> createScriptCallStack(size_t maxStackSize, bool emptyStackIsAllowed);
-PassRefPtr<ScriptCallStack> createScriptCallStack(JSC::ExecState*, size_t maxStackSize);
-PassRefPtr<ScriptCallStack> createScriptCallStackFromException(JSC::ExecState*, JSC::JSValue& exception, size_t maxStackSize);
-PassRefPtr<ScriptCallStack> createScriptCallStackForConsole(JSC::ExecState*);
-PassRefPtr<ScriptArguments> createScriptArguments(JSC::ExecState*, unsigned skipArgumentCount);
-
-} // namespace WebCore
-
-#endif // ScriptCallStackFactory_h
diff --git a/Source/WebCore/bindings/js/ScriptController.cpp b/Source/WebCore/bindings/js/ScriptController.cpp
index c0135ae8d..68eb91bed 100644
--- a/Source/WebCore/bindings/js/ScriptController.cpp
+++ b/Source/WebCore/bindings/js/ScriptController.cpp
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
* Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006-2016 Apple Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -22,36 +22,48 @@
#include "ScriptController.h"
#include "BridgeJSC.h"
+#include "CachedScriptFetcher.h"
+#include "CommonVM.h"
#include "ContentSecurityPolicy.h"
#include "DocumentLoader.h"
#include "Event.h"
-#include "EventNames.h"
#include "Frame.h"
#include "FrameLoaderClient.h"
#include "GCController.h"
#include "HTMLPlugInElement.h"
#include "InspectorInstrumentation.h"
+#include "JSDOMBindingSecurity.h"
+#include "JSDOMExceptionHandling.h"
#include "JSDOMWindow.h"
#include "JSDocument.h"
#include "JSMainThreadExecState.h"
+#include "LoadableModuleScript.h"
+#include "MainFrame.h"
+#include "MemoryPressureHandler.h"
+#include "ModuleFetchFailureKind.h"
#include "NP_jsobject.h"
#include "Page.h"
+#include "PageConsoleClient.h"
#include "PageGroup.h"
-#include "PluginView.h"
-#include "ScriptCallStack.h"
+#include "PluginViewBase.h"
#include "ScriptSourceCode.h"
#include "ScriptableDocumentParser.h"
#include "Settings.h"
-#include "StorageNamespace.h"
#include "UserGestureIndicator.h"
#include "WebCoreJSClientData.h"
#include "npruntime_impl.h"
#include "runtime_root.h"
-#include <bindings/ScriptValue.h>
#include <debugger/Debugger.h>
#include <heap/StrongInlines.h>
+#include <inspector/ScriptCallStack.h>
#include <runtime/InitializeThreading.h>
+#include <runtime/JSFunction.h>
+#include <runtime/JSInternalPromise.h>
#include <runtime/JSLock.h>
+#include <runtime/JSModuleRecord.h>
+#include <runtime/JSNativeStdFunction.h>
+#include <runtime/JSScriptFetcher.h>
+#include <wtf/SetForScope.h>
#include <wtf/Threading.h>
#include <wtf/text/TextPosition.h>
@@ -59,6 +71,18 @@ using namespace JSC;
namespace WebCore {
+static void collectGarbageAfterWindowShellDestruction()
+{
+ // Make sure to GC Extra Soon(tm) during memory pressure conditions
+ // to soften high peaks of memory usage during navigation.
+ if (MemoryPressureHandler::singleton().isUnderMemoryPressure()) {
+ // NOTE: We do the collection on next runloop to ensure that there's no pointer
+ // to the window object on the stack.
+ GCController::singleton().garbageCollectOnNextRunLoop();
+ } else
+ GCController::singleton().garbageCollectSoon();
+}
+
void ScriptController::initializeThreading()
{
#if !PLATFORM(IOS)
@@ -74,7 +98,7 @@ ScriptController::ScriptController(Frame& frame)
#if ENABLE(NETSCAPE_PLUGIN_API)
, m_windowScriptNPObject(0)
#endif
-#if PLATFORM(MAC)
+#if PLATFORM(COCOA)
, m_windowScriptObject(0)
#endif
{
@@ -85,16 +109,19 @@ ScriptController::~ScriptController()
disconnectPlatformScriptObjects();
if (m_cacheableBindingRootObject) {
- JSLockHolder lock(JSDOMWindowBase::commonVM());
+ JSLockHolder lock(commonVM());
m_cacheableBindingRootObject->invalidate();
- m_cacheableBindingRootObject = 0;
+ m_cacheableBindingRootObject = nullptr;
}
// It's likely that destroying m_windowShells will create a lot of garbage.
if (!m_windowShells.isEmpty()) {
- while (!m_windowShells.isEmpty())
- destroyWindowShell(*m_windowShells.begin()->key);
- gcController().garbageCollectSoon();
+ while (!m_windowShells.isEmpty()) {
+ ShellMap::iterator iter = m_windowShells.begin();
+ iter->value->window()->setConsoleClient(nullptr);
+ destroyWindowShell(*iter->key);
+ }
+ collectGarbageAfterWindowShellDestruction();
}
}
@@ -105,22 +132,24 @@ void ScriptController::destroyWindowShell(DOMWrapperWorld& world)
world.didDestroyWindowShell(this);
}
-JSDOMWindowShell* ScriptController::createWindowShell(DOMWrapperWorld& world)
+JSDOMWindowShell& ScriptController::createWindowShell(DOMWrapperWorld& world)
{
ASSERT(!m_windowShells.contains(&world));
- VM& vm = *world.vm();
+ VM& vm = world.vm();
Structure* structure = JSDOMWindowShell::createStructure(vm, jsNull());
Strong<JSDOMWindowShell> windowShell(vm, JSDOMWindowShell::create(vm, m_frame.document()->domWindow(), structure, world));
Strong<JSDOMWindowShell> windowShell2(windowShell);
m_windowShells.add(&world, windowShell);
world.didCreateWindowShell(this);
- return windowShell.get();
+ return *windowShell.get();
}
-Deprecated::ScriptValue ScriptController::evaluateInWorld(const ScriptSourceCode& sourceCode, DOMWrapperWorld& world)
+JSValue ScriptController::evaluateInWorld(const ScriptSourceCode& sourceCode, DOMWrapperWorld& world, ExceptionDetails* exceptionDetails)
{
+ JSLockHolder lock(world.vm());
+
const SourceCode& jsSourceCode = sourceCode.jsSourceCode();
String sourceURL = jsSourceCode.provider()->url();
@@ -136,77 +165,178 @@ Deprecated::ScriptValue ScriptController::evaluateInWorld(const ScriptSourceCode
const String* savedSourceURL = m_sourceURL;
m_sourceURL = &sourceURL;
- JSLockHolder lock(exec);
-
- Ref<Frame> protect(m_frame);
-
- InspectorInstrumentationCookie cookie = InspectorInstrumentation::willEvaluateScript(&m_frame, sourceURL, sourceCode.startLine());
+ Ref<Frame> protector(m_frame);
- JSValue evaluationException;
+ InspectorInstrumentationCookie cookie = InspectorInstrumentation::willEvaluateScript(m_frame, sourceURL, sourceCode.startLine());
- JSValue returnValue = JSMainThreadExecState::evaluate(exec, jsSourceCode, shell, &evaluationException);
+ NakedPtr<JSC::Exception> evaluationException;
+ JSValue returnValue = JSMainThreadExecState::profiledEvaluate(exec, JSC::ProfilingReason::Other, jsSourceCode, shell, evaluationException);
- InspectorInstrumentation::didEvaluateScript(cookie);
+ InspectorInstrumentation::didEvaluateScript(cookie, m_frame);
if (evaluationException) {
- reportException(exec, evaluationException, sourceCode.cachedScript());
+ reportException(exec, evaluationException, sourceCode.cachedScript(), exceptionDetails);
m_sourceURL = savedSourceURL;
- return Deprecated::ScriptValue();
+ return { };
}
m_sourceURL = savedSourceURL;
- return Deprecated::ScriptValue(exec->vm(), returnValue);
+ return returnValue;
+}
+
+JSValue ScriptController::evaluate(const ScriptSourceCode& sourceCode, ExceptionDetails* exceptionDetails)
+{
+ return evaluateInWorld(sourceCode, mainThreadNormalWorld(), exceptionDetails);
+}
+
+void ScriptController::loadModuleScriptInWorld(LoadableModuleScript& moduleScript, const String& moduleName, DOMWrapperWorld& world)
+{
+ JSLockHolder lock(world.vm());
+
+ auto& shell = *windowShell(world);
+ auto& state = *shell.window()->globalExec();
+
+ auto& promise = JSMainThreadExecState::loadModule(state, moduleName, JSC::JSScriptFetcher::create(state.vm(), { &moduleScript }));
+ setupModuleScriptHandlers(moduleScript, promise, world);
+}
+
+void ScriptController::loadModuleScript(LoadableModuleScript& moduleScript, const String& moduleName)
+{
+ loadModuleScriptInWorld(moduleScript, moduleName, mainThreadNormalWorld());
+}
+
+void ScriptController::loadModuleScriptInWorld(LoadableModuleScript& moduleScript, const ScriptSourceCode& sourceCode, DOMWrapperWorld& world)
+{
+ JSLockHolder lock(world.vm());
+
+ auto& shell = *windowShell(world);
+ auto& state = *shell.window()->globalExec();
+
+ auto& promise = JSMainThreadExecState::loadModule(state, sourceCode.jsSourceCode(), JSC::JSScriptFetcher::create(state.vm(), { &moduleScript }));
+ setupModuleScriptHandlers(moduleScript, promise, world);
+}
+
+void ScriptController::loadModuleScript(LoadableModuleScript& moduleScript, const ScriptSourceCode& sourceCode)
+{
+ loadModuleScriptInWorld(moduleScript, sourceCode, mainThreadNormalWorld());
+}
+
+JSC::JSValue ScriptController::linkAndEvaluateModuleScriptInWorld(LoadableModuleScript& moduleScript, DOMWrapperWorld& world)
+{
+ JSLockHolder lock(world.vm());
+
+ auto& shell = *windowShell(world);
+ auto& state = *shell.window()->globalExec();
+
+ // FIXME: Preventing Frame from being destroyed is essentially unnecessary.
+ // https://bugs.webkit.org/show_bug.cgi?id=164763
+ Ref<Frame> protector(m_frame);
+
+ NakedPtr<JSC::Exception> evaluationException;
+ auto returnValue = JSMainThreadExecState::linkAndEvaluateModule(state, Identifier::fromUid(&state.vm(), moduleScript.moduleKey()), jsUndefined(), evaluationException);
+ if (evaluationException) {
+ // FIXME: Give a chance to dump the stack trace if the "crossorigin" attribute allows.
+ // https://bugs.webkit.org/show_bug.cgi?id=164539
+ reportException(&state, evaluationException, nullptr);
+ return jsUndefined();
+ }
+ return returnValue;
+}
+
+JSC::JSValue ScriptController::linkAndEvaluateModuleScript(LoadableModuleScript& moduleScript)
+{
+ return linkAndEvaluateModuleScriptInWorld(moduleScript, mainThreadNormalWorld());
+}
+
+JSC::JSValue ScriptController::evaluateModule(const URL& sourceURL, JSModuleRecord& moduleRecord, DOMWrapperWorld& world)
+{
+ JSLockHolder lock(world.vm());
+
+ const auto& jsSourceCode = moduleRecord.sourceCode();
+
+ auto& shell = *windowShell(world);
+ auto& state = *shell.window()->globalExec();
+ SetForScope<const String*> sourceURLScope(m_sourceURL, &sourceURL.string());
+
+ Ref<Frame> protector(m_frame);
+
+ auto cookie = InspectorInstrumentation::willEvaluateScript(m_frame, sourceURL, jsSourceCode.firstLine().oneBasedInt());
+
+ auto returnValue = moduleRecord.evaluate(&state);
+ InspectorInstrumentation::didEvaluateScript(cookie, m_frame);
+
+ return returnValue;
+}
+
+JSC::JSValue ScriptController::evaluateModule(const URL& sourceURL, JSModuleRecord& moduleRecord)
+{
+ return evaluateModule(sourceURL, moduleRecord, mainThreadNormalWorld());
}
-Deprecated::ScriptValue ScriptController::evaluate(const ScriptSourceCode& sourceCode)
+Ref<DOMWrapperWorld> ScriptController::createWorld()
{
- return evaluateInWorld(sourceCode, mainThreadNormalWorld());
+ return DOMWrapperWorld::create(commonVM());
}
-PassRefPtr<DOMWrapperWorld> ScriptController::createWorld()
+Vector<JSC::Strong<JSDOMWindowShell>> ScriptController::windowShells()
{
- return DOMWrapperWorld::create(JSDOMWindow::commonVM());
+ Vector<JSC::Strong<JSDOMWindowShell>> windowShells;
+ copyValuesToVector(m_windowShells, windowShells);
+ return windowShells;
}
void ScriptController::getAllWorlds(Vector<Ref<DOMWrapperWorld>>& worlds)
{
- static_cast<WebCoreJSClientData*>(JSDOMWindow::commonVM()->clientData)->getAllWorlds(worlds);
+ static_cast<JSVMClientData*>(commonVM().clientData)->getAllWorlds(worlds);
}
-void ScriptController::clearWindowShell(DOMWindow* newDOMWindow, bool goingIntoPageCache)
+void ScriptController::clearWindowShellsNotMatchingDOMWindow(DOMWindow* newDOMWindow, bool goingIntoPageCache)
{
if (m_windowShells.isEmpty())
return;
- JSLockHolder lock(JSDOMWindowBase::commonVM());
+ JSLockHolder lock(commonVM());
- for (ShellMap::iterator iter = m_windowShells.begin(); iter != m_windowShells.end(); ++iter) {
- JSDOMWindowShell* windowShell = iter->value.get();
-
- if (&windowShell->window()->impl() == newDOMWindow)
+ for (auto& windowShell : windowShells()) {
+ if (&windowShell->window()->wrapped() == newDOMWindow)
continue;
- // Clear the debugger from the current window before setting the new window.
- attachDebugger(windowShell, 0);
-
+ // Clear the debugger and console from the current window before setting the new window.
+ attachDebugger(windowShell.get(), nullptr);
+ windowShell->window()->setConsoleClient(nullptr);
windowShell->window()->willRemoveFromWindowShell();
- windowShell->setWindow(newDOMWindow);
+ }
+ // It's likely that resetting our windows created a lot of garbage, unless
+ // it went in a back/forward cache.
+ if (!goingIntoPageCache)
+ collectGarbageAfterWindowShellDestruction();
+}
+
+void ScriptController::setDOMWindowForWindowShell(DOMWindow* newDOMWindow)
+{
+ if (m_windowShells.isEmpty())
+ return;
+
+ JSLockHolder lock(commonVM());
+
+ for (auto& windowShell : windowShells()) {
+ if (&windowShell->window()->wrapped() == newDOMWindow)
+ continue;
+
+ windowShell->setWindow(newDOMWindow);
+
// An m_cacheableBindingRootObject persists between page navigations
// so needs to know about the new JSDOMWindow.
if (m_cacheableBindingRootObject)
m_cacheableBindingRootObject->updateGlobalObject(windowShell->window());
if (Page* page = m_frame.page()) {
- attachDebugger(windowShell, page->debugger());
+ attachDebugger(windowShell.get(), page->debugger());
windowShell->window()->setProfileGroup(page->group().identifier());
+ windowShell->window()->setConsoleClient(&page->console());
}
}
-
- // It's likely that resetting our windows created a lot of garbage, unless
- // it went in a back/forward cache.
- if (!goingIntoPageCache)
- gcController().garbageCollectSoon();
}
JSDOMWindowShell* ScriptController::initScript(DOMWrapperWorld& world)
@@ -215,29 +345,97 @@ JSDOMWindowShell* ScriptController::initScript(DOMWrapperWorld& world)
JSLockHolder lock(world.vm());
- JSDOMWindowShell* windowShell = createWindowShell(world);
+ JSDOMWindowShell& windowShell = createWindowShell(world);
- windowShell->window()->updateDocument();
+ windowShell.window()->updateDocument();
- if (m_frame.document())
- windowShell->window()->setEvalEnabled(m_frame.document()->contentSecurityPolicy()->allowEval(0, ContentSecurityPolicy::SuppressReport), m_frame.document()->contentSecurityPolicy()->evalDisabledErrorMessage());
+ if (Document* document = m_frame.document())
+ document->contentSecurityPolicy()->didCreateWindowShell(windowShell);
if (Page* page = m_frame.page()) {
- attachDebugger(windowShell, page->debugger());
- windowShell->window()->setProfileGroup(page->group().identifier());
+ attachDebugger(&windowShell, page->debugger());
+ windowShell.window()->setProfileGroup(page->group().identifier());
+ windowShell.window()->setConsoleClient(&page->console());
}
m_frame.loader().dispatchDidClearWindowObjectInWorld(world);
- return windowShell;
+ return &windowShell;
+}
+
+static Identifier jsValueToModuleKey(ExecState* exec, JSValue value)
+{
+ if (value.isSymbol())
+ return Identifier::fromUid(jsCast<Symbol*>(value)->privateName());
+ ASSERT(value.isString());
+ return asString(value)->toIdentifier(exec);
+}
+
+void ScriptController::setupModuleScriptHandlers(LoadableModuleScript& moduleScriptRef, JSInternalPromise& promise, DOMWrapperWorld& world)
+{
+ auto& shell = *windowShell(world);
+ auto& state = *shell.window()->globalExec();
+
+ // It is not guaranteed that either fulfillHandler or rejectHandler is eventually called.
+ // For example, if the page load is canceled, the DeferredPromise used in the module loader pipeline will stop executing JS code.
+ // Thus the promise returned from this function could remain unresolved.
+
+ RefPtr<LoadableModuleScript> moduleScript(&moduleScriptRef);
+
+ auto& fulfillHandler = *JSNativeStdFunction::create(state.vm(), shell.window(), 1, String(), [moduleScript](ExecState* exec) {
+ Identifier moduleKey = jsValueToModuleKey(exec, exec->argument(0));
+ moduleScript->notifyLoadCompleted(*moduleKey.impl());
+ return JSValue::encode(jsUndefined());
+ });
+
+ auto& rejectHandler = *JSNativeStdFunction::create(state.vm(), shell.window(), 1, String(), [moduleScript](ExecState* exec) {
+ VM& vm = exec->vm();
+ JSValue errorValue = exec->argument(0);
+ if (errorValue.isObject()) {
+ auto* object = JSC::asObject(errorValue);
+ if (JSValue failureKindValue = object->getDirect(vm, static_cast<JSVMClientData&>(*vm.clientData).builtinNames().failureKindPrivateName())) {
+ // This is host propagated error in the module loader pipeline.
+ switch (static_cast<ModuleFetchFailureKind>(failureKindValue.asInt32())) {
+ case ModuleFetchFailureKind::WasErrored:
+ moduleScript->notifyLoadFailed(LoadableScript::Error {
+ LoadableScript::ErrorType::CachedScript,
+ std::nullopt
+ });
+ break;
+ case ModuleFetchFailureKind::WasCanceled:
+ moduleScript->notifyLoadWasCanceled();
+ break;
+ }
+ return JSValue::encode(jsUndefined());
+ }
+ }
+
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+ moduleScript->notifyLoadFailed(LoadableScript::Error {
+ LoadableScript::ErrorType::CachedScript,
+ LoadableScript::ConsoleMessage {
+ MessageSource::JS,
+ MessageLevel::Error,
+ retrieveErrorMessage(*exec, vm, errorValue, scope),
+ }
+ });
+ return JSValue::encode(jsUndefined());
+ });
+
+ promise.then(&state, &fulfillHandler, &rejectHandler);
}
TextPosition ScriptController::eventHandlerPosition() const
{
+ // FIXME: If we are not currently parsing, we should use our current location
+ // in JavaScript, to cover cases like "element.setAttribute('click', ...)".
+
+ // FIXME: This location maps to the end of the HTML tag, and not to the
+ // exact column number belonging to the event handler attribute.
ScriptableDocumentParser* parser = m_frame.document()->scriptableDocumentParser();
if (parser)
return parser->textPosition();
- return TextPosition::minimumPosition();
+ return TextPosition();
}
void ScriptController::enableEval()
@@ -261,20 +459,27 @@ bool ScriptController::processingUserGesture()
return UserGestureIndicator::processingUserGesture();
}
-bool ScriptController::canAccessFromCurrentOrigin(Frame *frame)
+bool ScriptController::processingUserGestureForMedia()
{
- ExecState* exec = JSMainThreadExecState::currentState();
- if (exec)
- return shouldAllowAccessToFrame(exec, frame);
- // If the current state is 0 we're in a call path where the DOM security
- // check doesn't apply (eg. parser).
- return true;
+ return UserGestureIndicator::processingUserGestureForMedia();
+}
+
+bool ScriptController::canAccessFromCurrentOrigin(Frame* frame)
+{
+ ExecState* state = JSMainThreadExecState::currentState();
+
+ // If the current state is null we're in a call path where the DOM security check doesn't apply (eg. parser).
+ if (!state)
+ return true;
+
+ return BindingSecurity::shouldAllowAccessToFrame(state, frame);
}
void ScriptController::attachDebugger(JSC::Debugger* debugger)
{
- for (ShellMap::iterator iter = m_windowShells.begin(); iter != m_windowShells.end(); ++iter)
- attachDebugger(iter->value.get(), debugger);
+ Vector<JSC::Strong<JSDOMWindowShell>> windowShells = this->windowShells();
+ for (size_t i = 0; i < windowShells.size(); ++i)
+ attachDebugger(windowShells[i].get(), debugger);
}
void ScriptController::attachDebugger(JSDOMWindowShell* shell, JSC::Debugger* debugger)
@@ -283,6 +488,7 @@ void ScriptController::attachDebugger(JSDOMWindowShell* shell, JSC::Debugger* de
return;
JSDOMWindow* globalObject = shell->window();
+ JSLockHolder lock(globalObject->vm());
if (debugger)
debugger->attach(globalObject);
else if (JSC::Debugger* currentDebugger = globalObject->debugger())
@@ -291,9 +497,11 @@ void ScriptController::attachDebugger(JSDOMWindowShell* shell, JSC::Debugger* de
void ScriptController::updateDocument()
{
- for (ShellMap::iterator iter = m_windowShells.begin(); iter != m_windowShells.end(); ++iter) {
- JSLockHolder lock(iter->key->vm());
- iter->value->window()->updateDocument();
+ Vector<JSC::Strong<JSDOMWindowShell>> windowShells = this->windowShells();
+ for (size_t i = 0; i < windowShells.size(); ++i) {
+ JSDOMWindowShell* windowShell = windowShells[i].get();
+ JSLockHolder lock(windowShell->world().vm());
+ windowShell->window()->updateDocument();
}
}
@@ -303,7 +511,7 @@ Bindings::RootObject* ScriptController::cacheableBindingRootObject()
return 0;
if (!m_cacheableBindingRootObject) {
- JSLockHolder lock(JSDOMWindowBase::commonVM());
+ JSLockHolder lock(commonVM());
m_cacheableBindingRootObject = Bindings::RootObject::create(0, globalObject(pluginWorld()));
}
return m_cacheableBindingRootObject.get();
@@ -315,13 +523,13 @@ Bindings::RootObject* ScriptController::bindingRootObject()
return 0;
if (!m_bindingRootObject) {
- JSLockHolder lock(JSDOMWindowBase::commonVM());
+ JSLockHolder lock(commonVM());
m_bindingRootObject = Bindings::RootObject::create(0, globalObject(pluginWorld()));
}
return m_bindingRootObject.get();
}
-PassRefPtr<Bindings::RootObject> ScriptController::createRootObject(void* nativeHandle)
+RefPtr<Bindings::RootObject> ScriptController::createRootObject(void* nativeHandle)
{
RootObjectMap::iterator it = m_rootObjects.find(nativeHandle);
if (it != m_rootObjects.end())
@@ -330,36 +538,28 @@ PassRefPtr<Bindings::RootObject> ScriptController::createRootObject(void* native
RefPtr<Bindings::RootObject> rootObject = Bindings::RootObject::create(nativeHandle, globalObject(pluginWorld()));
m_rootObjects.set(nativeHandle, rootObject);
- return rootObject.release();
-}
-
-#if ENABLE(INSPECTOR)
-void ScriptController::setCaptureCallStackForUncaughtExceptions(bool)
-{
+ return rootObject;
}
void ScriptController::collectIsolatedContexts(Vector<std::pair<JSC::ExecState*, SecurityOrigin*>>& result)
{
for (ShellMap::iterator iter = m_windowShells.begin(); iter != m_windowShells.end(); ++iter) {
JSC::ExecState* exec = iter->value->window()->globalExec();
- SecurityOrigin* origin = iter->value->window()->impl().document()->securityOrigin();
+ SecurityOrigin* origin = &iter->value->window()->wrapped().document()->securityOrigin();
result.append(std::pair<JSC::ExecState*, SecurityOrigin*>(exec, origin));
}
}
-#endif
-
#if ENABLE(NETSCAPE_PLUGIN_API)
-
NPObject* ScriptController::windowScriptNPObject()
{
if (!m_windowScriptNPObject) {
+ JSLockHolder lock(commonVM());
if (canExecuteScripts(NotAboutToExecuteScript)) {
// JavaScript is enabled, so there is a JavaScript window object.
// Return an NPObject bound to the window object.
JSDOMWindow* win = windowShell(pluginWorld())->window();
ASSERT(win);
- JSC::JSLockHolder lock(win->globalExec());
Bindings::RootObject* root = bindingRootObject();
m_windowScriptNPObject = _NPN_CreateScriptObject(0, win, root);
} else {
@@ -371,26 +571,15 @@ NPObject* ScriptController::windowScriptNPObject()
return m_windowScriptNPObject;
}
-
-NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement* plugin)
-{
- JSObject* object = jsObjectForPluginElement(plugin);
- if (!object)
- return _NPN_CreateNoScriptObject();
-
- // Wrap the JSObject in an NPObject
- return _NPN_CreateScriptObject(0, object, bindingRootObject());
-}
-
#endif
-#if !PLATFORM(MAC)
-PassRefPtr<JSC::Bindings::Instance> ScriptController::createScriptInstanceForWidget(Widget* widget)
+#if !PLATFORM(COCOA)
+RefPtr<JSC::Bindings::Instance> ScriptController::createScriptInstanceForWidget(Widget* widget)
{
- if (!widget->isPluginView())
- return 0;
+ if (!is<PluginViewBase>(*widget))
+ return nullptr;
- return toPluginView(widget)->bindingInstance();
+ return downcast<PluginViewBase>(*widget).bindingInstance();
}
#endif
@@ -400,9 +589,10 @@ JSObject* ScriptController::jsObjectForPluginElement(HTMLPlugInElement* plugin)
if (!canExecuteScripts(NotAboutToExecuteScript))
return 0;
+ JSLockHolder lock(commonVM());
+
// Create a JSObject bound to this element
JSDOMWindow* globalObj = globalObject(pluginWorld());
- JSLockHolder lock(globalObj->globalExec());
// FIXME: is normal okay? - used for NP plugins?
JSValue jsElementValue = toJS(globalObj->globalExec(), globalObj, plugin);
if (!jsElementValue || !jsElementValue.isObject())
@@ -411,7 +601,7 @@ JSObject* ScriptController::jsObjectForPluginElement(HTMLPlugInElement* plugin)
return jsElementValue.getObject();
}
-#if !PLATFORM(MAC)
+#if !PLATFORM(COCOA)
void ScriptController::updatePlatformScriptObjects()
{
@@ -436,7 +626,7 @@ void ScriptController::cleanupScriptObjectsForPlugin(void* nativeHandle)
void ScriptController::clearScriptObjects()
{
- JSLockHolder lock(JSDOMWindowBase::commonVM());
+ JSLockHolder lock(commonVM());
RootObjectMap::const_iterator end = m_rootObjects.end();
for (RootObjectMap::const_iterator it = m_rootObjects.begin(); it != end; ++it)
@@ -446,7 +636,7 @@ void ScriptController::clearScriptObjects()
if (m_bindingRootObject) {
m_bindingRootObject->invalidate();
- m_bindingRootObject = 0;
+ m_bindingRootObject = nullptr;
}
#if ENABLE(NETSCAPE_PLUGIN_API)
@@ -455,67 +645,53 @@ void ScriptController::clearScriptObjects()
// script object properly.
// This shouldn't cause any problems for plugins since they should have already been stopped and destroyed at this point.
_NPN_DeallocateObject(m_windowScriptNPObject);
- m_windowScriptNPObject = 0;
+ m_windowScriptNPObject = nullptr;
}
#endif
}
-Deprecated::ScriptValue ScriptController::executeScriptInWorld(DOMWrapperWorld& world, const String& script, bool forceUserGesture)
+JSValue ScriptController::executeScriptInWorld(DOMWrapperWorld& world, const String& script, bool forceUserGesture)
{
- UserGestureIndicator gestureIndicator(forceUserGesture ? DefinitelyProcessingUserGesture : PossiblyProcessingUserGesture);
- ScriptSourceCode sourceCode(script, m_frame.document()->url());
+ UserGestureIndicator gestureIndicator(forceUserGesture ? std::optional<ProcessingUserGestureState>(ProcessingUserGesture) : std::nullopt);
+ ScriptSourceCode sourceCode(script, m_frame.document()->url(), TextPosition(), JSC::SourceProviderSourceType::Program, CachedScriptFetcher::create(m_frame.document()->charset()));
if (!canExecuteScripts(AboutToExecuteScript) || isPaused())
- return Deprecated::ScriptValue();
+ return { };
return evaluateInWorld(sourceCode, world);
}
-bool ScriptController::shouldBypassMainWorldContentSecurityPolicy()
-{
- CallFrame* callFrame = JSDOMWindow::commonVM()->topCallFrame;
- if (callFrame == CallFrame::noCaller())
- return false;
- DOMWrapperWorld& domWrapperWorld = currentWorld(callFrame);
- if (domWrapperWorld.isNormal())
- return false;
- return true;
-}
-
bool ScriptController::canExecuteScripts(ReasonForCallingCanExecuteScripts reason)
{
if (m_frame.document() && m_frame.document()->isSandboxed(SandboxScripts)) {
// FIXME: This message should be moved off the console once a solution to https://bugs.webkit.org/show_bug.cgi?id=103274 exists.
if (reason == AboutToExecuteScript)
- m_frame.document()->addConsoleMessage(SecurityMessageSource, ErrorMessageLevel, "Blocked script execution in '" + m_frame.document()->url().stringCenterEllipsizedToLength() + "' because the document's frame is sandboxed and the 'allow-scripts' permission is not set.");
+ m_frame.document()->addConsoleMessage(MessageSource::Security, MessageLevel::Error, "Blocked script execution in '" + m_frame.document()->url().stringCenterEllipsizedToLength() + "' because the document's frame is sandboxed and the 'allow-scripts' permission is not set.");
return false;
}
- if (m_frame.document() && m_frame.document()->isViewSource()) {
- ASSERT(m_frame.document()->securityOrigin()->isUnique());
- return true;
- }
-
if (!m_frame.page())
return false;
return m_frame.loader().client().allowScript(m_frame.settings().isScriptEnabled());
}
-Deprecated::ScriptValue ScriptController::executeScript(const String& script, bool forceUserGesture)
+JSValue ScriptController::executeScript(const String& script, bool forceUserGesture, ExceptionDetails* exceptionDetails)
{
- UserGestureIndicator gestureIndicator(forceUserGesture ? DefinitelyProcessingUserGesture : PossiblyProcessingUserGesture);
- return executeScript(ScriptSourceCode(script, m_frame.document()->url()));
+ UserGestureIndicator gestureIndicator(forceUserGesture ? std::optional<ProcessingUserGestureState>(ProcessingUserGesture) : std::nullopt);
+ return executeScript(ScriptSourceCode(script, m_frame.document()->url(), TextPosition(), JSC::SourceProviderSourceType::Program, CachedScriptFetcher::create(m_frame.document()->charset())), exceptionDetails);
}
-Deprecated::ScriptValue ScriptController::executeScript(const ScriptSourceCode& sourceCode)
+JSValue ScriptController::executeScript(const ScriptSourceCode& sourceCode, ExceptionDetails* exceptionDetails)
{
if (!canExecuteScripts(AboutToExecuteScript) || isPaused())
- return Deprecated::ScriptValue();
+ return { }; // FIXME: Would jsNull be better?
- Ref<Frame> protect(m_frame); // Script execution can destroy the frame, and thus the ScriptController.
+ // FIXME: Preventing Frame from being destroyed is essentially unnecessary.
+ // https://bugs.webkit.org/show_bug.cgi?id=164763
+ Ref<Frame> protector(m_frame); // Script execution can destroy the frame, and thus the ScriptController.
- return evaluate(sourceCode);
+ return evaluate(sourceCode, exceptionDetails);
}
bool ScriptController::executeIfJavaScriptURL(const URL& url, ShouldReplaceDocumentIfJavaScriptURL shouldReplaceDocumentIfJavaScriptURL)
@@ -534,7 +710,7 @@ bool ScriptController::executeIfJavaScriptURL(const URL& url, ShouldReplaceDocum
const int javascriptSchemeLength = sizeof("javascript:") - 1;
String decodedURL = decodeURLEscapeSequences(url.string());
- Deprecated::ScriptValue result = executeScript(decodedURL.substring(javascriptSchemeLength));
+ auto result = executeScript(decodedURL.substring(javascriptSchemeLength));
// If executing script caused this frame to be removed from the page, we
// don't want to try to replace its document!
@@ -542,9 +718,7 @@ bool ScriptController::executeIfJavaScriptURL(const URL& url, ShouldReplaceDocum
return true;
String scriptResult;
- JSDOMWindowShell* shell = windowShell(mainThreadNormalWorld());
- JSC::ExecState* exec = shell->window()->globalExec();
- if (!result.getString(exec, scriptResult))
+ if (!result || !result.getString(windowShell(mainThreadNormalWorld())->window()->globalExec(), scriptResult))
return true;
// FIXME: We should always replace the document, but doing so
diff --git a/Source/WebCore/bindings/js/ScriptController.h b/Source/WebCore/bindings/js/ScriptController.h
index 67e96ec3c..58fd49da8 100644
--- a/Source/WebCore/bindings/js/ScriptController.h
+++ b/Source/WebCore/bindings/js/ScriptController.h
@@ -1,7 +1,7 @@
/*
* Copyright (C) 1999 Harri Porten (porten@kde.org)
* Copyright (C) 2001 Peter Kelly (pmk@post.com)
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008-2016 Apple Inc. All rights reserved.
* Copyright (C) 2008 Eric Seidel <eric@webkit.org>
*
* This library is free software; you can redistribute it and/or
@@ -19,8 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef ScriptController_h
-#define ScriptController_h
+#pragma once
#include "FrameLoaderTypes.h"
#include "JSDOMWindowShell.h"
@@ -30,37 +29,40 @@
#include <wtf/RefPtr.h>
#include <wtf/text/TextPosition.h>
-#if PLATFORM(MAC)
+#if PLATFORM(COCOA)
#include <wtf/RetainPtr.h>
-OBJC_CLASS WebScriptObject;
OBJC_CLASS JSContext;
+OBJC_CLASS WebScriptObject;
#endif
struct NPObject;
-namespace Deprecated {
-class ScriptValue;
-}
-
namespace JSC {
- class JSGlobalObject;
- class ExecState;
-
- namespace Bindings {
- class Instance;
- class RootObject;
- }
+class ExecState;
+class JSGlobalObject;
+class JSInternalPromise;
+class JSModuleRecord;
+
+namespace Bindings {
+class Instance;
+class RootObject;
+}
}
namespace WebCore {
-class HTMLPlugInElement;
+class CachedScriptFetcher;
class Frame;
+class HTMLDocument;
+class HTMLPlugInElement;
+class LoadableModuleScript;
class ScriptSourceCode;
class SecurityOrigin;
+class URL;
class Widget;
+struct ExceptionDetails;
-typedef HashMap<void*, RefPtr<JSC::Bindings::RootObject>> RootObjectMap;
+using RootObjectMap = HashMap<void*, RefPtr<JSC::Bindings::RootObject>>;
enum ReasonForCallingCanExecuteScripts {
AboutToExecuteScript,
@@ -68,18 +70,21 @@ enum ReasonForCallingCanExecuteScripts {
};
class ScriptController {
- friend class ScriptCachedFrameData;
+ WTF_MAKE_FAST_ALLOCATED;
+
typedef HashMap<RefPtr<DOMWrapperWorld>, JSC::Strong<JSDOMWindowShell>> ShellMap;
public:
explicit ScriptController(Frame&);
~ScriptController();
- static PassRefPtr<DOMWrapperWorld> createWorld();
+ WEBCORE_EXPORT static Ref<DOMWrapperWorld> createWorld();
- JSDOMWindowShell* createWindowShell(DOMWrapperWorld&);
+ JSDOMWindowShell& createWindowShell(DOMWrapperWorld&);
void destroyWindowShell(DOMWrapperWorld&);
+ Vector<JSC::Strong<JSDOMWindowShell>> windowShells();
+
JSDOMWindowShell* windowShell(DOMWrapperWorld& world)
{
ShellMap::iterator iter = m_windowShells.find(&world);
@@ -97,9 +102,9 @@ public:
static void getAllWorlds(Vector<Ref<DOMWrapperWorld>>&);
- Deprecated::ScriptValue executeScript(const ScriptSourceCode&);
- Deprecated::ScriptValue executeScript(const String& script, bool forceUserGesture = false);
- Deprecated::ScriptValue executeScriptInWorld(DOMWrapperWorld&, const String& script, bool forceUserGesture = false);
+ JSC::JSValue executeScript(const ScriptSourceCode&, ExceptionDetails* = nullptr);
+ WEBCORE_EXPORT JSC::JSValue executeScript(const String& script, bool forceUserGesture = false, ExceptionDetails* = nullptr);
+ WEBCORE_EXPORT JSC::JSValue executeScriptInWorld(DOMWrapperWorld&, const String& script, bool forceUserGesture = false);
// Returns true if argument is a JavaScript URL.
bool executeIfJavaScriptURL(const URL&, ShouldReplaceDocumentIfJavaScriptURL shouldReplaceDocumentIfJavaScriptURL = ReplaceDocumentIfJavaScriptURL);
@@ -108,18 +113,30 @@ public:
// Darwin is an exception to this rule: it is OK to call this function from any thread, even reentrantly.
static void initializeThreading();
- Deprecated::ScriptValue evaluate(const ScriptSourceCode&);
- Deprecated::ScriptValue evaluateInWorld(const ScriptSourceCode&, DOMWrapperWorld&);
+ JSC::JSValue evaluate(const ScriptSourceCode&, ExceptionDetails* = nullptr);
+ JSC::JSValue evaluateInWorld(const ScriptSourceCode&, DOMWrapperWorld&, ExceptionDetails* = nullptr);
+
+ void loadModuleScriptInWorld(LoadableModuleScript&, const String& moduleName, DOMWrapperWorld&);
+ void loadModuleScript(LoadableModuleScript&, const String& moduleName);
+ void loadModuleScriptInWorld(LoadableModuleScript&, const ScriptSourceCode&, DOMWrapperWorld&);
+ void loadModuleScript(LoadableModuleScript&, const ScriptSourceCode&);
+
+ JSC::JSValue linkAndEvaluateModuleScriptInWorld(LoadableModuleScript& , DOMWrapperWorld&);
+ JSC::JSValue linkAndEvaluateModuleScript(LoadableModuleScript&);
+
+ JSC::JSValue evaluateModule(const URL&, JSC::JSModuleRecord&, DOMWrapperWorld&);
+ JSC::JSValue evaluateModule(const URL&, JSC::JSModuleRecord&);
WTF::TextPosition eventHandlerPosition() const;
void enableEval();
void disableEval(const String& errorMessage);
- static bool processingUserGesture();
+ WEBCORE_EXPORT static bool processingUserGesture();
+ WEBCORE_EXPORT static bool processingUserGestureForMedia();
static bool canAccessFromCurrentOrigin(Frame*);
- bool canExecuteScripts(ReasonForCallingCanExecuteScripts);
+ WEBCORE_EXPORT bool canExecuteScripts(ReasonForCallingCanExecuteScripts);
// Debugger can be 0 to detach any existing Debugger.
void attachDebugger(JSC::Debugger*); // Attaches/detaches in all worlds/window shells.
@@ -130,44 +147,40 @@ public:
const String* sourceURL() const { return m_sourceURL; } // 0 if we are not evaluating any script
- void clearWindowShell(DOMWindow* newDOMWindow, bool goingIntoPageCache);
+ void clearWindowShellsNotMatchingDOMWindow(DOMWindow*, bool goingIntoPageCache);
+ void setDOMWindowForWindowShell(DOMWindow*);
void updateDocument();
void namedItemAdded(HTMLDocument*, const AtomicString&) { }
void namedItemRemoved(HTMLDocument*, const AtomicString&) { }
void clearScriptObjects();
- void cleanupScriptObjectsForPlugin(void*);
+ WEBCORE_EXPORT void cleanupScriptObjectsForPlugin(void*);
void updatePlatformScriptObjects();
- PassRefPtr<JSC::Bindings::Instance> createScriptInstanceForWidget(Widget*);
- JSC::Bindings::RootObject* bindingRootObject();
+ RefPtr<JSC::Bindings::Instance> createScriptInstanceForWidget(Widget*);
+ WEBCORE_EXPORT JSC::Bindings::RootObject* bindingRootObject();
JSC::Bindings::RootObject* cacheableBindingRootObject();
- PassRefPtr<JSC::Bindings::RootObject> createRootObject(void* nativeHandle);
+ WEBCORE_EXPORT RefPtr<JSC::Bindings::RootObject> createRootObject(void* nativeHandle);
-#if ENABLE(INSPECTOR)
- static void setCaptureCallStackForUncaughtExceptions(bool);
void collectIsolatedContexts(Vector<std::pair<JSC::ExecState*, SecurityOrigin*>>&);
-#endif
-#if PLATFORM(MAC)
- WebScriptObject* windowScriptObject();
- JSContext *javaScriptContext();
+#if PLATFORM(COCOA)
+ WEBCORE_EXPORT WebScriptObject* windowScriptObject();
+ WEBCORE_EXPORT JSContext *javaScriptContext();
#endif
- JSC::JSObject* jsObjectForPluginElement(HTMLPlugInElement*);
+ WEBCORE_EXPORT JSC::JSObject* jsObjectForPluginElement(HTMLPlugInElement*);
#if ENABLE(NETSCAPE_PLUGIN_API)
- NPObject* createScriptObjectForPluginElement(HTMLPlugInElement*);
- NPObject* windowScriptNPObject();
+ WEBCORE_EXPORT NPObject* windowScriptNPObject();
#endif
- bool shouldBypassMainWorldContentSecurityPolicy();
-
private:
- JSDOMWindowShell* initScript(DOMWrapperWorld&);
+ WEBCORE_EXPORT JSDOMWindowShell* initScript(DOMWrapperWorld&);
+ void setupModuleScriptHandlers(LoadableModuleScript&, JSC::JSInternalPromise&, DOMWrapperWorld&);
void disconnectPlatformScriptObjects();
@@ -188,11 +201,9 @@ private:
#if ENABLE(NETSCAPE_PLUGIN_API)
NPObject* m_windowScriptNPObject;
#endif
-#if PLATFORM(MAC)
+#if PLATFORM(COCOA)
RetainPtr<WebScriptObject> m_windowScriptObject;
#endif
};
} // namespace WebCore
-
-#endif // ScriptController_h
diff --git a/Source/WebCore/bindings/js/ScriptGlobalObject.cpp b/Source/WebCore/bindings/js/ScriptGlobalObject.cpp
index a8b5a620f..2275ff939 100644
--- a/Source/WebCore/bindings/js/ScriptGlobalObject.cpp
+++ b/Source/WebCore/bindings/js/ScriptGlobalObject.cpp
@@ -31,63 +31,38 @@
#include "config.h"
#include "ScriptGlobalObject.h"
-#include "JSDOMBinding.h"
-#include <bindings/ScriptObject.h>
-#include <runtime/JSLock.h>
-
-#if ENABLE(INSPECTOR)
+#include "JSDOMConvert.h"
+#include "JSDOMExceptionHandling.h"
#include "JSInspectorFrontendHost.h"
-#endif
+#include <runtime/IdentifierInlines.h>
using namespace JSC;
namespace WebCore {
-static bool handleException(JSC::ExecState* scriptState)
-{
- if (!scriptState->hadException())
- return true;
-
- reportException(scriptState, scriptState->exception());
- return false;
-}
-
-bool ScriptGlobalObject::set(JSC::ExecState* scriptState, const char* name, const Deprecated::ScriptObject& value)
-{
- JSLockHolder lock(scriptState);
- scriptState->lexicalGlobalObject()->putDirect(scriptState->vm(), Identifier(scriptState, name), value.jsObject());
- return handleException(scriptState);
-}
-
-#if ENABLE(INSPECTOR)
-bool ScriptGlobalObject::set(JSC::ExecState* scriptState, const char* name, InspectorFrontendHost* value)
+bool ScriptGlobalObject::set(ExecState& scriptState, const char* name, InspectorFrontendHost& value)
{
- JSLockHolder lock(scriptState);
- JSDOMGlobalObject* globalObject = jsCast<JSDOMGlobalObject*>(scriptState->lexicalGlobalObject());
- globalObject->putDirect(scriptState->vm(), Identifier(scriptState, name), toJS(scriptState, globalObject, value));
- return handleException(scriptState);
-}
-#endif // ENABLE(INSPECTOR)
-
-bool ScriptGlobalObject::get(JSC::ExecState* scriptState, const char* name, Deprecated::ScriptObject& value)
-{
- JSLockHolder lock(scriptState);
- JSValue jsValue = scriptState->lexicalGlobalObject()->get(scriptState, Identifier(scriptState, name));
- if (!jsValue)
- return false;
-
- if (!jsValue.isObject())
+ auto& vm = scriptState.vm();
+ JSLockHolder lock(vm);
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+ auto& globalObject = *jsCast<JSDOMGlobalObject*>(scriptState.lexicalGlobalObject());
+ globalObject.putDirect(vm, Identifier::fromString(&vm, name), toJS<IDLInterface<InspectorFrontendHost>>(scriptState, globalObject, value));
+ if (UNLIKELY(scope.exception())) {
+ reportException(&scriptState, scope.exception());
return false;
-
- value = Deprecated::ScriptObject(scriptState, asObject(jsValue));
+ }
return true;
}
-bool ScriptGlobalObject::remove(JSC::ExecState* scriptState, const char* name)
+bool ScriptGlobalObject::get(ExecState& scriptState, const char* name, JSObject*& object)
{
- JSLockHolder lock(scriptState);
- scriptState->lexicalGlobalObject()->methodTable()->deleteProperty(scriptState->lexicalGlobalObject(), scriptState, Identifier(scriptState, name));
- return handleException(scriptState);
+ auto& vm = scriptState.vm();
+ JSLockHolder lock(vm);
+ JSValue value = scriptState.lexicalGlobalObject()->get(&scriptState, Identifier::fromString(&vm, name));
+ if (!value || !value.isObject())
+ return false;
+ object = asObject(value);
+ return true;
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/ScriptGlobalObject.h b/Source/WebCore/bindings/js/ScriptGlobalObject.h
index 8aa055bd6..f879a025d 100644
--- a/Source/WebCore/bindings/js/ScriptGlobalObject.h
+++ b/Source/WebCore/bindings/js/ScriptGlobalObject.h
@@ -28,15 +28,11 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ScriptGlobalObject_h
-#define ScriptGlobalObject_h
-
-namespace Deprecated {
-class ScriptObject;
-}
+#pragma once
namespace JSC {
class ExecState;
+class JSObject;
}
namespace WebCore {
@@ -45,17 +41,11 @@ class InspectorFrontendHost;
class ScriptGlobalObject {
public:
- static bool set(JSC::ExecState*, const char* name, const Deprecated::ScriptObject&);
-#if ENABLE(INSPECTOR)
- static bool set(JSC::ExecState*, const char* name, InspectorFrontendHost*);
-#endif
+ WEBCORE_EXPORT static bool set(JSC::ExecState&, const char* name, InspectorFrontendHost&);
+ static bool get(JSC::ExecState&, const char* name, JSC::JSObject*&);
- static bool get(JSC::ExecState*, const char* name, Deprecated::ScriptObject&);
- static bool remove(JSC::ExecState*, const char* name);
private:
- ScriptGlobalObject() { }
+ ScriptGlobalObject() = delete;
};
} // namespace WebCore
-
-#endif // ScriptGlobalObject_h
diff --git a/Source/WebCore/bindings/js/ScriptHeapSnapshot.h b/Source/WebCore/bindings/js/ScriptHeapSnapshot.h
deleted file mode 100644
index 5269ff925..000000000
--- a/Source/WebCore/bindings/js/ScriptHeapSnapshot.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * Copyright (c) 2010, Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef ScriptHeapSnapshot_h
-#define ScriptHeapSnapshot_h
-
-#include <wtf/RefCounted.h>
-#include <wtf/text/WTFString.h>
-
-namespace WebCore {
-
-typedef uint32_t SnapshotObjectId;
-
-class ScriptHeapSnapshot : public RefCounted<ScriptHeapSnapshot> {
-public:
- class OutputStream {
- public:
- virtual ~OutputStream() { }
- virtual void Write(const String& chunk) = 0;
- virtual void Close() = 0;
- };
-
- virtual ~ScriptHeapSnapshot() { }
-
- String title() const { return ""; }
- unsigned int uid() const { return 0; }
-
- void writeJSON(OutputStream*) { }
- SnapshotObjectId maxSnapshotJSObjectId() const { return 0; }
-
-private:
- ScriptHeapSnapshot() { }
-};
-
-} // namespace WebCore
-
-#endif // ScriptHeapSnapshot_h
diff --git a/Source/WebCore/bindings/js/ScriptModuleLoader.cpp b/Source/WebCore/bindings/js/ScriptModuleLoader.cpp
new file mode 100644
index 000000000..b67ffa3e6
--- /dev/null
+++ b/Source/WebCore/bindings/js/ScriptModuleLoader.cpp
@@ -0,0 +1,294 @@
+/*
+ * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ScriptModuleLoader.h"
+
+#include "CachedModuleScriptLoader.h"
+#include "CachedScript.h"
+#include "CachedScriptFetcher.h"
+#include "Document.h"
+#include "Frame.h"
+#include "JSDOMBinding.h"
+#include "LoadableModuleScript.h"
+#include "MIMETypeRegistry.h"
+#include "ModuleFetchFailureKind.h"
+#include "ScriptController.h"
+#include "ScriptSourceCode.h"
+#include "WebCoreJSClientData.h"
+#include <runtime/Completion.h>
+#include <runtime/JSInternalPromise.h>
+#include <runtime/JSInternalPromiseDeferred.h>
+#include <runtime/JSModuleRecord.h>
+#include <runtime/JSScriptFetcher.h>
+#include <runtime/JSSourceCode.h>
+#include <runtime/JSString.h>
+#include <runtime/Symbol.h>
+
+namespace WebCore {
+
+ScriptModuleLoader::ScriptModuleLoader(Document& document)
+ : m_document(document)
+{
+}
+
+ScriptModuleLoader::~ScriptModuleLoader()
+{
+ for (auto& loader : m_loaders)
+ loader->clearClient();
+}
+
+static bool isRootModule(JSC::JSValue importerModuleKey)
+{
+ return importerModuleKey.isSymbol() || importerModuleKey.isUndefined();
+}
+
+static Expected<URL, ASCIILiteral> resolveModuleSpecifier(Document& document, const String& specifier, const URL& baseURL)
+{
+ // https://html.spec.whatwg.org/multipage/webappapis.html#resolve-a-module-specifier
+
+ URL absoluteURL(URL(), specifier);
+ if (absoluteURL.isValid())
+ return absoluteURL;
+
+ if (!specifier.startsWith('/') && !specifier.startsWith("./") && !specifier.startsWith("../"))
+ return makeUnexpected(ASCIILiteral("Module specifier does not start with \"/\", \"./\", or \"../\"."));
+
+ auto result = document.completeURL(specifier, baseURL);
+ if (!result.isValid())
+ return makeUnexpected(ASCIILiteral("Module name does not resolve to a valid URL."));
+ return result;
+}
+
+JSC::JSInternalPromise* ScriptModuleLoader::resolve(JSC::JSGlobalObject* jsGlobalObject, JSC::ExecState* exec, JSC::JSModuleLoader*, JSC::JSValue moduleNameValue, JSC::JSValue importerModuleKey, JSC::JSValue)
+{
+ auto& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(jsGlobalObject);
+ auto& jsPromise = *JSC::JSInternalPromiseDeferred::create(exec, &globalObject);
+ auto promise = DeferredPromise::create(globalObject, jsPromise);
+
+ // We use a Symbol as a special purpose; It means this module is an inline module.
+ // So there is no correct URL to retrieve the module source code. If the module name
+ // value is a Symbol, it is used directly as a module key.
+ if (moduleNameValue.isSymbol()) {
+ promise->resolve<IDLAny>(JSC::Symbol::create(exec->vm(), asSymbol(moduleNameValue)->privateName().uid()));
+ return jsPromise.promise();
+ }
+
+ if (!moduleNameValue.isString()) {
+ promise->reject(TypeError, ASCIILiteral("Importer module key is not a Symbol or a String."));
+ return jsPromise.promise();
+ }
+
+ String specifier = asString(moduleNameValue)->value(exec);
+ URL baseURL;
+ if (isRootModule(importerModuleKey))
+ baseURL = m_document.baseURL();
+ else {
+ ASSERT(importerModuleKey.isString());
+ URL importerModuleRequestURL(URL(), asString(importerModuleKey)->value(exec));
+ ASSERT_WITH_MESSAGE(importerModuleRequestURL.isValid(), "Invalid module referrer never starts importing dependent modules.");
+
+ auto iterator = m_requestURLToResponseURLMap.find(importerModuleRequestURL);
+ ASSERT_WITH_MESSAGE(iterator != m_requestURLToResponseURLMap.end(), "Module referrer must register itself to the map before starting importing dependent modules.");
+ baseURL = iterator->value;
+ }
+
+ auto result = resolveModuleSpecifier(m_document, specifier, baseURL);
+ if (!result) {
+ promise->reject(TypeError, result.error());
+ return jsPromise.promise();
+ }
+
+ promise->resolve<IDLDOMString>(result->string());
+ return jsPromise.promise();
+}
+
+static void rejectToPropagateNetworkError(DeferredPromise& deferred, ModuleFetchFailureKind failureKind, ASCIILiteral message)
+{
+ deferred.rejectWithCallback([&] (JSC::ExecState& state, JSDOMGlobalObject&) {
+ // We annotate exception with special private symbol. It allows us to distinguish these errors from the user thrown ones.
+ JSC::VM& vm = state.vm();
+ // FIXME: Propagate more descriptive error.
+ // https://bugs.webkit.org/show_bug.cgi?id=167553
+ auto* error = JSC::createTypeError(&state, message);
+ ASSERT(error);
+ error->putDirect(vm, static_cast<JSVMClientData&>(*vm.clientData).builtinNames().failureKindPrivateName(), JSC::jsNumber(static_cast<int32_t>(failureKind)));
+ return error;
+ });
+}
+
+JSC::JSInternalPromise* ScriptModuleLoader::fetch(JSC::JSGlobalObject* jsGlobalObject, JSC::ExecState* exec, JSC::JSModuleLoader*, JSC::JSValue moduleKeyValue, JSC::JSValue scriptFetcher)
+{
+ ASSERT(JSC::jsDynamicCast<JSC::JSScriptFetcher*>(exec->vm(), scriptFetcher));
+
+ auto& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(jsGlobalObject);
+ auto& jsPromise = *JSC::JSInternalPromiseDeferred::create(exec, &globalObject);
+ auto deferred = DeferredPromise::create(globalObject, jsPromise);
+ if (moduleKeyValue.isSymbol()) {
+ deferred->reject(TypeError, ASCIILiteral("Symbol module key should be already fulfilled with the inlined resource."));
+ return jsPromise.promise();
+ }
+
+ if (!moduleKeyValue.isString()) {
+ deferred->reject(TypeError, ASCIILiteral("Module key is not Symbol or String."));
+ return jsPromise.promise();
+ }
+
+ // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script
+
+ URL completedURL(URL(), asString(moduleKeyValue)->value(exec));
+ if (!completedURL.isValid()) {
+ deferred->reject(TypeError, ASCIILiteral("Module key is a valid URL."));
+ return jsPromise.promise();
+ }
+
+ auto loader = CachedModuleScriptLoader::create(*this, deferred.get(), *static_cast<CachedScriptFetcher*>(JSC::jsCast<JSC::JSScriptFetcher*>(scriptFetcher)->fetcher()));
+ m_loaders.add(loader.copyRef());
+ if (!loader->load(m_document, completedURL)) {
+ loader->clearClient();
+ m_loaders.remove(WTFMove(loader));
+ rejectToPropagateNetworkError(deferred.get(), ModuleFetchFailureKind::WasErrored, ASCIILiteral("Importing a module script failed."));
+ return jsPromise.promise();
+ }
+
+ return jsPromise.promise();
+}
+
+JSC::JSValue ScriptModuleLoader::evaluate(JSC::JSGlobalObject*, JSC::ExecState* exec, JSC::JSModuleLoader*, JSC::JSValue moduleKeyValue, JSC::JSValue moduleRecordValue, JSC::JSValue)
+{
+ JSC::VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ // FIXME: Currently, we only support JSModuleRecord.
+ // Once the reflective part of the module loader is supported, we will handle arbitrary values.
+ // https://whatwg.github.io/loader/#registry-prototype-provide
+ auto* moduleRecord = jsDynamicDowncast<JSC::JSModuleRecord*>(vm, moduleRecordValue);
+ if (!moduleRecord)
+ return JSC::jsUndefined();
+
+ URL sourceURL;
+ if (moduleKeyValue.isSymbol())
+ sourceURL = m_document.url();
+ else if (moduleKeyValue.isString())
+ sourceURL = URL(URL(), asString(moduleKeyValue)->value(exec));
+ else
+ return JSC::throwTypeError(exec, scope, ASCIILiteral("Module key is not Symbol or String."));
+
+ if (!sourceURL.isValid())
+ return JSC::throwTypeError(exec, scope, ASCIILiteral("Module key is an invalid URL."));
+
+ if (auto* frame = m_document.frame())
+ return frame->script().evaluateModule(sourceURL, *moduleRecord);
+ return JSC::jsUndefined();
+}
+
+static JSC::JSInternalPromise* rejectPromise(JSC::ExecState& state, JSDOMGlobalObject& globalObject, ExceptionCode ec, ASCIILiteral message)
+{
+ auto& jsPromise = *JSC::JSInternalPromiseDeferred::create(&state, &globalObject);
+ auto deferred = DeferredPromise::create(globalObject, jsPromise);
+ deferred->reject(ec, WTFMove(message));
+ return jsPromise.promise();
+}
+
+JSC::JSInternalPromise* ScriptModuleLoader::importModule(JSC::JSGlobalObject* jsGlobalObject, JSC::ExecState* exec, JSC::JSModuleLoader*, JSC::JSString* moduleName, const JSC::SourceOrigin& sourceOrigin)
+{
+ auto& state = *exec;
+ JSC::VM& vm = exec->vm();
+ auto& globalObject = *JSC::jsCast<JSDOMGlobalObject*>(jsGlobalObject);
+
+ // If SourceOrigin and/or CachedScriptFetcher is null, we import the module with the default fetcher.
+ // SourceOrigin can be null if the source code is not coupled with the script file.
+ // The examples,
+ // 1. The code evaluated by the inspector.
+ // 2. The other unusual code execution like the evaluation through the NPAPI.
+ // 3. The code from injected bundle's script.
+ // 4. The code from extension script.
+ URL baseURL;
+ RefPtr<JSC::ScriptFetcher> scriptFetcher;
+ if (sourceOrigin.isNull()) {
+ baseURL = m_document.baseURL();
+ scriptFetcher = CachedScriptFetcher::create(m_document.charset());
+ } else {
+ baseURL = URL(URL(), sourceOrigin.string());
+ if (!baseURL.isValid())
+ return rejectPromise(state, globalObject, TypeError, ASCIILiteral("Importer module key is not a Symbol or a String."));
+
+ if (sourceOrigin.fetcher())
+ scriptFetcher = sourceOrigin.fetcher();
+ else
+ scriptFetcher = CachedScriptFetcher::create(m_document.charset());
+ }
+ ASSERT(baseURL.isValid());
+ ASSERT(scriptFetcher);
+
+ auto specifier = moduleName->value(exec);
+ auto result = resolveModuleSpecifier(m_document, specifier, baseURL);
+ if (!result)
+ return rejectPromise(state, globalObject, TypeError, result.error());
+
+ return JSC::importModule(exec, JSC::Identifier::fromString(&vm, result->string()), JSC::JSScriptFetcher::create(vm, WTFMove(scriptFetcher) ));
+}
+
+void ScriptModuleLoader::notifyFinished(CachedModuleScriptLoader& loader, RefPtr<DeferredPromise> promise)
+{
+ // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script
+
+ if (!m_loaders.remove(&loader))
+ return;
+ loader.clearClient();
+
+ auto& cachedScript = *loader.cachedScript();
+
+ if (cachedScript.resourceError().isAccessControl()) {
+ promise->reject(TypeError, ASCIILiteral("Cross-origin script load denied by Cross-Origin Resource Sharing policy."));
+ return;
+ }
+
+ if (cachedScript.errorOccurred()) {
+ rejectToPropagateNetworkError(*promise, ModuleFetchFailureKind::WasErrored, ASCIILiteral("Importing a module script failed."));
+ return;
+ }
+
+ if (cachedScript.wasCanceled()) {
+ rejectToPropagateNetworkError(*promise, ModuleFetchFailureKind::WasCanceled, ASCIILiteral("Importing a module script is canceled."));
+ return;
+ }
+
+ if (!MIMETypeRegistry::isSupportedJavaScriptMIMEType(cachedScript.response().mimeType())) {
+ // https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-single-module-script
+ // The result of extracting a MIME type from response's header list (ignoring parameters) is not a JavaScript MIME type.
+ // For historical reasons, fetching a classic script does not include MIME type checking. In contrast, module scripts will fail to load if they are not of a correct MIME type.
+ promise->reject(TypeError, makeString("'", cachedScript.response().mimeType(), "' is not a valid JavaScript MIME type."));
+ return;
+ }
+
+ m_requestURLToResponseURLMap.add(cachedScript.url(), cachedScript.response().url());
+ promise->resolveWithCallback([&] (JSC::ExecState& state, JSDOMGlobalObject&) {
+ return JSC::JSSourceCode::create(state.vm(),
+ JSC::SourceCode { ScriptSourceCode { &cachedScript, JSC::SourceProviderSourceType::Module, loader.scriptFetcher() }.jsSourceCode() });
+ });
+}
+
+}
diff --git a/Source/WebCore/bindings/js/ScriptModuleLoader.h b/Source/WebCore/bindings/js/ScriptModuleLoader.h
new file mode 100644
index 000000000..6e7a61b57
--- /dev/null
+++ b/Source/WebCore/bindings/js/ScriptModuleLoader.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2015, 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "CachedModuleScriptLoader.h"
+#include "CachedModuleScriptLoaderClient.h"
+#include "URL.h"
+#include "URLHash.h"
+#include <runtime/JSCJSValue.h>
+#include <wtf/Noncopyable.h>
+
+namespace JSC {
+
+class ExecState;
+class JSGlobalObject;
+class JSInternalPromise;
+class JSModuleLoader;
+class SourceOrigin;
+
+}
+
+namespace WebCore {
+
+class Document;
+class JSDOMGlobalObject;
+
+class ScriptModuleLoader final : private CachedModuleScriptLoaderClient {
+ WTF_MAKE_NONCOPYABLE(ScriptModuleLoader); WTF_MAKE_FAST_ALLOCATED;
+public:
+ explicit ScriptModuleLoader(Document&);
+ ~ScriptModuleLoader();
+
+ Document& document() { return m_document; }
+
+ JSC::JSInternalPromise* resolve(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue moduleName, JSC::JSValue importerModuleKey, JSC::JSValue scriptFetcher);
+ JSC::JSInternalPromise* fetch(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue moduleKey, JSC::JSValue scriptFetcher);
+ JSC::JSValue evaluate(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSValue moduleKey, JSC::JSValue moduleRecord, JSC::JSValue scriptFetcher);
+ JSC::JSInternalPromise* importModule(JSC::JSGlobalObject*, JSC::ExecState*, JSC::JSModuleLoader*, JSC::JSString*, const JSC::SourceOrigin&);
+
+private:
+ void notifyFinished(CachedModuleScriptLoader&, RefPtr<DeferredPromise>) final;
+
+ Document& m_document;
+ HashMap<URL, URL> m_requestURLToResponseURLMap;
+ HashSet<Ref<CachedModuleScriptLoader>> m_loaders;
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/ScriptProfile.cpp b/Source/WebCore/bindings/js/ScriptProfile.cpp
deleted file mode 100644
index c8778a580..000000000
--- a/Source/WebCore/bindings/js/ScriptProfile.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include "ScriptProfile.h"
-
-#include "JSDOMBinding.h"
-#include <inspector/InspectorValues.h>
-#include <profiler/Profile.h>
-#include <profiler/ProfileNode.h>
-
-namespace WebCore {
-
-PassRefPtr<ScriptProfile> ScriptProfile::create(PassRefPtr<JSC::Profile> profile)
-{
- if (!profile)
- return 0;
- return adoptRef(new ScriptProfile(profile));
-}
-
-ScriptProfile::ScriptProfile(PassRefPtr<JSC::Profile> profile)
- : m_profile(profile)
-{
-}
-
-ScriptProfile::~ScriptProfile()
-{
-}
-
-String ScriptProfile::title() const
-{
- return m_profile->title();
-}
-
-unsigned int ScriptProfile::uid() const
-{
- return m_profile->uid();
-}
-
-ScriptProfileNode* ScriptProfile::head() const
-{
- return m_profile->head();
-}
-
-double ScriptProfile::idleTime() const
-{
- return 0.0;
-}
-
-#if ENABLE(INSPECTOR)
-static PassRefPtr<Inspector::TypeBuilder::Profiler::CPUProfileNode> buildInspectorObjectFor(const JSC::ProfileNode* node)
-{
- typedef Vector<RefPtr<JSC::ProfileNode>> ProfileNodesList;
- const ProfileNodesList& nodeChildren = node->children();
- ProfileNodesList::const_iterator end = nodeChildren.end();
- RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::Profiler::CPUProfileNode>> children = Inspector::TypeBuilder::Array<Inspector::TypeBuilder::Profiler::CPUProfileNode>::create();
- for (ProfileNodesList::const_iterator iter = nodeChildren.begin(); iter != end; ++iter)
- children->addItem(buildInspectorObjectFor(iter->get()));
-
- RefPtr<Inspector::TypeBuilder::Profiler::CPUProfileNode> result = Inspector::TypeBuilder::Profiler::CPUProfileNode::create()
- .setFunctionName(node->functionName())
- .setUrl(node->url())
- .setLineNumber(node->lineNumber())
- .setTotalTime(node->totalTime())
- .setSelfTime(node->selfTime())
- .setNumberOfCalls(node->numberOfCalls())
- .setCallUID(node->callIdentifier().hash())
- .setChildren(children.release());
- return result.release();
-}
-
-PassRefPtr<Inspector::TypeBuilder::Profiler::CPUProfileNode> ScriptProfile::buildInspectorObjectForHead() const
-{
- return buildInspectorObjectFor(m_profile->head());
-}
-
-PassRefPtr<Inspector::TypeBuilder::Profiler::CPUProfileNode> ScriptProfile::buildInspectorObjectForBottomUpHead() const
-{
- return 0;
-}
-#endif
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/ScriptProfile.h b/Source/WebCore/bindings/js/ScriptProfile.h
deleted file mode 100644
index 1f4c03ec9..000000000
--- a/Source/WebCore/bindings/js/ScriptProfile.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef ScriptProfile_h
-#define ScriptProfile_h
-
-#include "ScriptProfileNode.h"
-#include <wtf/Forward.h>
-#include <wtf/PassRefPtr.h>
-#include <wtf/RefCounted.h>
-#include <wtf/RefPtr.h>
-
-#if ENABLE(INSPECTOR)
-#include "InspectorWebTypeBuilders.h"
-#endif
-
-namespace JSC {
-class Profile;
-}
-
-namespace WebCore {
-
-class ScriptProfile : public RefCounted<ScriptProfile> {
-public:
- static PassRefPtr<ScriptProfile> create(PassRefPtr<JSC::Profile> profile);
- virtual ~ScriptProfile();
-
- String title() const;
- unsigned int uid() const;
- ScriptProfileNode* head() const;
- double idleTime() const;
-
-#if ENABLE(INSPECTOR)
- PassRefPtr<Inspector::TypeBuilder::Profiler::CPUProfileNode> buildInspectorObjectForHead() const;
- PassRefPtr<Inspector::TypeBuilder::Profiler::CPUProfileNode> buildInspectorObjectForBottomUpHead() const;
-#endif
-
-private:
- ScriptProfile(PassRefPtr<JSC::Profile> profile);
-
- RefPtr<JSC::Profile> m_profile;
-};
-
-
-} // namespace WebCore
-
-#endif // ScriptProfile_h
diff --git a/Source/WebCore/bindings/js/ScriptProfiler.cpp b/Source/WebCore/bindings/js/ScriptProfiler.cpp
deleted file mode 100644
index a30e7b285..000000000
--- a/Source/WebCore/bindings/js/ScriptProfiler.cpp
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include "ScriptProfiler.h"
-
-#include "GCController.h"
-#include "JSDOMBinding.h"
-#include "JSDOMWindow.h"
-#include "MainFrame.h"
-#include "Page.h"
-#include "ScriptState.h"
-#include <bindings/ScriptObject.h>
-#include <bindings/ScriptValue.h>
-#include <profiler/LegacyProfiler.h>
-#include <wtf/Forward.h>
-
-namespace WebCore {
-
-void ScriptProfiler::collectGarbage()
-{
- gcController().garbageCollectSoon();
-}
-
-Deprecated::ScriptObject ScriptProfiler::objectByHeapObjectId(unsigned)
-{
- return Deprecated::ScriptObject();
-}
-
-unsigned ScriptProfiler::getHeapObjectId(const Deprecated::ScriptValue&)
-{
- return 0;
-}
-
-void ScriptProfiler::start(JSC::ExecState* state, const String& title)
-{
- JSC::LegacyProfiler::profiler()->startProfiling(state, title);
-}
-
-void ScriptProfiler::startForPage(Page* inspectedPage, const String& title)
-{
- JSC::ExecState* scriptState = toJSDOMWindow(&inspectedPage->mainFrame(), debuggerWorld())->globalExec();
- start(scriptState, title);
-}
-
-void ScriptProfiler::startForWorkerGlobalScope(WorkerGlobalScope* context, const String& title)
-{
- start(execStateFromWorkerGlobalScope(context), title);
-}
-
-PassRefPtr<ScriptProfile> ScriptProfiler::stop(JSC::ExecState* state, const String& title)
-{
- RefPtr<JSC::Profile> profile = JSC::LegacyProfiler::profiler()->stopProfiling(state, title);
- return ScriptProfile::create(profile);
-}
-
-PassRefPtr<ScriptProfile> ScriptProfiler::stopForPage(Page* inspectedPage, const String& title)
-{
- JSC::ExecState* scriptState = toJSDOMWindow(&inspectedPage->mainFrame(), debuggerWorld())->globalExec();
- return stop(scriptState, title);
-}
-
-PassRefPtr<ScriptProfile> ScriptProfiler::stopForWorkerGlobalScope(WorkerGlobalScope* context, const String& title)
-{
- return stop(execStateFromWorkerGlobalScope(context), title);
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/ScriptProfiler.h b/Source/WebCore/bindings/js/ScriptProfiler.h
deleted file mode 100644
index 3e99168a4..000000000
--- a/Source/WebCore/bindings/js/ScriptProfiler.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright (C) 2010 Apple Inc. All rights reserved.
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef ScriptProfiler_h
-#define ScriptProfiler_h
-
-#include "ScriptHeapSnapshot.h"
-#include "ScriptProfile.h"
-#include "ScriptState.h"
-#include <wtf/Forward.h>
-#include <wtf/PassRefPtr.h>
-
-namespace Deprecated {
-class ScriptObject;
-class ScriptValue;
-}
-
-namespace WebCore {
-
-class Page;
-class WorkerGlobalScope;
-
-class ScriptProfiler {
- WTF_MAKE_NONCOPYABLE(ScriptProfiler);
-public:
- class HeapSnapshotProgress {
- public:
- virtual ~HeapSnapshotProgress() { }
- virtual void Start(int totalWork) = 0;
- virtual void Worked(int workDone) = 0;
- virtual void Done() = 0;
- virtual bool isCanceled() = 0;
- };
-
- static void collectGarbage();
- static Deprecated::ScriptObject objectByHeapObjectId(unsigned id);
- static unsigned getHeapObjectId(const Deprecated::ScriptValue&);
- static void start(JSC::ExecState*, const String& title);
- static void startForPage(Page*, const String& title);
- static void startForWorkerGlobalScope(WorkerGlobalScope*, const String& title);
- static PassRefPtr<ScriptProfile> stop(JSC::ExecState*, const String& title);
- static PassRefPtr<ScriptProfile> stopForPage(Page*, const String& title);
- static PassRefPtr<ScriptProfile> stopForWorkerGlobalScope(WorkerGlobalScope*, const String& title);
- static PassRefPtr<ScriptHeapSnapshot> takeHeapSnapshot(const String&, HeapSnapshotProgress*) { return 0; }
- static bool isSampling() { return false; }
- static bool hasHeapProfiler() { return false; }
- static HashMap<String, double>* currentProfileNameIdleTimeMap() { return 0; }
-};
-
-} // namespace WebCore
-
-#endif // ScriptProfiler_h
diff --git a/Source/WebCore/bindings/js/ScriptSourceCode.h b/Source/WebCore/bindings/js/ScriptSourceCode.h
index 2d3c15970..06a8edc83 100644
--- a/Source/WebCore/bindings/js/ScriptSourceCode.h
+++ b/Source/WebCore/bindings/js/ScriptSourceCode.h
@@ -28,11 +28,11 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ScriptSourceCode_h
-#define ScriptSourceCode_h
+#pragma once
#include "CachedResourceHandle.h"
#include "CachedScript.h"
+#include "CachedScriptFetcher.h"
#include "CachedScriptSourceProvider.h"
#include "URL.h"
#include <parser/SourceProvider.h>
@@ -43,43 +43,44 @@ namespace WebCore {
class ScriptSourceCode {
public:
- ScriptSourceCode(const String& source, const URL& url = URL(), const TextPosition& startPosition = TextPosition::minimumPosition())
- : m_provider(JSC::StringSourceProvider::create(source, url.isNull() ? String() : url.string(), startPosition))
- , m_code(m_provider, startPosition.m_line.oneBasedInt(), startPosition.m_column.oneBasedInt())
+ ScriptSourceCode(const String& source, const URL& url = URL(), const TextPosition& startPosition = TextPosition(), JSC::SourceProviderSourceType sourceType = JSC::SourceProviderSourceType::Program)
+ : m_provider(JSC::StringSourceProvider::create(source, JSC::SourceOrigin { url.string() }, url.string(), startPosition, sourceType))
+ , m_code(m_provider.copyRef(), startPosition.m_line.oneBasedInt(), startPosition.m_column.oneBasedInt())
, m_url(url)
{
}
- explicit ScriptSourceCode(CachedScript* cachedScript)
- : m_provider(CachedScriptSourceProvider::create(cachedScript))
- , m_code(m_provider)
+ ScriptSourceCode(CachedScript* cachedScript, JSC::SourceProviderSourceType sourceType, Ref<CachedScriptFetcher>&& scriptFetcher)
+ : m_provider(CachedScriptSourceProvider::create(cachedScript, sourceType, WTFMove(scriptFetcher)))
+ , m_code(m_provider.copyRef())
, m_cachedScript(cachedScript)
{
}
+ ScriptSourceCode(const String& source, const URL& url, const TextPosition& startPosition, JSC::SourceProviderSourceType sourceType, Ref<CachedScriptFetcher>&& scriptFetcher)
+ : m_provider(JSC::StringSourceProvider::create(source, JSC::SourceOrigin { url.string(), WTFMove(scriptFetcher) }, url.string(), startPosition, sourceType))
+ , m_code(m_provider.copyRef(), startPosition.m_line.oneBasedInt(), startPosition.m_column.oneBasedInt())
+ , m_url(url)
+ {
+ }
+
bool isEmpty() const { return m_code.length() == 0; }
const JSC::SourceCode& jsSourceCode() const { return m_code; }
- const String& source() const { return m_provider->source(); }
+ StringView source() const { return m_provider->source(); }
- int startLine() const { return m_code.firstLine(); }
+ int startLine() const { return m_code.firstLine().oneBasedInt(); }
CachedScript* cachedScript() const { return m_cachedScript.get(); }
const URL& url() const { return m_url; }
private:
- RefPtr<JSC::SourceProvider> m_provider;
-
+ Ref<JSC::SourceProvider> m_provider;
JSC::SourceCode m_code;
-
CachedResourceHandle<CachedScript> m_cachedScript;
-
URL m_url;
-
};
} // namespace WebCore
-
-#endif // ScriptSourceCode_h
diff --git a/Source/WebCore/bindings/js/ScriptState.cpp b/Source/WebCore/bindings/js/ScriptState.cpp
index af1048dce..301c7cc50 100644
--- a/Source/WebCore/bindings/js/ScriptState.cpp
+++ b/Source/WebCore/bindings/js/ScriptState.cpp
@@ -50,23 +50,32 @@ namespace WebCore {
DOMWindow* domWindowFromExecState(JSC::ExecState* scriptState)
{
JSC::JSGlobalObject* globalObject = scriptState->lexicalGlobalObject();
- if (!globalObject->inherits(JSDOMWindowBase::info()))
- return 0;
- return &JSC::jsCast<JSDOMWindowBase*>(globalObject)->impl();
+ JSC::VM& vm = globalObject->vm();
+ if (!globalObject->inherits(vm, JSDOMWindowBase::info()))
+ return nullptr;
+ return &JSC::jsCast<JSDOMWindowBase*>(globalObject)->wrapped();
+}
+
+Frame* frameFromExecState(JSC::ExecState* scriptState)
+{
+ ScriptExecutionContext* context = scriptExecutionContextFromExecState(scriptState);
+ Document* document = is<Document>(context) ? downcast<Document>(context) : nullptr;
+ return document ? document->frame() : nullptr;
}
ScriptExecutionContext* scriptExecutionContextFromExecState(JSC::ExecState* scriptState)
{
JSC::JSGlobalObject* globalObject = scriptState->lexicalGlobalObject();
- if (!globalObject->inherits(JSDOMGlobalObject::info()))
- return 0;
+ JSC::VM& vm = globalObject->vm();
+ if (!globalObject->inherits(vm, JSDOMGlobalObject::info()))
+ return nullptr;
return JSC::jsCast<JSDOMGlobalObject*>(globalObject)->scriptExecutionContext();
}
JSC::ExecState* mainWorldExecState(Frame* frame)
{
if (!frame)
- return 0;
+ return nullptr;
JSDOMWindowShell* shell = frame->script().windowShell(mainThreadNormalWorld());
return shell->window()->globalExec();
}
@@ -74,18 +83,18 @@ JSC::ExecState* mainWorldExecState(Frame* frame)
JSC::ExecState* execStateFromNode(DOMWrapperWorld& world, Node* node)
{
if (!node)
- return 0;
+ return nullptr;
Frame* frame = node->document().frame();
if (!frame)
- return 0;
+ return nullptr;
if (!frame->script().canExecuteScripts(NotAboutToExecuteScript))
- return 0;
+ return nullptr;
return frame->script().globalObject(world)->globalExec();
}
JSC::ExecState* execStateFromPage(DOMWrapperWorld& world, Page* page)
{
- return page->mainFrame().script().globalObject(world)->globalExec();
+ return page ? page->mainFrame().script().globalObject(world)->globalExec() : nullptr;
}
JSC::ExecState* execStateFromWorkerGlobalScope(WorkerGlobalScope* workerGlobalScope)
diff --git a/Source/WebCore/bindings/js/ScriptState.h b/Source/WebCore/bindings/js/ScriptState.h
index 70d14c7cd..74421fd95 100644
--- a/Source/WebCore/bindings/js/ScriptState.h
+++ b/Source/WebCore/bindings/js/ScriptState.h
@@ -29,14 +29,14 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ScriptState_h
-#define ScriptState_h
+#pragma once
namespace JSC {
class ExecState;
}
namespace WebCore {
+
class DOMWindow;
class DOMWrapperWorld;
class Frame;
@@ -45,21 +45,14 @@ class Page;
class ScriptExecutionContext;
class WorkerGlobalScope;
-// The idea is to expose "state-like" methods (hadException, and any other
-// methods where ExecState just dips into vm) of JSC::ExecState as a
-// separate abstraction.
-// For now, the separation is purely by convention.
-typedef JSC::ExecState ScriptState;
-
DOMWindow* domWindowFromExecState(JSC::ExecState*);
+Frame* frameFromExecState(JSC::ExecState*);
ScriptExecutionContext* scriptExecutionContextFromExecState(JSC::ExecState*);
JSC::ExecState* mainWorldExecState(Frame*);
JSC::ExecState* execStateFromNode(DOMWrapperWorld&, Node*);
-JSC::ExecState* execStateFromPage(DOMWrapperWorld&, Page*);
+WEBCORE_EXPORT JSC::ExecState* execStateFromPage(DOMWrapperWorld&, Page*);
JSC::ExecState* execStateFromWorkerGlobalScope(WorkerGlobalScope*);
} // namespace WebCore
-
-#endif // ScriptState_h
diff --git a/Source/WebCore/bindings/js/ScriptWrappable.h b/Source/WebCore/bindings/js/ScriptWrappable.h
index 5b6c65e30..fc0dca0a8 100644
--- a/Source/WebCore/bindings/js/ScriptWrappable.h
+++ b/Source/WebCore/bindings/js/ScriptWrappable.h
@@ -29,8 +29,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ScriptWrappable_h
-#define ScriptWrappable_h
+#pragma once
#include <heap/Weak.h>
@@ -40,18 +39,22 @@ class WeakHandleOwner;
namespace WebCore {
-class JSDOMWrapper;
+class JSDOMObject;
class ScriptWrappable {
public:
- JSDOMWrapper* wrapper() const;
- void setWrapper(JSDOMWrapper*, JSC::WeakHandleOwner*, void*);
- void clearWrapper(JSDOMWrapper*);
+ JSDOMObject* wrapper() const;
+ void setWrapper(JSDOMObject*, JSC::WeakHandleOwner*, void*);
+ void clearWrapper(JSDOMObject*);
+
+ template<typename Derived>
+ static ptrdiff_t offsetOfWrapper() { return CAST_OFFSET(Derived*, ScriptWrappable*) + OBJECT_OFFSETOF(ScriptWrappable, m_wrapper); }
+
+protected:
+ ~ScriptWrappable() { }
private:
- JSC::Weak<JSDOMWrapper> m_wrapper;
+ JSC::Weak<JSDOMObject> m_wrapper;
};
} // namespace WebCore
-
-#endif // ScriptWrappable_h
diff --git a/Source/WebCore/bindings/js/ScriptWrappableInlines.h b/Source/WebCore/bindings/js/ScriptWrappableInlines.h
index dabb657eb..f102c217c 100644
--- a/Source/WebCore/bindings/js/ScriptWrappableInlines.h
+++ b/Source/WebCore/bindings/js/ScriptWrappableInlines.h
@@ -29,8 +29,7 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef ScriptWrappableInlines_h
-#define ScriptWrappableInlines_h
+#pragma once
#include "JSDOMWrapper.h"
#include <heap/Weak.h>
@@ -38,22 +37,20 @@
namespace WebCore {
-inline JSDOMWrapper* ScriptWrappable::wrapper() const
+inline JSDOMObject* ScriptWrappable::wrapper() const
{
return m_wrapper.get();
}
-inline void ScriptWrappable::setWrapper(JSDOMWrapper* wrapper, JSC::WeakHandleOwner* wrapperOwner, void* context)
+inline void ScriptWrappable::setWrapper(JSDOMObject* wrapper, JSC::WeakHandleOwner* wrapperOwner, void* context)
{
ASSERT(!m_wrapper);
- m_wrapper = JSC::Weak<JSDOMWrapper>(wrapper, wrapperOwner, context);
+ m_wrapper = JSC::Weak<JSDOMObject>(wrapper, wrapperOwner, context);
}
-inline void ScriptWrappable::clearWrapper(JSDOMWrapper* wrapper)
+inline void ScriptWrappable::clearWrapper(JSDOMObject* wrapper)
{
weakClear(m_wrapper, wrapper);
}
} // namespace WebCore
-
-#endif // ScriptWrappableInlines_h
diff --git a/Source/WebCore/bindings/js/SerializedScriptValue.cpp b/Source/WebCore/bindings/js/SerializedScriptValue.cpp
index 1f7919289..c9904c091 100644
--- a/Source/WebCore/bindings/js/SerializedScriptValue.cpp
+++ b/Source/WebCore/bindings/js/SerializedScriptValue.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2013, 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -28,49 +28,56 @@
#include "SerializedScriptValue.h"
#include "Blob.h"
+#include "BlobRegistry.h"
#include "CryptoKeyAES.h"
#include "CryptoKeyDataOctetSequence.h"
#include "CryptoKeyDataRSAComponents.h"
#include "CryptoKeyHMAC.h"
#include "CryptoKeyRSA.h"
-#include "ExceptionCode.h"
#include "File.h"
#include "FileList.h"
+#include "IDBValue.h"
#include "ImageData.h"
#include "JSBlob.h"
#include "JSCryptoKey.h"
+#include "JSDOMBinding.h"
#include "JSDOMGlobalObject.h"
#include "JSFile.h"
#include "JSFileList.h"
#include "JSImageData.h"
#include "JSMessagePort.h"
#include "JSNavigator.h"
-#include "NotImplemented.h"
+#include "ScriptExecutionContext.h"
+#include "ScriptState.h"
#include "SharedBuffer.h"
#include "WebCoreJSClientData.h"
#include <limits>
#include <JavaScriptCore/APICast.h>
-#include <JavaScriptCore/APIShims.h>
#include <runtime/ArrayBuffer.h>
#include <runtime/BooleanObject.h>
#include <runtime/DateInstance.h>
#include <runtime/Error.h>
+#include <runtime/Exception.h>
#include <runtime/ExceptionHelpers.h>
+#include <runtime/IterationKind.h>
#include <runtime/JSArrayBuffer.h>
#include <runtime/JSArrayBufferView.h>
+#include <runtime/JSCInlines.h>
#include <runtime/JSDataView.h>
#include <runtime/JSMap.h>
+#include <runtime/JSMapIterator.h>
#include <runtime/JSSet.h>
+#include <runtime/JSSetIterator.h>
#include <runtime/JSTypedArrays.h>
-#include <runtime/MapData.h>
#include <runtime/ObjectConstructor.h>
-#include <runtime/Operations.h>
#include <runtime/PropertyNameArray.h>
#include <runtime/RegExp.h>
#include <runtime/RegExpObject.h>
#include <runtime/TypedArrayInlines.h>
#include <runtime/TypedArrays.h>
#include <wtf/HashTraits.h>
+#include <wtf/MainThread.h>
+#include <wtf/RunLoop.h>
#include <wtf/Vector.h>
using namespace JSC;
@@ -85,9 +92,20 @@ namespace WebCore {
static const unsigned maximumFilterRecursion = 40000;
+enum class SerializationReturnCode {
+ SuccessfullyCompleted,
+ StackOverflowError,
+ InterruptedExecutionError,
+ ValidationError,
+ ExistingExceptionError,
+ DataCloneError,
+ UnspecifiedError
+};
+
enum WalkerState { StateUnknown, ArrayStartState, ArrayStartVisitMember, ArrayEndVisitMember,
ObjectStartState, ObjectStartVisitMember, ObjectEndVisitMember,
- MapDataStartVisitEntry, MapDataEndVisitKey, MapDataEndVisitValue };
+ MapDataStartVisitEntry, MapDataEndVisitKey, MapDataEndVisitValue,
+ SetDataStartVisitEntry, SetDataEndVisitKey };
// These can't be reordered, and any new types must be added to the end of the list
enum SerializationTag {
@@ -122,9 +140,11 @@ enum SerializationTag {
SetObjectTag = 29,
MapObjectTag = 30,
NonMapPropertiesTag = 31,
+ NonSetPropertiesTag = 32,
#if ENABLE(SUBTLE_CRYPTO)
- CryptoKeyTag = 32,
+ CryptoKeyTag = 33,
#endif
+ SharedArrayBufferTag = 34,
ErrorTag = 255
};
@@ -166,6 +186,8 @@ static unsigned typedArrayElementSize(ArrayBufferViewSubtag tag)
#if ENABLE(SUBTLE_CRYPTO)
+const uint32_t currentKeyFormatVersion = 1;
+
enum class CryptoKeyClassSubtag {
HMAC = 0,
AES = 1,
@@ -217,7 +239,7 @@ enum class CryptoAlgorithmIdentifierTag {
};
const uint8_t cryptoAlgorithmIdentifierTagMaximumValue = 21;
-static unsigned countUsages(CryptoKeyUsage usages)
+static unsigned countUsages(CryptoKeyUsageBitmap usages)
{
// Fast bit count algorithm for sparse bit maps.
unsigned count = 0;
@@ -239,12 +261,16 @@ static unsigned countUsages(CryptoKeyUsage usages)
* and EmptyStringObjectTag for serialization of Boolean, Number and String objects.
* Version 4. added support for serializing non-index properties of arrays.
* Version 5. added support for Map and Set types.
+ * Version 6. added support for 8-bit strings.
*/
-static const unsigned CurrentVersion = 5;
+static const unsigned CurrentVersion = 6;
static const unsigned TerminatorTag = 0xFFFFFFFF;
static const unsigned StringPoolTag = 0xFFFFFFFE;
static const unsigned NonIndexPropertiesTag = 0xFFFFFFFD;
+// The high bit of a StringData's length determines the character size.
+static const unsigned StringDataIs8BitFlag = 0x80000000;
+
/*
* Object serialization is performed according to the following grammar, all tags
* are recorded as a single uint8_t.
@@ -264,9 +290,10 @@ static const unsigned NonIndexPropertiesTag = 0xFFFFFFFD;
*
* Map :- MapObjectTag MapData
*
- * Set :- SetObjectTag MapData
+ * Set :- SetObjectTag SetData
*
- * MapData :- (<key:Value><value:Value>) NonMapPropertiesTag (<name:StringData><value:Value>)* TerminatorTag
+ * MapData :- (<key:Value><value:Value>)* NonMapPropertiesTag (<name:StringData><value:Value>)* TerminatorTag
+ * SetData :- (<key:Value>)* NonSetPropertiesTag (<name:StringData><value:Value>)* TerminatorTag
*
* Terminal :-
* UndefinedTag
@@ -293,7 +320,11 @@ static const unsigned NonIndexPropertiesTag = 0xFFFFFFFD;
* | ArrayBuffer
* | ArrayBufferViewTag ArrayBufferViewSubtag <byteOffset:uint32_t> <byteLength:uint32_t> (ArrayBuffer | ObjectReference)
* | ArrayBufferTransferTag <value:uint32_t>
- * | CryptoKeyTag <extractable:int32_t> <usagesCount:uint32_t> <usages:byte{usagesCount}> CryptoKeyClassSubtag (CryptoKeyHMAC | CryptoKeyAES | CryptoKeyRSA)
+ * | CryptoKeyTag <wrappedKeyLength:uint32_t> <factor:byte{wrappedKeyLength}>
+ *
+ * Inside wrapped crypto key, data is serialized in this format:
+ *
+ * <keyFormatVersion:uint32_t> <extractable:int32_t> <usagesCount:uint32_t> <usages:byte{usagesCount}> CryptoKeyClassSubtag (CryptoKeyHMAC | CryptoKeyAES | CryptoKeyRSA)
*
* String :-
* EmptyStringTag
@@ -305,13 +336,13 @@ static const unsigned NonIndexPropertiesTag = 0xFFFFFFFD;
*
* StringData :-
* StringPoolTag <cpIndex:IndexType>
- * (not (TerminatorTag | StringPoolTag))<length:uint32_t><characters:UChar{length}> // Added to constant pool when seen, string length 0xFFFFFFFF is disallowed
+ * (not (TerminatorTag | StringPoolTag))<is8Bit:uint32_t:1><length:uint32_t:31><characters:CharType{length}> // Added to constant pool when seen, string length 0xFFFFFFFF is disallowed
*
* File :-
* FileTag FileData
*
* FileData :-
- * <path:StringData> <url:StringData> <type:StringData>
+ * <path:StringData> <url:StringData> <type:StringData> <name:StringData>
*
* FileList :-
* FileListTag <length:uint32_t>(<file:FileData>){length}
@@ -354,7 +385,7 @@ static const unsigned NonIndexPropertiesTag = 0xFFFFFFFD;
* <factorSize:uint32_t> <factor:byte{factorSize}> <crtExponentSize:uint32_t> <crtExponent:byte{crtExponentSize}> <crtCoefficientSize:uint32_t> <crtCoefficient:byte{crtCoefficientSize}>
*/
-typedef std::pair<JSC::JSValue, SerializationReturnCode> DeserializationResult;
+using DeserializationResult = std::pair<JSC::JSValue, SerializationReturnCode>;
class CloneBase {
protected:
@@ -366,18 +397,13 @@ protected:
bool shouldTerminate()
{
- return m_exec->hadException();
- }
-
- void throwStackOverflow()
- {
- m_exec->vm().throwException(m_exec, createStackOverflowError(m_exec));
+ VM& vm = m_exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ return scope.exception();
}
- NO_RETURN_DUE_TO_ASSERT
void fail()
{
- ASSERT_NOT_REACHED();
m_failed = true;
}
@@ -386,6 +412,24 @@ protected:
MarkedArgumentBuffer m_gcBuffer;
};
+#if ENABLE(SUBTLE_CRYPTO)
+static bool wrapCryptoKey(ExecState* exec, const Vector<uint8_t>& key, Vector<uint8_t>& wrappedKey)
+{
+ ScriptExecutionContext* scriptExecutionContext = scriptExecutionContextFromExecState(exec);
+ if (!scriptExecutionContext)
+ return false;
+ return scriptExecutionContext->wrapCryptoKey(key, wrappedKey);
+}
+
+static bool unwrapCryptoKey(ExecState* exec, const Vector<uint8_t>& wrappedKey, Vector<uint8_t>& key)
+{
+ ScriptExecutionContext* scriptExecutionContext = scriptExecutionContextFromExecState(exec);
+ if (!scriptExecutionContext)
+ return false;
+ return scriptExecutionContext->unwrapCryptoKey(wrappedKey, key);
+}
+#endif
+
#if ASSUME_LITTLE_ENDIAN
template <typename T> static void writeLittleEndian(Vector<uint8_t>& buffer, T value)
{
@@ -433,24 +477,26 @@ template <> bool writeLittleEndian<uint8_t>(Vector<uint8_t>& buffer, const uint8
class CloneSerializer : CloneBase {
public:
- static SerializationReturnCode serialize(ExecState* exec, JSValue value,
- MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers,
- Vector<String>& blobURLs, Vector<uint8_t>& out)
+ static SerializationReturnCode serialize(ExecState* exec, JSValue value, Vector<RefPtr<MessagePort>>& messagePorts, Vector<RefPtr<JSC::ArrayBuffer>>& arrayBuffers, Vector<String>& blobURLs, Vector<uint8_t>& out, SerializationContext context, ArrayBufferContentsArray& sharedBuffers)
{
- CloneSerializer serializer(exec, messagePorts, arrayBuffers, blobURLs, out);
+ CloneSerializer serializer(exec, messagePorts, arrayBuffers, blobURLs, out, context, sharedBuffers);
return serializer.serialize(value);
}
- static bool serialize(const String& s, Vector<uint8_t>& out)
+ static bool serialize(StringView string, Vector<uint8_t>& out)
{
writeLittleEndian(out, CurrentVersion);
- if (s.isEmpty()) {
+ if (string.isEmpty()) {
writeLittleEndian<uint8_t>(out, EmptyStringTag);
return true;
}
writeLittleEndian<uint8_t>(out, StringTag);
- writeLittleEndian(out, s.length());
- return writeLittleEndian(out, s.impl()->deprecatedCharacters(), s.length());
+ if (string.is8Bit()) {
+ writeLittleEndian(out, string.length() | StringDataIs8BitFlag);
+ return writeLittleEndian(out, string.characters8(), string.length());
+ }
+ writeLittleEndian(out, string.length());
+ return writeLittleEndian(out, string.characters16(), string.length());
}
static void serializeUndefined(Vector<uint8_t>& out)
@@ -480,11 +526,13 @@ public:
private:
typedef HashMap<JSObject*, uint32_t> ObjectPool;
- CloneSerializer(ExecState* exec, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, Vector<String>& blobURLs, Vector<uint8_t>& out)
+ CloneSerializer(ExecState* exec, Vector<RefPtr<MessagePort>>& messagePorts, Vector<RefPtr<JSC::ArrayBuffer>>& arrayBuffers, Vector<String>& blobURLs, Vector<uint8_t>& out, SerializationContext context, ArrayBufferContentsArray& sharedBuffers)
: CloneBase(exec)
, m_buffer(out)
, m_blobURLs(blobURLs)
- , m_emptyIdentifier(exec, emptyString())
+ , m_emptyIdentifier(Identifier::fromString(exec, emptyString()))
+ , m_context(context)
+ , m_sharedBuffers(sharedBuffers)
{
write(CurrentVersion);
fillTransferMap(messagePorts, m_transferredMessagePorts);
@@ -492,13 +540,13 @@ private:
}
template <class T>
- void fillTransferMap(Vector<RefPtr<T>, 1>* input, ObjectPool& result)
+ void fillTransferMap(Vector<RefPtr<T>>& input, ObjectPool& result)
{
- if (!input)
+ if (input.isEmpty())
return;
JSDOMGlobalObject* globalObject = jsCast<JSDOMGlobalObject*>(m_exec->lexicalGlobalObject());
- for (size_t i = 0; i < input->size(); i++) {
- JSC::JSValue value = toJS(m_exec, globalObject, input->at(i).get());
+ for (size_t i = 0; i < input.size(); i++) {
+ JSC::JSValue value = toJS(m_exec, globalObject, input[i].get());
JSC::JSObject* obj = value.getObject();
if (obj && !result.contains(obj))
result.add(obj, i);
@@ -507,27 +555,27 @@ private:
SerializationReturnCode serialize(JSValue in);
- bool isArray(JSValue value)
+ bool isArray(VM& vm, JSValue value)
{
if (!value.isObject())
return false;
JSObject* object = asObject(value);
- return isJSArray(object) || object->inherits(JSArray::info());
+ return isJSArray(object) || object->inherits(vm, JSArray::info());
}
- bool isMap(JSValue value)
+ bool isMap(VM& vm, JSValue value)
{
if (!value.isObject())
return false;
JSObject* object = asObject(value);
- return object->inherits(JSMap::info());
+ return object->inherits(vm, JSMap::info());
}
- bool isSet(JSValue value)
+ bool isSet(VM& vm, JSValue value)
{
if (!value.isObject())
return false;
JSObject* object = asObject(value);
- return object->inherits(JSSet::info());
+ return object->inherits(vm, JSSet::info());
}
bool checkForDuplicate(JSObject* object)
@@ -538,7 +586,7 @@ private:
// Handle duplicate references
if (found != m_objectPool.end()) {
write(ObjectReferenceTag);
- ASSERT(static_cast<int32_t>(found->value) < m_objectPool.size());
+ ASSERT(found->value < m_objectPool.size());
writeObjectIndex(found->value);
return true;
}
@@ -604,7 +652,7 @@ private:
JSValue getProperty(JSObject* object, const Identifier& propertyName)
{
- PropertySlot slot(object);
+ PropertySlot slot(object, PropertySlot::InternalMethodType::Get);
if (object->methodTable()->getOwnPropertySlot(object, m_exec, propertyName, slot))
return slot.getValue(m_exec, propertyName);
return JSValue();
@@ -638,58 +686,59 @@ private:
}
}
- void dumpString(String str)
+ void dumpString(const String& string)
{
- if (str.isEmpty())
+ if (string.isEmpty())
write(EmptyStringTag);
else {
write(StringTag);
- write(str);
+ write(string);
}
}
- void dumpStringObject(String str)
+ void dumpStringObject(const String& string)
{
- if (str.isEmpty())
+ if (string.isEmpty())
write(EmptyStringObjectTag);
else {
write(StringObjectTag);
- write(str);
+ write(string);
}
}
bool dumpArrayBufferView(JSObject* obj, SerializationReturnCode& code)
{
+ VM& vm = m_exec->vm();
write(ArrayBufferViewTag);
- if (obj->inherits(JSDataView::info()))
+ if (obj->inherits(vm, JSDataView::info()))
write(DataViewTag);
- else if (obj->inherits(JSUint8ClampedArray::info()))
+ else if (obj->inherits(vm, JSUint8ClampedArray::info()))
write(Uint8ClampedArrayTag);
- else if (obj->inherits(JSInt8Array::info()))
+ else if (obj->inherits(vm, JSInt8Array::info()))
write(Int8ArrayTag);
- else if (obj->inherits(JSUint8Array::info()))
+ else if (obj->inherits(vm, JSUint8Array::info()))
write(Uint8ArrayTag);
- else if (obj->inherits(JSInt16Array::info()))
+ else if (obj->inherits(vm, JSInt16Array::info()))
write(Int16ArrayTag);
- else if (obj->inherits(JSUint16Array::info()))
+ else if (obj->inherits(vm, JSUint16Array::info()))
write(Uint16ArrayTag);
- else if (obj->inherits(JSInt32Array::info()))
+ else if (obj->inherits(vm, JSInt32Array::info()))
write(Int32ArrayTag);
- else if (obj->inherits(JSUint32Array::info()))
+ else if (obj->inherits(vm, JSUint32Array::info()))
write(Uint32ArrayTag);
- else if (obj->inherits(JSFloat32Array::info()))
+ else if (obj->inherits(vm, JSFloat32Array::info()))
write(Float32ArrayTag);
- else if (obj->inherits(JSFloat64Array::info()))
+ else if (obj->inherits(vm, JSFloat64Array::info()))
write(Float64ArrayTag);
else
return false;
- RefPtr<ArrayBufferView> arrayBufferView = toArrayBufferView(obj);
+ RefPtr<ArrayBufferView> arrayBufferView = toPossiblySharedArrayBufferView(vm, obj);
write(static_cast<uint32_t>(arrayBufferView->byteOffset()));
write(static_cast<uint32_t>(arrayBufferView->byteLength()));
- RefPtr<ArrayBuffer> arrayBuffer = arrayBufferView->buffer();
+ RefPtr<ArrayBuffer> arrayBuffer = arrayBufferView->possiblySharedBuffer();
if (!arrayBuffer) {
- code = ValidationError;
+ code = SerializationReturnCode::ValidationError;
return true;
}
JSValue bufferObj = toJS(m_exec, jsCast<JSDOMGlobalObject*>(m_exec->lexicalGlobalObject()), arrayBuffer.get());
@@ -704,8 +753,7 @@ private:
}
if (value.isString()) {
- String str = asString(value)->value(m_exec);
- dumpString(str);
+ dumpString(asString(value)->value(m_exec));
return true;
}
@@ -715,31 +763,32 @@ private:
return true;
}
- if (value.isObject() && asObject(value)->inherits(DateInstance::info())) {
+ VM& vm = m_exec->vm();
+ if (value.isObject() && asObject(value)->inherits(vm, DateInstance::info())) {
write(DateTag);
write(asDateInstance(value)->internalNumber());
return true;
}
- if (isArray(value))
+ if (isArray(vm, value))
return false;
if (value.isObject()) {
JSObject* obj = asObject(value);
- if (obj->inherits(BooleanObject::info())) {
+ if (obj->inherits(vm, BooleanObject::info())) {
if (!startObjectInternal(obj)) // handle duplicates
return true;
write(asBooleanObject(value)->internalValue().toBoolean(m_exec) ? TrueObjectTag : FalseObjectTag);
return true;
}
- if (obj->inherits(StringObject::info())) {
+ if (obj->inherits(vm, StringObject::info())) {
if (!startObjectInternal(obj)) // handle duplicates
return true;
String str = asString(asStringObject(value)->internalValue())->value(m_exec);
dumpStringObject(str);
return true;
}
- if (obj->inherits(NumberObject::info())) {
+ if (obj->inherits(vm, NumberObject::info())) {
if (!startObjectInternal(obj)) // handle duplicates
return true;
write(NumberObjectTag);
@@ -747,12 +796,12 @@ private:
write(obj->internalValue().asNumber());
return true;
}
- if (File* file = toFile(obj)) {
+ if (File* file = JSFile::toWrapped(vm, obj)) {
write(FileTag);
write(file);
return true;
}
- if (FileList* list = toFileList(obj)) {
+ if (FileList* list = JSFileList::toWrapped(vm, obj)) {
write(FileListTag);
unsigned length = list->length();
write(length);
@@ -760,7 +809,7 @@ private:
write(list->item(i));
return true;
}
- if (Blob* blob = toBlob(obj)) {
+ if (Blob* blob = JSBlob::toWrapped(vm, obj)) {
write(BlobTag);
m_blobURLs.append(blob->url());
write(blob->url());
@@ -768,7 +817,7 @@ private:
write(blob->size());
return true;
}
- if (ImageData* data = toImageData(obj)) {
+ if (ImageData* data = JSImageData::toWrapped(vm, obj)) {
write(ImageDataTag);
write(data->width());
write(data->height());
@@ -776,7 +825,7 @@ private:
write(data->data()->data(), data->data()->length());
return true;
}
- if (obj->inherits(RegExpObject::info())) {
+ if (obj->inherits(vm, RegExpObject::info())) {
RegExpObject* regExp = asRegExpObject(obj);
char flags[3];
int flagCount = 0;
@@ -791,7 +840,7 @@ private:
write(String(flags, flagCount));
return true;
}
- if (obj->inherits(JSMessagePort::info())) {
+ if (obj->inherits(vm, JSMessagePort::info())) {
ObjectPool::iterator index = m_transferredMessagePorts.find(obj);
if (index != m_transferredMessagePorts.end()) {
write(MessagePortReferenceTag);
@@ -799,12 +848,12 @@ private:
return true;
}
// MessagePort object could not be found in transferred message ports
- code = ValidationError;
+ code = SerializationReturnCode::ValidationError;
return true;
}
- if (ArrayBuffer* arrayBuffer = toArrayBuffer(obj)) {
+ if (ArrayBuffer* arrayBuffer = toPossiblySharedArrayBuffer(vm, obj)) {
if (arrayBuffer->isNeutered()) {
- code = ValidationError;
+ code = SerializationReturnCode::ValidationError;
return true;
}
ObjectPool::iterator index = m_transferredArrayBuffers.find(obj);
@@ -815,12 +864,25 @@ private:
}
if (!startObjectInternal(obj)) // handle duplicates
return true;
+
+ if (arrayBuffer->isShared()
+ && m_context == SerializationContext::WorkerPostMessage) {
+ uint32_t index = m_sharedBuffers.size();
+ ArrayBufferContents contents;
+ if (arrayBuffer->shareWith(contents)) {
+ write(SharedArrayBufferTag);
+ m_sharedBuffers.append(WTFMove(contents));
+ write(index);
+ return true;
+ }
+ }
+
write(ArrayBufferTag);
write(arrayBuffer->byteLength());
write(static_cast<const uint8_t*>(arrayBuffer->data()), arrayBuffer->byteLength());
return true;
}
- if (obj->inherits(JSArrayBufferView::info())) {
+ if (obj->inherits(vm, JSArrayBufferView::info())) {
if (checkForDuplicate(obj))
return true;
bool success = dumpArrayBufferView(obj, code);
@@ -828,9 +890,19 @@ private:
return success;
}
#if ENABLE(SUBTLE_CRYPTO)
- if (CryptoKey* key = toCryptoKey(obj)) {
+ if (CryptoKey* key = JSCryptoKey::toWrapped(vm, obj)) {
write(CryptoKeyTag);
- write(key);
+ Vector<uint8_t> serializedKey;
+ Vector<String> dummyBlobURLs;
+ Vector<RefPtr<MessagePort>> dummyMessagePorts;
+ Vector<RefPtr<JSC::ArrayBuffer>> dummyArrayBuffers;
+ ArrayBufferContentsArray dummySharedBuffers;
+ CloneSerializer rawKeySerializer(m_exec, dummyMessagePorts, dummyArrayBuffers, dummyBlobURLs, serializedKey, SerializationContext::Default, dummySharedBuffers);
+ rawKeySerializer.write(key);
+ Vector<uint8_t> wrappedKey;
+ if (!wrapCryptoKey(m_exec, serializedKey, wrappedKey))
+ return false;
+ write(wrappedKey);
return true;
}
#endif
@@ -921,7 +993,7 @@ private:
template <class T> void writeConstantPoolIndex(const T& constantPool, unsigned i)
{
- ASSERT(static_cast<int32_t>(i) < constantPool.size());
+ ASSERT(i < constantPool.size());
if (constantPool.size() <= 0xFF)
write(static_cast<uint8_t>(i));
else if (constantPool.size() <= 0xFFFF)
@@ -933,28 +1005,34 @@ private:
void write(const Identifier& ident)
{
const String& str = ident.string();
- StringConstantPool::AddResult addResult = m_constantPool.add(str.impl(), m_constantPool.size());
+ StringConstantPool::AddResult addResult = m_constantPool.add(ident.impl(), m_constantPool.size());
if (!addResult.isNewEntry) {
write(StringPoolTag);
writeStringIndex(addResult.iterator->value);
return;
}
- // This condition is unlikely to happen as they would imply an ~8gb
- // string but we should guard against it anyway
- if (str.length() >= StringPoolTag) {
- fail();
- return;
- }
+ unsigned length = str.length();
// Guard against overflow
- if (str.length() > (std::numeric_limits<uint32_t>::max() - sizeof(uint32_t)) / sizeof(UChar)) {
+ if (length > (std::numeric_limits<uint32_t>::max() - sizeof(uint32_t)) / sizeof(UChar)) {
fail();
return;
}
- writeLittleEndian<uint32_t>(m_buffer, str.length());
- if (!writeLittleEndian<uint16_t>(m_buffer, reinterpret_cast<const uint16_t*>(str.deprecatedCharacters()), str.length()))
+ if (str.is8Bit())
+ writeLittleEndian<uint32_t>(m_buffer, length | StringDataIs8BitFlag);
+ else
+ writeLittleEndian<uint32_t>(m_buffer, length);
+
+ if (!length)
+ return;
+ if (str.is8Bit()) {
+ if (!writeLittleEndian(m_buffer, str.characters8(), length))
+ fail();
+ return;
+ }
+ if (!writeLittleEndian(m_buffer, str.characters16(), length))
fail();
}
@@ -963,7 +1041,7 @@ private:
if (str.isNull())
write(m_emptyIdentifier);
else
- write(Identifier(m_exec, str));
+ write(Identifier::fromString(m_exec, str));
}
void write(const Vector<uint8_t>& vector)
@@ -979,6 +1057,7 @@ private:
write(file->path());
write(file->url());
write(file->type());
+ write(file->name());
}
#if ENABLE(SUBTLE_CRYPTO)
@@ -1095,9 +1174,11 @@ private:
void write(const CryptoKey* key)
{
+ write(currentKeyFormatVersion);
+
write(key->extractable());
- CryptoKeyUsage usages = key->usagesBitmap();
+ CryptoKeyUsageBitmap usages = key->usagesBitmap();
write(countUsages(usages));
if (usages & CryptoKeyUsageEncrypt)
write(CryptoKeyUsageTag::Encrypt);
@@ -1119,23 +1200,23 @@ private:
switch (key->keyClass()) {
case CryptoKeyClass::HMAC:
write(CryptoKeyClassSubtag::HMAC);
- write(toCryptoKeyHMAC(key)->key());
- write(toCryptoKeyHMAC(key)->hashAlgorithmIdentifier());
+ write(downcast<CryptoKeyHMAC>(*key).key());
+ write(downcast<CryptoKeyHMAC>(*key).hashAlgorithmIdentifier());
break;
case CryptoKeyClass::AES:
write(CryptoKeyClassSubtag::AES);
write(key->algorithmIdentifier());
- write(toCryptoKeyAES(key)->key());
+ write(downcast<CryptoKeyAES>(*key).key());
break;
case CryptoKeyClass::RSA:
write(CryptoKeyClassSubtag::RSA);
write(key->algorithmIdentifier());
CryptoAlgorithmIdentifier hash;
- bool isRestrictedToHash = toCryptoKeyRSA(key)->isRestrictedToHash(hash);
+ bool isRestrictedToHash = downcast<CryptoKeyRSA>(*key).isRestrictedToHash(hash);
write(isRestrictedToHash);
if (isRestrictedToHash)
write(hash);
- write(toCryptoKeyDataRSAComponents(*key->exportData()));
+ write(downcast<CryptoKeyDataRSAComponents>(*key->exportData()));
break;
}
}
@@ -1151,20 +1232,23 @@ private:
ObjectPool m_objectPool;
ObjectPool m_transferredMessagePorts;
ObjectPool m_transferredArrayBuffers;
- typedef HashMap<RefPtr<StringImpl>, uint32_t, IdentifierRepHash> StringConstantPool;
+ typedef HashMap<RefPtr<UniquedStringImpl>, uint32_t, IdentifierRepHash> StringConstantPool;
StringConstantPool m_constantPool;
Identifier m_emptyIdentifier;
+ SerializationContext m_context;
+ ArrayBufferContentsArray& m_sharedBuffers;
};
SerializationReturnCode CloneSerializer::serialize(JSValue in)
{
+ VM& vm = m_exec->vm();
Vector<uint32_t, 16> indexStack;
Vector<uint32_t, 16> lengthStack;
Vector<PropertyNameArray, 16> propertyStack;
Vector<JSObject*, 32> inputObjectStack;
- Vector<MapData*, 4> mapDataStack;
- Vector<MapData::const_iterator, 4> iteratorStack;
- Vector<JSValue, 4> iteratorValueStack;
+ Vector<JSMapIterator*, 4> mapIteratorStack;
+ Vector<JSSetIterator*, 4> setIteratorStack;
+ Vector<JSValue, 4> mapIteratorValueStack;
Vector<WalkerState, 16> stateStack;
WalkerState state = StateUnknown;
JSValue inValue = in;
@@ -1172,9 +1256,9 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in)
switch (state) {
arrayStartState:
case ArrayStartState: {
- ASSERT(isArray(inValue));
+ ASSERT(isArray(vm, inValue));
if (inputObjectStack.size() > maximumFilterRecursion)
- return StackOverflowError;
+ return SerializationReturnCode::StackOverflowError;
JSArray* inArray = asArray(inValue);
unsigned length = inArray->length();
@@ -1193,8 +1277,8 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in)
indexStack.removeLast();
lengthStack.removeLast();
- propertyStack.append(PropertyNameArray(m_exec));
- array->methodTable()->getOwnNonIndexPropertyNames(array, m_exec, propertyStack.last(), ExcludeDontEnumProperties);
+ propertyStack.append(PropertyNameArray(m_exec, PropertyNameMode::Strings));
+ array->methodTable()->getOwnNonIndexPropertyNames(array, m_exec, propertyStack.last(), EnumerationMode());
if (propertyStack.last().size()) {
write(NonIndexPropertiesTag);
indexStack.append(0);
@@ -1213,9 +1297,9 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in)
}
write(index);
- SerializationReturnCode terminalCode = SuccessfullyCompleted;
+ auto terminalCode = SerializationReturnCode::SuccessfullyCompleted;
if (dumpIfTerminal(inValue, terminalCode)) {
- if (terminalCode != SuccessfullyCompleted)
+ if (terminalCode != SerializationReturnCode::SuccessfullyCompleted)
return terminalCode;
indexStack.last()++;
goto arrayStartVisitMember;
@@ -1231,7 +1315,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in)
case ObjectStartState: {
ASSERT(inValue.isObject());
if (inputObjectStack.size() > maximumFilterRecursion)
- return StackOverflowError;
+ return SerializationReturnCode::StackOverflowError;
JSObject* inObject = asObject(inValue);
if (!startObject(inObject))
break;
@@ -1239,12 +1323,12 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in)
// objects have been handled. If we reach this point and
// the input is not an Object object then we should throw
// a DataCloneError.
- if (inObject->classInfo() != JSFinalObject::info())
- return DataCloneError;
+ if (inObject->classInfo(vm) != JSFinalObject::info())
+ return SerializationReturnCode::DataCloneError;
inputObjectStack.append(inObject);
indexStack.append(0);
- propertyStack.append(PropertyNameArray(m_exec));
- inObject->methodTable()->getOwnPropertyNames(inObject, m_exec, propertyStack.last(), ExcludeDontEnumProperties);
+ propertyStack.append(PropertyNameArray(m_exec, PropertyNameMode::Strings));
+ inObject->methodTable()->getOwnPropertyNames(inObject, m_exec, propertyStack.last(), EnumerationMode());
}
objectStartVisitMember:
FALLTHROUGH;
@@ -1261,7 +1345,7 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in)
}
inValue = getProperty(object, properties[index]);
if (shouldTerminate())
- return ExistingExceptionError;
+ return SerializationReturnCode::ExistingExceptionError;
if (!inValue) {
// Property was removed during serialisation
@@ -1271,20 +1355,20 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in)
write(properties[index]);
if (shouldTerminate())
- return ExistingExceptionError;
+ return SerializationReturnCode::ExistingExceptionError;
- SerializationReturnCode terminalCode = SuccessfullyCompleted;
+ auto terminalCode = SerializationReturnCode::SuccessfullyCompleted;
if (!dumpIfTerminal(inValue, terminalCode)) {
stateStack.append(ObjectEndVisitMember);
goto stateUnknown;
}
- if (terminalCode != SuccessfullyCompleted)
+ if (terminalCode != SerializationReturnCode::SuccessfullyCompleted)
return terminalCode;
FALLTHROUGH;
}
case ObjectEndVisitMember: {
if (shouldTerminate())
- return ExistingExceptionError;
+ return SerializationReturnCode::ExistingExceptionError;
indexStack.last()++;
goto objectStartVisitMember;
@@ -1292,78 +1376,97 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in)
mapStartState: {
ASSERT(inValue.isObject());
if (inputObjectStack.size() > maximumFilterRecursion)
- return StackOverflowError;
+ return SerializationReturnCode::StackOverflowError;
JSMap* inMap = jsCast<JSMap*>(inValue);
if (!startMap(inMap))
break;
- MapData* mapData = inMap->mapData();
- m_gcBuffer.append(mapData);
- mapDataStack.append(mapData);
- iteratorStack.append(mapData->begin());
+ JSMapIterator* iterator = JSMapIterator::create(vm, m_exec->lexicalGlobalObject()->mapIteratorStructure(), inMap, IterateKeyValue);
+ m_gcBuffer.append(inMap);
+ m_gcBuffer.append(iterator);
+ mapIteratorStack.append(iterator);
inputObjectStack.append(inMap);
goto mapDataStartVisitEntry;
}
- setStartState: {
- ASSERT(inValue.isObject());
- if (inputObjectStack.size() > maximumFilterRecursion)
- return StackOverflowError;
- JSSet* inSet = jsCast<JSSet*>(inValue);
- if (!startSet(inSet))
- break;
- MapData* mapData = inSet->mapData();
- m_gcBuffer.append(mapData);
- mapDataStack.append(mapData);
- iteratorStack.append(mapData->begin());
- inputObjectStack.append(inSet);
- goto mapDataStartVisitEntry;
- }
mapDataStartVisitEntry:
case MapDataStartVisitEntry: {
- MapData::const_iterator& ptr = iteratorStack.last();
- MapData* mapData = mapDataStack.last();
- if (ptr == mapData->end()) {
- iteratorStack.removeLast();
- mapDataStack.removeLast();
+ JSMapIterator* iterator = mapIteratorStack.last();
+ JSValue key, value;
+ if (!iterator->nextKeyValue(m_exec, key, value)) {
+ mapIteratorStack.removeLast();
JSObject* object = inputObjectStack.last();
- ASSERT(jsDynamicCast<JSSet*>(object) || jsDynamicCast<JSMap*>(object));
- propertyStack.append(PropertyNameArray(m_exec));
- object->methodTable()->getOwnPropertyNames(object, m_exec, propertyStack.last(), ExcludeDontEnumProperties);
+ ASSERT(jsDynamicDowncast<JSMap*>(vm, object));
+ propertyStack.append(PropertyNameArray(m_exec, PropertyNameMode::Strings));
+ object->methodTable()->getOwnPropertyNames(object, m_exec, propertyStack.last(), EnumerationMode());
write(NonMapPropertiesTag);
indexStack.append(0);
goto objectStartVisitMember;
}
- inValue = ptr.key();
- m_gcBuffer.append(ptr.value());
- iteratorValueStack.append(ptr.value());
+ inValue = key;
+ m_gcBuffer.append(value);
+ mapIteratorValueStack.append(value);
stateStack.append(MapDataEndVisitKey);
goto stateUnknown;
}
case MapDataEndVisitKey: {
- inValue = iteratorValueStack.last();
- iteratorValueStack.removeLast();
+ inValue = mapIteratorValueStack.last();
+ mapIteratorValueStack.removeLast();
stateStack.append(MapDataEndVisitValue);
goto stateUnknown;
}
case MapDataEndVisitValue: {
- if (iteratorStack.last() != mapDataStack.last()->end())
- ++iteratorStack.last();
goto mapDataStartVisitEntry;
}
+ setStartState: {
+ ASSERT(inValue.isObject());
+ if (inputObjectStack.size() > maximumFilterRecursion)
+ return SerializationReturnCode::StackOverflowError;
+ JSSet* inSet = jsCast<JSSet*>(inValue);
+ if (!startSet(inSet))
+ break;
+ JSSetIterator* iterator = JSSetIterator::create(vm, m_exec->lexicalGlobalObject()->setIteratorStructure(), inSet, IterateKey);
+ m_gcBuffer.append(inSet);
+ m_gcBuffer.append(iterator);
+ setIteratorStack.append(iterator);
+ inputObjectStack.append(inSet);
+ goto setDataStartVisitEntry;
+ }
+ setDataStartVisitEntry:
+ case SetDataStartVisitEntry: {
+ JSSetIterator* iterator = setIteratorStack.last();
+ JSValue key;
+ if (!iterator->next(m_exec, key)) {
+ setIteratorStack.removeLast();
+ JSObject* object = inputObjectStack.last();
+ ASSERT(jsDynamicDowncast<JSSet*>(vm, object));
+ propertyStack.append(PropertyNameArray(m_exec, PropertyNameMode::Strings));
+ object->methodTable()->getOwnPropertyNames(object, m_exec, propertyStack.last(), EnumerationMode());
+ write(NonSetPropertiesTag);
+ indexStack.append(0);
+ goto objectStartVisitMember;
+ }
+ inValue = key;
+ stateStack.append(SetDataEndVisitKey);
+ goto stateUnknown;
+ }
+ case SetDataEndVisitKey: {
+ goto setDataStartVisitEntry;
+ }
+
stateUnknown:
case StateUnknown: {
- SerializationReturnCode terminalCode = SuccessfullyCompleted;
+ auto terminalCode = SerializationReturnCode::SuccessfullyCompleted;
if (dumpIfTerminal(inValue, terminalCode)) {
- if (terminalCode != SuccessfullyCompleted)
+ if (terminalCode != SerializationReturnCode::SuccessfullyCompleted)
return terminalCode;
break;
}
- if (isArray(inValue))
+ if (isArray(vm, inValue))
goto arrayStartState;
- if (isMap(inValue))
+ if (isMap(vm, inValue))
goto mapStartState;
- if (isSet(inValue))
+ if (isSet(vm, inValue))
goto setStartState;
goto objectStartState;
}
@@ -1375,13 +1478,11 @@ SerializationReturnCode CloneSerializer::serialize(JSValue in)
stateStack.removeLast();
}
if (m_failed)
- return UnspecifiedError;
+ return SerializationReturnCode::UnspecifiedError;
- return SuccessfullyCompleted;
+ return SerializationReturnCode::SuccessfullyCompleted;
}
-typedef Vector<JSC::ArrayBufferContents> ArrayBufferContentsArray;
-
class CloneDeserializer : CloneBase {
public:
static String deserializeString(const Vector<uint8_t>& buffer)
@@ -1397,23 +1498,23 @@ public:
if (!readLittleEndian(ptr, end, tag) || tag != StringTag)
return String();
uint32_t length;
- if (!readLittleEndian(ptr, end, length) || length >= StringPoolTag)
+ if (!readLittleEndian(ptr, end, length))
return String();
+ bool is8Bit = length & StringDataIs8BitFlag;
+ length &= ~StringDataIs8BitFlag;
String str;
- if (!readString(ptr, end, str, length))
+ if (!readString(ptr, end, str, length, is8Bit))
return String();
- return String(str.impl());
+ return str;
}
- static DeserializationResult deserialize(ExecState* exec, JSGlobalObject* globalObject,
- MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContentsArray,
- const Vector<uint8_t>& buffer)
+ static DeserializationResult deserialize(ExecState* exec, JSGlobalObject* globalObject, Vector<RefPtr<MessagePort>>& messagePorts, ArrayBufferContentsArray* arrayBufferContentsArray, const Vector<uint8_t>& buffer, const Vector<String>& blobURLs, const Vector<String> blobFilePaths, ArrayBufferContentsArray* sharedBuffers)
{
if (!buffer.size())
- return std::make_pair(jsNull(), UnspecifiedError);
- CloneDeserializer deserializer(exec, globalObject, messagePorts, arrayBufferContentsArray, buffer);
+ return std::make_pair(jsNull(), SerializationReturnCode::UnspecifiedError);
+ CloneDeserializer deserializer(exec, globalObject, messagePorts, arrayBufferContentsArray, buffer, blobURLs, blobFilePaths, sharedBuffers);
if (!deserializer.isValid())
- return std::make_pair(JSValue(), ValidationError);
+ return std::make_pair(JSValue(), SerializationReturnCode::ValidationError);
return deserializer.deserialize();
}
@@ -1456,12 +1557,10 @@ private:
size_t m_index;
};
- CloneDeserializer(ExecState* exec, JSGlobalObject* globalObject,
- MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContents,
- const Vector<uint8_t>& buffer)
+ CloneDeserializer(ExecState* exec, JSGlobalObject* globalObject, Vector<RefPtr<MessagePort>>& messagePorts, ArrayBufferContentsArray* arrayBufferContents, const Vector<uint8_t>& buffer)
: CloneBase(exec)
, m_globalObject(globalObject)
- , m_isDOMGlobalObject(globalObject->inherits(JSDOMGlobalObject::info()))
+ , m_isDOMGlobalObject(globalObject->inherits(globalObject->vm(), JSDOMGlobalObject::info()))
, m_ptr(buffer.data())
, m_end(buffer.data() + buffer.size())
, m_version(0xFFFFFFFF)
@@ -1473,13 +1572,26 @@ private:
m_version = 0xFFFFFFFF;
}
- DeserializationResult deserialize();
-
- void throwValidationError()
+ CloneDeserializer(ExecState* exec, JSGlobalObject* globalObject, Vector<RefPtr<MessagePort>>& messagePorts, ArrayBufferContentsArray* arrayBufferContents, const Vector<uint8_t>& buffer, const Vector<String>& blobURLs, const Vector<String> blobFilePaths, ArrayBufferContentsArray* sharedBuffers)
+ : CloneBase(exec)
+ , m_globalObject(globalObject)
+ , m_isDOMGlobalObject(globalObject->inherits(globalObject->vm(), JSDOMGlobalObject::info()))
+ , m_ptr(buffer.data())
+ , m_end(buffer.data() + buffer.size())
+ , m_version(0xFFFFFFFF)
+ , m_messagePorts(messagePorts)
+ , m_arrayBufferContents(arrayBufferContents)
+ , m_arrayBuffers(arrayBufferContents ? arrayBufferContents->size() : 0)
+ , m_blobURLs(blobURLs)
+ , m_blobFilePaths(blobFilePaths)
+ , m_sharedBuffers(sharedBuffers)
{
- m_exec->vm().throwException(m_exec, createTypeError(m_exec, "Unable to deserialize data."));
+ if (!read(m_version))
+ m_version = 0xFFFFFFFF;
}
+ DeserializationResult deserialize();
+
bool isValid() const { return m_version <= CurrentVersion; }
template <typename T> bool readLittleEndian(T& value)
@@ -1582,11 +1694,19 @@ private:
return read(i);
}
- static bool readString(const uint8_t*& ptr, const uint8_t* end, String& str, unsigned length)
+ static bool readString(const uint8_t*& ptr, const uint8_t* end, String& str, unsigned length, bool is8Bit)
{
if (length >= std::numeric_limits<int32_t>::max() / sizeof(UChar))
return false;
+ if (is8Bit) {
+ if ((end - ptr) < static_cast<int>(length))
+ return false;
+ str = String(reinterpret_cast<const LChar*>(ptr), length);
+ ptr += length;
+ return true;
+ }
+
unsigned size = length * sizeof(UChar);
if ((end - ptr) < static_cast<int>(size))
return false;
@@ -1602,7 +1722,7 @@ private:
readLittleEndian(ptr, end, ch);
buffer.append(ch);
}
- str = String::adopt(buffer);
+ str = String::adopt(WTFMove(buffer));
#endif
return true;
}
@@ -1637,8 +1757,10 @@ private:
cachedString = CachedStringRef(&m_constantPool, index);
return true;
}
+ bool is8Bit = length & StringDataIs8BitFlag;
+ length &= ~StringDataIs8BitFlag;
String str;
- if (!readString(m_ptr, m_end, str, length)) {
+ if (!readString(m_ptr, m_end, str, length, is8Bit)) {
fail();
return false;
}
@@ -1683,8 +1805,17 @@ private:
CachedStringRef type;
if (!readStringData(type))
return 0;
+ CachedStringRef name;
+ if (!readStringData(name))
+ return 0;
+
+ // If the blob URL for this file has an associated blob file path, prefer that one over the "built-in" path.
+ String filePath = blobFilePathForBlobURL(url->string());
+ if (filePath.isEmpty())
+ filePath = path->string();
+
if (m_isDOMGlobalObject)
- file = File::create(path->string(), URL(URL(), url->string()), type->string());
+ file = File::deserialize(filePath, URL(URL(), url->string()), type->string(), name->string());
return true;
}
@@ -1700,7 +1831,7 @@ private:
return true;
}
- bool readArrayBufferView(JSValue& arrayBufferView)
+ bool readArrayBufferView(VM& vm, JSValue& arrayBufferView)
{
ArrayBufferViewSubtag arrayBufferViewSubtag;
if (!readArrayBufferViewSubtag(arrayBufferViewSubtag))
@@ -1712,7 +1843,7 @@ private:
if (!read(byteLength))
return false;
JSObject* arrayBufferObj = asObject(readTerminal());
- if (!arrayBufferObj || !arrayBufferObj->inherits(JSArrayBuffer::info()))
+ if (!arrayBufferObj || !arrayBufferObj->inherits(vm, JSArrayBuffer::info()))
return false;
unsigned elementSize = typedArrayElementSize(arrayBufferViewSubtag);
@@ -1722,37 +1853,37 @@ private:
if (length * elementSize != byteLength)
return false;
- RefPtr<ArrayBuffer> arrayBuffer = toArrayBuffer(arrayBufferObj);
+ RefPtr<ArrayBuffer> arrayBuffer = toPossiblySharedArrayBuffer(vm, arrayBufferObj);
switch (arrayBufferViewSubtag) {
case DataViewTag:
- arrayBufferView = getJSValue(DataView::create(arrayBuffer, byteOffset, length).get());
+ arrayBufferView = getJSValue(DataView::create(WTFMove(arrayBuffer), byteOffset, length).get());
return true;
case Int8ArrayTag:
- arrayBufferView = getJSValue(Int8Array::create(arrayBuffer, byteOffset, length).get());
+ arrayBufferView = toJS(m_exec, m_globalObject, Int8Array::create(WTFMove(arrayBuffer), byteOffset, length).get());
return true;
case Uint8ArrayTag:
- arrayBufferView = getJSValue(Uint8Array::create(arrayBuffer, byteOffset, length).get());
+ arrayBufferView = toJS(m_exec, m_globalObject, Uint8Array::create(WTFMove(arrayBuffer), byteOffset, length).get());
return true;
case Uint8ClampedArrayTag:
- arrayBufferView = getJSValue(Uint8ClampedArray::create(arrayBuffer, byteOffset, length).get());
+ arrayBufferView = toJS(m_exec, m_globalObject, Uint8ClampedArray::create(WTFMove(arrayBuffer), byteOffset, length).get());
return true;
case Int16ArrayTag:
- arrayBufferView = getJSValue(Int16Array::create(arrayBuffer, byteOffset, length).get());
+ arrayBufferView = toJS(m_exec, m_globalObject, Int16Array::create(WTFMove(arrayBuffer), byteOffset, length).get());
return true;
case Uint16ArrayTag:
- arrayBufferView = getJSValue(Uint16Array::create(arrayBuffer, byteOffset, length).get());
+ arrayBufferView = toJS(m_exec, m_globalObject, Uint16Array::create(WTFMove(arrayBuffer), byteOffset, length).get());
return true;
case Int32ArrayTag:
- arrayBufferView = getJSValue(Int32Array::create(arrayBuffer, byteOffset, length).get());
+ arrayBufferView = toJS(m_exec, m_globalObject, Int32Array::create(WTFMove(arrayBuffer), byteOffset, length).get());
return true;
case Uint32ArrayTag:
- arrayBufferView = getJSValue(Uint32Array::create(arrayBuffer, byteOffset, length).get());
+ arrayBufferView = toJS(m_exec, m_globalObject, Uint32Array::create(WTFMove(arrayBuffer), byteOffset, length).get());
return true;
case Float32ArrayTag:
- arrayBufferView = getJSValue(Float32Array::create(arrayBuffer, byteOffset, length).get());
+ arrayBufferView = toJS(m_exec, m_globalObject, Float32Array::create(WTFMove(arrayBuffer), byteOffset, length).get());
return true;
case Float64ArrayTag:
- arrayBufferView = getJSValue(Float64Array::create(arrayBuffer, byteOffset, length).get());
+ arrayBufferView = toJS(m_exec, m_globalObject, Float64Array::create(WTFMove(arrayBuffer), byteOffset, length).get());
return true;
default:
return false;
@@ -1884,7 +2015,7 @@ private:
return true;
}
- bool readHMACKey(bool extractable, CryptoKeyUsage usages, RefPtr<CryptoKey>& result)
+ bool readHMACKey(bool extractable, CryptoKeyUsageBitmap usages, RefPtr<CryptoKey>& result)
{
Vector<uint8_t> keyData;
if (!read(keyData))
@@ -1896,7 +2027,7 @@ private:
return true;
}
- bool readAESKey(bool extractable, CryptoKeyUsage usages, RefPtr<CryptoKey>& result)
+ bool readAESKey(bool extractable, CryptoKeyUsageBitmap usages, RefPtr<CryptoKey>& result)
{
CryptoAlgorithmIdentifier algorithm;
if (!read(algorithm))
@@ -1910,7 +2041,7 @@ private:
return true;
}
- bool readRSAKey(bool extractable, CryptoKeyUsage usages, RefPtr<CryptoKey>& result)
+ bool readRSAKey(bool extractable, CryptoKeyUsageBitmap usages, RefPtr<CryptoKey>& result)
{
CryptoAlgorithmIdentifier algorithm;
if (!read(algorithm))
@@ -1936,10 +2067,8 @@ private:
if (type == CryptoKeyAsymmetricTypeSubtag::Public) {
auto keyData = CryptoKeyDataRSAComponents::createPublic(modulus, exponent);
- auto key = CryptoKeyRSA::create(algorithm, *keyData, extractable, usages);
- if (isRestrictedToHash)
- key->restrictToHash(hash);
- result = std::move(key);
+ auto key = CryptoKeyRSA::create(algorithm, hash, isRestrictedToHash, *keyData, extractable, usages);
+ result = WTFMove(key);
return true;
}
@@ -1953,10 +2082,8 @@ private:
if (!primeCount) {
auto keyData = CryptoKeyDataRSAComponents::createPrivate(modulus, exponent, privateExponent);
- auto key = CryptoKeyRSA::create(algorithm, *keyData, extractable, usages);
- if (isRestrictedToHash)
- key->restrictToHash(hash);
- result = std::move(key);
+ auto key = CryptoKeyRSA::create(algorithm, hash, isRestrictedToHash, *keyData, extractable, usages);
+ result = WTFMove(key);
return true;
}
@@ -1987,15 +2114,17 @@ private:
}
auto keyData = CryptoKeyDataRSAComponents::createPrivateWithAdditionalData(modulus, exponent, privateExponent, firstPrimeInfo, secondPrimeInfo, otherPrimeInfos);
- auto key = CryptoKeyRSA::create(algorithm, *keyData, extractable, usages);
- if (isRestrictedToHash)
- key->restrictToHash(hash);
- result = std::move(key);
+ auto key = CryptoKeyRSA::create(algorithm, hash, isRestrictedToHash, *keyData, extractable, usages);
+ result = WTFMove(key);
return true;
}
bool readCryptoKey(JSValue& cryptoKey)
{
+ uint32_t keyFormatVersion;
+ if (!read(keyFormatVersion) || keyFormatVersion > currentKeyFormatVersion)
+ return false;
+
int32_t extractable;
if (!read(extractable))
return false;
@@ -2004,7 +2133,7 @@ private:
if (!read(usagesCount))
return false;
- CryptoKeyUsage usages = 0;
+ CryptoKeyUsageBitmap usages = 0;
for (uint32_t i = 0; i < usagesCount; ++i) {
CryptoKeyUsageTag usage;
if (!read(usage))
@@ -2066,6 +2195,12 @@ private:
return toJS(m_exec, jsCast<JSDOMGlobalObject*>(m_globalObject), nativeObj);
}
+ template<class T>
+ JSValue getJSValue(T& nativeObj)
+ {
+ return getJSValue(&nativeObj);
+ }
+
JSValue readTerminal()
{
SerializationTag tag = readTag();
@@ -2132,29 +2267,29 @@ private:
unsigned length = 0;
if (!read(length))
return JSValue();
- RefPtr<FileList> result = FileList::create();
+ Vector<RefPtr<File>> files;
for (unsigned i = 0; i < length; i++) {
RefPtr<File> file;
if (!readFile(file))
return JSValue();
if (m_isDOMGlobalObject)
- result->append(file.get());
+ files.append(WTFMove(file));
}
if (!m_isDOMGlobalObject)
return jsNull();
- return getJSValue(result.get());
+ return getJSValue(FileList::create(WTFMove(files)).get());
}
case ImageDataTag: {
- int32_t width;
+ uint32_t width;
if (!read(width))
return JSValue();
- int32_t height;
+ uint32_t height;
if (!read(height))
return JSValue();
uint32_t length;
if (!read(length))
return JSValue();
- if (m_end < ((uint8_t*)0) + length || m_ptr > m_end - length) {
+ if (static_cast<uint32_t>(m_end - m_ptr) < length) {
fail();
return JSValue();
}
@@ -2162,8 +2297,17 @@ private:
m_ptr += length;
return jsNull();
}
- RefPtr<ImageData> result = ImageData::create(IntSize(width, height));
- memcpy(result->data()->data(), m_ptr, length);
+ IntSize imageSize(width, height);
+ RELEASE_ASSERT(!length || (imageSize.area() * 4).unsafeGet() <= length);
+ RefPtr<ImageData> result = ImageData::create(imageSize);
+ if (!result) {
+ fail();
+ return JSValue();
+ }
+ if (length)
+ memcpy(result->data()->data(), m_ptr, length);
+ else
+ result->data()->zeroFill();
m_ptr += length;
return getJSValue(result.get());
}
@@ -2179,7 +2323,7 @@ private:
return JSValue();
if (!m_isDOMGlobalObject)
return jsNull();
- return getJSValue(Blob::create(URL(URL(), url->string()), type->string(), size).get());
+ return getJSValue(Blob::deserialize(URL(URL(), url->string()), type->string(), size, blobFilePathForBlobURL(url->string())).get());
}
case StringTag: {
CachedStringRef cachedString;
@@ -2227,11 +2371,11 @@ private:
case MessagePortReferenceTag: {
uint32_t index;
bool indexSuccessfullyRead = read(index);
- if (!indexSuccessfullyRead || !m_messagePorts || index >= m_messagePorts->size()) {
+ if (!indexSuccessfullyRead || index >= m_messagePorts.size()) {
fail();
return JSValue();
}
- return getJSValue(m_messagePorts->at(index).get());
+ return getJSValue(m_messagePorts[index].get());
}
case ArrayBufferTag: {
RefPtr<ArrayBuffer> arrayBuffer;
@@ -2239,7 +2383,14 @@ private:
fail();
return JSValue();
}
- JSValue result = getJSValue(arrayBuffer.get());
+ Structure* structure = m_globalObject->arrayBufferStructure(arrayBuffer->sharingMode());
+ // A crazy RuntimeFlags mismatch could mean that we are not equipped to handle shared
+ // array buffers while the sender is. In that case, we would see a null structure here.
+ if (!structure) {
+ fail();
+ return JSValue();
+ }
+ JSValue result = JSArrayBuffer::create(m_exec->vm(), structure, WTFMove(arrayBuffer));
m_gcBuffer.append(result);
return result;
}
@@ -2252,13 +2403,27 @@ private:
}
if (!m_arrayBuffers[index])
- m_arrayBuffers[index] = ArrayBuffer::create(m_arrayBufferContents->at(index));
+ m_arrayBuffers[index] = ArrayBuffer::create(WTFMove(m_arrayBufferContents->at(index)));
return getJSValue(m_arrayBuffers[index].get());
}
+ case SharedArrayBufferTag: {
+ uint32_t index = UINT_MAX;
+ bool indexSuccessfullyRead = read(index);
+ if (!indexSuccessfullyRead || !m_sharedBuffers || index >= m_sharedBuffers->size()) {
+ fail();
+ return JSValue();
+ }
+
+ RELEASE_ASSERT(m_sharedBuffers->at(index));
+ RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(WTFMove(m_sharedBuffers->at(index)));
+ JSValue result = getJSValue(buffer.get());
+ m_gcBuffer.append(result);
+ return result;
+ }
case ArrayBufferViewTag: {
JSValue arrayBufferView;
- if (!readArrayBufferView(arrayBufferView)) {
+ if (!readArrayBufferView(m_exec->vm(), arrayBufferView)) {
fail();
return JSValue();
}
@@ -2267,8 +2432,20 @@ private:
}
#if ENABLE(SUBTLE_CRYPTO)
case CryptoKeyTag: {
+ Vector<uint8_t> wrappedKey;
+ if (!read(wrappedKey)) {
+ fail();
+ return JSValue();
+ }
+ Vector<uint8_t> serializedKey;
+ if (!unwrapCryptoKey(m_exec, wrappedKey, serializedKey)) {
+ fail();
+ return JSValue();
+ }
JSValue cryptoKey;
- if (!readCryptoKey(cryptoKey)) {
+ Vector<RefPtr<MessagePort>> dummyMessagePorts;
+ CloneDeserializer rawKeyDeserializer(m_exec, m_globalObject, dummyMessagePorts, nullptr, serializedKey);
+ if (!rawKeyDeserializer.readCryptoKey(cryptoKey)) {
fail();
return JSValue();
}
@@ -2282,9 +2459,10 @@ private:
}
}
- bool consumeMapDataTerminationIfPossible()
+ template<SerializationTag Tag>
+ bool consumeCollectionDataTerminationIfPossible()
{
- if (readTag() == NonMapPropertiesTag)
+ if (readTag() == Tag)
return true;
m_ptr--;
return false;
@@ -2296,18 +2474,36 @@ private:
const uint8_t* m_end;
unsigned m_version;
Vector<CachedString> m_constantPool;
- MessagePortArray* m_messagePorts;
+ Vector<RefPtr<MessagePort>>& m_messagePorts;
ArrayBufferContentsArray* m_arrayBufferContents;
- ArrayBufferArray m_arrayBuffers;
+ Vector<RefPtr<JSC::ArrayBuffer>> m_arrayBuffers;
+ Vector<String> m_blobURLs;
+ Vector<String> m_blobFilePaths;
+ ArrayBufferContentsArray* m_sharedBuffers;
+
+ String blobFilePathForBlobURL(const String& blobURL)
+ {
+ size_t i = 0;
+ for (; i < m_blobURLs.size(); ++i) {
+ if (m_blobURLs[i] == blobURL)
+ break;
+ }
+
+ return i < m_blobURLs.size() ? m_blobFilePaths[i] : String();
+ }
};
DeserializationResult CloneDeserializer::deserialize()
{
+ VM& vm = m_exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
Vector<uint32_t, 16> indexStack;
Vector<Identifier, 16> propertyNameStack;
Vector<JSObject*, 32> outputObjectStack;
- Vector<JSValue, 4> keyStack;
- Vector<MapData*, 4> mapDataStack;
+ Vector<JSValue, 4> mapKeyStack;
+ Vector<JSMap*, 4> mapStack;
+ Vector<JSSet*, 4> setStack;
Vector<WalkerState, 16> stateStack;
WalkerState state = StateUnknown;
JSValue outValue;
@@ -2322,6 +2518,8 @@ DeserializationResult CloneDeserializer::deserialize()
goto error;
}
JSArray* outArray = constructEmptyArray(m_exec, 0, m_globalObject, length);
+ if (UNLIKELY(scope.exception()))
+ goto error;
m_gcBuffer.append(outArray);
outputObjectStack.append(outArray);
}
@@ -2361,7 +2559,7 @@ DeserializationResult CloneDeserializer::deserialize()
objectStartState:
case ObjectStartState: {
if (outputObjectStack.size() > maximumFilterRecursion)
- return std::make_pair(JSValue(), StackOverflowError);
+ return std::make_pair(JSValue(), SerializationReturnCode::StackOverflowError);
JSObject* outObject = constructEmptyObject(m_exec, m_globalObject->objectPrototype());
m_gcBuffer.append(outObject);
outputObjectStack.append(outObject);
@@ -2382,11 +2580,11 @@ DeserializationResult CloneDeserializer::deserialize()
}
if (JSValue terminal = readTerminal()) {
- putProperty(outputObjectStack.last(), Identifier(m_exec, cachedString->string()), terminal);
+ putProperty(outputObjectStack.last(), Identifier::fromString(m_exec, cachedString->string()), terminal);
goto objectStartVisitMember;
}
stateStack.append(ObjectEndVisitMember);
- propertyNameStack.append(Identifier(m_exec, cachedString->string()));
+ propertyNameStack.append(Identifier::fromString(m_exec, cachedString->string()));
goto stateUnknown;
}
case ObjectEndVisitMember: {
@@ -2396,45 +2594,61 @@ DeserializationResult CloneDeserializer::deserialize()
}
mapObjectStartState: {
if (outputObjectStack.size() > maximumFilterRecursion)
- return std::make_pair(JSValue(), StackOverflowError);
- JSMap* map = JSMap::create(m_exec->vm(), m_globalObject->mapStructure());
+ return std::make_pair(JSValue(), SerializationReturnCode::StackOverflowError);
+ JSMap* map = JSMap::create(m_exec, m_exec->vm(), m_globalObject->mapStructure());
+ if (UNLIKELY(scope.exception()))
+ goto error;
m_gcBuffer.append(map);
outputObjectStack.append(map);
- MapData* mapData = map->mapData();
- mapDataStack.append(mapData);
- goto mapDataStartVisitEntry;
- }
- setObjectStartState: {
- if (outputObjectStack.size() > maximumFilterRecursion)
- return std::make_pair(JSValue(), StackOverflowError);
- JSSet* set = JSSet::create(m_exec->vm(), m_globalObject->setStructure());
- m_gcBuffer.append(set);
- outputObjectStack.append(set);
- MapData* mapData = set->mapData();
- mapDataStack.append(mapData);
+ mapStack.append(map);
goto mapDataStartVisitEntry;
}
mapDataStartVisitEntry:
case MapDataStartVisitEntry: {
- if (consumeMapDataTerminationIfPossible()) {
- mapDataStack.removeLast();
+ if (consumeCollectionDataTerminationIfPossible<NonMapPropertiesTag>()) {
+ mapStack.removeLast();
goto objectStartVisitMember;
}
stateStack.append(MapDataEndVisitKey);
goto stateUnknown;
}
-
case MapDataEndVisitKey: {
- keyStack.append(outValue);
+ mapKeyStack.append(outValue);
stateStack.append(MapDataEndVisitValue);
goto stateUnknown;
}
-
case MapDataEndVisitValue: {
- mapDataStack.last()->set(m_exec, keyStack.last(), outValue);
- keyStack.removeLast();
+ mapStack.last()->set(m_exec, mapKeyStack.last(), outValue);
+ mapKeyStack.removeLast();
goto mapDataStartVisitEntry;
}
+
+ setObjectStartState: {
+ if (outputObjectStack.size() > maximumFilterRecursion)
+ return std::make_pair(JSValue(), SerializationReturnCode::StackOverflowError);
+ JSSet* set = JSSet::create(m_exec, m_exec->vm(), m_globalObject->setStructure());
+ if (UNLIKELY(scope.exception()))
+ goto error;
+ m_gcBuffer.append(set);
+ outputObjectStack.append(set);
+ setStack.append(set);
+ goto setDataStartVisitEntry;
+ }
+ setDataStartVisitEntry:
+ case SetDataStartVisitEntry: {
+ if (consumeCollectionDataTerminationIfPossible<NonSetPropertiesTag>()) {
+ setStack.removeLast();
+ goto objectStartVisitMember;
+ }
+ stateStack.append(SetDataEndVisitKey);
+ goto stateUnknown;
+ }
+ case SetDataEndVisitKey: {
+ JSSet* set = setStack.last();
+ set->add(m_exec, outValue);
+ goto setDataStartVisitEntry;
+ }
+
stateUnknown:
case StateUnknown:
if (JSValue terminal = readTerminal()) {
@@ -2460,63 +2674,39 @@ DeserializationResult CloneDeserializer::deserialize()
}
ASSERT(outValue);
ASSERT(!m_failed);
- return std::make_pair(outValue, SuccessfullyCompleted);
+ return std::make_pair(outValue, SerializationReturnCode::SuccessfullyCompleted);
error:
fail();
- return std::make_pair(JSValue(), ValidationError);
-}
-
-void SerializedScriptValue::addBlobURL(const String& string)
-{
- m_blobURLs.append(Vector<uint16_t>());
- m_blobURLs.last().reserveCapacity(string.length());
- for (size_t i = 0; i < string.length(); i++)
- m_blobURLs.last().append(string.characterAt(i));
- m_blobURLs.last().resize(m_blobURLs.last().size());
+ return std::make_pair(JSValue(), SerializationReturnCode::ValidationError);
}
SerializedScriptValue::~SerializedScriptValue()
{
}
-SerializedScriptValue::SerializedScriptValue(const Vector<uint8_t>& buffer)
- : m_data(buffer)
+SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>&& buffer)
+ : m_data(WTFMove(buffer))
{
}
-SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer)
+SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>&& buffer, const Vector<String>& blobURLs, std::unique_ptr<ArrayBufferContentsArray> arrayBufferContentsArray, std::unique_ptr<ArrayBufferContentsArray> sharedBufferContentsArray)
+ : m_data(WTFMove(buffer))
+ , m_arrayBufferContentsArray(WTFMove(arrayBufferContentsArray))
+ , m_sharedBufferContentsArray(WTFMove(sharedBufferContentsArray))
{
- m_data.swap(buffer);
+ // Since this SerializedScriptValue is meant to be passed between threads, its String data members
+ // need to be isolatedCopies so we don't run into thread safety issues for the StringImpls.
+ m_blobURLs.reserveInitialCapacity(blobURLs.size());
+ for (auto& url : blobURLs)
+ m_blobURLs.uncheckedAppend(url.isolatedCopy());
}
-SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer, Vector<String>& blobURLs)
+static ExceptionOr<std::unique_ptr<ArrayBufferContentsArray>> transferArrayBuffers(VM& vm, const Vector<RefPtr<JSC::ArrayBuffer>>& arrayBuffers)
{
- m_data.swap(buffer);
- for (auto& string : blobURLs)
- addBlobURL(string);
-}
+ if (arrayBuffers.isEmpty())
+ return nullptr;
-SerializedScriptValue::SerializedScriptValue(Vector<uint8_t>& buffer, Vector<String>& blobURLs, PassOwnPtr<ArrayBufferContentsArray> arrayBufferContentsArray)
- : m_arrayBufferContentsArray(arrayBufferContentsArray)
-{
- m_data.swap(buffer);
- for (auto& string : blobURLs)
- addBlobURL(string);
-}
-
-PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::transferArrayBuffers(
- ExecState* exec, ArrayBufferArray& arrayBuffers, SerializationReturnCode& code)
-{
- for (size_t i = 0; i < arrayBuffers.size(); i++) {
- if (arrayBuffers[i]->isNeutered()) {
- code = ValidationError;
- return nullptr;
- }
- }
-
- OwnPtr<ArrayBufferContentsArray> contents = adoptPtr(new ArrayBufferContentsArray(arrayBuffers.size()));
- Vector<Ref<DOMWrapperWorld>> worlds;
- static_cast<WebCoreJSClientData*>(exec->vm().clientData)->getAllWorlds(worlds);
+ auto contents = std::make_unique<ArrayBufferContentsArray>(arrayBuffers.size());
HashSet<JSC::ArrayBuffer*> visited;
for (size_t arrayBufferIndex = 0; arrayBufferIndex < arrayBuffers.size(); arrayBufferIndex++) {
@@ -2524,207 +2714,255 @@ PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValu
continue;
visited.add(arrayBuffers[arrayBufferIndex].get());
- bool result = arrayBuffers[arrayBufferIndex]->transfer(contents->at(arrayBufferIndex));
- if (!result) {
- code = ValidationError;
- return nullptr;
- }
+ bool result = arrayBuffers[arrayBufferIndex]->transferTo(vm, contents->at(arrayBufferIndex));
+ if (!result)
+ return Exception { TypeError };
+ }
+
+ return WTFMove(contents);
+}
+
+static void maybeThrowExceptionIfSerializationFailed(ExecState& state, SerializationReturnCode code)
+{
+ auto& vm = state.vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+
+ switch (code) {
+ case SerializationReturnCode::SuccessfullyCompleted:
+ break;
+ case SerializationReturnCode::StackOverflowError:
+ throwException(&state, scope, createStackOverflowError(&state));
+ break;
+ case SerializationReturnCode::ValidationError:
+ throwTypeError(&state, scope, ASCIILiteral("Unable to deserialize data."));
+ break;
+ case SerializationReturnCode::DataCloneError:
+ throwDataCloneError(state, scope);
+ break;
+ case SerializationReturnCode::ExistingExceptionError:
+ case SerializationReturnCode::UnspecifiedError:
+ break;
+ case SerializationReturnCode::InterruptedExecutionError:
+ ASSERT_NOT_REACHED();
}
- return contents.release();
}
+static Exception exceptionForSerializationFailure(SerializationReturnCode code)
+{
+ ASSERT(code != SerializationReturnCode::SuccessfullyCompleted);
+
+ switch (code) {
+ case SerializationReturnCode::StackOverflowError:
+ return Exception { StackOverflowError };
+ case SerializationReturnCode::ValidationError:
+ return Exception { TypeError };
+ case SerializationReturnCode::DataCloneError:
+ return Exception { DATA_CLONE_ERR };
+ case SerializationReturnCode::ExistingExceptionError:
+ return Exception { ExistingExceptionError };
+ case SerializationReturnCode::UnspecifiedError:
+ return Exception { TypeError };
+ case SerializationReturnCode::SuccessfullyCompleted:
+ case SerializationReturnCode::InterruptedExecutionError:
+ ASSERT_NOT_REACHED();
+ return Exception { TypeError };
+ }
+ ASSERT_NOT_REACHED();
+ return Exception { TypeError };
+}
-PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(ExecState* exec, JSValue value,
- MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers,
- SerializationErrorMode throwExceptions)
+RefPtr<SerializedScriptValue> SerializedScriptValue::create(ExecState& exec, JSValue value, SerializationErrorMode throwExceptions)
{
Vector<uint8_t> buffer;
Vector<String> blobURLs;
- SerializationReturnCode code = CloneSerializer::serialize(exec, value, messagePorts, arrayBuffers, blobURLs, buffer);
-
- OwnPtr<ArrayBufferContentsArray> arrayBufferContentsArray;
+ Vector<RefPtr<MessagePort>> dummyMessagePorts;
+ Vector<RefPtr<JSC::ArrayBuffer>> dummyArrayBuffers;
+ ArrayBufferContentsArray dummySharedBuffers;
+ auto code = CloneSerializer::serialize(&exec, value, dummyMessagePorts, dummyArrayBuffers, blobURLs, buffer, SerializationContext::Default, dummySharedBuffers);
- if (arrayBuffers && serializationDidCompleteSuccessfully(code))
- arrayBufferContentsArray = transferArrayBuffers(exec, *arrayBuffers, code);
-
- if (throwExceptions == Throwing)
+ if (throwExceptions == SerializationErrorMode::Throwing)
maybeThrowExceptionIfSerializationFailed(exec, code);
- if (!serializationDidCompleteSuccessfully(code))
- return 0;
+ if (code != SerializationReturnCode::SuccessfullyCompleted)
+ return nullptr;
- return adoptRef(new SerializedScriptValue(buffer, blobURLs, arrayBufferContentsArray.release()));
+ return adoptRef(*new SerializedScriptValue(WTFMove(buffer), blobURLs, nullptr, nullptr));
}
-PassRefPtr<SerializedScriptValue> SerializedScriptValue::create()
+ExceptionOr<Ref<SerializedScriptValue>> SerializedScriptValue::create(ExecState& state, JSValue value, Vector<JSC::Strong<JSC::JSObject>>&& transferList, Vector<RefPtr<MessagePort>>& messagePorts, SerializationContext context)
{
- Vector<uint8_t> buffer;
- return adoptRef(new SerializedScriptValue(buffer));
-}
+ VM& vm = state.vm();
+ Vector<RefPtr<JSC::ArrayBuffer>> arrayBuffers;
+ for (auto& transferable : transferList) {
+ if (auto arrayBuffer = toPossiblySharedArrayBuffer(vm, transferable.get())) {
+ if (arrayBuffer->isNeutered())
+ return Exception { DATA_CLONE_ERR };
+ if (arrayBuffer->isShared())
+ return Exception { TypeError };
+ arrayBuffers.append(WTFMove(arrayBuffer));
+ continue;
+ }
+ if (auto port = JSMessagePort::toWrapped(vm, transferable.get())) {
+ // FIXME: This should check if the port is detached as per https://html.spec.whatwg.org/multipage/infrastructure.html#istransferable.
+ messagePorts.append(WTFMove(port));
+ continue;
+ }
+
+ return Exception { DATA_CLONE_ERR };
+ }
-PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& string)
-{
Vector<uint8_t> buffer;
- if (!CloneSerializer::serialize(string, buffer))
- return 0;
- return adoptRef(new SerializedScriptValue(buffer));
-}
+ Vector<String> blobURLs;
+ std::unique_ptr<ArrayBufferContentsArray> sharedBuffers = std::make_unique<ArrayBufferContentsArray>();
+ auto code = CloneSerializer::serialize(&state, value, messagePorts, arrayBuffers, blobURLs, buffer, context, *sharedBuffers);
-#if ENABLE(INDEXED_DATABASE)
-PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(JSC::ExecState* exec, JSC::JSValue value)
-{
- return SerializedScriptValue::create(exec, value, 0, 0);
-}
+ if (code != SerializationReturnCode::SuccessfullyCompleted)
+ return exceptionForSerializationFailure(code);
-PassRefPtr<SerializedScriptValue> SerializedScriptValue::numberValue(double value)
-{
- Vector<uint8_t> buffer;
- CloneSerializer::serializeNumber(value, buffer);
- return adoptRef(new SerializedScriptValue(buffer));
+ auto arrayBufferContentsArray = transferArrayBuffers(vm, arrayBuffers);
+ if (arrayBufferContentsArray.hasException())
+ return arrayBufferContentsArray.releaseException();
+
+ return adoptRef(*new SerializedScriptValue(WTFMove(buffer), blobURLs, arrayBufferContentsArray.releaseReturnValue(), context == SerializationContext::WorkerPostMessage ? WTFMove(sharedBuffers) : nullptr));
}
-JSValue SerializedScriptValue::deserialize(JSC::ExecState* exec, JSC::JSGlobalObject* globalObject)
+RefPtr<SerializedScriptValue> SerializedScriptValue::create(StringView string)
{
- return deserialize(exec, globalObject, 0);
+ Vector<uint8_t> buffer;
+ if (!CloneSerializer::serialize(string, buffer))
+ return nullptr;
+ return adoptRef(*new SerializedScriptValue(WTFMove(buffer)));
}
-#endif
-PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(JSContextRef originContext, JSValueRef apiValue,
- MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers,
- JSValueRef* exception)
+RefPtr<SerializedScriptValue> SerializedScriptValue::create(JSContextRef originContext, JSValueRef apiValue, JSValueRef* exception)
{
ExecState* exec = toJS(originContext);
- APIEntryShim entryShim(exec);
+ VM& vm = exec->vm();
+ JSLockHolder locker(vm);
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+
JSValue value = toJS(exec, apiValue);
- RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::create(exec, value, messagePorts, arrayBuffers);
- if (exec->hadException()) {
+ RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::create(*exec, value);
+ if (UNLIKELY(scope.exception())) {
if (exception)
- *exception = toRef(exec, exec->exception());
- exec->clearException();
- return 0;
+ *exception = toRef(exec, scope.exception()->value());
+ scope.clearException();
+ return nullptr;
}
ASSERT(serializedValue);
- return serializedValue.release();
+ return serializedValue;
}
-PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(JSContextRef originContext, JSValueRef apiValue,
- JSValueRef* exception)
+String SerializedScriptValue::toString()
{
- return create(originContext, apiValue, 0, 0, exception);
+ return CloneDeserializer::deserializeString(m_data);
}
-String SerializedScriptValue::toString()
+JSValue SerializedScriptValue::deserialize(ExecState& exec, JSGlobalObject* globalObject, SerializationErrorMode throwExceptions)
{
- return CloneDeserializer::deserializeString(m_data);
+ Vector<RefPtr<MessagePort>> dummyMessagePorts;
+ return deserialize(exec, globalObject, dummyMessagePorts, throwExceptions);
}
-JSValue SerializedScriptValue::deserialize(ExecState* exec, JSGlobalObject* globalObject,
- MessagePortArray* messagePorts, SerializationErrorMode throwExceptions)
+JSValue SerializedScriptValue::deserialize(ExecState& exec, JSGlobalObject* globalObject, Vector<RefPtr<MessagePort>>& messagePorts, SerializationErrorMode throwExceptions)
{
- DeserializationResult result = CloneDeserializer::deserialize(exec, globalObject, messagePorts,
- m_arrayBufferContentsArray.get(), m_data);
- if (throwExceptions == Throwing)
- maybeThrowExceptionIfSerializationFailed(exec, result.second);
- return result.first;
+ Vector<String> dummyBlobs;
+ Vector<String> dummyPaths;
+ return deserialize(exec, globalObject, messagePorts, dummyBlobs, dummyPaths, throwExceptions);
}
-#if ENABLE(INSPECTOR)
-Deprecated::ScriptValue SerializedScriptValue::deserializeForInspector(JSC::ExecState* scriptState)
+JSValue SerializedScriptValue::deserialize(ExecState& exec, JSGlobalObject* globalObject, Vector<RefPtr<MessagePort>>& messagePorts, const Vector<String>& blobURLs, const Vector<String>& blobFilePaths, SerializationErrorMode throwExceptions)
{
- JSValue value = deserialize(scriptState, scriptState->lexicalGlobalObject(), 0);
- return Deprecated::ScriptValue(scriptState->vm(), value);
+ DeserializationResult result = CloneDeserializer::deserialize(&exec, globalObject, messagePorts, m_arrayBufferContentsArray.get(), m_data, blobURLs, blobFilePaths, m_sharedBufferContentsArray.get());
+ if (throwExceptions == SerializationErrorMode::Throwing)
+ maybeThrowExceptionIfSerializationFailed(exec, result.second);
+ return result.first ? result.first : jsNull();
}
-#endif
-JSValueRef SerializedScriptValue::deserialize(JSContextRef destinationContext, JSValueRef* exception, MessagePortArray* messagePorts)
+JSValueRef SerializedScriptValue::deserialize(JSContextRef destinationContext, JSValueRef* exception)
{
ExecState* exec = toJS(destinationContext);
- APIEntryShim entryShim(exec);
- JSValue value = deserialize(exec, exec->lexicalGlobalObject(), messagePorts);
- if (exec->hadException()) {
+ VM& vm = exec->vm();
+ JSLockHolder locker(vm);
+ auto scope = DECLARE_CATCH_SCOPE(vm);
+
+ JSValue value = deserialize(*exec, exec->lexicalGlobalObject());
+ if (UNLIKELY(scope.exception())) {
if (exception)
- *exception = toRef(exec, exec->exception());
- exec->clearException();
- return 0;
+ *exception = toRef(exec, scope.exception()->value());
+ scope.clearException();
+ return nullptr;
}
ASSERT(value);
return toRef(exec, value);
}
-
-JSValueRef SerializedScriptValue::deserialize(JSContextRef destinationContext, JSValueRef* exception)
+Ref<SerializedScriptValue> SerializedScriptValue::nullValue()
{
- return deserialize(destinationContext, exception, 0);
+ return adoptRef(*new SerializedScriptValue(Vector<uint8_t>()));
}
-PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue()
+uint32_t SerializedScriptValue::wireFormatVersion()
{
- return SerializedScriptValue::create();
+ return CurrentVersion;
}
-PassRefPtr<SerializedScriptValue> SerializedScriptValue::undefinedValue()
+#if ENABLE(INDEXED_DATABASE)
+Vector<String> SerializedScriptValue::blobURLsIsolatedCopy() const
{
- Vector<uint8_t> buffer;
- CloneSerializer::serializeUndefined(buffer);
- return adoptRef(new SerializedScriptValue(buffer));
-}
+ Vector<String> result;
+ result.reserveInitialCapacity(m_blobURLs.size());
+ for (auto& url : m_blobURLs)
+ result.uncheckedAppend(url.isolatedCopy());
-PassRefPtr<SerializedScriptValue> SerializedScriptValue::booleanValue(bool value)
-{
- Vector<uint8_t> buffer;
- CloneSerializer::serializeBoolean(value, buffer);
- return adoptRef(new SerializedScriptValue(buffer));
+ return result;
}
-PassRefPtr<SerializedScriptValue> SerializedScriptValue::serialize(const Deprecated::ScriptValue& value, JSC::ExecState* scriptState, SerializationErrorMode throwExceptions)
+void SerializedScriptValue::writeBlobsToDiskForIndexedDB(WTF::Function<void (const IDBValue&)>&& completionHandler)
{
- return SerializedScriptValue::create(scriptState, value.jsValue(), nullptr, nullptr, throwExceptions);
-}
+ ASSERT(isMainThread());
+ ASSERT(hasBlobURLs());
-PassRefPtr<SerializedScriptValue> SerializedScriptValue::serialize(const Deprecated::ScriptValue& value, JSC::ExecState* scriptState, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, bool& didThrow)
-{
- RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::create(scriptState, value.jsValue(), messagePorts, arrayBuffers);
- didThrow = scriptState->hadException();
- return serializedValue.release();
-}
+ RefPtr<SerializedScriptValue> protectedThis(this);
+ blobRegistry().writeBlobsToTemporaryFiles(m_blobURLs, [completionHandler = WTFMove(completionHandler), this, protectedThis = WTFMove(protectedThis)](auto& blobFilePaths) {
+ ASSERT(isMainThread());
-Deprecated::ScriptValue SerializedScriptValue::deserialize(JSC::ExecState* scriptState, SerializedScriptValue* value, SerializationErrorMode throwExceptions)
-{
- return Deprecated::ScriptValue(scriptState->vm(), value->deserialize(scriptState, scriptState->lexicalGlobalObject(), 0, throwExceptions));
-}
+ if (blobFilePaths.isEmpty()) {
+ // We should have successfully written blobs to temporary files.
+ // If we failed, then we can't successfully store this record.
+ completionHandler({ });
+ return;
+ }
-void SerializedScriptValue::maybeThrowExceptionIfSerializationFailed(ExecState* exec, SerializationReturnCode code)
-{
- if (code == SuccessfullyCompleted)
- return;
-
- switch (code) {
- case StackOverflowError:
- exec->vm().throwException(exec, createStackOverflowError(exec));
- break;
- case ValidationError:
- exec->vm().throwException(exec, createTypeError(exec, "Unable to deserialize data."));
- break;
- case DataCloneError:
- setDOMException(exec, DATA_CLONE_ERR);
- break;
- case ExistingExceptionError:
- break;
- case UnspecifiedError:
- break;
- default:
- ASSERT_NOT_REACHED();
- }
+ ASSERT(m_blobURLs.size() == blobFilePaths.size());
+
+ completionHandler({ *this, m_blobURLs, blobFilePaths });
+ });
}
-bool SerializedScriptValue::serializationDidCompleteSuccessfully(SerializationReturnCode code)
+IDBValue SerializedScriptValue::writeBlobsToDiskForIndexedDBSynchronously()
{
- return (code == SuccessfullyCompleted);
-}
+ ASSERT(!isMainThread());
-uint32_t SerializedScriptValue::wireFormatVersion()
-{
- return CurrentVersion;
-}
+ IDBValue value;
+ Lock lock;
+ Condition condition;
+ lock.lock();
+
+ RunLoop::main().dispatch([this, conditionPtr = &condition, valuePtr = &value] {
+ writeBlobsToDiskForIndexedDB([conditionPtr, valuePtr](const IDBValue& result) {
+ ASSERT(isMainThread());
+ valuePtr->setAsIsolatedCopy(result);
+
+ conditionPtr->notifyAll();
+ });
+ });
+ condition.wait(lock);
+
+ return value;
}
+
+#endif // ENABLE(INDEXED_DATABASE)
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/SerializedScriptValue.h b/Source/WebCore/bindings/js/SerializedScriptValue.h
index 37b31729a..1729011c4 100644
--- a/Source/WebCore/bindings/js/SerializedScriptValue.h
+++ b/Source/WebCore/bindings/js/SerializedScriptValue.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009, 2013 Apple Inc. All rights reserved.
+ * Copyright (C) 2009, 2013, 2016 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -10,10 +10,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -24,16 +24,14 @@
*
*/
-#ifndef SerializedScriptValue_h
-#define SerializedScriptValue_h
+#pragma once
-#include "ScriptState.h"
-#include <bindings/ScriptValue.h>
+#include "ExceptionOr.h"
#include <heap/Strong.h>
#include <runtime/ArrayBuffer.h>
#include <runtime/JSCJSValue.h>
#include <wtf/Forward.h>
-#include <wtf/PassRefPtr.h>
+#include <wtf/Function.h>
#include <wtf/RefCounted.h>
#include <wtf/text/WTFString.h>
@@ -42,96 +40,67 @@ typedef const struct OpaqueJSValue* JSValueRef;
namespace WebCore {
+class IDBValue;
class MessagePort;
-typedef Vector<RefPtr<MessagePort>, 1> MessagePortArray;
-typedef Vector<RefPtr<JSC::ArrayBuffer>, 1> ArrayBufferArray;
-
-enum SerializationReturnCode {
- SuccessfullyCompleted,
- StackOverflowError,
- InterruptedExecutionError,
- ValidationError,
- ExistingExceptionError,
- DataCloneError,
- UnspecifiedError
-};
-
-enum SerializationErrorMode { NonThrowing, Throwing };
-
class SharedBuffer;
+enum class SerializationReturnCode;
-class SerializedScriptValue :
-#if ENABLE(INDEXED_DATABASE)
- public ThreadSafeRefCounted<SerializedScriptValue> {
-#else
- public RefCounted<SerializedScriptValue> {
-#endif
+enum class SerializationErrorMode { NonThrowing, Throwing };
+enum class SerializationContext { Default, WorkerPostMessage };
+
+using ArrayBufferContentsArray = Vector<JSC::ArrayBufferContents>;
+
+class SerializedScriptValue : public ThreadSafeRefCounted<SerializedScriptValue> {
public:
- static PassRefPtr<SerializedScriptValue> create(JSC::ExecState*, JSC::JSValue, MessagePortArray*, ArrayBufferArray*, SerializationErrorMode = Throwing);
- static PassRefPtr<SerializedScriptValue> create(JSContextRef, JSValueRef, MessagePortArray*, ArrayBufferArray*, JSValueRef* exception);
- static PassRefPtr<SerializedScriptValue> create(JSContextRef, JSValueRef, JSValueRef* exception);
+ WEBCORE_EXPORT static RefPtr<SerializedScriptValue> create(JSC::ExecState&, JSC::JSValue, SerializationErrorMode = SerializationErrorMode::Throwing);
+
+ WEBCORE_EXPORT static ExceptionOr<Ref<SerializedScriptValue>> create(JSC::ExecState&, JSC::JSValue, Vector<JSC::Strong<JSC::JSObject>>&& transfer, Vector<RefPtr<MessagePort>>&, SerializationContext = SerializationContext::Default);
- static PassRefPtr<SerializedScriptValue> create(const String&);
- static PassRefPtr<SerializedScriptValue> adopt(Vector<uint8_t>& buffer)
+ WEBCORE_EXPORT static RefPtr<SerializedScriptValue> create(StringView);
+ static Ref<SerializedScriptValue> adopt(Vector<uint8_t>&& buffer)
{
- return adoptRef(new SerializedScriptValue(buffer));
+ return adoptRef(*new SerializedScriptValue(WTFMove(buffer)));
}
- static PassRefPtr<SerializedScriptValue> create();
- static PassRefPtr<SerializedScriptValue> nullValue();
- static PassRefPtr<SerializedScriptValue> undefinedValue();
- static PassRefPtr<SerializedScriptValue> booleanValue(bool value);
+ static Ref<SerializedScriptValue> nullValue();
- static PassRefPtr<SerializedScriptValue> serialize(const Deprecated::ScriptValue&, JSC::ExecState*, SerializationErrorMode = Throwing);
- static PassRefPtr<SerializedScriptValue> serialize(const Deprecated::ScriptValue&, JSC::ExecState*, MessagePortArray*, ArrayBufferArray*, bool&);
- static Deprecated::ScriptValue deserialize(JSC::ExecState*, SerializedScriptValue*, SerializationErrorMode = Throwing);
+ WEBCORE_EXPORT JSC::JSValue deserialize(JSC::ExecState&, JSC::JSGlobalObject*, SerializationErrorMode = SerializationErrorMode::Throwing);
+ WEBCORE_EXPORT JSC::JSValue deserialize(JSC::ExecState&, JSC::JSGlobalObject*, Vector<RefPtr<MessagePort>>&, SerializationErrorMode = SerializationErrorMode::Throwing);
+ JSC::JSValue deserialize(JSC::ExecState&, JSC::JSGlobalObject*, Vector<RefPtr<MessagePort>>&, const Vector<String>& blobURLs, const Vector<String>& blobFilePaths, SerializationErrorMode = SerializationErrorMode::Throwing);
static uint32_t wireFormatVersion();
String toString();
-
- JSC::JSValue deserialize(JSC::ExecState*, JSC::JSGlobalObject*, MessagePortArray*, SerializationErrorMode = Throwing);
- JSValueRef deserialize(JSContextRef, JSValueRef* exception, MessagePortArray*);
- JSValueRef deserialize(JSContextRef, JSValueRef* exception);
-#if ENABLE(INSPECTOR)
- Deprecated::ScriptValue deserializeForInspector(JSC::ExecState*);
-#endif
+ // API implementation helpers. These don't expose special behavior for ArrayBuffers or MessagePorts.
+ WEBCORE_EXPORT static RefPtr<SerializedScriptValue> create(JSContextRef, JSValueRef, JSValueRef* exception);
+ WEBCORE_EXPORT JSValueRef deserialize(JSContextRef, JSValueRef* exception);
const Vector<uint8_t>& data() const { return m_data; }
bool hasBlobURLs() const { return !m_blobURLs.isEmpty(); }
- void blobURLs(Vector<String>&) const;
#if ENABLE(INDEXED_DATABASE)
- static PassRefPtr<SerializedScriptValue> create(JSC::ExecState*, JSC::JSValue);
- static PassRefPtr<SerializedScriptValue> numberValue(double value);
- JSC::JSValue deserialize(JSC::ExecState*, JSC::JSGlobalObject*);
-#endif
+ Vector<String> blobURLsIsolatedCopy() const;
+ void writeBlobsToDiskForIndexedDB(WTF::Function<void (const IDBValue&)>&& completionHandler);
+ IDBValue writeBlobsToDiskForIndexedDBSynchronously();
+#endif // ENABLE(INDEXED_DATABASE)
- static PassRefPtr<SerializedScriptValue> createFromWireBytes(const Vector<uint8_t>& data)
+ static Ref<SerializedScriptValue> createFromWireBytes(Vector<uint8_t>&& data)
{
- return adoptRef(new SerializedScriptValue(data));
+ return adoptRef(*new SerializedScriptValue(WTFMove(data)));
}
const Vector<uint8_t>& toWireBytes() const { return m_data; }
- ~SerializedScriptValue();
+ WEBCORE_EXPORT ~SerializedScriptValue();
private:
- typedef Vector<JSC::ArrayBufferContents> ArrayBufferContentsArray;
- static void maybeThrowExceptionIfSerializationFailed(JSC::ExecState*, SerializationReturnCode);
- static bool serializationDidCompleteSuccessfully(SerializationReturnCode);
- static PassOwnPtr<ArrayBufferContentsArray> transferArrayBuffers(JSC::ExecState*, ArrayBufferArray&, SerializationReturnCode&);
- void addBlobURL(const String&);
-
- SerializedScriptValue(const Vector<unsigned char>&);
- SerializedScriptValue(Vector<unsigned char>&);
- SerializedScriptValue(Vector<unsigned char>&, Vector<String>& blobURLs);
- SerializedScriptValue(Vector<unsigned char>&, Vector<String>& blobURLs, PassOwnPtr<ArrayBufferContentsArray>);
+ WEBCORE_EXPORT SerializedScriptValue(Vector<unsigned char>&&);
+ SerializedScriptValue(Vector<unsigned char>&&, const Vector<String>& blobURLs, std::unique_ptr<ArrayBufferContentsArray>, std::unique_ptr<ArrayBufferContentsArray> sharedBuffers);
+
Vector<unsigned char> m_data;
- OwnPtr<ArrayBufferContentsArray> m_arrayBufferContentsArray;
- Vector<Vector<uint16_t>> m_blobURLs;
+ std::unique_ptr<ArrayBufferContentsArray> m_arrayBufferContentsArray;
+ std::unique_ptr<ArrayBufferContentsArray> m_sharedBufferContentsArray;
+ Vector<String> m_blobURLs;
};
}
-
-#endif // SerializedScriptValue_h
diff --git a/Source/WebCore/bindings/js/StructuredClone.cpp b/Source/WebCore/bindings/js/StructuredClone.cpp
new file mode 100644
index 000000000..4869ac0df
--- /dev/null
+++ b/Source/WebCore/bindings/js/StructuredClone.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "config.h"
+#include "StructuredClone.h"
+
+#include "JSDOMBinding.h"
+#include "JSDOMExceptionHandling.h"
+#include <runtime/JSTypedArrays.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+EncodedJSValue JSC_HOST_CALL structuredCloneArrayBuffer(ExecState* state)
+{
+ ASSERT(state);
+ ASSERT(state->argumentCount());
+ ASSERT(state->lexicalGlobalObject());
+
+ VM& vm = state->vm();
+ auto* buffer = toUnsharedArrayBuffer(vm, state->uncheckedArgument(0));
+ if (!buffer) {
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ throwDataCloneError(*state, scope);
+ return { };
+ }
+ return JSValue::encode(JSArrayBuffer::create(state->vm(), state->lexicalGlobalObject()->arrayBufferStructure(ArrayBufferSharingMode::Default), ArrayBuffer::tryCreate(buffer->data(), buffer->byteLength())));
+}
+
+EncodedJSValue JSC_HOST_CALL structuredCloneArrayBufferView(ExecState* state)
+{
+ ASSERT(state);
+ ASSERT(state->argumentCount());
+
+ JSValue value = state->uncheckedArgument(0);
+ VM& vm = state->vm();
+ auto* bufferView = jsDynamicDowncast<JSArrayBufferView*>(vm, value);
+ ASSERT(bufferView);
+
+ auto* buffer = bufferView->unsharedBuffer();
+ if (!buffer) {
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ throwDataCloneError(*state, scope);
+ return { };
+ }
+ auto bufferClone = ArrayBuffer::tryCreate(buffer->data(), buffer->byteLength());
+
+ if (jsDynamicDowncast<JSInt8Array*>(vm, value))
+ return JSValue::encode(JSInt8Array::create(state, bufferView->structure(), WTFMove(bufferClone), bufferView->byteOffset(), bufferView->length()));
+ if (jsDynamicDowncast<JSInt16Array*>(vm, value))
+ return JSValue::encode(JSInt16Array::create(state, bufferView->structure(), WTFMove(bufferClone), bufferView->byteOffset(), bufferView->length()));
+ if (jsDynamicDowncast<JSInt32Array*>(vm, value))
+ return JSValue::encode(JSInt32Array::create(state, bufferView->structure(), WTFMove(bufferClone), bufferView->byteOffset(), bufferView->length()));
+ if (jsDynamicDowncast<JSUint8Array*>(vm, value))
+ return JSValue::encode(JSUint8Array::create(state, bufferView->structure(), WTFMove(bufferClone), bufferView->byteOffset(), bufferView->length()));
+ if (jsDynamicDowncast<JSUint8ClampedArray*>(vm, value))
+ return JSValue::encode(JSUint8ClampedArray::create(state, bufferView->structure(), WTFMove(bufferClone), bufferView->byteOffset(), bufferView->length()));
+ if (jsDynamicDowncast<JSUint16Array*>(vm, value))
+ return JSValue::encode(JSUint16Array::create(state, bufferView->structure(), WTFMove(bufferClone), bufferView->byteOffset(), bufferView->length()));
+ if (jsDynamicDowncast<JSUint32Array*>(vm, value))
+ return JSValue::encode(JSUint32Array::create(state, bufferView->structure(), WTFMove(bufferClone), bufferView->byteOffset(), bufferView->length()));
+ if (jsDynamicDowncast<JSFloat32Array*>(vm, value))
+ return JSValue::encode(JSFloat32Array::create(state, bufferView->structure(), WTFMove(bufferClone), bufferView->byteOffset(), bufferView->length()));
+ if (jsDynamicDowncast<JSFloat64Array*>(vm, value))
+ return JSValue::encode(JSFloat64Array::create(state, bufferView->structure(), WTFMove(bufferClone), bufferView->byteOffset(), bufferView->length()));
+ if (jsDynamicDowncast<JSDataView*>(vm, value))
+ return JSValue::encode(JSDataView::create(state, bufferView->structure(), WTFMove(bufferClone), bufferView->byteOffset(), bufferView->length()));
+
+ ASSERT_NOT_REACHED();
+ return JSValue::encode(jsUndefined());
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSHTMLInputElementCustom.h b/Source/WebCore/bindings/js/StructuredClone.h
index f5222d24c..ea6d01b69 100644
--- a/Source/WebCore/bindings/js/JSHTMLInputElementCustom.h
+++ b/Source/WebCore/bindings/js/StructuredClone.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2016 Apple Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -20,12 +20,18 @@
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
*/
-#ifndef JSHTMLInputElementCustom_h
-#define JSHTMLInputElementCustom_h
+namespace JSC {
+using EncodedJSValue = int64_t;
+class ExecState;
+}
+
+namespace WebCore {
-#include "JSHTMLInputElement.h"
+JSC::EncodedJSValue JSC_HOST_CALL structuredCloneArrayBuffer(JSC::ExecState*);
+JSC::EncodedJSValue JSC_HOST_CALL structuredCloneArrayBufferView(JSC::ExecState*);
-#endif // JSHTMLInputElementCustom_h
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/WebCoreBuiltinNames.h b/Source/WebCore/bindings/js/WebCoreBuiltinNames.h
new file mode 100644
index 000000000..8ab00bc07
--- /dev/null
+++ b/Source/WebCore/bindings/js/WebCoreBuiltinNames.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2015, Canon Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Canon Inc. nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <builtins/BuiltinUtils.h>
+
+namespace WebCore {
+
+#define WEBCORE_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(macro)\
+ macro(addTrack) \
+ macro(appendFromJS) \
+ macro(autoAllocateChunkSize) \
+ macro(body) \
+ macro(cancel) \
+ macro(cloneForJS) \
+ macro(closeRequested) \
+ macro(closedPromiseCapability) \
+ macro(consume) \
+ macro(consumeChunk) \
+ macro(controlledReadableStream) \
+ macro(controller) \
+ macro(createReadableStreamSource) \
+ macro(disturbed) \
+ macro(failureKind) \
+ macro(fetchRequest) \
+ macro(fillFromJS) \
+ macro(finishConsumingStream) \
+ macro(getUserMedia) \
+ macro(getRemoteStreams) \
+ macro(getSenders) \
+ macro(getTracks) \
+ macro(initializeWith) \
+ macro(isDisturbed) \
+ macro(isLoading) \
+ macro(localStreams) \
+ macro(makeThisTypeError) \
+ macro(makeGetterTypeError) \
+ macro(mediaStreamTrackConstraints) \
+ macro(operations) \
+ macro(ownerReadableStream) \
+ macro(pendingPullIntos) \
+ macro(privateGetStats) \
+ macro(pull) \
+ macro(pulling) \
+ macro(pullAgain) \
+ macro(queue) \
+ macro(queuedAddIceCandidate) \
+ macro(queuedCreateAnswer) \
+ macro(queuedCreateOffer) \
+ macro(queuedSetLocalDescription) \
+ macro(queuedSetRemoteDescription) \
+ macro(reader) \
+ macro(readIntoRequests) \
+ macro(readRequests) \
+ macro(readableStreamController) \
+ macro(readyPromiseCapability) \
+ macro(removeTrack) \
+ macro(responseCacheIsValid) \
+ macro(retrieveResponse) \
+ macro(response) \
+ macro(setBody) \
+ macro(setStatus) \
+ macro(state) \
+ macro(startConsumingStream) \
+ macro(started) \
+ macro(startedPromise) \
+ macro(storedError) \
+ macro(strategy) \
+ macro(strategyHWM) \
+ macro(streamClosed) \
+ macro(streamClosing) \
+ macro(streamErrored) \
+ macro(streamReadable) \
+ macro(streamWaiting) \
+ macro(streamWritable) \
+ macro(structuredCloneArrayBuffer) \
+ macro(structuredCloneArrayBufferView) \
+ macro(totalQueuedBytes) \
+ macro(underlyingByteSource) \
+ macro(underlyingSink) \
+ macro(underlyingSource) \
+ macro(writing) \
+ macro(Headers) \
+ macro(MediaStream) \
+ macro(MediaStreamTrack) \
+ macro(ReadableByteStreamController) \
+ macro(ReadableStream) \
+ macro(ReadableStreamDefaultController) \
+ macro(ReadableStreamDefaultReader) \
+ macro(Request) \
+ macro(Response) \
+ macro(RTCIceCandidate) \
+ macro(RTCSessionDescription) \
+ macro(XMLHttpRequest)
+
+class WebCoreBuiltinNames {
+public:
+ explicit WebCoreBuiltinNames(JSC::VM* vm)
+ : m_vm(*vm)
+ WEBCORE_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(INITIALIZE_BUILTIN_NAMES)
+ {
+#define EXPORT_NAME(name) m_vm.propertyNames->appendExternalName(name##PublicName(), name##PrivateName());
+ WEBCORE_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(EXPORT_NAME)
+#undef EXPORT_NAME
+ }
+
+ WEBCORE_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(DECLARE_BUILTIN_IDENTIFIER_ACCESSOR)
+
+private:
+ JSC::VM& m_vm;
+ WEBCORE_COMMON_PRIVATE_IDENTIFIERS_EACH_PROPERTY_NAME(DECLARE_BUILTIN_NAMES)
+};
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/WebCoreJSClientData.cpp b/Source/WebCore/bindings/js/WebCoreJSClientData.cpp
new file mode 100644
index 000000000..d87931f6e
--- /dev/null
+++ b/Source/WebCore/bindings/js/WebCoreJSClientData.cpp
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WebCoreJSClientData.h"
+
+#include "JSDOMBinding.h"
+#include <heap/HeapInlines.h>
+#include <heap/MarkingConstraint.h>
+#include <heap/MarkedAllocatorInlines.h>
+#include <heap/MarkedBlockInlines.h>
+#include <heap/SubspaceInlines.h>
+#include <heap/VisitingTimeout.h>
+#include <runtime/VM.h>
+#include <wtf/MainThread.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSVMClientData::JSVMClientData(VM& vm)
+ : m_builtinFunctions(vm)
+ , m_builtinNames(&vm)
+ , m_outputConstraintSpace("WebCore Wrapper w/ Output Constraint", vm.heap)
+ , m_globalObjectOutputConstraintSpace("WebCore Global Object w/ Output Constraint", vm.heap)
+{
+}
+
+JSVMClientData::~JSVMClientData()
+{
+ ASSERT(m_worldSet.contains(m_normalWorld.get()));
+ ASSERT(m_worldSet.size() == 1);
+ ASSERT(m_normalWorld->hasOneRef());
+ m_normalWorld = nullptr;
+ ASSERT(m_worldSet.isEmpty());
+}
+
+void JSVMClientData::getAllWorlds(Vector<Ref<DOMWrapperWorld>>& worlds)
+{
+ ASSERT(worlds.isEmpty());
+
+ worlds.reserveInitialCapacity(m_worldSet.size());
+ for (auto it = m_worldSet.begin(), end = m_worldSet.end(); it != end; ++it)
+ worlds.uncheckedAppend(*(*it));
+}
+
+void JSVMClientData::initNormalWorld(VM* vm)
+{
+ JSVMClientData* clientData = new JSVMClientData(*vm);
+ vm->clientData = clientData; // ~VM deletes this pointer.
+
+ auto constraint = std::make_unique<MarkingConstraint>(
+ "Wcoc", "WebCore Output Constraints",
+ [vm, clientData, lastExecutionVersion = vm->heap.mutatorExecutionVersion()]
+ (SlotVisitor& slotVisitor, const VisitingTimeout&) mutable {
+ Heap& heap = vm->heap;
+
+ if (heap.mutatorExecutionVersion() == lastExecutionVersion)
+ return;
+
+ lastExecutionVersion = heap.mutatorExecutionVersion();
+
+ // We have to manage the visit count here ourselves. We need to know that if this adds
+ // opaque roots then we cannot declare termination yet. The way we signal this to the
+ // constraint solver is by adding to the visit count.
+
+ size_t numOpaqueRootsBefore = heap.numOpaqueRoots();
+
+ // FIXME: Make this parallel!
+ unsigned numRevisited = 0;
+ clientData->forEachOutputConstraintSpace(
+ [&] (Subspace& subspace) {
+ subspace.forEachMarkedCell(
+ [&] (HeapCell* heapCell, HeapCell::Kind) {
+ JSCell* cell = static_cast<JSCell*>(heapCell);
+ cell->methodTable(*vm)->visitOutputConstraints(cell, slotVisitor);
+ numRevisited++;
+ });
+ });
+ if (Options::logGC())
+ dataLog("(", numRevisited, ")");
+
+ slotVisitor.mergeIfNecessary();
+
+ slotVisitor.addToVisitCount(heap.numOpaqueRoots() - numOpaqueRootsBefore);
+ },
+ ConstraintVolatility::SeldomGreyed);
+ vm->heap.addMarkingConstraint(WTFMove(constraint));
+
+ clientData->m_normalWorld = DOMWrapperWorld::create(*vm, true);
+ vm->m_typedArrayController = adoptRef(new WebCoreTypedArrayController());
+}
+
+} // namespace WebCore
+
diff --git a/Source/WebCore/bindings/js/WebCoreJSClientData.h b/Source/WebCore/bindings/js/WebCoreJSClientData.h
index 87e95de0f..47243c6de 100644
--- a/Source/WebCore/bindings/js/WebCoreJSClientData.h
+++ b/Source/WebCore/bindings/js/WebCoreJSClientData.h
@@ -1,6 +1,6 @@
/*
* Copyright (C) 1999-2001 Harri Porten (porten@kde.org)
- * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2003-2017 Apple Inc. All rights reserved.
* Copyright (C) 2007 Samuel Weinig <sam@webkit.org>
* Copyright (C) 2009 Google, Inc. All rights reserved.
*
@@ -19,46 +19,31 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef WebCoreJSClientData_h
-#define WebCoreJSClientData_h
+#pragma once
#include "DOMWrapperWorld.h"
-#include "DOMObjectHashTableMap.h"
+#include "WebCoreBuiltinNames.h"
+#include "WebCoreJSBuiltins.h"
#include "WebCoreTypedArrayController.h"
#include <wtf/HashSet.h>
#include <wtf/RefPtr.h>
namespace WebCore {
-class WebCoreJSClientData : public JSC::VM::ClientData {
- WTF_MAKE_NONCOPYABLE(WebCoreJSClientData); WTF_MAKE_FAST_ALLOCATED;
+class JSVMClientData : public JSC::VM::ClientData {
+ WTF_MAKE_NONCOPYABLE(JSVMClientData); WTF_MAKE_FAST_ALLOCATED;
friend class VMWorldIterator;
- friend void initNormalWorldClientData(JSC::VM*);
public:
- WebCoreJSClientData()
- {
- }
+ explicit JSVMClientData(JSC::VM&);
- virtual ~WebCoreJSClientData()
- {
- ASSERT(m_worldSet.contains(m_normalWorld.get()));
- ASSERT(m_worldSet.size() == 1);
- ASSERT(m_normalWorld->hasOneRef());
- m_normalWorld.clear();
- ASSERT(m_worldSet.isEmpty());
- }
+ virtual ~JSVMClientData();
+
+ WEBCORE_EXPORT static void initNormalWorld(JSC::VM*);
DOMWrapperWorld& normalWorld() { return *m_normalWorld; }
- void getAllWorlds(Vector<Ref<DOMWrapperWorld>>& worlds)
- {
- ASSERT(worlds.isEmpty());
-
- worlds.reserveInitialCapacity(m_worldSet.size());
- for (auto it = m_worldSet.begin(), end = m_worldSet.end(); it != end; ++it)
- worlds.uncheckedAppend(*(*it));
- }
+ void getAllWorlds(Vector<Ref<DOMWrapperWorld>>&);
void rememberWorld(DOMWrapperWorld& world)
{
@@ -72,21 +57,28 @@ public:
m_worldSet.remove(&world);
}
- DOMObjectHashTableMap hashTableMap;
+ WebCoreBuiltinNames& builtinNames() { return m_builtinNames; }
+ JSBuiltinFunctions& builtinFunctions() { return m_builtinFunctions; }
+
+ JSC::Subspace& outputConstraintSpace() { return m_outputConstraintSpace; }
+ JSC::Subspace& globalObjectOutputConstraintSpace() { return m_globalObjectOutputConstraintSpace; }
+
+ template<typename Func>
+ void forEachOutputConstraintSpace(const Func& func)
+ {
+ func(m_outputConstraintSpace);
+ func(m_globalObjectOutputConstraintSpace);
+ }
private:
HashSet<DOMWrapperWorld*> m_worldSet;
RefPtr<DOMWrapperWorld> m_normalWorld;
-};
-inline void initNormalWorldClientData(JSC::VM* vm)
-{
- WebCoreJSClientData* webCoreJSClientData = new WebCoreJSClientData;
- vm->clientData = webCoreJSClientData; // ~VM deletes this pointer.
- webCoreJSClientData->m_normalWorld = DOMWrapperWorld::create(vm, true);
- vm->m_typedArrayController = adoptRef(new WebCoreTypedArrayController());
-}
+ JSBuiltinFunctions m_builtinFunctions;
+ WebCoreBuiltinNames m_builtinNames;
+
+ JSC::JSDestructibleObjectSubspace m_outputConstraintSpace;
+ JSC::JSSegmentedVariableObjectSubspace m_globalObjectOutputConstraintSpace;
+};
} // namespace WebCore
-
-#endif // WebCoreJSClientData_h
diff --git a/Source/WebCore/bindings/js/WebCoreTypedArrayController.cpp b/Source/WebCore/bindings/js/WebCoreTypedArrayController.cpp
index 0db3d5237..a3c938518 100644
--- a/Source/WebCore/bindings/js/WebCoreTypedArrayController.cpp
+++ b/Source/WebCore/bindings/js/WebCoreTypedArrayController.cpp
@@ -26,11 +26,11 @@
#include "config.h"
#include "WebCoreTypedArrayController.h"
-#include "JSDOMBinding.h"
+#include "JSDOMConvertBufferSource.h"
#include "JSDOMGlobalObject.h"
#include <runtime/ArrayBuffer.h>
#include <runtime/JSArrayBuffer.h>
-#include <runtime/Operations.h>
+#include <runtime/JSCInlines.h>
namespace WebCore {
@@ -47,20 +47,26 @@ JSC::JSArrayBuffer* WebCoreTypedArrayController::toJS(JSC::ExecState* state, JSC
return JSC::jsCast<JSC::JSArrayBuffer*>(WebCore::toJS(state, JSC::jsCast<JSDOMGlobalObject*>(globalObject), buffer));
}
+void WebCoreTypedArrayController::registerWrapper(JSC::JSGlobalObject* globalObject, JSC::ArrayBuffer* native, JSC::JSArrayBuffer* wrapper)
+{
+ cacheWrapper(JSC::jsCast<JSDOMGlobalObject*>(globalObject)->world(), native, wrapper);
+}
+
+bool WebCoreTypedArrayController::isAtomicsWaitAllowedOnCurrentThread()
+{
+ return !isMainThread();
+}
+
bool WebCoreTypedArrayController::JSArrayBufferOwner::isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown> handle, void*, JSC::SlotVisitor& visitor)
{
- auto& wrapper = *JSC::jsCast<JSC::JSArrayBuffer*>(handle.get().asCell());
- if (!wrapper.hasCustomProperties())
- return false;
+ auto& wrapper = *JSC::jsCast<JSC::JSArrayBuffer*>(handle.slot()->asCell());
return visitor.containsOpaqueRoot(wrapper.impl());
}
void WebCoreTypedArrayController::JSArrayBufferOwner::finalize(JSC::Handle<JSC::Unknown> handle, void* context)
{
- auto& wrapper = *static_cast<JSC::JSArrayBuffer*>(handle.get().asCell());
- auto& buffer = *wrapper.impl();
- uncacheWrapper(*static_cast<DOMWrapperWorld*>(context), &buffer, &wrapper);
- buffer.deref();
+ auto& wrapper = *static_cast<JSC::JSArrayBuffer*>(handle.slot()->asCell());
+ uncacheWrapper(*static_cast<DOMWrapperWorld*>(context), wrapper.impl(), &wrapper);
}
} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/WebCoreTypedArrayController.h b/Source/WebCore/bindings/js/WebCoreTypedArrayController.h
index 23f3eb0f0..3bb94bc85 100644
--- a/Source/WebCore/bindings/js/WebCoreTypedArrayController.h
+++ b/Source/WebCore/bindings/js/WebCoreTypedArrayController.h
@@ -23,13 +23,15 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef WebCoreTypedArrayController_h
-#define WebCoreTypedArrayController_h
+#pragma once
-#include <heap/Weak.h>
#include <runtime/JSGlobalObject.h>
#include <runtime/TypedArrayController.h>
+namespace JSC {
+class WeakHandleOwner;
+}
+
namespace WebCore {
class WebCoreTypedArrayController : public JSC::TypedArrayController {
@@ -37,21 +39,20 @@ public:
WebCoreTypedArrayController();
virtual ~WebCoreTypedArrayController();
- virtual JSC::JSArrayBuffer* toJS(JSC::ExecState*, JSC::JSGlobalObject*, JSC::ArrayBuffer*) override;
-
+ JSC::JSArrayBuffer* toJS(JSC::ExecState*, JSC::JSGlobalObject*, JSC::ArrayBuffer*) override;
+ void registerWrapper(JSC::JSGlobalObject*, ArrayBuffer*, JSC::JSArrayBuffer*) override;
+ bool isAtomicsWaitAllowedOnCurrentThread() override;
+
JSC::WeakHandleOwner* wrapperOwner() { return &m_owner; }
private:
class JSArrayBufferOwner : public JSC::WeakHandleOwner {
public:
- virtual bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::SlotVisitor&) override;
- virtual void finalize(JSC::Handle<JSC::Unknown>, void* context) override;
+ bool isReachableFromOpaqueRoots(JSC::Handle<JSC::Unknown>, void* context, JSC::SlotVisitor&) override;
+ void finalize(JSC::Handle<JSC::Unknown>, void* context) override;
};
JSArrayBufferOwner m_owner;
};
} // namespace WebCore
-
-#endif // WebCoreTypedArrayController_h
-
diff --git a/Source/WebCore/bindings/js/WorkerScriptController.cpp b/Source/WebCore/bindings/js/WorkerScriptController.cpp
index 579a0b4af..230af90bd 100644
--- a/Source/WebCore/bindings/js/WorkerScriptController.cpp
+++ b/Source/WebCore/bindings/js/WorkerScriptController.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2016 Apple Inc. All Rights Reserved.
* Copyright (C) 2011, 2012 Google Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -11,18 +11,17 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
@@ -30,23 +29,18 @@
#include "JSDOMBinding.h"
#include "JSDedicatedWorkerGlobalScope.h"
+#include "JSEventTarget.h"
#include "ScriptSourceCode.h"
#include "WebCoreJSClientData.h"
+#include "WorkerConsoleClient.h"
#include "WorkerGlobalScope.h"
-#include "WorkerObjectProxy.h"
-#include "WorkerScriptDebugServer.h"
-#include "WorkerThread.h"
#include <bindings/ScriptValue.h>
#include <heap/StrongInlines.h>
-#include <interpreter/Interpreter.h>
#include <runtime/Completion.h>
+#include <runtime/Exception.h>
#include <runtime/ExceptionHelpers.h>
-#include <runtime/Error.h>
#include <runtime/JSLock.h>
-
-#if ENABLE(SHARED_WORKERS)
-#include "JSSharedWorkerGlobalScope.h"
-#endif
+#include <runtime/Watchdog.h>
using namespace JSC;
@@ -56,16 +50,21 @@ WorkerScriptController::WorkerScriptController(WorkerGlobalScope* workerGlobalSc
: m_vm(VM::create())
, m_workerGlobalScope(workerGlobalScope)
, m_workerGlobalScopeWrapper(*m_vm)
- , m_executionForbidden(false)
{
- initNormalWorldClientData(m_vm.get());
+ m_vm->heap.acquireAccess(); // It's not clear that we have good discipline for heap access, so turn it on permanently.
+ m_vm->ensureWatchdog();
+ JSVMClientData::initNormalWorld(m_vm.get());
}
WorkerScriptController::~WorkerScriptController()
{
JSLockHolder lock(vm());
+ if (m_workerGlobalScopeWrapper) {
+ m_workerGlobalScopeWrapper->setConsoleClient(nullptr);
+ m_consoleClient = nullptr;
+ }
m_workerGlobalScopeWrapper.clear();
- m_vm.clear();
+ m_vm = nullptr;
}
void WorkerScriptController::initScript()
@@ -77,35 +76,28 @@ void WorkerScriptController::initScript()
// Explicitly protect the global object's prototype so it isn't collected
// when we allocate the global object. (Once the global object is fully
// constructed, it can mark its own prototype.)
- Structure* workerGlobalScopePrototypeStructure = JSWorkerGlobalScopePrototype::createStructure(*m_vm, 0, jsNull());
- Strong<JSWorkerGlobalScopePrototype> workerGlobalScopePrototype(*m_vm, JSWorkerGlobalScopePrototype::create(*m_vm, 0, workerGlobalScopePrototypeStructure));
-
if (m_workerGlobalScope->isDedicatedWorkerGlobalScope()) {
- Structure* dedicatedContextPrototypeStructure = JSDedicatedWorkerGlobalScopePrototype::createStructure(*m_vm, 0, workerGlobalScopePrototype.get());
- Strong<JSDedicatedWorkerGlobalScopePrototype> dedicatedContextPrototype(*m_vm, JSDedicatedWorkerGlobalScopePrototype::create(*m_vm, 0, dedicatedContextPrototypeStructure));
- Structure* structure = JSDedicatedWorkerGlobalScope::createStructure(*m_vm, 0, dedicatedContextPrototype.get());
+ Structure* dedicatedContextPrototypeStructure = JSDedicatedWorkerGlobalScopePrototype::createStructure(*m_vm, nullptr, jsNull());
+ Strong<JSDedicatedWorkerGlobalScopePrototype> dedicatedContextPrototype(*m_vm, JSDedicatedWorkerGlobalScopePrototype::create(*m_vm, nullptr, dedicatedContextPrototypeStructure));
+ Structure* structure = JSDedicatedWorkerGlobalScope::createStructure(*m_vm, nullptr, dedicatedContextPrototype.get());
+ auto* proxyStructure = JSProxy::createStructure(*m_vm, nullptr, jsNull(), PureForwardingProxyType);
+ auto* proxy = JSProxy::create(*m_vm, proxyStructure);
- m_workerGlobalScopeWrapper.set(*m_vm, JSDedicatedWorkerGlobalScope::create(*m_vm, structure, static_cast<DedicatedWorkerGlobalScope*>(m_workerGlobalScope)));
- workerGlobalScopePrototypeStructure->setGlobalObject(*m_vm, m_workerGlobalScopeWrapper.get());
+ m_workerGlobalScopeWrapper.set(*m_vm, JSDedicatedWorkerGlobalScope::create(*m_vm, structure, static_cast<DedicatedWorkerGlobalScope&>(*m_workerGlobalScope), proxy));
dedicatedContextPrototypeStructure->setGlobalObject(*m_vm, m_workerGlobalScopeWrapper.get());
ASSERT(structure->globalObject() == m_workerGlobalScopeWrapper);
ASSERT(m_workerGlobalScopeWrapper->structure()->globalObject() == m_workerGlobalScopeWrapper);
- workerGlobalScopePrototype->structure()->setGlobalObject(*m_vm, m_workerGlobalScopeWrapper.get());
dedicatedContextPrototype->structure()->setGlobalObject(*m_vm, m_workerGlobalScopeWrapper.get());
-#if ENABLE(SHARED_WORKERS)
- } else {
- ASSERT(m_workerGlobalScope->isSharedWorkerGlobalScope());
- Structure* sharedContextPrototypeStructure = JSSharedWorkerGlobalScopePrototype::createStructure(*m_vm, 0, workerGlobalScopePrototype.get());
- Strong<JSSharedWorkerGlobalScopePrototype> sharedContextPrototype(*m_vm, JSSharedWorkerGlobalScopePrototype::create(*m_vm, 0, sharedContextPrototypeStructure));
- Structure* structure = JSSharedWorkerGlobalScope::createStructure(*m_vm, 0, sharedContextPrototype.get());
-
- m_workerGlobalScopeWrapper.set(*m_vm, JSSharedWorkerGlobalScope::create(*m_vm, structure, static_cast<SharedWorkerGlobalScope*>(m_workerGlobalScope)));
- workerGlobalScopePrototype->structure()->setGlobalObject(*m_vm, m_workerGlobalScopeWrapper.get());
- sharedContextPrototype->structure()->setGlobalObject(*m_vm, m_workerGlobalScopeWrapper.get());
-#endif
+ dedicatedContextPrototype->structure()->setPrototypeWithoutTransition(*m_vm, JSWorkerGlobalScope::prototype(*m_vm, m_workerGlobalScopeWrapper.get()));
+
+ proxy->setTarget(*m_vm, m_workerGlobalScopeWrapper.get());
+ proxy->structure()->setGlobalObject(*m_vm, m_workerGlobalScopeWrapper.get());
}
ASSERT(m_workerGlobalScopeWrapper->globalObject() == m_workerGlobalScopeWrapper);
- ASSERT(asObject(m_workerGlobalScopeWrapper->prototype())->globalObject() == m_workerGlobalScopeWrapper);
+ ASSERT(asObject(m_workerGlobalScopeWrapper->getPrototypeDirect())->globalObject() == m_workerGlobalScopeWrapper);
+
+ m_consoleClient = std::make_unique<WorkerConsoleClient>(*m_workerGlobalScope);
+ m_workerGlobalScopeWrapper->setConsoleClient(m_consoleClient.get());
}
void WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode)
@@ -113,15 +105,15 @@ void WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode)
if (isExecutionForbidden())
return;
- Deprecated::ScriptValue exception;
- evaluate(sourceCode, &exception);
- if (exception.jsValue()) {
+ NakedPtr<JSC::Exception> exception;
+ evaluate(sourceCode, exception);
+ if (exception) {
JSLockHolder lock(vm());
- reportException(m_workerGlobalScopeWrapper->globalExec(), exception.jsValue());
+ reportException(m_workerGlobalScopeWrapper->globalExec(), exception);
}
}
-void WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, Deprecated::ScriptValue* exception)
+void WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, NakedPtr<JSC::Exception>& returnedException)
{
if (isExecutionForbidden())
return;
@@ -129,47 +121,52 @@ void WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, Deprec
initScriptIfNeeded();
ExecState* exec = m_workerGlobalScopeWrapper->globalExec();
- JSLockHolder lock(exec);
+ VM& vm = exec->vm();
+ JSLockHolder lock(vm);
- JSValue evaluationException;
- JSC::evaluate(exec, sourceCode.jsSourceCode(), m_workerGlobalScopeWrapper.get(), &evaluationException);
+ JSC::evaluate(exec, sourceCode.jsSourceCode(), m_workerGlobalScopeWrapper->globalThis(), returnedException);
- if ((evaluationException && isTerminatedExecutionException(evaluationException)) || m_workerGlobalScopeWrapper->vm().watchdog.didFire()) {
+ if ((returnedException && isTerminatedExecutionException(vm, returnedException)) || isTerminatingExecution()) {
forbidExecution();
return;
}
- if (evaluationException) {
+ if (returnedException) {
String errorMessage;
int lineNumber = 0;
int columnNumber = 0;
String sourceURL = sourceCode.url().string();
- if (m_workerGlobalScope->sanitizeScriptError(errorMessage, lineNumber, columnNumber, sourceURL, sourceCode.cachedScript()))
- *exception = Deprecated::ScriptValue(*m_vm, exec->vm().throwException(exec, createError(exec, errorMessage.impl())));
- else
- *exception = Deprecated::ScriptValue(*m_vm, evaluationException);
+ JSC::Strong<JSC::Unknown> error;
+ if (m_workerGlobalScope->sanitizeScriptError(errorMessage, lineNumber, columnNumber, sourceURL, error, sourceCode.cachedScript()))
+ returnedException = JSC::Exception::create(vm, createError(exec, errorMessage.impl()));
}
}
-void WorkerScriptController::setException(const Deprecated::ScriptValue& exception)
+void WorkerScriptController::setException(JSC::Exception* exception)
{
- m_workerGlobalScopeWrapper->globalExec()->vm().throwException(m_workerGlobalScopeWrapper->globalExec(), exception.jsValue());
+ JSC::ExecState* exec = m_workerGlobalScopeWrapper->globalExec();
+ VM& vm = exec->vm();
+ auto scope = DECLARE_THROW_SCOPE(vm);
+ throwException(exec, scope, exception);
}
void WorkerScriptController::scheduleExecutionTermination()
{
// The mutex provides a memory barrier to ensure that once
- // termination is scheduled, isExecutionTerminating will
+ // termination is scheduled, isTerminatingExecution() will
// accurately reflect that state when called from another thread.
- MutexLocker locker(m_scheduledTerminationMutex);
- m_vm->watchdog.fire();
+ LockHolder locker(m_scheduledTerminationMutex);
+ m_isTerminatingExecution = true;
+
+ ASSERT(m_vm->watchdog());
+ m_vm->watchdog()->terminateSoon();
}
-bool WorkerScriptController::isExecutionTerminating() const
+bool WorkerScriptController::isTerminatingExecution() const
{
// See comments in scheduleExecutionTermination regarding mutex usage.
- MutexLocker locker(m_scheduledTerminationMutex);
- return m_vm->watchdog.didFire();
+ LockHolder locker(m_scheduledTerminationMutex);
+ return m_isTerminatingExecution;
}
void WorkerScriptController::forbidExecution()
@@ -192,6 +189,16 @@ void WorkerScriptController::disableEval(const String& errorMessage)
m_workerGlobalScopeWrapper->setEvalEnabled(false, errorMessage);
}
+void WorkerScriptController::releaseHeapAccess()
+{
+ m_vm->heap.releaseAccess();
+}
+
+void WorkerScriptController::acquireHeapAccess()
+{
+ m_vm->heap.acquireAccess();
+}
+
void WorkerScriptController::attachDebugger(JSC::Debugger* debugger)
{
initScriptIfNeeded();
diff --git a/Source/WebCore/bindings/js/WorkerScriptController.h b/Source/WebCore/bindings/js/WorkerScriptController.h
index 025c37d2c..460455208 100644
--- a/Source/WebCore/bindings/js/WorkerScriptController.h
+++ b/Source/WebCore/bindings/js/WorkerScriptController.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 Apple Inc. All Rights Reserved.
+ * Copyright (C) 2008, 2015, 2016 Apple Inc. All Rights Reserved.
* Copyright (C) 2012 Google Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -11,10 +11,10 @@
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
- * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
@@ -22,20 +22,15 @@
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
*/
-#ifndef WorkerScriptController_h
-#define WorkerScriptController_h
+#pragma once
#include <debugger/Debugger.h>
#include <heap/Strong.h>
#include <wtf/Forward.h>
-#include <wtf/Threading.h>
-
-namespace Deprecated {
-class ScriptValue;
-}
+#include <wtf/Lock.h>
+#include <wtf/NakedPtr.h>
namespace JSC {
class VM;
@@ -45,6 +40,7 @@ namespace WebCore {
class JSWorkerGlobalScope;
class ScriptSourceCode;
+ class WorkerConsoleClient;
class WorkerGlobalScope;
class WorkerScriptController {
@@ -60,9 +56,9 @@ namespace WebCore {
}
void evaluate(const ScriptSourceCode&);
- void evaluate(const ScriptSourceCode&, Deprecated::ScriptValue* exception);
+ void evaluate(const ScriptSourceCode&, NakedPtr<JSC::Exception>& returnedException);
- void setException(const Deprecated::ScriptValue&);
+ void setException(JSC::Exception*);
// Async request to terminate a JS run execution. Eventually causes termination
// exception raised during JS execution, if the worker thread happens to run JS.
@@ -70,7 +66,7 @@ namespace WebCore {
// forbidExecution()/isExecutionForbidden() to guard against reentry into JS.
// Can be called from any thread.
void scheduleExecutionTermination();
- bool isExecutionTerminating() const;
+ bool isTerminatingExecution() const;
// Called on Worker thread when JS exits with termination exception caused by forbidExecution() request,
// or by Worker thread termination code to prevent future entry into JS.
@@ -79,7 +75,10 @@ namespace WebCore {
void disableEval(const String& errorMessage);
- JSC::VM* vm() { return m_vm.get(); }
+ JSC::VM& vm() { return *m_vm; }
+
+ void releaseHeapAccess();
+ void acquireHeapAccess();
void attachDebugger(JSC::Debugger*);
void detachDebugger(JSC::Debugger*);
@@ -95,10 +94,10 @@ namespace WebCore {
RefPtr<JSC::VM> m_vm;
WorkerGlobalScope* m_workerGlobalScope;
JSC::Strong<JSWorkerGlobalScope> m_workerGlobalScopeWrapper;
- bool m_executionForbidden;
- mutable Mutex m_scheduledTerminationMutex;
+ std::unique_ptr<WorkerConsoleClient> m_consoleClient;
+ bool m_executionForbidden { false };
+ bool m_isTerminatingExecution { false };
+ mutable Lock m_scheduledTerminationMutex;
};
} // namespace WebCore
-
-#endif // WorkerScriptController_h
diff --git a/Source/WebCore/bindings/js/WorkerScriptDebugServer.cpp b/Source/WebCore/bindings/js/WorkerScriptDebugServer.cpp
deleted file mode 100644
index 76c95eebc..000000000
--- a/Source/WebCore/bindings/js/WorkerScriptDebugServer.cpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (c) 2011 Google Inc. All rights reserved.
- * Copyright (c) 2013 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "WorkerScriptDebugServer.h"
-
-#include "JSDOMBinding.h"
-#include "Timer.h"
-#include "WorkerDebuggerAgent.h"
-#include "WorkerGlobalScope.h"
-#include "WorkerRunLoop.h"
-#include "WorkerThread.h"
-#include <runtime/VM.h>
-#include <wtf/PassOwnPtr.h>
-
-using namespace Inspector;
-
-namespace WebCore {
-
-WorkerScriptDebugServer::WorkerScriptDebugServer(WorkerGlobalScope* context, const String& mode)
- : ScriptDebugServer(true)
- , m_workerGlobalScope(context)
- , m_debuggerTaskMode(mode)
-{
-}
-
-void WorkerScriptDebugServer::addListener(ScriptDebugListener* listener)
-{
- if (!listener)
- return;
-
- bool wasEmpty = m_listeners.isEmpty();
- m_listeners.add(listener);
-
- if (wasEmpty) {
- m_workerGlobalScope->script()->attachDebugger(this);
- recompileAllJSFunctions();
- }
-}
-
-void WorkerScriptDebugServer::removeListener(ScriptDebugListener* listener, bool skipRecompile)
-{
- if (!listener)
- return;
-
- m_listeners.remove(listener);
-
- if (m_listeners.isEmpty()) {
- m_workerGlobalScope->script()->detachDebugger(this);
- if (!skipRecompile)
- recompileAllJSFunctions();
- }
-}
-
-void WorkerScriptDebugServer::recompileAllJSFunctions()
-{
- JSC::VM* vm = m_workerGlobalScope->script()->vm();
-
- JSC::JSLockHolder lock(vm);
- JSC::Debugger::recompileAllJSFunctions(vm);
-}
-
-void WorkerScriptDebugServer::runEventLoopWhilePaused()
-{
- TimerBase::fireTimersInNestedEventLoop();
-
- MessageQueueWaitResult result;
- do {
- result = m_workerGlobalScope->thread()->runLoop().runInMode(m_workerGlobalScope, m_debuggerTaskMode);
- // Keep waiting until execution is resumed.
- } while (result != MessageQueueTerminated && !m_doneProcessingDebuggerEvents);
-}
-
-void WorkerScriptDebugServer::reportException(JSC::ExecState* exec, JSC::JSValue exception) const
-{
- WebCore::reportException(exec, exception);
-}
-
-void WorkerScriptDebugServer::interruptAndRunTask(PassOwnPtr<ScriptDebugServer::Task>)
-{
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/WorkerScriptDebugServer.h b/Source/WebCore/bindings/js/WorkerScriptDebugServer.h
deleted file mode 100644
index 78efd0bc7..000000000
--- a/Source/WebCore/bindings/js/WorkerScriptDebugServer.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 2011 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- * * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#ifndef WorkerScriptDebugServer_h
-#define WorkerScriptDebugServer_h
-
-#include <inspector/ScriptDebugServer.h>
-
-namespace WebCore {
-
-class WorkerGlobalScope;
-
-class WorkerScriptDebugServer final : public Inspector::ScriptDebugServer {
- WTF_MAKE_NONCOPYABLE(WorkerScriptDebugServer);
-public:
- WorkerScriptDebugServer(WorkerGlobalScope*, const String&);
- ~WorkerScriptDebugServer() { }
-
- virtual void recompileAllJSFunctions() override;
-
- void addListener(Inspector::ScriptDebugListener*);
- void removeListener(Inspector::ScriptDebugListener*, bool skipRecompile);
-
- void interruptAndRunTask(PassOwnPtr<ScriptDebugServer::Task>);
-
-private:
- virtual ListenerSet* getListenersForGlobalObject(JSC::JSGlobalObject*) override { return &m_listeners; }
- virtual void didPause(JSC::JSGlobalObject*) override { }
- virtual void didContinue(JSC::JSGlobalObject*) override { }
- virtual void runEventLoopWhilePaused() override;
- virtual bool isContentScript(JSC::ExecState*) const override { return false; }
- virtual void reportException(JSC::ExecState*, JSC::JSValue) const override;
-
- WorkerGlobalScope* m_workerGlobalScope;
- ListenerSet m_listeners;
- String m_debuggerTaskMode;
-};
-
-} // namespace WebCore
-
-#endif // WorkerScriptDebugServer_h