diff options
author | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-08 14:30:41 +0200 |
---|---|---|
committer | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-12 13:49:54 +0200 |
commit | ab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch) | |
tree | 498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/third_party/WebKit/Source/bindings | |
parent | 4ce69f7403811819800e7c5ae1318b2647e778d1 (diff) |
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca
Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/third_party/WebKit/Source/bindings')
335 files changed, 18697 insertions, 22464 deletions
diff --git a/chromium/third_party/WebKit/Source/bindings/BUILD.gn b/chromium/third_party/WebKit/Source/bindings/BUILD.gn new file mode 100644 index 00000000000..14c48c29542 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/BUILD.gn @@ -0,0 +1,105 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/WebKit/Source/bindings/bindings.gni") +import("//third_party/WebKit/Source/build/scripts/scripts.gni") +import("//third_party/WebKit/Source/core/core.gni") +import("//third_party/WebKit/Source/modules/modules.gni") + +visibility = "//third_party/WebKit/*" + +# Main interface IDL files (excluding dependencies and testing) +# are included as properties on global objects, and in aggregate bindings. +main_interface_idl_files = core_idl_files + modules_idl_files + +main_interface_idl_files_list = "$target_gen_dir/main_interface_idl_files.tmp" +write_file(main_interface_idl_files_list, + rebase_path(main_interface_idl_files, root_build_dir)) + +generated_global_constructors_idl_files = [ + "$blink_output_dir/WindowConstructors.idl", + "$blink_output_dir/SharedWorkerGlobalScopeConstructors.idl", + "$blink_output_dir/DedicatedWorkerGlobalScopeConstructors.idl", + "$blink_output_dir/ServiceWorkerGlobalScopeConstructors.idl", +] +generated_global_constructors_header_files = [ + "$blink_output_dir/WindowConstructors.h", + "$blink_output_dir/SharedWorkerGlobalScopeConstructors.h", + "$blink_output_dir/DedicatedWorkerGlobalScopeConstructors.h", + "$blink_output_dir/ServiceWorkerGlobalScopeConstructors.h", +] + +# FIXME: Generate separate core_global_objects +# http://crbug.com/358074 +# GYP version: generated.gyp:global_objects +action("global_objects") { + script = "scripts/compute_global_objects.py" + + source_prereqs = [ + "scripts/utilities.py", + # Only look in main IDL files (exclude dependencies and testing, + # which should not define global objects). + main_interface_idl_files_list, + ] + main_interface_idl_files + + outputs = [ + "$bindings_output_dir/GlobalObjects.pickle", + ] + + args = [ + "--idl-files-list", + rebase_path(main_interface_idl_files_list, root_build_dir), + "--write-file-only-if-changed=1", # Always true for Ninja. FIXME: remove + # when everything switched to GN. + "--", + rebase_path("$bindings_output_dir/GlobalObjects.pickle", root_build_dir), + ] +} + +# GYP version: generated.gyp:global_constructors_idls +action("global_constructors_idls") { + script = "scripts/generate_global_constructors.py" + + source_prereqs = [ + "scripts/generate_global_constructors.py", + "scripts/utilities.py", + "$bindings_output_dir/GlobalObjects.pickle", + # Only includes main IDL files (exclude dependencies and testing, + # which should not appear on global objects). + main_interface_idl_files_list, + ] + main_interface_idl_files + + outputs = generated_global_constructors_idl_files + + generated_global_constructors_header_files + + args = [ + "--idl-files-list", + rebase_path(main_interface_idl_files_list, root_build_dir), + "--global-objects-file", + rebase_path("$bindings_output_dir/GlobalObjects.pickle", root_build_dir), + "--write-file-only-if-changed=1", # Always true for Ninja. + "--", + "Window", + rebase_path("$blink_output_dir/WindowConstructors.idl", root_build_dir), + "SharedWorkerGlobalScope", + rebase_path("$blink_output_dir/SharedWorkerGlobalScopeConstructors.idl", + root_build_dir), + "DedicatedWorkerGlobalScope", + rebase_path("$blink_output_dir/DedicatedWorkerGlobalScopeConstructors.idl", + root_build_dir), + "ServiceWorkerGlobalScope", + rebase_path("$blink_output_dir/ServiceWorkerGlobalScopeConstructors.idl", + root_build_dir), + ] + + deps = [ ":global_objects" ] +} + +# GYP version: generated.gyp:generated_idls +group("generated_idls") { + deps = [ + ":global_constructors_idls", + "//third_party/WebKit/Source/core:generated_testing_idls", + ] +} diff --git a/chromium/third_party/WebKit/Source/bindings/IDLExtendedAttributes.txt b/chromium/third_party/WebKit/Source/bindings/IDLExtendedAttributes.txt index d361d4854d1..4d6bdca2849 100644 --- a/chromium/third_party/WebKit/Source/bindings/IDLExtendedAttributes.txt +++ b/chromium/third_party/WebKit/Source/bindings/IDLExtendedAttributes.txt @@ -25,7 +25,7 @@ # Note that including an empty value in the list, as in [Attr=X||Y], # is NOT valid: the value is optional, but empty values are not allowed. # - "Attr=*" means that Attr takes a required value, which can be -# arbitrary and combinations thereof, e.g. [Attr=IndexedDB], +# arbitrary, and combinations thereof, e.g. [Attr=IndexedDB], # [Attr=DeleteFunction], [Attr=X|Y]. # - "Attr=|*" means that Attr takes an optional value, which can be # arbitrary, e.g. [Attr], [Attr=X]. @@ -34,7 +34,6 @@ # ActiveDOMObject -ActivityLogging=ForAllWorlds|GetterForAllWorlds|SetterForAllWorlds|ForIsolatedWorlds|GetterForIsolatedWorlds|SetterForIsolatedWorlds CachedAttribute=* CallWith=ExecutionContext|ScriptState|ScriptArguments|ActiveWindow|FirstWindow|ThisValue CheckSecurity=Frame|Node @@ -44,11 +43,10 @@ Constructor # FIXME: remove [ConstructorCallWith=Document], as can instead use # [ConstructorCallWith=ExecutionContext] + toDocument(executionContext) ConstructorCallWith=ExecutionContext|Document -Custom=|Getter|Setter|LegacyCallAsFunction|ToV8|VisitDOMWrapper|Wrap +Custom=|Getter|Setter|LegacyCallAsFunction|ToV8|VisitDOMWrapper|Wrap|PropertyGetter|PropertyEnumerator|PropertyQuery CustomConstructor CustomElementCallbacks -CustomEnumerateProperty -Default=NullString|Undefined +Default=Undefined DependentLifetime DeprecateAs=* DoNotCheckConstants @@ -57,36 +55,47 @@ DoNotCheckSignature EnforceRange EventConstructor ExposeJSAccessors -GenerateVisitDOMWrapper=document|element|owner|ownerNode -GlobalContext=Window|WorkerGlobalScope|SharedWorkerGlobalScope|DedicatedWorkerGlobalScope|ServiceWorkerGlobalScope +Exposed=* +GarbageCollected +Global=|* Immutable ImplementedAs=* InitializedByEventConstructor -# FIXME: We should remove this extended attribute once the needed refactoring is complete. -LegacyImplementedInBaseClass +LegacyTreatAsPartialInterface +LogActivity=|GetterOnly|SetterOnly +LogAllWorlds +LogPreviousValue MeasureAs=* NamedConstructor=* NoInterfaceObject NotEnumerable OverrideBuiltins +PartialInterfaceImplementedAs=* # Valid values for [PerContextEnabled] are Context Features, in # ContextFeatures::FeatureType in Source/core/dom/ContextFeatures.h PerContextEnabled=* PerWorldBindings +PrimaryGlobal=|* PutForwards=* RaisesException=|Getter|Setter|Constructor ReadOnly Reflect=|* +ReflectEmpty=* +ReflectInvalid=* +ReflectMissing=* +ReflectOnly=* Replaceable # Valid values for [RuntimeEnabled] are the Runtime Enabled Features, listed in # Source/core/page/RuntimeEnabledFeatures.in RuntimeEnabled=* -SetReference=* -SetterCallWith=ExecutionContext|ScriptState|ScriptArguments|ActiveWindow|FirstWindow +SetWrapperReferenceFrom=* +SetWrapperReferenceTo=* +SetterCallWith=ExecutionContext|ScriptArguments|ActiveWindow|FirstWindow SpecialWrapFor=* -StrictTypeChecking -TreatNullAs=NullString|* +TreatNullAs=NullString TreatReturnedNullStringAs=Null|Undefined -TreatUndefinedAs=NullString|* +TreatUndefinedAs=NullString +TypeChecking=Interface|Nullable|Unrestricted URL Unforgeable +WillBeGarbageCollected diff --git a/chromium/third_party/WebKit/Source/bindings/OWNERS b/chromium/third_party/WebKit/Source/bindings/OWNERS index adf3dd03ebf..fa13cd3bd64 100644 --- a/chromium/third_party/WebKit/Source/bindings/OWNERS +++ b/chromium/third_party/WebKit/Source/bindings/OWNERS @@ -10,5 +10,6 @@ japhet@chromium.org jochen@chromium.org marja@chromium.org mkwst@chromium.org +nbarth@chromium.org pfeldman@chromium.org yurys@chromium.org diff --git a/chromium/third_party/WebKit/Source/bindings/PRESUBMIT.py b/chromium/third_party/WebKit/Source/bindings/PRESUBMIT.py index dc3cc1f57a9..605322d3dd3 100644 --- a/chromium/third_party/WebKit/Source/bindings/PRESUBMIT.py +++ b/chromium/third_party/WebKit/Source/bindings/PRESUBMIT.py @@ -32,8 +32,17 @@ See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for more details about the presubmit API built into gcl. """ +# Changes to v8/ do not change generated code or tests, so exclude from +# _RunBindingsTests +BLACK_LIST = (r'.*\bv8[\\\/].*',) def _RunBindingsTests(input_api, output_api): + # Skip if nothing to do + source_filter = lambda x: input_api.FilterSourceFile( + x, black_list=input_api.DEFAULT_BLACK_LIST + BLACK_LIST) + if not input_api.AffectedFiles(file_filter=source_filter): + return [] + if input_api.is_committing: message_type = output_api.PresubmitError else: diff --git a/chromium/third_party/WebKit/Source/bindings/__init__.py b/chromium/third_party/WebKit/Source/bindings/__init__.py new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/__init__.py diff --git a/chromium/third_party/WebKit/Source/bindings/bindings.gni b/chromium/third_party/WebKit/Source/bindings/bindings.gni new file mode 100644 index 00000000000..73b987df4f3 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/bindings.gni @@ -0,0 +1,51 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# All paths in this file should be absolute so it can be imported into +# different contexts. + +# v8/custom/custom.gypi -------------------------------------------------------- + +# These paths are relative to v8/custom. +_v8_custom_gypi = exec_script( + "//build/gypi_to_gn.py", + [ rebase_path("v8/custom/custom.gypi") ], + "scope", + [ "v8/custom/custom.gypi" ]) + +bindings_v8_custom_dir = get_path_info("v8/custom", "abspath") +bindings_v8_custom_files = get_path_info( + rebase_path(_v8_custom_gypi.bindings_v8_custom_files, ".", + bindings_v8_custom_dir), + "abspath") + +# v8/v8.gypi ------------------------------------------------------------------- + +# These paths are relative to v8. +_v8_gypi = exec_script( + "//build/gypi_to_gn.py", + [ rebase_path("v8/v8.gypi") ], + "scope", + [ "v8/v8.gypi" ]) + +bindings_v8_dir = get_path_info("v8", "abspath") + +# v8.gypi references includes a reference to the custom_files list. Manually +# expand that. +_rel_bindings_v8_files = _v8_gypi.bindings_v8_files +_rel_bindings_v8_files -= [ "<@(bindings_v8_custom_files)" ] +bindings_v8_files = get_path_info( + rebase_path(_rel_bindings_v8_files, ".", "v8"), + "abspath") +bindings_v8_files += bindings_v8_custom_files + +# bindings.gypi ---------------------------------------------------------------- + +bindings_dir = get_path_info(".", "abspath") +blink_output_dir = "$root_gen_dir/blink" +bindings_output_dir = "$root_gen_dir/blink/bindings" + +bindings_unittest_files = get_path_info( + rebase_path(_v8_gypi.bindings_v8_unittest_files, ".", bindings_v8_dir), + "abspath") diff --git a/chromium/third_party/WebKit/Source/bindings/bindings.gypi b/chromium/third_party/WebKit/Source/bindings/bindings.gypi index 78b7a9bb640..354b185c083 100644 --- a/chromium/third_party/WebKit/Source/bindings/bindings.gypi +++ b/chromium/third_party/WebKit/Source/bindings/bindings.gypi @@ -1,280 +1,15 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + { + 'includes': [ + 'v8/v8.gypi', + ], 'variables': { - 'bindings_dir': ['.'], - 'bindings_files': [ - 'v8/ActiveDOMCallback.cpp', - 'v8/ActiveDOMCallback.h', - 'v8/ArrayValue.cpp', - 'v8/ArrayValue.h', - 'v8/BindingSecurity.cpp', - 'v8/BindingSecurity.h', - 'v8/CallbackPromiseAdapter.h', - 'v8/CustomElementBinding.cpp', - 'v8/CustomElementBinding.h', - 'v8/CustomElementConstructorBuilder.cpp', - 'v8/CustomElementConstructorBuilder.h', - 'v8/CustomElementWrapper.cpp', - 'v8/CustomElementWrapper.h', - 'v8/DOMDataStore.cpp', - 'v8/DOMDataStore.h', - 'v8/DOMRequestState.h', - 'v8/DOMWrapperMap.h', - 'v8/DOMWrapperWorld.cpp', - 'v8/DOMWrapperWorld.h', - 'v8/Dictionary.cpp', - 'v8/Dictionary.h', - 'v8/ExceptionMessages.h', - 'v8/ExceptionMessages.cpp', - 'v8/ExceptionState.h', - 'v8/ExceptionState.cpp', - 'v8/ExceptionStatePlaceholder.h', - 'v8/ExceptionStatePlaceholder.cpp', - 'v8/IDBBindingUtilities.cpp', - 'v8/IDBBindingUtilities.h', - 'v8/NPV8Object.cpp', - 'v8/NPV8Object.h', - 'v8/PageScriptDebugServer.cpp', - 'v8/PageScriptDebugServer.h', - 'v8/RetainedDOMInfo.cpp', - 'v8/RetainedDOMInfo.h', - 'v8/RetainedObjectInfo.h', - 'v8/ScheduledAction.cpp', - 'v8/ScheduledAction.h', - 'v8/ScopedPersistent.h', - 'v8/ScriptCallStackFactory.cpp', - 'v8/ScriptCallStackFactory.h', - 'v8/ScriptController.cpp', - 'v8/ScriptController.h', - 'v8/ScriptDebugServer.cpp', - 'v8/ScriptDebugServer.h', - 'v8/ScriptEventListener.cpp', - 'v8/ScriptEventListener.h', - 'v8/ScriptFunctionCall.cpp', - 'v8/ScriptFunctionCall.h', - 'v8/ScriptGCEvent.cpp', - 'v8/ScriptGCEvent.h', - 'v8/ScriptHeapSnapshot.cpp', - 'v8/ScriptHeapSnapshot.h', - 'v8/ScriptObject.cpp', - 'v8/ScriptObject.h', - 'v8/ScriptPreprocessor.cpp', - 'v8/ScriptPreprocessor.h', - 'v8/ScriptProfiler.cpp', - 'v8/ScriptProfiler.h', - 'v8/ScriptPromise.cpp', - 'v8/ScriptPromise.h', - 'v8/ScriptPromiseResolver.cpp', - 'v8/ScriptPromiseResolver.h', - 'v8/ScriptRegexp.cpp', - 'v8/ScriptRegexp.h', - 'v8/ScriptScope.cpp', - 'v8/ScriptScope.h', - 'v8/ScriptSourceCode.h', - 'v8/ScriptState.cpp', - 'v8/ScriptState.h', - 'v8/ScriptString.cpp', - 'v8/ScriptString.h', - 'v8/ScriptValue.cpp', - 'v8/ScriptValue.h', - 'v8/ScriptWrappable.h', - 'v8/SerializedScriptValue.cpp', - 'v8/SerializedScriptValue.h', - 'v8/SharedPersistent.h', - 'v8/UnsafePersistent.h', - 'v8/V8AbstractEventListener.cpp', - 'v8/V8AbstractEventListener.h', - 'v8/V8Binding.cpp', - 'v8/V8Binding.h', - 'v8/V8BindingMacros.h', - 'v8/V8Callback.cpp', - 'v8/V8Callback.h', - 'v8/V8CustomElementLifecycleCallbacks.cpp', - 'v8/V8CustomElementLifecycleCallbacks.h', - 'v8/V8DOMActivityLogger.h', - 'v8/V8DOMConfiguration.cpp', - 'v8/V8DOMConfiguration.h', - 'v8/V8ErrorHandler.cpp', - 'v8/V8ErrorHandler.h', - 'v8/V8DOMWrapper.cpp', - 'v8/V8DOMWrapper.h', - 'v8/V8EventListener.cpp', - 'v8/V8EventListener.h', - 'v8/V8EventListenerList.cpp', - 'v8/V8EventListenerList.h', - 'v8/V8GCController.cpp', - 'v8/V8GCController.h', - 'v8/V8GCForContextDispose.cpp', - 'v8/V8GCForContextDispose.h', - 'v8/V8HiddenPropertyName.cpp', - 'v8/V8HiddenPropertyName.h', - 'v8/V8Initializer.cpp', - 'v8/V8Initializer.h', - 'v8/V8LazyEventListener.cpp', - 'v8/V8LazyEventListener.h', - 'v8/V8MutationCallback.cpp', - 'v8/V8MutationCallback.h', - 'v8/V8NPObject.cpp', - 'v8/V8NPObject.h', - 'v8/V8NPUtils.cpp', - 'v8/V8NPUtils.h', - 'v8/V8NodeFilterCondition.cpp', - 'v8/V8NodeFilterCondition.h', - 'v8/V8ObjectConstructor.cpp', - 'v8/V8ObjectConstructor.h', - 'v8/V8PerContextData.cpp', - 'v8/V8PerContextData.h', - 'v8/V8PerIsolateData.cpp', - 'v8/V8PerIsolateData.h', - 'v8/V8RecursionScope.cpp', - 'v8/V8RecursionScope.h', - 'v8/V8ScriptRunner.cpp', - 'v8/V8ScriptRunner.h', - 'v8/V8StringResource.cpp', - 'v8/V8StringResource.h', - 'v8/V8ThrowException.cpp', - 'v8/V8ThrowException.h', - 'v8/V8Utilities.cpp', - 'v8/V8Utilities.h', - 'v8/V8ValueCache.cpp', - 'v8/V8ValueCache.h', - 'v8/V8WindowShell.cpp', - 'v8/V8WindowShell.h', - 'v8/V8WorkerGlobalScopeEventListener.cpp', - 'v8/V8WorkerGlobalScopeEventListener.h', - 'v8/WorkerScriptController.cpp', - 'v8/WorkerScriptController.h', - 'v8/WorkerScriptDebugServer.cpp', - 'v8/WorkerScriptDebugServer.h', - 'v8/WrapperTypeInfo.h', - 'v8/custom/V8AlgorithmCustom.cpp', - 'v8/custom/V8ArrayBufferCustom.cpp', - 'v8/custom/V8ArrayBufferCustom.h', - 'v8/custom/V8ArrayBufferViewCustom.cpp', - 'v8/custom/V8ArrayBufferViewCustom.h', - 'v8/custom/V8AudioNodeCustom.cpp', - 'v8/custom/V8BiquadFilterNodeCustom.cpp', - 'v8/custom/V8BlobCustom.cpp', - 'v8/custom/V8BlobCustomHelpers.cpp', - 'v8/custom/V8BlobCustomHelpers.h', - 'v8/custom/V8CSSRuleCustom.cpp', - 'v8/custom/V8CSSStyleDeclarationCustom.cpp', - 'v8/custom/V8CSSValueCustom.cpp', - 'v8/custom/V8CanvasRenderingContext2DCustom.cpp', - 'v8/custom/V8CanvasRenderingContextCustom.cpp', - 'v8/custom/V8CryptoCustom.cpp', - 'v8/custom/V8CustomEventCustom.cpp', - 'v8/custom/V8CustomSQLStatementErrorCallback.cpp', - 'v8/custom/V8CustomXPathNSResolver.cpp', - 'v8/custom/V8CustomXPathNSResolver.h', - 'v8/custom/V8DataViewCustom.cpp', - 'v8/custom/V8DataViewCustom.h', - 'v8/custom/V8DedicatedWorkerGlobalScopeCustom.cpp', - 'v8/custom/V8DeviceMotionEventCustom.cpp', - 'v8/custom/V8DeviceOrientationEventCustom.cpp', - 'v8/custom/V8DocumentCustom.cpp', - 'v8/custom/V8EntryCustom.cpp', - 'v8/custom/V8EntrySyncCustom.cpp', - 'v8/custom/V8EventCustom.cpp', - 'v8/custom/V8EventTargetCustom.cpp', - 'v8/custom/V8ErrorEventCustom.cpp', - 'v8/custom/V8FileCustom.cpp', - 'v8/custom/V8FileReaderCustom.cpp', - 'v8/custom/V8Float32ArrayCustom.h', - 'v8/custom/V8Float64ArrayCustom.h', - 'v8/custom/V8FormDataCustom.cpp', - 'v8/custom/V8GeolocationCustom.cpp', - 'v8/custom/V8HTMLAllCollectionCustom.cpp', - 'v8/custom/V8HTMLCanvasElementCustom.cpp', - 'v8/custom/V8HTMLCollectionCustom.cpp', - 'v8/custom/V8HTMLDocumentCustom.cpp', - 'v8/custom/V8HTMLElementCustom.cpp', - 'v8/custom/V8HTMLFormControlsCollectionCustom.cpp', - 'v8/custom/V8HTMLFrameElementCustom.cpp', - 'v8/custom/V8HTMLOptionsCollectionCustom.cpp', - 'v8/custom/V8HTMLPlugInElementCustom.cpp', - 'v8/custom/V8HistoryCustom.cpp', - 'v8/custom/V8ImageDataCustom.cpp', - 'v8/custom/V8InjectedScriptHostCustom.cpp', - 'v8/custom/V8InjectedScriptManager.cpp', - 'v8/custom/V8InspectorFrontendHostCustom.cpp', - 'v8/custom/V8Int8ArrayCustom.h', - 'v8/custom/V8Int16ArrayCustom.h', - 'v8/custom/V8Int32ArrayCustom.h', - 'v8/custom/V8JavaScriptCallFrameCustom.cpp', - 'v8/custom/V8LocationCustom.cpp', - 'v8/custom/V8MIDIInputCustom.cpp', - 'v8/custom/V8MIDIOutputCustom.cpp', - 'v8/custom/V8MessageChannelCustom.cpp', - 'v8/custom/V8MessageEventCustom.cpp', - 'v8/custom/V8MessagePortCustom.cpp', - 'v8/custom/V8MutationObserverCustom.cpp', - 'v8/custom/V8NodeCustom.cpp', - 'v8/custom/V8NodeListCustom.cpp', - 'v8/custom/V8OscillatorNodeCustom.cpp', - 'v8/custom/V8PannerNodeCustom.cpp', - 'v8/custom/V8PerformanceEntryCustom.cpp', - 'v8/custom/V8PopStateEventCustom.cpp', - 'v8/custom/V8PromiseCustom.cpp', - 'v8/custom/V8SQLResultSetRowListCustom.cpp', - 'v8/custom/V8SQLTransactionCustom.cpp', - 'v8/custom/V8SQLTransactionSyncCustom.cpp', - 'v8/custom/V8SVGElementCustom.cpp', - 'v8/custom/V8SVGLengthCustom.cpp', - 'v8/custom/V8SVGPathSegCustom.cpp', - 'v8/custom/V8StyleSheetCustom.cpp', - 'v8/custom/V8TextCustom.cpp', - 'v8/custom/V8TextTrackCueCustom.cpp', - 'v8/custom/V8TrackEventCustom.cpp', - 'v8/custom/V8TypedArrayCustom.h', - 'v8/custom/V8Uint8ArrayCustom.h', - 'v8/custom/V8Uint8ClampedArrayCustom.h', - 'v8/custom/V8Uint16ArrayCustom.h', - 'v8/custom/V8Uint32ArrayCustom.h', - 'v8/custom/V8WebGLRenderingContextCustom.cpp', - 'v8/custom/V8WebKitPointCustom.cpp', - 'v8/custom/V8WindowCustom.cpp', - 'v8/custom/V8WorkerGlobalScopeCustom.cpp', - 'v8/custom/V8WorkerCryptoCustom.cpp', - 'v8/custom/V8WorkerCustom.cpp', - 'v8/custom/V8XMLHttpRequestCustom.cpp', - 'v8/custom/V8XSLTProcessorCustom.cpp', - 'v8/npruntime.cpp', - 'v8/npruntime_impl.h', - 'v8/npruntime_priv.h', - ], + 'bindings_dir': '.', 'bindings_unittest_files': [ - 'v8/IDBBindingUtilitiesTest.cpp', - 'v8/ScriptPromiseResolverTest.cpp', - ], - 'conditions': [ - ['OS=="win" and buildtype=="Official"', { - # On windows official release builds, we try to preserve symbol space. - 'derived_sources_aggregate_files': [ - '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/V8DerivedSourcesAll.cpp', - ], - },{ - 'derived_sources_aggregate_files': [ - '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/V8DerivedSources01.cpp', - '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/V8DerivedSources02.cpp', - '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/V8DerivedSources03.cpp', - '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/V8DerivedSources04.cpp', - '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/V8DerivedSources05.cpp', - '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/V8DerivedSources06.cpp', - '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/V8DerivedSources07.cpp', - '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/V8DerivedSources08.cpp', - '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/V8DerivedSources09.cpp', - '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/V8DerivedSources10.cpp', - '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/V8DerivedSources11.cpp', - '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/V8DerivedSources12.cpp', - '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/V8DerivedSources13.cpp', - '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/V8DerivedSources14.cpp', - '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/V8DerivedSources15.cpp', - '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/V8DerivedSources16.cpp', - '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/V8DerivedSources17.cpp', - '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/V8DerivedSources18.cpp', - '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/V8DerivedSources19.cpp', - ], - }], + '<@(bindings_v8_unittest_files)', ], }, } diff --git a/chromium/third_party/WebKit/Source/bindings/core/BUILD.gn b/chromium/third_party/WebKit/Source/bindings/core/BUILD.gn new file mode 100644 index 00000000000..3f85f3c7fd6 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/core/BUILD.gn @@ -0,0 +1,18 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/WebKit/Source/bindings/core/core.gni") +import("//third_party/WebKit/Source/bindings/core/idl.gni") +import("//third_party/WebKit/Source/bindings/scripts/scripts.gni") + +visibility = "//third_party/WebKit/*" + +# GYP version: Source/bindings/core/generated.gyp:interfaces_info_individual_core +compute_interfaces_info_individual("interfaces_info_individual_core") { + sources_static = core_static_idl_files + sources_generated = core_generated_idl_files + component_dir = "core" + output_file = + "$bindings_core_output_dir/InterfacesInfoCoreIndividual.pickle" +} diff --git a/chromium/third_party/WebKit/Source/bindings/core/core.gni b/chromium/third_party/WebKit/Source/bindings/core/core.gni new file mode 100644 index 00000000000..8cfaf086e26 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/core/core.gni @@ -0,0 +1,8 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# FIXME: factor out bindings_core http://crbug.com/358074 +import("//third_party/WebKit/Source/bindings/bindings.gni") + +bindings_core_output_dir = "$bindings_output_dir/core" diff --git a/chromium/third_party/WebKit/Source/bindings/core/core.gypi b/chromium/third_party/WebKit/Source/bindings/core/core.gypi new file mode 100644 index 00000000000..5e36cb5386b --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/core/core.gypi @@ -0,0 +1,15 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'includes': [ + '../modules/v8/generated.gypi', # FIXME: remove once core scripts generate qualified includes correctly: http://crbug.com/358074 + '../v8/v8.gypi', # FIXME: should be v8/v8.gypi: http://crbug.com/358074 + 'v8/generated.gypi', + ], + + 'variables': { + 'bindings_core_output_dir': '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/core', + }, +} diff --git a/chromium/third_party/WebKit/Source/bindings/core/generated.gyp b/chromium/third_party/WebKit/Source/bindings/core/generated.gyp new file mode 100644 index 00000000000..2492486fe30 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/core/generated.gyp @@ -0,0 +1,72 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Generate IDL interfaces info for core, used to generate bindings +# +# Design doc: http://www.chromium.org/developers/design-documents/idl-build + +{ + 'includes': [ + # ../.. == Source + '../../bindings/scripts/scripts.gypi', + '../../core/core.gypi', + 'core.gypi', + 'generated.gypi', + 'idl.gypi', + ], + + 'targets': [ +################################################################################ + { + 'target_name': 'core_global_objects', + 'variables': { + 'idl_files': '<(core_idl_files)', + 'output_file': '<(bindings_core_output_dir)/GlobalObjectsCore.pickle', + }, + 'includes': ['../../bindings/scripts/global_objects.gypi'], + }, +################################################################################ + { + 'target_name': 'core_global_constructors_idls', + 'dependencies': [ + 'core_global_objects', + ], + 'variables': { + 'idl_files': '<(core_idl_files)', + 'global_objects_file': + '<(bindings_core_output_dir)/GlobalObjectsCore.pickle', + 'global_names_idl_files': [ + 'Window', + '<(blink_core_output_dir)/WindowCoreConstructors.idl', + 'SharedWorkerGlobalScope', + '<(blink_core_output_dir)/SharedWorkerGlobalScopeCoreConstructors.idl', + 'DedicatedWorkerGlobalScope', + '<(blink_core_output_dir)/DedicatedWorkerGlobalScopeCoreConstructors.idl', + ], + 'outputs': [ + '<@(core_global_constructors_generated_idl_files)', + '<@(core_global_constructors_generated_header_files)', + ], + }, + 'includes': ['../../bindings/scripts/global_constructors.gypi'], + }, +################################################################################ + { + 'target_name': 'interfaces_info_individual_core', + 'dependencies': [ + '../../core/core_generated.gyp:generated_testing_idls', + 'core_global_constructors_idls', + ], + 'variables': { + 'static_idl_files': '<(core_static_idl_files)', + 'generated_idl_files': '<(core_generated_idl_files)', + 'component_dir': 'core', + 'output_file': + '<(bindings_core_output_dir)/InterfacesInfoCoreIndividual.pickle', + }, + 'includes': ['../../bindings/scripts/interfaces_info_individual.gypi'], + }, +################################################################################ + ], # targets +} diff --git a/chromium/third_party/WebKit/Source/bindings/core/generated.gypi b/chromium/third_party/WebKit/Source/bindings/core/generated.gypi new file mode 100644 index 00000000000..e3d457b66a9 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/core/generated.gypi @@ -0,0 +1,24 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'includes': [ + '../../core/core_generated.gypi', + ], + + 'variables': { + # Global constructors + 'core_global_constructors_generated_idl_files': [ + '<(blink_core_output_dir)/WindowCoreConstructors.idl', + '<(blink_core_output_dir)/SharedWorkerGlobalScopeCoreConstructors.idl', + '<(blink_core_output_dir)/DedicatedWorkerGlobalScopeCoreConstructors.idl', + ], + + 'core_global_constructors_generated_header_files': [ + '<(blink_core_output_dir)/WindowCoreConstructors.h', + '<(blink_core_output_dir)/SharedWorkerGlobalScopeCoreConstructors.h', + '<(blink_core_output_dir)/DedicatedWorkerGlobalScopeCoreConstructors.h', + ], + }, +} diff --git a/chromium/third_party/WebKit/Source/bindings/core/idl.gni b/chromium/third_party/WebKit/Source/bindings/core/idl.gni new file mode 100644 index 00000000000..39cb5fff5ad --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/core/idl.gni @@ -0,0 +1,57 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/WebKit/Source/bindings/idl.gni") +import("//third_party/WebKit/Source/core/core.gni") + +# Don't actually read idl.gypi since that just defines variables in terms of +# others, which gypi_to_gn doesn't handle. + +# IDL file lists; see: http://www.chromium.org/developers/web-idl-interfaces +# Interface IDL files: generate individual bindings (includes testing) +core_interface_idl_files = + core_idl_files + + webcore_testing_idl_files + + generated_webcore_testing_idl_files + +# Static IDL files +core_static_interface_idl_files = + core_idl_files + + webcore_testing_idl_files +core_static_dependency_idl_files = + core_dependency_idl_files + +# Generated IDL files +core_generated_interface_idl_files = + generated_webcore_testing_idl_files # interfaces +core_generated_dependency_idl_files = + # FIXME: Generate separate core_global_constructors_idls + # http://crbug.com/358074 + generated_global_constructors_idl_files # partial interfaces + +# Static IDL files / Generated IDL files +# +# In GYP, paths need to be passed separately for static and generated files, as +# static files are listed in a temporary file (b/c too long for command line), +# but generated files must be passed at the command line, as their paths are +# not fixed at GYP time, when the temporary file is generated, because their +# paths depend on the build directory, which varies. +# +# FIXME: GN does not have this restriction and we can combine them. While GYP +# is still supported, we match its behavior for easier maintenance but this can +# be simplified. +core_static_idl_files = + core_static_interface_idl_files + + core_static_dependency_idl_files +core_generated_idl_files = + core_generated_interface_idl_files + + core_generated_dependency_idl_files + +# Dependency IDL files: don't generate individual bindings, but do process +# in IDL dependency computation, and count as build dependencies +# 'core_dependency_idl_files' is already used in Source/core, so avoid +# collision +core_all_dependency_idl_files = + core_static_dependency_idl_files + + core_generated_dependency_idl_files diff --git a/chromium/third_party/WebKit/Source/bindings/core/idl.gypi b/chromium/third_party/WebKit/Source/bindings/core/idl.gypi new file mode 100644 index 00000000000..b4d1842b90d --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/core/idl.gypi @@ -0,0 +1,71 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# IDL file lists; see: http://www.chromium.org/developers/web-idl-interfaces + +{ + 'includes': [ + '../../core/core.gypi', + 'generated.gypi', + ], + + 'variables': { + # IDL file lists; see: http://www.chromium.org/developers/web-idl-interfaces + # Interface IDL files: generate individual bindings (includes testing) + 'core_interface_idl_files': [ + '<@(core_idl_files)', + '<@(webcore_testing_idl_files)', + '<@(generated_webcore_testing_idl_files)', + ], + + # Write lists of main IDL files to a file, so that the command lines don't + # exceed OS length limits. + 'core_idl_files_list': '<|(core_idl_files_list.tmp <@(core_idl_files))', + + # Dependency IDL files: don't generate individual bindings, but do process + # in IDL dependency computation, and count as build dependencies + # 'core_dependency_idl_files' is already used in Source/core, so avoid + # collision + 'core_all_dependency_idl_files': [ + '<@(core_static_dependency_idl_files)', + '<@(core_generated_dependency_idl_files)', + ], + + # Static IDL files / Generated IDL files + # Paths need to be passed separately for static and generated files, as + # static files are listed in a temporary file (b/c too long for command + # line), but generated files must be passed at the command line, as their + # paths are not fixed at GYP time, when the temporary file is generated, + # because their paths depend on the build directory, which varies. + 'core_static_idl_files': [ + '<@(core_static_interface_idl_files)', + '<@(core_static_dependency_idl_files)', + ], + 'core_static_idl_files_list': + '<|(core_static_idl_files_list.tmp <@(core_static_idl_files))', + + 'core_generated_idl_files': [ + '<@(core_generated_interface_idl_files)', + '<@(core_generated_dependency_idl_files)', + ], + + # Static IDL files + 'core_static_interface_idl_files': [ + '<@(core_idl_files)', + '<@(webcore_testing_idl_files)', + ], + 'core_static_dependency_idl_files': [ + '<@(core_dependency_idl_files)', + ], + + # Generated IDL files + 'core_generated_interface_idl_files': [ + '<@(generated_webcore_testing_idl_files)', # interfaces + ], + + 'core_generated_dependency_idl_files': [ + '<@(core_global_constructors_generated_idl_files)', # partial interfaces + ], + }, +} diff --git a/chromium/third_party/WebKit/Source/bindings/core/v8/BUILD.gn b/chromium/third_party/WebKit/Source/bindings/core/v8/BUILD.gn new file mode 100644 index 00000000000..6223986ca19 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/core/v8/BUILD.gn @@ -0,0 +1,32 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/WebKit/Source/bindings/core/idl.gni") + +import("//third_party/WebKit/Source/bindings/core/v8/generated.gni") +import("//third_party/WebKit/Source/bindings/scripts/scripts.gni") +import("//third_party/WebKit/Source/core/core.gni") + +visibility = "//third_party/WebKit/Source/*" + +# bindings_core_v8_generated in core/v8/generated.gyp +group("bindings_core_v8_generated") { + deps = [ + ":bindings_core_v8_generated_aggregate", + ":bindings_core_v8_generated_individual", + ] +} + +# bindings_core_generated_aggregate in core/v8/generated.gyp +aggregate_generated_bindings("bindings_core_v8_generated_aggregate") { + sources = core_idl_files + component_dir = "core" + outputs = bindings_core_generated_aggregate_files +} + +# bindings_core_v8_generated_individual in core/v8/generated.gyp +idl_compiler("bindings_core_v8_generated_individual") { + sources = core_interface_idl_files + output_dir = bindings_core_v8_output_dir +} diff --git a/chromium/third_party/WebKit/Source/bindings/core/v8/generated.gni b/chromium/third_party/WebKit/Source/bindings/core/v8/generated.gni new file mode 100644 index 00000000000..516022d1c91 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/core/v8/generated.gni @@ -0,0 +1,35 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/WebKit/Source/bindings/bindings.gni") + +bindings_core_v8_output_dir = "$bindings_output_dir/core/v8" + +if (is_win && is_official_build) { + bindings_core_generated_aggregate_files = [ + "$bindings_core_v8_output_dir/V8GeneratedCoreBindings.cpp", + ] +} else { + bindings_core_generated_aggregate_files = [ + "$bindings_core_v8_output_dir/V8GeneratedCoreBindings01.cpp", + "$bindings_core_v8_output_dir/V8GeneratedCoreBindings02.cpp", + "$bindings_core_v8_output_dir/V8GeneratedCoreBindings03.cpp", + "$bindings_core_v8_output_dir/V8GeneratedCoreBindings04.cpp", + "$bindings_core_v8_output_dir/V8GeneratedCoreBindings05.cpp", + "$bindings_core_v8_output_dir/V8GeneratedCoreBindings06.cpp", + "$bindings_core_v8_output_dir/V8GeneratedCoreBindings07.cpp", + "$bindings_core_v8_output_dir/V8GeneratedCoreBindings08.cpp", + "$bindings_core_v8_output_dir/V8GeneratedCoreBindings09.cpp", + "$bindings_core_v8_output_dir/V8GeneratedCoreBindings10.cpp", + "$bindings_core_v8_output_dir/V8GeneratedCoreBindings11.cpp", + "$bindings_core_v8_output_dir/V8GeneratedCoreBindings12.cpp", + "$bindings_core_v8_output_dir/V8GeneratedCoreBindings13.cpp", + "$bindings_core_v8_output_dir/V8GeneratedCoreBindings14.cpp", + "$bindings_core_v8_output_dir/V8GeneratedCoreBindings15.cpp", + "$bindings_core_v8_output_dir/V8GeneratedCoreBindings16.cpp", + "$bindings_core_v8_output_dir/V8GeneratedCoreBindings17.cpp", + "$bindings_core_v8_output_dir/V8GeneratedCoreBindings18.cpp", + "$bindings_core_v8_output_dir/V8GeneratedCoreBindings19.cpp", + ] +} diff --git a/chromium/third_party/WebKit/Source/bindings/core/v8/generated.gyp b/chromium/third_party/WebKit/Source/bindings/core/v8/generated.gyp new file mode 100644 index 00000000000..6a61c2e7a4d --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/core/v8/generated.gyp @@ -0,0 +1,135 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Generate IDL bindings for core, plus aggregate bindings files. +# +# Design doc: http://www.chromium.org/developers/design-documents/idl-build + +{ + 'includes': [ + # ../../.. == Source + '../../../bindings/bindings.gypi', + '../../../bindings/core/generated.gypi', + '../../../bindings/core/idl.gypi', + # FIXME: need info about modules IDL files because some core IDL files + # depend on modules IDL files http://crbug.com/358074 + '../../../bindings/modules/idl.gypi', + '../../../bindings/modules/modules.gypi', + '../../../bindings/scripts/scripts.gypi', + '../../../core/core.gypi', + 'generated.gypi', + ], + + 'targets': [ +################################################################################ + { + # GN version: //third_party/WebKit/Source/bindings/core/v8:bindings_core_v8_generated_individual + 'target_name': 'bindings_core_v8_generated_individual', + 'type': 'none', + # The 'binding' rule generates .h files, so mark as hard_dependency, per: + # https://code.google.com/p/gyp/wiki/InputFormatReference#Linking_Dependencies + 'hard_dependency': 1, + 'dependencies': [ + '../../../core/core_generated.gyp:generated_testing_idls', + '../generated.gyp:core_global_constructors_idls', + # FIXME: should not depend on modules, but partial interface definitions + # in modules change bindings for core http://crbug.com/358074 + '../../modules/generated.gyp:modules_global_constructors_idls', + '<(bindings_scripts_dir)/scripts.gyp:cached_jinja_templates', + '<(bindings_scripts_dir)/scripts.gyp:cached_lex_yacc_tables', + # FIXME: should be interfaces_info_core (w/o modules) + # http://crbug.com/358074 + '../../modules/generated.gyp:interfaces_info', + ], + 'sources': [ + '<@(core_interface_idl_files)', + ], + 'rules': [{ + 'rule_name': 'binding', + 'extension': 'idl', + 'msvs_external_rule': 1, + 'inputs': [ + '<@(idl_lexer_parser_files)', # to be explicit (covered by parsetab) + '<@(idl_compiler_files)', + '<(bindings_scripts_output_dir)/lextab.py', + '<(bindings_scripts_output_dir)/parsetab.pickle', + '<(bindings_scripts_output_dir)/cached_jinja_templates.stamp', + '<(bindings_dir)/IDLExtendedAttributes.txt', + # If the dependency structure or public interface info (e.g., + # [ImplementedAs]) changes, we rebuild all files, since we're not + # computing dependencies file-by-file in the build. + # This data is generally stable. + '<(bindings_modules_output_dir)/InterfacesInfoModules.pickle', + # Further, if any dependency (partial interface or implemented + # interface) changes, rebuild everything, since every IDL potentially + # depends on them, because we're not computing dependencies + # file-by-file. + # FIXME: This is too conservative, and causes excess rebuilds: + # compute this file-by-file. http://crbug.com/341748 + # FIXME: should be core_all_dependency_idl_files only, but some core IDL + # files depend on modules IDL files http://crbug.com/358074 + '<@(all_dependency_idl_files)', + ], + 'outputs': [ + '<(bindings_core_v8_output_dir)/V8<(RULE_INPUT_ROOT).cpp', + '<(bindings_core_v8_output_dir)/V8<(RULE_INPUT_ROOT).h', + ], + # sanitize-win-build-log.sed uses a regex which matches this command + # line (Python script + .idl file being processed). + # Update that regex if command line changes (other than changing flags) + 'action': [ + 'python', + '-S', # skip 'import site' to speed up startup + '<(bindings_scripts_dir)/idl_compiler.py', + '--cache-dir', + '<(bindings_scripts_output_dir)', + '--output-dir', + '<(bindings_core_v8_output_dir)', + '--interfaces-info', + '<(bindings_modules_output_dir)/InterfacesInfoModules.pickle', + '--write-file-only-if-changed', + '<(write_file_only_if_changed)', + '<(RULE_INPUT_PATH)', + ], + 'message': 'Generating binding from <(RULE_INPUT_PATH)', + }], + }, +################################################################################ + { + # GN version: //third_party/WebKit/Source/bindings/core/v8:bindings_core_v8_generated_aggregate + 'target_name': 'bindings_core_v8_generated_aggregate', + 'type': 'none', + 'actions': [{ + 'action_name': 'generate_aggregate_bindings_core_v8', + 'inputs': [ + '<(bindings_scripts_dir)/aggregate_generated_bindings.py', + '<(core_idl_files_list)', + ], + 'outputs': [ + '<@(bindings_core_v8_generated_aggregate_files)', + ], + 'action': [ + 'python', + '<(bindings_scripts_dir)/aggregate_generated_bindings.py', + 'core', + '<(core_idl_files_list)', + '--', + '<@(bindings_core_v8_generated_aggregate_files)', + ], + 'message': 'Generating aggregate generated core V8 bindings files', + }], + }, +################################################################################ + { + # GN version: //third_party/WebKit/Source/bindings/core/v8:bindings_core_v8_generated + 'target_name': 'bindings_core_v8_generated', + 'type': 'none', + 'dependencies': [ + 'bindings_core_v8_generated_aggregate', + 'bindings_core_v8_generated_individual', + ], + }, +################################################################################ + ], # targets +} diff --git a/chromium/third_party/WebKit/Source/bindings/core/v8/generated.gypi b/chromium/third_party/WebKit/Source/bindings/core/v8/generated.gypi new file mode 100644 index 00000000000..a599286ad05 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/core/v8/generated.gypi @@ -0,0 +1,41 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + 'bindings_core_v8_output_dir': '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/core/v8', + + 'conditions': [ + ['OS=="win" and buildtype=="Official"', { + # On Windows Official release builds, we try to preserve symbol + # space. + 'bindings_core_v8_generated_aggregate_files': [ + '<(bindings_core_v8_output_dir)/V8GeneratedCoreBindings.cpp', + ], + }, { + 'bindings_core_v8_generated_aggregate_files': [ + '<(bindings_core_v8_output_dir)/V8GeneratedCoreBindings01.cpp', + '<(bindings_core_v8_output_dir)/V8GeneratedCoreBindings02.cpp', + '<(bindings_core_v8_output_dir)/V8GeneratedCoreBindings03.cpp', + '<(bindings_core_v8_output_dir)/V8GeneratedCoreBindings04.cpp', + '<(bindings_core_v8_output_dir)/V8GeneratedCoreBindings05.cpp', + '<(bindings_core_v8_output_dir)/V8GeneratedCoreBindings06.cpp', + '<(bindings_core_v8_output_dir)/V8GeneratedCoreBindings07.cpp', + '<(bindings_core_v8_output_dir)/V8GeneratedCoreBindings08.cpp', + '<(bindings_core_v8_output_dir)/V8GeneratedCoreBindings09.cpp', + '<(bindings_core_v8_output_dir)/V8GeneratedCoreBindings10.cpp', + '<(bindings_core_v8_output_dir)/V8GeneratedCoreBindings11.cpp', + '<(bindings_core_v8_output_dir)/V8GeneratedCoreBindings12.cpp', + '<(bindings_core_v8_output_dir)/V8GeneratedCoreBindings13.cpp', + '<(bindings_core_v8_output_dir)/V8GeneratedCoreBindings14.cpp', + '<(bindings_core_v8_output_dir)/V8GeneratedCoreBindings15.cpp', + '<(bindings_core_v8_output_dir)/V8GeneratedCoreBindings16.cpp', + '<(bindings_core_v8_output_dir)/V8GeneratedCoreBindings17.cpp', + '<(bindings_core_v8_output_dir)/V8GeneratedCoreBindings18.cpp', + '<(bindings_core_v8_output_dir)/V8GeneratedCoreBindings19.cpp', + ], + }], + ], + }, +} diff --git a/chromium/third_party/WebKit/Source/bindings/derived_sources.gyp b/chromium/third_party/WebKit/Source/bindings/derived_sources.gyp deleted file mode 100644 index 20f34614da0..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/derived_sources.gyp +++ /dev/null @@ -1,316 +0,0 @@ -# -# Copyright (C) 2013 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. -# - -{ - 'includes': [ - '../build/scripts/scripts.gypi', - '../build/win/precompile.gypi', - '../build/scripts/scripts.gypi', - '../core/core.gypi', - '../modules/modules.gypi', - 'bindings.gypi', - ], - - 'variables': { - 'main_idl_files': [ - '<@(core_idl_files)', - '<@(modules_idl_files)', - '<@(svg_idl_files)', - ], - 'support_idl_files': [ - '<@(webcore_testing_support_idl_files)', - '<@(modules_testing_support_idl_files)', - ], - 'generated_support_idl_files': [ - '<@(generated_webcore_testing_support_idl_files)', - ], - 'compiler_module_files': [ - 'scripts/idl_compiler.py', - '<(DEPTH)/third_party/ply/lex.py', - '<(DEPTH)/third_party/ply/yacc.py', - # jinja2/__init__.py contains version string, so sufficient for package - '<(DEPTH)/third_party/jinja2/__init__.py', - '<(DEPTH)/third_party/markupsafe/__init__.py', # jinja2 dep - '<(DEPTH)/tools/idl_parser/idl_lexer.py', - '<(DEPTH)/tools/idl_parser/idl_node.py', - '<(DEPTH)/tools/idl_parser/idl_parser.py', - 'scripts/blink_idl_lexer.py', - 'scripts/blink_idl_parser.py', - 'scripts/code_generator_v8.py', - 'scripts/idl_definitions.py', - 'scripts/idl_definitions_builder.py', - 'scripts/idl_reader.py', - 'scripts/idl_validator.py', - 'scripts/interface_dependency_resolver.py', - 'scripts/v8_attributes.py', - 'scripts/v8_callback_interface.py', - 'scripts/v8_interface.py', - 'scripts/v8_types.py', - 'scripts/v8_utilities.py', - ], - 'code_generator_template_files': [ - 'templates/attributes.cpp', - 'templates/callback_interface.cpp', - 'templates/callback_interface.h', - 'templates/interface_base.cpp', - 'templates/interface.cpp', - 'templates/interface.h', - ], - - 'bindings_output_dir': '<(SHARED_INTERMEDIATE_DIR)/blink/bindings', - 'generated_global_constructors_idl_files': [ - '<(SHARED_INTERMEDIATE_DIR)/blink/WindowConstructors.idl', - '<(SHARED_INTERMEDIATE_DIR)/blink/WorkerGlobalScopeConstructors.idl', - '<(SHARED_INTERMEDIATE_DIR)/blink/SharedWorkerGlobalScopeConstructors.idl', - '<(SHARED_INTERMEDIATE_DIR)/blink/DedicatedWorkerGlobalScopeConstructors.idl', - '<(SHARED_INTERMEDIATE_DIR)/ServiceWorkerGlobalScopeConstructors.idl', - ], - - 'conditions': [ - ['OS=="win" and buildtype=="Official"', { - # On windows official release builds, we try to preserve symbol space. - 'derived_sources_aggregate_files': [ - '<(bindings_output_dir)/V8DerivedSourcesAll.cpp', - ], - },{ - 'derived_sources_aggregate_files': [ - '<(bindings_output_dir)/V8DerivedSources01.cpp', - '<(bindings_output_dir)/V8DerivedSources02.cpp', - '<(bindings_output_dir)/V8DerivedSources03.cpp', - '<(bindings_output_dir)/V8DerivedSources04.cpp', - '<(bindings_output_dir)/V8DerivedSources05.cpp', - '<(bindings_output_dir)/V8DerivedSources06.cpp', - '<(bindings_output_dir)/V8DerivedSources07.cpp', - '<(bindings_output_dir)/V8DerivedSources08.cpp', - '<(bindings_output_dir)/V8DerivedSources09.cpp', - '<(bindings_output_dir)/V8DerivedSources10.cpp', - '<(bindings_output_dir)/V8DerivedSources11.cpp', - '<(bindings_output_dir)/V8DerivedSources12.cpp', - '<(bindings_output_dir)/V8DerivedSources13.cpp', - '<(bindings_output_dir)/V8DerivedSources14.cpp', - '<(bindings_output_dir)/V8DerivedSources15.cpp', - '<(bindings_output_dir)/V8DerivedSources16.cpp', - '<(bindings_output_dir)/V8DerivedSources17.cpp', - '<(bindings_output_dir)/V8DerivedSources18.cpp', - '<(bindings_output_dir)/V8DerivedSources19.cpp', - ], - }], - # The bindings generator can not write generated files if they are identical - # to the already existing file – that way they don't need to be recompiled. - # However, a reverse dependency having a newer timestamp than a - # generated binding can confuse some build systems, so only use this on - # ninja which explicitly supports this use case (gyp turns all actions into - # ninja restat rules). - ['"<(GENERATOR)"=="ninja"', { - 'write_file_only_if_changed': '--write-file-only-if-changed 1', - },{ - 'write_file_only_if_changed': '--write-file-only-if-changed 0', - }], - ], - }, - - 'target_defaults': { - 'variables': { - 'optimize': 'max', - }, - }, - - 'targets': [{ - 'target_name': 'interface_dependencies', - 'type': 'none', - 'actions': [{ - 'action_name': 'compute_interface_dependencies', - 'variables': { - # Write sources into a file, so that the action command line won't - # exceed OS limits. - 'main_idl_files_list': '<|(main_idl_files_list.tmp <@(main_idl_files))', - 'support_idl_files_list': '<|(support_idl_files_list.tmp <@(support_idl_files))', - }, - 'inputs': [ - 'scripts/compute_dependencies.py', - '<(main_idl_files_list)', - '<@(main_idl_files)', - '<(support_idl_files_list)', - '<@(support_idl_files)', - ], - 'outputs': [ - '<(SHARED_INTERMEDIATE_DIR)/blink/InterfaceDependencies.txt', - '<(SHARED_INTERMEDIATE_DIR)/blink/BindingsDerivedSources.txt', - '<@(generated_global_constructors_idl_files)', - '<(SHARED_INTERMEDIATE_DIR)/blink/EventInterfaces.in', - ], - 'msvs_cygwin_shell': 0, - 'action': [ - 'python', - 'scripts/compute_dependencies.py', - '--main-idl-files-list', - '<(main_idl_files_list)', - '--support-idl-files-list', - '<(support_idl_files_list)', - '--interface-dependencies-file', - '<(SHARED_INTERMEDIATE_DIR)/blink/InterfaceDependencies.txt', - '--bindings-derived-sources-file', - '<(SHARED_INTERMEDIATE_DIR)/blink/BindingsDerivedSources.txt', - '--window-constructors-file', - '<(SHARED_INTERMEDIATE_DIR)/blink/WindowConstructors.idl', - '--workerglobalscope-constructors-file', - '<(SHARED_INTERMEDIATE_DIR)/blink/WorkerGlobalScopeConstructors.idl', - '--sharedworkerglobalscope-constructors-file', - '<(SHARED_INTERMEDIATE_DIR)/blink/SharedWorkerGlobalScopeConstructors.idl', - '--dedicatedworkerglobalscope-constructors-file', - '<(SHARED_INTERMEDIATE_DIR)/blink/DedicatedWorkerGlobalScopeConstructors.idl', - '--serviceworkerglobalscope-constructors-file', - '<(SHARED_INTERMEDIATE_DIR)/ServiceWorkerGlobalScopeConstructors.idl', - '--event-names-file', - '<(SHARED_INTERMEDIATE_DIR)/blink/EventInterfaces.in', - '<@(write_file_only_if_changed)', - ], - 'message': 'Resolving partial interfaces dependencies in all IDL files', - }] - }, - { - 'target_name': 'bindings_sources', - 'type': 'none', - # The 'binding' rule generates .h files, so mark as hard_dependency, per: - # https://code.google.com/p/gyp/wiki/InputFormatReference#Linking_Dependencies - 'hard_dependency': 1, - 'dependencies': [ - 'interface_dependencies', - '../config.gyp:config', - '../core/core_derived_sources.gyp:generate_test_support_idls', - ], - 'sources': [ - '<@(main_idl_files)', - '<@(support_idl_files)', - '<@(generated_support_idl_files)', - ], - 'rules': [{ - 'rule_name': 'binding', - 'extension': 'idl', - 'msvs_external_rule': 1, - 'inputs': [ - 'scripts/generate_bindings.pl', - 'scripts/code_generator_v8.pm', - 'scripts/idl_parser.pm', - 'scripts/idl_serializer.pm', - '../build/scripts/preprocessor.pm', - 'IDLExtendedAttributes.txt', - # FIXME: If the dependency structure changes, we rebuild all files, - # since we're not computing dependencies file-by-file in the build. - '<(SHARED_INTERMEDIATE_DIR)/blink/InterfaceDependencies.txt', - # FIXME: Similarly, if any partial interface changes, rebuild - # everything, since every IDL potentially depends on them, because - # we're not computing dependencies file-by-file. - # - # If a new partial interface is added, need to regyp to update these - # dependencies, as these are computed statically at gyp runtime. - '<!@pymod_do_main(list_idl_files_with_partial_interface <@(main_idl_files) <@(support_idl_files))', - # Generated IDLs are all partial interfaces, hence everything - # potentially depends on them. - '<@(generated_global_constructors_idl_files)', - ], - 'outputs': [ - '<(bindings_output_dir)/V8<(RULE_INPUT_ROOT).cpp', - '<(bindings_output_dir)/V8<(RULE_INPUT_ROOT).h', - ], - 'variables': { - # IDL include paths. The generator will search recursively for IDL - # files under these locations. - 'generator_include_dirs': [ - '--include', '../core', - '--include', '../modules', - '--include', '<(SHARED_INTERMEDIATE_DIR)/blink', - ], - # Hook for embedders to specify extra directories to find IDL files. - 'extra_blink_generator_include_dirs%': [], - }, - 'msvs_cygwin_shell': 0, - # sanitize-win-build-log.sed uses a regex which matches this command - # line (Perl script + .idl file being processed). - # Update that regex if command line changes (other than changing flags) - 'action': [ - '<(perl_exe)', - '-w', - '-Iscripts', - '-I../build/scripts', - '-I<(DEPTH)/third_party/JSON/out/lib/perl5', - 'scripts/generate_bindings.pl', - '--outputDir', - '<(bindings_output_dir)', - '--idlAttributesFile', - 'IDLExtendedAttributes.txt', - '<@(generator_include_dirs)', - '<@(extra_blink_generator_include_dirs)', - '--interfaceDependenciesFile', - '<(SHARED_INTERMEDIATE_DIR)/blink/InterfaceDependencies.txt', - '--additionalIdlFiles', - # Generated IDL files aren't listed in InterfaceDependencies.txt, - # b/c they aren't available at GYP run time, so we need to sort them - # manually, depending on whether they are (main) interface files, - # for which we generate bindings, or dependencies, for which we don't. - # generated_support_idl_files are main interfaces, so generate - # bindings, but generated_global_constructors_idl_files are all - # partial interfaces, so don't (b/c generated by dependents). - '<(generated_support_idl_files)', - '<@(preprocessor)', - '<@(write_file_only_if_changed)', - '<(RULE_INPUT_PATH)', - ], - 'message': 'Generating binding from <(RULE_INPUT_PATH)', - }], - }, - { - 'target_name': 'bindings_derived_sources', - 'type': 'none', - 'dependencies': [ - 'interface_dependencies', - 'bindings_sources', - ], - 'actions': [{ - 'action_name': 'derived_sources_all_in_one', - 'inputs': [ - '../build/scripts/action_derivedsourcesallinone.py', - '<(SHARED_INTERMEDIATE_DIR)/blink/BindingsDerivedSources.txt', - ], - 'outputs': [ - '<@(derived_sources_aggregate_files)', - ], - 'action': [ - 'python', - '../build/scripts/action_derivedsourcesallinone.py', - '<(SHARED_INTERMEDIATE_DIR)/blink/BindingsDerivedSources.txt', - '--', - '<@(derived_sources_aggregate_files)', - ], - 'message': 'Generating bindings derived sources', - }], - }, - ], -} diff --git a/chromium/third_party/WebKit/Source/bindings/idl.gni b/chromium/third_party/WebKit/Source/bindings/idl.gni new file mode 100644 index 00000000000..cc12a67ba3d --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/idl.gni @@ -0,0 +1,21 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/WebKit/Source/bindings/bindings.gni") + +# Global constructors +# FIXME: Split into core vs. modules http://crbug.com/358074 +generated_global_constructors_idl_files = [ + "$blink_output_dir/WindowConstructors.idl", + "$blink_output_dir/SharedWorkerGlobalScopeConstructors.idl", + "$blink_output_dir/DedicatedWorkerGlobalScopeConstructors.idl", + "$blink_output_dir/ServiceWorkerGlobalScopeConstructors.idl", +] + +generated_global_constructors_header_files = [ + "$blink_output_dir/WindowConstructors.h", + "$blink_output_dir/SharedWorkerGlobalScopeConstructors.h", + "$blink_output_dir/DedicatedWorkerGlobalScopeConstructors.h", + "$blink_output_dir/ServiceWorkerGlobalScopeConstructors.h", +] diff --git a/chromium/third_party/WebKit/Source/bindings/modules/BUILD.gn b/chromium/third_party/WebKit/Source/bindings/modules/BUILD.gn new file mode 100644 index 00000000000..5fad650cd1c --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/modules/BUILD.gn @@ -0,0 +1,120 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/WebKit/Source/modules/modules.gni") +import("//third_party/WebKit/Source/bindings/core/core.gni") +import("//third_party/WebKit/Source/bindings/modules/modules.gni") +import("//third_party/WebKit/Source/bindings/scripts/scripts.gni") +import("//third_party/WebKit/Source/build/scripts/scripts.gni") + +visibility = "//third_party/WebKit/*" + +# GYP version: Source/bindings/modules/generated.gyp:bindings_modules_generated +group("bindings_modules_generated") { + deps = [ + ":modules_bindings_generated_event_interfaces", + ":bindings_modules_generated_event_modules_factory", + ":bindings_modules_generated_event_modules_names", + ":bindings_modules_generated_event_target_modules_factory", + ":bindings_modules_generated_event_target_modules_names", + ] +} + +# GYP version: event_interfaces action in bindings_modules_generated +generate_event_interfaces("modules_bindings_generated_event_interfaces") { + sources = modules_event_idl_files + output_file = "EventModulesInterfaces.in" + suffix = "Modules" +} + +# GYP version: EventModulesFactory action in bindings_modules_generated +make_event_factory("bindings_modules_generated_event_modules_factory") { + in_files = [ + "$root_gen_dir/blink/EventModulesInterfaces.in", + ] + outputs = [ + "$blink_modules_output_dir/EventModules.cpp", + "$blink_modules_output_dir/EventModulesHeaders.h", + "$blink_modules_output_dir/EventModulesInterfaces.h", + ] +} + +# GYP version: EventModulesNames action in bindings_modules_generated +make_names("bindings_modules_generated_event_modules_names") { + in_files = [ + "$root_gen_dir/blink/EventModulesInterfaces.in", + ] + outputs = [ + "$blink_modules_output_dir/EventModulesNames.cpp", + "$blink_modules_output_dir/EventModulesNames.h", + ] +} + +# GYP version: EventTargetModulesFactory action in bindings_modules_generated +make_event_factory("bindings_modules_generated_event_target_modules_factory") { + in_files = [ + "../../modules/EventTargetModulesFactory.in", + ] + outputs = [ + "$blink_modules_output_dir/EventTargetModulesHeaders.h", + "$blink_modules_output_dir/EventTargetModulesInterfaces.h", + ] +} + +# GYP version: EventTargetModulesNames action in bindings_modules_generated +make_names("bindings_modules_generated_event_target_modules_names") { + in_files = [ + "../../modules/EventTargetModulesFactory.in", + ] + outputs = [ + "$blink_modules_output_dir/EventTargetModulesNames.cpp", + "$blink_modules_output_dir/EventTargetModulesNames.h", + ] +} + +# ------------------------------------------------------------------------------ + +# GYP version: Source/bindings/modules/generated.gyp:interfaces_info_individual_modules +compute_interfaces_info_individual("interfaces_info_individual_modules") { + sources_static = modules_static_idl_files + # No generated files currently, will add with constructors + sources_generated = [] + component_dir = "modules" + output_file = + "$bindings_modules_output_dir/InterfacesInfoModulesIndividual.pickle" +} + +# GYP version: Source/bindings/modules/generated.gyp:interfaces_info +action("interfaces_info") { + script = "$bindings_scripts_dir/compute_interfaces_info_overall.py" + + source_prereqs = [ + "$bindings_core_output_dir/InterfacesInfoCoreIndividual.pickle", + "$bindings_modules_output_dir/InterfacesInfoModulesIndividual.pickle", + ] + outputs = [ + "$bindings_modules_output_dir/InterfacesInfoModules.pickle", + ] + + args = [ + "--write-file-only-if-changed=1", + "--", + rebase_path( + "$bindings_core_output_dir/InterfacesInfoCoreIndividual.pickle", + root_build_dir), + rebase_path( + "$bindings_modules_output_dir/InterfacesInfoModulesIndividual.pickle", + root_build_dir), + rebase_path( + "$bindings_modules_output_dir/InterfacesInfoModules.pickle", + root_build_dir), + ] + + deps = [ + ":interfaces_info_individual_modules", + "//third_party/WebKit/Source/bindings/core:interfaces_info_individual_core", + ] +} + + diff --git a/chromium/third_party/WebKit/Source/bindings/modules/generated.gyp b/chromium/third_party/WebKit/Source/bindings/modules/generated.gyp new file mode 100644 index 00000000000..9b697541a52 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/modules/generated.gyp @@ -0,0 +1,242 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Generate IDL interfaces info for modules, used to generate bindings +# +# Design doc: http://www.chromium.org/developers/design-documents/idl-build + +{ + 'includes': [ + # ../.. == Source + '../../bindings/core/core.gypi', + '../../bindings/scripts/scripts.gypi', + '../../build/scripts/scripts.gypi', # FIXME: Needed for event files, should be in modules, not bindings_modules http://crbug.com/358074 + '../../modules/modules.gypi', + 'generated.gypi', + 'idl.gypi', + 'modules.gypi', + ], + + 'targets': [ +################################################################################ + { + # GN version: //third_party/WebKit/Source/bindings/modules:bindings_modules_generated + # FIXME: Should be in modules, not bindings_modules http://crbug.com/358074 + 'target_name': 'modules_event_generated', + 'type': 'none', + 'actions': [ + { + # GN version: //third_party/WebKit/Source/bindings/modules:modules_bindings_generated_event_interfaces + 'action_name': 'event_interfaces', + 'variables': { + 'event_idl_files': [ + '<@(modules_event_idl_files)', + ], + 'event_idl_files_list': + '<|(event_idl_files_list.tmp <@(event_idl_files))', + }, + 'inputs': [ + '<(bindings_scripts_dir)/generate_event_interfaces.py', + '<(bindings_scripts_dir)/utilities.py', + '<(event_idl_files_list)', + '<@(event_idl_files)', + ], + 'outputs': [ + '<(blink_modules_output_dir)/EventModulesInterfaces.in', + ], + 'action': [ + 'python', + '<(bindings_scripts_dir)/generate_event_interfaces.py', + '--event-idl-files-list', + '<(event_idl_files_list)', + '--event-interfaces-file', + '<(blink_modules_output_dir)/EventModulesInterfaces.in', + '--write-file-only-if-changed', + '<(write_file_only_if_changed)', + '--suffix', + 'Modules', + ], + }, + { + # GN version: //third_party/WebKit/Source/bindings/modules:bindings_modules_generated_event_modules_factory + 'action_name': 'EventModulesFactory', + 'inputs': [ + '<@(make_event_factory_files)', + '<(blink_modules_output_dir)/EventModulesInterfaces.in', + ], + 'outputs': [ + '<(blink_modules_output_dir)/EventModules.cpp', + '<(blink_modules_output_dir)/EventModulesHeaders.h', + '<(blink_modules_output_dir)/EventModulesInterfaces.h', + ], + 'action': [ + 'python', + '../../build/scripts/make_event_factory.py', + '<(blink_modules_output_dir)/EventModulesInterfaces.in', + '--output_dir', + '<(blink_modules_output_dir)', + ], + }, + { + # GN version: //third_party/WebKit/Source/bindings/modules:bindings_modules_generated_event_modules_names + 'action_name': 'EventModulesNames', + 'inputs': [ + '<@(make_names_files)', + '<(blink_modules_output_dir)/EventModulesInterfaces.in', + ], + 'outputs': [ + '<(blink_modules_output_dir)/EventModulesNames.cpp', + '<(blink_modules_output_dir)/EventModulesNames.h', + ], + 'action': [ + 'python', + '../../build/scripts/make_names.py', + '<(blink_modules_output_dir)/EventModulesInterfaces.in', + '--output_dir', + '<(blink_modules_output_dir)', + ], + }, + { + # GN version: //third_party/WebKit/Source/bindings/modules:bindings_modules_generated_event_target_modules_factory + 'action_name': 'EventTargetModulesFactory', + 'inputs': [ + '<@(make_event_factory_files)', + '../../modules/EventTargetModulesFactory.in', + ], + 'outputs': [ + '<(blink_modules_output_dir)/EventTargetModulesHeaders.h', + '<(blink_modules_output_dir)/EventTargetModulesInterfaces.h', + ], + 'action': [ + 'python', + '../../build/scripts/make_event_factory.py', + '../../modules/EventTargetModulesFactory.in', + '--output_dir', + '<(blink_modules_output_dir)', + ], + }, + { + # GN version: //third_party/WebKit/Source/bindings/modules:bindings_modules_generated_event_target_modules_names + 'action_name': 'EventTargetModulesNames', + 'inputs': [ + '<@(make_names_files)', + '../../modules/EventTargetModulesFactory.in', + ], + 'outputs': [ + '<(blink_modules_output_dir)/EventTargetModulesNames.cpp', + '<(blink_modules_output_dir)/EventTargetModulesNames.h', + ], + 'action': [ + 'python', + '../../build/scripts/make_names.py', + '../../modules/EventTargetModulesFactory.in', + '--output_dir', + '<(blink_modules_output_dir)', + ], + }, + ], + }, +################################################################################ + { + 'target_name': 'modules_global_objects', + 'dependencies': [ + '../core/generated.gyp:core_global_objects', + ], + 'variables': { + 'idl_files': '<(modules_idl_files)', + 'input_files': [ + '<(bindings_core_output_dir)/GlobalObjectsCore.pickle', + ], + 'output_file': + '<(bindings_modules_output_dir)/GlobalObjectsModules.pickle', + }, + 'includes': ['../../bindings/scripts/global_objects.gypi'], + }, +################################################################################ + { + # Global constructors for global objects in modules (ServiceWorker) + # but interfaces in core. + 'target_name': 'modules_core_global_constructors_idls', + 'dependencies': [ + 'modules_global_objects', + ], + 'variables': { + 'idl_files': '<(core_idl_files)', + 'global_objects_file': + '<(bindings_modules_output_dir)/GlobalObjectsModules.pickle', + 'global_names_idl_files': [ + 'ServiceWorkerGlobalScope', + '<(blink_modules_output_dir)/ServiceWorkerGlobalScopeCoreConstructors.idl', + ], + 'outputs': [ + '<@(modules_core_global_constructors_generated_idl_files)', + '<@(modules_core_global_constructors_generated_header_files)', + ], + }, + 'includes': ['../../bindings/scripts/global_constructors.gypi'], + }, +################################################################################ + { + 'target_name': 'modules_global_constructors_idls', + 'dependencies': [ + 'modules_global_objects', + ], + 'variables': { + 'idl_files': '<(modules_idl_files)', + 'global_objects_file': + '<(bindings_modules_output_dir)/GlobalObjectsModules.pickle', + 'global_names_idl_files': [ + 'Window', + '<(blink_modules_output_dir)/WindowModulesConstructors.idl', + 'SharedWorkerGlobalScope', + '<(blink_modules_output_dir)/SharedWorkerGlobalScopeModulesConstructors.idl', + 'DedicatedWorkerGlobalScope', + '<(blink_modules_output_dir)/DedicatedWorkerGlobalScopeModulesConstructors.idl', + 'ServiceWorkerGlobalScope', + '<(blink_modules_output_dir)/ServiceWorkerGlobalScopeModulesConstructors.idl', + ], + 'outputs': [ + '<@(modules_global_constructors_generated_idl_files)', + '<@(modules_global_constructors_generated_header_files)', + ], + }, + 'includes': ['../../bindings/scripts/global_constructors.gypi'], + }, +################################################################################ + { + 'target_name': 'interfaces_info_individual_modules', + 'dependencies': [ + 'modules_core_global_constructors_idls', + 'modules_global_constructors_idls', + ], + 'variables': { + 'static_idl_files': '<(modules_static_idl_files)', + 'generated_idl_files': '<(modules_generated_idl_files)', + 'component_dir': 'modules', + 'output_file': + '<(bindings_modules_output_dir)/InterfacesInfoModulesIndividual.pickle', + }, + 'includes': ['../../bindings/scripts/interfaces_info_individual.gypi'], + }, +################################################################################ + { + # GN version: //third_party/WebKit/Source/bindings/modules:interfaces_info + 'target_name': 'interfaces_info', + 'dependencies': [ + '../core/generated.gyp:interfaces_info_individual_core', + 'interfaces_info_individual_modules', + ], + 'variables': { + 'input_files': [ + '<(bindings_core_output_dir)/InterfacesInfoCoreIndividual.pickle', + '<(bindings_modules_output_dir)/InterfacesInfoModulesIndividual.pickle', + ], + 'output_file': + '<(bindings_modules_output_dir)/InterfacesInfoModules.pickle', + }, + 'includes': ['../../bindings/scripts/interfaces_info_overall.gypi'], + }, +################################################################################ + ], # targets +} diff --git a/chromium/third_party/WebKit/Source/bindings/modules/generated.gypi b/chromium/third_party/WebKit/Source/bindings/modules/generated.gypi new file mode 100644 index 00000000000..0cd8bdf4226 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/modules/generated.gypi @@ -0,0 +1,34 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'includes': [ + '../../modules/modules_generated.gypi', + ], + + 'variables': { + # Global constructors + # Global object in modules, constructors for interfaces in core + 'modules_core_global_constructors_generated_idl_files': [ + '<(blink_modules_output_dir)/ServiceWorkerGlobalScopeCoreConstructors.idl', + ], + 'modules_core_global_constructors_generated_header_files': [ + '<(blink_modules_output_dir)/ServiceWorkerGlobalScopeCoreConstructors.h', + ], + + # Global object in modules, constructors for interfaces in modules + 'modules_global_constructors_generated_idl_files': [ + '<(blink_modules_output_dir)/WindowModulesConstructors.idl', + '<(blink_modules_output_dir)/SharedWorkerGlobalScopeModulesConstructors.idl', + '<(blink_modules_output_dir)/DedicatedWorkerGlobalScopeModulesConstructors.idl', + '<(blink_modules_output_dir)/ServiceWorkerGlobalScopeModulesConstructors.idl', + ], + 'modules_global_constructors_generated_header_files': [ + '<(blink_modules_output_dir)/WindowModulesConstructors.h', + '<(blink_modules_output_dir)/SharedWorkerGlobalScopeModulesConstructors.h', + '<(blink_modules_output_dir)/DedicatedWorkerGlobalScopeModulesConstructors.h', + '<(blink_modules_output_dir)/ServiceWorkerGlobalScopeModulesConstructors.h', + ], + }, +} diff --git a/chromium/third_party/WebKit/Source/bindings/modules/idl.gni b/chromium/third_party/WebKit/Source/bindings/modules/idl.gni new file mode 100644 index 00000000000..433c325ba3e --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/modules/idl.gni @@ -0,0 +1,42 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/WebKit/Source/bindings/core/idl.gni") +import("//third_party/WebKit/Source/modules/modules.gni") + +# IDL file lists; see: http://www.chromium.org/developers/web-idl-interfaces + +# Static IDL files +modules_static_interface_idl_files = + modules_idl_files +modules_static_dependency_idl_files = + modules_dependency_idl_files + + modules_testing_dependency_idl_files + +# Static IDL files / Generated IDL files +# +# In GYP, paths need to be passed separately for static and generated files, as +# static files are listed in a temporary file (b/c too long for command line), +# but generated files must be passed at the command line, as their paths are +# not fixed at GYP time, when the temporary file is generated, because their +# paths depend on the build directory, which varies. +# +# FIXME: GN does not have this limitation and we can combine the lists. +# Currently we keep the GYP/GN builds in sync for simplicity, but this can be +# cleaned up once GYP is not used. +modules_static_idl_files = + modules_static_interface_idl_files + + modules_static_dependency_idl_files + +# 'modules_dependency_idl_files' is already used in Source/modules, so avoid +# collision +modules_all_dependency_idl_files = + modules_static_dependency_idl_files + #+ modules_generated_dependency_idl_files + +# Dependency IDL files: don't generate individual bindings, but do process +# in IDL dependency computation, and count as build dependencies +all_dependency_idl_files = + core_all_dependency_idl_files + + modules_all_dependency_idl_files diff --git a/chromium/third_party/WebKit/Source/bindings/modules/idl.gypi b/chromium/third_party/WebKit/Source/bindings/modules/idl.gypi new file mode 100644 index 00000000000..8814be0a4e7 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/modules/idl.gypi @@ -0,0 +1,72 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# IDL file lists; see: http://www.chromium.org/developers/web-idl-interfaces + +{ + 'includes': [ + '../../modules/modules.gypi', + '../core/idl.gypi', + 'generated.gypi', + ], + + 'variables': { + # IDL file lists; see: http://www.chromium.org/developers/web-idl-interfaces + + # Interface IDL files: generate individual bindings (includes testing) + 'modules_interface_idl_files': [ + # No testing or generated interface IDL files in modules currently + '<@(modules_idl_files)', + ], + + # Write lists of main IDL files to a file, so that the command lines don't + # exceed OS length limits. + 'modules_idl_files_list': '<|(modules_idl_files_list.tmp <@(modules_idl_files))', + + # Dependency IDL files: don't generate individual bindings, but do process + # in IDL dependency computation, and count as build dependencies + 'all_dependency_idl_files': [ + '<@(core_all_dependency_idl_files)', + '<@(modules_all_dependency_idl_files)', + ], + # 'modules_dependency_idl_files' is already used in Source/modules, so avoid + # collision + 'modules_all_dependency_idl_files': [ + '<@(modules_static_dependency_idl_files)', + '<@(modules_generated_dependency_idl_files)', + ], + + # Static IDL files / Generated IDL files + # Paths need to be passed separately for static and generated files, as + # static files are listed in a temporary file (b/c too long for command + # line), but generated files must be passed at the command line, as their + # paths are not fixed at GYP time, when the temporary file is generated, + # because their paths depend on the build directory, which varies. + 'modules_static_idl_files': [ + '<@(modules_static_interface_idl_files)', + '<@(modules_static_dependency_idl_files)', + ], + 'modules_static_idl_files_list': + '<|(modules_static_idl_files_list.tmp <@(modules_static_idl_files))', + + 'modules_generated_idl_files': [ + '<@(modules_generated_dependency_idl_files)', + ], + + # Static IDL files + 'modules_static_interface_idl_files': [ + '<@(modules_idl_files)', + ], + 'modules_static_dependency_idl_files': [ + '<@(modules_dependency_idl_files)', + '<@(modules_testing_dependency_idl_files)', + ], + + # Generated IDL files + 'modules_generated_dependency_idl_files': [ + '<@(modules_core_global_constructors_generated_idl_files)', # partial interfaces + '<@(modules_global_constructors_generated_idl_files)', # partial interfaces + ], + }, +} diff --git a/chromium/third_party/WebKit/Source/bindings/modules/modules.gni b/chromium/third_party/WebKit/Source/bindings/modules/modules.gni new file mode 100644 index 00000000000..649abde724a --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/modules/modules.gni @@ -0,0 +1,8 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# FIXME: factor out bindings_core http://crbug.com/358074 +import("//third_party/WebKit/Source/bindings/bindings.gni") + +bindings_modules_output_dir = "$bindings_output_dir/bindings/modules" diff --git a/chromium/third_party/WebKit/Source/bindings/modules/modules.gypi b/chromium/third_party/WebKit/Source/bindings/modules/modules.gypi new file mode 100644 index 00000000000..700655e81e6 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/modules/modules.gypi @@ -0,0 +1,13 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'includes': [ + 'v8/generated.gypi', + ], + + 'variables': { + 'bindings_modules_output_dir': '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/modules', + }, +} diff --git a/chromium/third_party/WebKit/Source/bindings/modules/v8/BUILD.gn b/chromium/third_party/WebKit/Source/bindings/modules/v8/BUILD.gn new file mode 100644 index 00000000000..7dc2ffb56fb --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/modules/v8/BUILD.gn @@ -0,0 +1,32 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/WebKit/Source/bindings/modules/v8/generated.gni") +import("//third_party/WebKit/Source/bindings/scripts/scripts.gni") +import("//third_party/WebKit/Source/modules/modules.gni") + +visibility = "//third_party/WebKit/*" + +# bindings_modules_generated in modules/v8/generated.gyp +group("bindings_modules_generated") { + deps = [ + ":bindings_modules_generated_aggregate", + ":bindings_modules_generated_individual", + ] +} + +# bindings_modules_generated_aggregate in modules/v8/generated.gyp +aggregate_generated_bindings("bindings_modules_generated_aggregate") { + sources = modules_idl_files + component_dir = "modules" + outputs = bindings_modules_generated_aggregate_files +} + +# bindings_modules_generated_individual in modules/v8/generated.gyp +idl_compiler("bindings_modules_generated_individual") { + # Note in GYP this is modules_interface_idl_files but this variable is just + # defined to modules_idl_files. + sources = modules_idl_files + output_dir = bindings_modules_v8_output_dir +} diff --git a/chromium/third_party/WebKit/Source/bindings/modules/v8/generated.gni b/chromium/third_party/WebKit/Source/bindings/modules/v8/generated.gni new file mode 100644 index 00000000000..bdea030fafb --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/modules/v8/generated.gni @@ -0,0 +1,35 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/WebKit/Source/bindings/bindings.gni") + +bindings_modules_v8_output_dir = "$bindings_output_dir/modules/v8" + +if (is_win && is_official_build) { + bindings_modules_generated_aggregate_files = [ + "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings.cpp", + ] +} else { + bindings_modules_generated_aggregate_files = [ + "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings01.cpp", + "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings02.cpp", + "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings03.cpp", + "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings04.cpp", + "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings05.cpp", + "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings06.cpp", + "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings07.cpp", + "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings08.cpp", + "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings09.cpp", + "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings10.cpp", + "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings11.cpp", + "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings12.cpp", + "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings13.cpp", + "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings14.cpp", + "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings15.cpp", + "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings16.cpp", + "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings17.cpp", + "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings18.cpp", + "$bindings_modules_v8_output_dir/V8GeneratedModulesBindings19.cpp", + ] +} diff --git a/chromium/third_party/WebKit/Source/bindings/modules/v8/generated.gyp b/chromium/third_party/WebKit/Source/bindings/modules/v8/generated.gyp new file mode 100644 index 00000000000..ffe504b1769 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/modules/v8/generated.gyp @@ -0,0 +1,121 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Generate IDL bindings for modules, plus aggregate bindings files. +# +# Design doc: http://www.chromium.org/developers/design-documents/idl-build + +{ + 'includes': [ + # ../../.. == Source + '../../../bindings/bindings.gypi', + '../../../bindings/modules/idl.gypi', + '../../../bindings/modules/modules.gypi', + '../../../bindings/scripts/scripts.gypi', + '../../../modules/modules.gypi', + 'generated.gypi', + ], + + 'targets': [ +################################################################################ + { + 'target_name': 'bindings_modules_v8_generated_individual', + 'type': 'none', + # The 'binding' rule generates .h files, so mark as hard_dependency, per: + # https://code.google.com/p/gyp/wiki/InputFormatReference#Linking_Dependencies + 'hard_dependency': 1, + 'dependencies': [ + '../../core/generated.gyp:core_global_constructors_idls', + '../generated.gyp:modules_global_constructors_idls', + '../generated.gyp:interfaces_info', + '<(bindings_scripts_dir)/scripts.gyp:cached_jinja_templates', + '<(bindings_scripts_dir)/scripts.gyp:cached_lex_yacc_tables', + ], + 'sources': [ + '<@(modules_interface_idl_files)', + ], + 'rules': [{ + 'rule_name': 'binding', + 'extension': 'idl', + 'msvs_external_rule': 1, + 'inputs': [ + '<@(idl_lexer_parser_files)', # to be explicit (covered by parsetab) + '<@(idl_compiler_files)', + '<(bindings_scripts_output_dir)/lextab.py', + '<(bindings_scripts_output_dir)/parsetab.pickle', + '<(bindings_scripts_output_dir)/cached_jinja_templates.stamp', + '<(bindings_dir)/IDLExtendedAttributes.txt', + # If the dependency structure or public interface info (e.g., + # [ImplementedAs]) changes, we rebuild all files, since we're not + # computing dependencies file-by-file in the build. + # This data is generally stable. + '<(bindings_modules_output_dir)/InterfacesInfoModules.pickle', + # Further, if any dependency (partial interface or implemented + # interface) changes, rebuild everything, since every IDL potentially + # depends on them, because we're not computing dependencies + # file-by-file. + # FIXME: This is too conservative, and causes excess rebuilds: + # compute this file-by-file. http://crbug.com/341748 + '<@(all_dependency_idl_files)', + ], + 'outputs': [ + '<(bindings_modules_v8_output_dir)/V8<(RULE_INPUT_ROOT).cpp', + '<(bindings_modules_v8_output_dir)/V8<(RULE_INPUT_ROOT).h', + ], + # sanitize-win-build-log.sed uses a regex which matches this command + # line (Python script + .idl file being processed). + # Update that regex if command line changes (other than changing flags) + 'action': [ + 'python', + '-S', # skip 'import site' to speed up startup + '<(bindings_scripts_dir)/idl_compiler.py', + '--cache-dir', + '<(bindings_scripts_output_dir)', + '--output-dir', + '<(bindings_modules_v8_output_dir)', + '--interfaces-info', + '<(bindings_modules_output_dir)/InterfacesInfoModules.pickle', + '--write-file-only-if-changed', + '<(write_file_only_if_changed)', + '<(RULE_INPUT_PATH)', + ], + 'message': 'Generating binding from <(RULE_INPUT_PATH)', + }], + }, +################################################################################ + { + 'target_name': 'bindings_modules_v8_generated_aggregate', + 'type': 'none', + 'actions': [{ + 'action_name': 'generate_aggregate_bindings_modules_v8', + 'inputs': [ + '<(bindings_scripts_dir)/aggregate_generated_bindings.py', + '<(modules_idl_files_list)', + ], + 'outputs': [ + '<@(bindings_modules_v8_generated_aggregate_files)', + ], + 'action': [ + 'python', + '<(bindings_scripts_dir)/aggregate_generated_bindings.py', + 'modules', + '<(modules_idl_files_list)', + '--', + '<@(bindings_modules_v8_generated_aggregate_files)', + ], + 'message': 'Generating aggregate generated modules V8 bindings files', + }], + }, +################################################################################ + { + 'target_name': 'bindings_modules_v8_generated', + 'type': 'none', + 'dependencies': [ + 'bindings_modules_v8_generated_aggregate', + 'bindings_modules_v8_generated_individual', + ], + }, +################################################################################ + ], # targets +} diff --git a/chromium/third_party/WebKit/Source/bindings/modules/v8/generated.gypi b/chromium/third_party/WebKit/Source/bindings/modules/v8/generated.gypi new file mode 100644 index 00000000000..eb00db7b1fd --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/modules/v8/generated.gypi @@ -0,0 +1,41 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + 'bindings_modules_v8_output_dir': '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/modules/v8', + + 'conditions': [ + ['OS=="win" and buildtype=="Official"', { + # On Windows Official release builds, we try to preserve symbol + # space. + 'bindings_modules_v8_generated_aggregate_files': [ + '<(bindings_modules_v8_output_dir)/V8GeneratedModulesBindings.cpp', + ], + }, { + 'bindings_modules_v8_generated_aggregate_files': [ + '<(bindings_modules_v8_output_dir)/V8GeneratedModulesBindings01.cpp', + '<(bindings_modules_v8_output_dir)/V8GeneratedModulesBindings02.cpp', + '<(bindings_modules_v8_output_dir)/V8GeneratedModulesBindings03.cpp', + '<(bindings_modules_v8_output_dir)/V8GeneratedModulesBindings04.cpp', + '<(bindings_modules_v8_output_dir)/V8GeneratedModulesBindings05.cpp', + '<(bindings_modules_v8_output_dir)/V8GeneratedModulesBindings06.cpp', + '<(bindings_modules_v8_output_dir)/V8GeneratedModulesBindings07.cpp', + '<(bindings_modules_v8_output_dir)/V8GeneratedModulesBindings08.cpp', + '<(bindings_modules_v8_output_dir)/V8GeneratedModulesBindings09.cpp', + '<(bindings_modules_v8_output_dir)/V8GeneratedModulesBindings10.cpp', + '<(bindings_modules_v8_output_dir)/V8GeneratedModulesBindings11.cpp', + '<(bindings_modules_v8_output_dir)/V8GeneratedModulesBindings12.cpp', + '<(bindings_modules_v8_output_dir)/V8GeneratedModulesBindings13.cpp', + '<(bindings_modules_v8_output_dir)/V8GeneratedModulesBindings14.cpp', + '<(bindings_modules_v8_output_dir)/V8GeneratedModulesBindings15.cpp', + '<(bindings_modules_v8_output_dir)/V8GeneratedModulesBindings16.cpp', + '<(bindings_modules_v8_output_dir)/V8GeneratedModulesBindings17.cpp', + '<(bindings_modules_v8_output_dir)/V8GeneratedModulesBindings18.cpp', + '<(bindings_modules_v8_output_dir)/V8GeneratedModulesBindings19.cpp', + ], + }], + ], + }, +} diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/BUILD.gn b/chromium/third_party/WebKit/Source/bindings/scripts/BUILD.gn new file mode 100644 index 00000000000..1d5c639c3e1 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/BUILD.gn @@ -0,0 +1,48 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/WebKit/Source/bindings/bindings.gni") +import("//third_party/WebKit/Source/bindings/scripts/scripts.gni") +import("//third_party/WebKit/Source/bindings/templates/templates.gni") + +visibility = "//third_party/WebKit/*" + +# A separate pre-caching step is *not required* to use lex/parse table +# caching in PLY, as the caches are concurrency-safe. +# However, pre-caching ensures that all compiler processes use the cached +# files (hence maximizing speed), instead of early processes building the +# tables themselves (as they've not yet been written when they start). +# +# GYP version: scripts.gyp:cached_lex_yacc_tables +action("cached_lex_yacc_tables") { + script = "blink_idl_parser.py" + + source_prereqs = idl_lexer_parser_files + outputs = [ + "$bindings_scripts_output_dir/lextab.py", + "$bindings_scripts_output_dir/parsetab.pickle", + ] + + args = [ rebase_path(bindings_output_dir, root_build_dir) ] +} + +# A separate pre-caching step is *required* to use bytecode caching in +# Jinja (which improves speed significantly), as the bytecode cache is +# not concurrency-safe on write; details in code_generator_v8.py. +# +# GYP version: scripts.gyp:cached_jinja_templates +action("cached_jinja_templates") { + script = "code_generator_v8.py" + + source_prereqs = jinja_module_files + [ "code_generator_v8.py" ] + + code_generator_template_files + # Dummy file to track dependency. + stamp_file = "$bindings_scripts_output_dir/cached_jinja_templates.stamp" + outputs = [ stamp_file ] + + args = [ + rebase_path(bindings_scripts_output_dir, root_build_dir), + rebase_path(stamp_file, root_build_dir), + ] +} diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/__init__.py b/chromium/third_party/WebKit/Source/bindings/scripts/__init__.py new file mode 100644 index 00000000000..e69de29bb2d --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/__init__.py diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/aggregate_generated_bindings.py b/chromium/third_party/WebKit/Source/bindings/scripts/aggregate_generated_bindings.py new file mode 100755 index 00000000000..c6d3e3a5ed3 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/aggregate_generated_bindings.py @@ -0,0 +1,229 @@ +#!/usr/bin/python +# +# 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. +# +# Copyright (c) 2009 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Generate aggregate .cpp files that include multiple V8 binding .cpp files. + +This can be a single output file, to preserve symbol space; or multiple output +files, to reduce maximum compilation unit size and allow parallel compilation. + +Usage: +aggregate_generated_bindings.py COMPONENT_DIR IDL_FILES_LIST -- OUTPUT_FILE1 OUTPUT_FILE2 ... + +COMPONENT_DIR is the relative directory of a component, e.g., 'core', 'modules'. +IDL_FILES_LIST is a text file containing the IDL file paths, so the command +line doesn't exceed OS length limits. +OUTPUT_FILE1 etc. are filenames of output files. + +Design doc: http://www.chromium.org/developers/design-documents/idl-build +""" + +import errno +import os +import re +import subprocess +import sys + +from utilities import idl_filename_to_interface_name + +# A regexp for finding Conditional attributes in interface definitions. +CONDITIONAL_PATTERN = re.compile( + r'\[' + r'[^\]]*' + r'Conditional=([\_0-9a-zA-Z&|]*)' + r'[^\]]*' + r'\]\s*' + r'((callback|partial)\s+)?' + r'interface\s+' + r'\w+\s*' + r'(:\s*\w+\s*)?' + r'{', + re.MULTILINE) + +COPYRIGHT_TEMPLATE = """/* + * THIS FILE WAS AUTOMATICALLY GENERATED, DO NOT EDIT. + * + * This file was generated by the action_derivedsourcesallinone.py script. + * + * 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: + * 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. + */ +""" + + +def format_conditional(conditional): + """Wraps conditional with ENABLE() and replace '&','|' with '&&','||' if + more than one conditional is specified.""" + def wrap_with_enable(s): + if s in ['|', '&']: + return s * 2 + return 'ENABLE(' + s + ')' + return ' '.join(map(wrap_with_enable, conditional)) + + +def extract_conditional(idl_file_path): + """Find [Conditional] interface extended attribute.""" + with open(idl_file_path) as idl_file: + idl_contents = idl_file.read() + + match = CONDITIONAL_PATTERN.search(idl_contents) + if not match: + return None + conditional = match.group(1) + return re.split('([|&])', conditional) + + +def extract_meta_data(file_paths): + """Extracts conditional and interface name from each IDL file.""" + meta_data_list = [] + + for file_path in file_paths: + if not file_path.endswith('.idl'): + print 'WARNING: non-IDL file passed: "%s"' % file_path + continue + if not os.path.exists(file_path): + print 'WARNING: file not found: "%s"' % file_path + continue + + # Extract interface name from file name + interface_name = idl_filename_to_interface_name(file_path) + + meta_data = { + 'conditional': extract_conditional(file_path), + 'name': interface_name, + } + meta_data_list.append(meta_data) + + return meta_data_list + + +def generate_content(component_dir, files_meta_data_this_partition): + # Add fixed content. + output = [COPYRIGHT_TEMPLATE, + '#define NO_IMPLICIT_ATOMICSTRING\n\n'] + + # List all includes segmented by if and endif. + prev_conditional = None + files_meta_data_this_partition.sort(key=lambda e: e['conditional']) + for meta_data in files_meta_data_this_partition: + conditional = meta_data['conditional'] + if prev_conditional != conditional: + if prev_conditional: + output.append('#endif\n') + if conditional: + output.append('\n#if %s\n' % format_conditional(conditional)) + prev_conditional = conditional + + output.append('#include "bindings/%s/v8/V8%s.cpp"\n' % + (component_dir, meta_data['name'])) + + if prev_conditional: + output.append('#endif\n') + + return ''.join(output) + + +def write_content(content, output_file_name): + parent_path, file_name = os.path.split(output_file_name) + if not os.path.exists(parent_path): + print 'Creating directory: %s' % parent_path + os.makedirs(parent_path) + with open(output_file_name, 'w') as f: + f.write(content) + + +def resolve_cygpath(cygdrive_names): + if not cygdrive_names: + return [] + cmd = ['cygpath', '-f', '-', '-wa'] + process = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + idl_file_names = [] + for file_name in cygdrive_names: + process.stdin.write('%s\n' % file_name) + process.stdin.flush() + idl_file_names.append(process.stdout.readline().rstrip()) + process.stdin.close() + process.wait() + return idl_file_names + + +def main(args): + if len(args) <= 4: + raise Exception('Expected at least 5 arguments.') + component_dir = args[1] + input_file_name = args[2] + in_out_break_index = args.index('--') + output_file_names = args[in_out_break_index + 1:] + + with open(input_file_name) as input_file: + file_names = sorted([os.path.realpath(line.rstrip('\n')) + for line in input_file]) + idl_file_names = [file_name for file_name in file_names + if not file_name.startswith('/cygdrive')] + cygdrive_names = [file_name for file_name in file_names + if file_name.startswith('/cygdrive')] + idl_file_names.extend(resolve_cygpath(cygdrive_names)) + + files_meta_data = extract_meta_data(idl_file_names) + total_partitions = len(output_file_names) + for partition, file_name in enumerate(output_file_names): + files_meta_data_this_partition = [ + meta_data for meta_data in files_meta_data + if hash(meta_data['name']) % total_partitions == partition] + file_contents = generate_content(component_dir, + files_meta_data_this_partition) + write_content(file_contents, file_name) + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/blink_idl_lexer.py b/chromium/third_party/WebKit/Source/bindings/scripts/blink_idl_lexer.py index 4e6aa291e32..bbde34268b4 100644 --- a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/blink_idl_lexer.py +++ b/chromium/third_party/WebKit/Source/bindings/scripts/blink_idl_lexer.py @@ -46,6 +46,9 @@ Web IDL Grammar: http://www.w3.org/TR/WebIDL/#idl-grammar PLY: http://www.dabeaz.com/ply/ + +Design doc: +http://www.chromium.org/developers/design-documents/idl-compiler#TOC-Front-end """ # Disable attribute validation, as lint can't import parent class to check @@ -54,11 +57,16 @@ PLY: import os.path import sys -# Base lexer is in Chromium src/tools/idl_parser +# PLY is in Chromium src/third_party/ply module_path, module_name = os.path.split(__file__) -tools_dir = os.path.join(module_path, os.pardir, os.pardir, os.pardir, os.pardir, os.pardir, os.pardir, 'tools') -sys.path.append(tools_dir) +third_party = os.path.join(module_path, os.pardir, os.pardir, os.pardir, os.pardir) +# Insert at front to override system libraries, and after path[0] == script dir +sys.path.insert(1, third_party) +from ply import lex +# Base lexer is in Chromium src/tools/idl_parser +tools_dir = os.path.join(third_party, os.pardir, 'tools') +sys.path.append(tools_dir) from idl_parser.idl_lexer import IDLLexer REMOVE_TOKENS = ['COMMENT'] @@ -80,11 +88,40 @@ class BlinkIDLLexer(IDLLexer): for token in tokens: self._RemoveToken(token) - def __init__(self): + def __init__(self, debug=False, optimize=True, outputdir=None): + if debug: + # Turn off optimization and caching to help debugging + optimize = False + outputdir = None + if outputdir: + # Need outputdir in path because lex imports the cached lex table + # as a Python module + sys.path.append(outputdir) + IDLLexer.__init__(self) + # Overrides to parent class self._RemoveTokens(REMOVE_TOKENS) + # Optimized mode substantially decreases startup time (by disabling + # error checking), and also allows use of Python's optimized mode. + # See: Optimized Mode + # http://www.dabeaz.com/ply/ply.html#ply_nn15 + self._lexobj = lex.lex(object=self, + debug=debug, + optimize=optimize, + outputdir=outputdir) + + +################################################################################ + +def main(argv): + # If file itself executed, build and cache lex table + try: + outputdir = argv[1] + except IndexError as err: + print 'Usage: %s OUTPUT_DIR' % argv[0] + return 1 + lexer = BlinkIDLLexer(outputdir=outputdir) -# If run by itself, attempt to build the lexer if __name__ == '__main__': - lexer = BlinkIDLLexer() + sys.exit(main(sys.argv)) diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/blink_idl_parser.py b/chromium/third_party/WebKit/Source/bindings/scripts/blink_idl_parser.py index 3418c9f37be..6b205f2421c 100644 --- a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/blink_idl_parser.py +++ b/chromium/third_party/WebKit/Source/bindings/scripts/blink_idl_parser.py @@ -40,6 +40,9 @@ Web IDL Grammar: http://www.w3.org/TR/WebIDL/#idl-grammar PLY: http://www.dabeaz.com/ply/ + +Design doc: +http://www.chromium.org/developers/design-documents/idl-compiler#TOC-Front-end """ # Disable check for line length and Member as Function due to how grammar rules @@ -56,13 +59,13 @@ import sys # PLY is in Chromium src/third_party/ply module_path, module_name = os.path.split(__file__) -third_party = os.path.join(module_path, os.pardir, os.pardir, os.pardir, os.pardir, os.pardir) +third_party = os.path.join(module_path, os.pardir, os.pardir, os.pardir, os.pardir) # Insert at front to override system libraries, and after path[0] == script dir sys.path.insert(1, third_party) from ply import yacc # Base parser is in Chromium src/tools/idl_parser -tools_dir = os.path.join(module_path, os.pardir, os.pardir, os.pardir, os.pardir, os.pardir, os.pardir, 'tools') +tools_dir = os.path.join(module_path, os.pardir, os.pardir, os.pardir, os.pardir, os.pardir, 'tools') sys.path.append(tools_dir) from idl_parser.idl_parser import IDLParser, ListFromConcat from idl_parser.idl_parser import ParseFile as parse_file @@ -86,6 +89,12 @@ REMOVED_RULES = ['Top', # [0] 'CommentsRest', # [0.2] ] +# Remove rules from base class +# FIXME: add a class method upstream: @classmethod IDLParser._RemoveRules +for rule in REMOVED_RULES: + production_name = 'p_' + rule + delattr(IDLParser, production_name) + class BlinkIDLParser(IDLParser): # [1] @@ -231,30 +240,6 @@ class BlinkIDLParser(IDLParser): p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'DOMString'), self.BuildAttribute('NAME', p[1])) - # [b30] Add StaticAttribute - def p_AttributeOrOperation(self, p): - """AttributeOrOperation : STRINGIFIER StringifierAttributeOrOperation - | Attribute - | StaticAttribute - | Operation""" - # Standard is (no StaticAttribute): - # AttributeOrOperation : STRINGIFIER StringifierAttributeOrOperation - # | Attribute - # | Operation - if len(p) > 2: - # FIXME: Clearer to add stringifier property here, as: - # p[2].AddChildren(self.BuildTrue('STRINGIFIER')) - # Fix when actually implementing stringifiers. - p[0] = p[2] - else: - p[0] = p[1] - - # [b30.1] - def p_StaticAttribute(self, p): - """StaticAttribute : STATIC Attribute""" - p[2].AddChildren(self.BuildTrue('STATIC')) - p[0] = p[2] - # [b47] def p_ExceptionMember(self, p): """ExceptionMember : Const @@ -305,6 +290,7 @@ class BlinkIDLParser(IDLParser): | ExtendedAttributeArgList | ExtendedAttributeIdent | ExtendedAttributeIdentList + | ExtendedAttributeStringLiteralList | ExtendedAttributeNamedArgList""" p[0] = p[1] @@ -371,24 +357,69 @@ class BlinkIDLParser(IDLParser): else: p[0] = p[1] - def __dir__(self): - # Remove REMOVED_RULES from listing so yacc doesn't parse them - # FIXME: Upstream - keys = set(self.__dict__.keys() + dir(self.__class__)) - for rule in REMOVED_RULES: - production_name = 'p_' + rule - if production_name in keys: - keys.remove(production_name) - return list(keys) - - def __init__(self, lexer=None, verbose=False, debug=False, mute_error=False, outputdir=''): - lexer = lexer or BlinkIDLLexer() + # Blink extension: Add support for compound Extended Attribute values over string literals ("A"|"B") + def p_ExtendedAttributeStringLiteralList(self, p): + """ExtendedAttributeStringLiteralList : identifier '=' StringLiteralOrList""" + value = self.BuildAttribute('VALUE', p[3]) + p[0] = self.BuildNamed('ExtAttribute', p, 1, value) + + # Blink extension: one or more string literals. The values aren't propagated as literals, + # but their by their value only. + def p_StringLiteralOrList(self, p): + """StringLiteralOrList : StringLiteral '|' StringLiteralOrList + | StringLiteral""" + def unwrap_string(ls): + """Reach in and grab the string literal's "NAME".""" + return ls[1].value + + if len(p) > 3: + p[0] = unwrap_string(p[1]) + p[2] + p[3] + else: + p[0] = unwrap_string(p[1]) + + def __init__(self, + # common parameters + debug=False, + # idl_parser parameters + lexer=None, verbose=False, mute_error=False, + # yacc parameters + outputdir='', optimize=True, write_tables=False, + picklefile=None): + if debug: + # Turn off optimization and caching, and write out tables, + # to help debugging + optimize = False + outputdir = None + picklefile = None + write_tables = True + if outputdir: + picklefile = picklefile or os.path.join(outputdir, 'parsetab.pickle') + + lexer = lexer or BlinkIDLLexer(debug=debug, + outputdir=outputdir, + optimize=optimize) self.lexer = lexer self.tokens = lexer.KnownTokens() # Using SLR (instead of LALR) generates the table faster, # but produces the same output. This is ok b/c Web IDL (and Blink IDL) # is an SLR grammar (as is often the case for simple LL(1) grammars). - self.yaccobj = yacc.yacc(module=self, start=STARTING_SYMBOL, method='SLR', debug=debug, outputdir=outputdir) + # + # Optimized mode substantially decreases startup time (by disabling + # error checking), and also allows use of Python's optimized mode. + # See: Using Python's Optimized Mode + # http://www.dabeaz.com/ply/ply.html#ply_nn38 + # + # |picklefile| allows simpler importing than |tabmodule| (parsetab.py), + # as we don't need to modify sys.path; virtually identical speed. + # See: CHANGES, Version 3.2 + # http://ply.googlecode.com/svn/trunk/CHANGES + self.yaccobj = yacc.yacc(module=self, + start=STARTING_SYMBOL, + method='SLR', + debug=debug, + optimize=optimize, + write_tables=write_tables, + picklefile=picklefile) self.parse_debug = debug self.verbose = verbose self.mute_error = mute_error @@ -399,6 +430,17 @@ class BlinkIDLParser(IDLParser): self._last_error_pos = 0 -# If run by itself, attempt to build the parser +################################################################################ + +def main(argv): + # If file itself executed, cache parse table + try: + outputdir = argv[1] + except IndexError as err: + print 'Usage: %s OUTPUT_DIR' % argv[0] + return 1 + parser = BlinkIDLParser(outputdir=outputdir) + + if __name__ == '__main__': - parser = BlinkIDLParser() + sys.exit(main(sys.argv)) diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/code_generator_v8.pm b/chromium/third_party/WebKit/Source/bindings/scripts/code_generator_v8.pm deleted file mode 100644 index e19e9aa9015..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/scripts/code_generator_v8.pm +++ /dev/null @@ -1,6351 +0,0 @@ -# Copyright (C) 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org> -# Copyright (C) 2006 Anders Carlsson <andersca@mac.com> -# Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com> -# Copyright (C) 2006 Alexey Proskuryakov <ap@webkit.org> -# Copyright (C) 2006 Apple Computer, Inc. -# Copyright (C) 2007, 2008, 2009, 2012 Google Inc. -# Copyright (C) 2009 Cameron McCormack <cam@mcc.id.au> -# Copyright (C) Research In Motion Limited 2010. All rights reserved. -# Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies) -# Copyright (C) 2012 Ericsson AB. All rights reserved. -# Copyright (C) 2013 Samsung Electronics. 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 -# 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., 59 Temple Place - Suite 330, -# Boston, MA 02111-1307, USA. -# - -package Block; - -# Sample code: -# my $outer = new Block("Free Name 1", "namespace Foo {", "} // namespace Foo"); -# $outer->add(" void foo() {}"); -# my $inner = new Block("Free Name 2", "namespace Bar {", "} // namespace Bar"); -# $inner->add(" void bar() {}"); -# $outer->add($inner); -# print $outer->toString(); -# -# Output code: -# namespace Foo { -# void foo() {} -# namespace Bar { -# void bar() {} -# } // namespace Bar -# } // namespace Foo - -sub new -{ - my $package = shift; - my $name = shift || "Anonymous block"; - my $header = shift || ""; - my $footer = shift || ""; - - my $object = { - "name" => $name, - "header" => [$header], - "footer" => [$footer], - "contents" => [], - }; - bless $object, $package; - return $object; -} - -sub addHeader -{ - my $object = shift; - my $header = shift || ""; - - push(@{$object->{header}}, $header); -} - -sub addFooter -{ - my $object = shift; - my $footer = shift || ""; - - push(@{$object->{footer}}, $footer); -} - -sub add -{ - my $object = shift; - my $content = shift || ""; - - push(@{$object->{contents}}, $content); -} - -sub toString -{ - my $object = shift; - - my $header = join "", @{$object->{header}}; - my $footer = join "", @{$object->{footer}}; - my $code = ""; - $code .= "/* BEGIN " . $object->{name} . " */\n" if $verbose; - $code .= $header . "\n" if $header; - for my $content (@{$object->{contents}}) { - if (ref($content) eq "Block") { - $code .= $content->toString(); - } else { - $code .= $content; - } - } - $code .= $footer . "\n" if $footer; - $code .= "/* END " . $object->{name} . " */\n" if $verbose; - return $code; -} - - -package code_generator_v8; - -use strict; -use Cwd; -use File::Basename; -use File::Find; -use File::Spec; - -my $idlDocument; -my $idlDirectories; -my $preprocessor; -my $verbose; -my $interfaceIdlFiles; -my $writeFileOnlyIfChanged; -my $sourceRoot; - -# Cache of IDL file pathnames. -my $idlFiles; -my $cachedInterfaces = {}; - -my %implIncludes = (); -my %headerIncludes = (); - -# Header code structure: -# Root ... Copyright, include duplication check -# Conditional ... #if FEATURE ... #endif (to be removed soon) -# Includes -# NameSpaceWebCore -# Class -# ClassPublic -# ClassPrivate -my %header; - -# Implementation code structure: -# Root ... Copyright -# Conditional ... #if FEATURE ... #endif (to be removed soon) -# Includes -# NameSpaceWebCore -# NameSpaceInternal ... namespace ${implClassName}V8Internal in case of non-callback -my %implementation; - -# Promise is not yet in the Web IDL spec but is going to be speced -# as primitive types in the future. -# Since V8 dosn't provide Promise primitive object currently, -# primitiveTypeHash doesn't contain Promise. -my %primitiveTypeHash = ("Date" => 1, - "DOMString" => 1, - "DOMTimeStamp" => 1, # typedef unsigned long long - "boolean" => 1, - "void" => 1, - "byte" => 1, - "octet" => 1, - "short" => 1, - "long" => 1, - "long long" => 1, - "unsigned short" => 1, - "unsigned long" => 1, - "unsigned long long" => 1, - "float" => 1, - "double" => 1, - ); - -my %integerTypeHash = ("byte" => 1, - "octet" => 1, - "short" => 1, - "long" => 1, - "long long" => 1, - "unsigned short" => 1, - "unsigned long" => 1, - "unsigned long long" => 1, - ); - -my %nonWrapperTypes = ("CompareHow" => 1, - "Dictionary" => 1, - "EventListener" => 1, - "EventHandler" => 1, - "MediaQueryListListener" => 1, - "NodeFilter" => 1, - "SerializedScriptValue" => 1, - "any" => 1, - ); - -my %typedArrayHash = ("ArrayBuffer" => [], - "ArrayBufferView" => [], - "Uint8Array" => ["unsigned char", "v8::kExternalUnsignedByteArray"], - "Uint8ClampedArray" => ["unsigned char", "v8::kExternalPixelArray"], - "Uint16Array" => ["unsigned short", "v8::kExternalUnsignedShortArray"], - "Uint32Array" => ["unsigned int", "v8::kExternalUnsignedIntArray"], - "Int8Array" => ["signed char", "v8::kExternalByteArray"], - "Int16Array" => ["short", "v8::kExternalShortArray"], - "Int32Array" => ["int", "v8::kExternalIntArray"], - "Float32Array" => ["float", "v8::kExternalFloatArray"], - "Float64Array" => ["double", "v8::kExternalDoubleArray"], - ); - -my %callbackFunctionTypeHash = (); - -my %enumTypeHash = (); - -my %svgAttributesInHTMLHash = ("class" => 1, "id" => 1, "onabort" => 1, "onclick" => 1, - "onerror" => 1, "onload" => 1, "onmousedown" => 1, - "onmouseenter" => 1, "onmouseleave" => 1, - "onmousemove" => 1, "onmouseout" => 1, "onmouseover" => 1, - "onmouseup" => 1, "onresize" => 1, "onscroll" => 1, - "onunload" => 1); - -my %svgTypeNeedingTearOff = ( - "SVGAngle" => "SVGPropertyTearOff<SVGAngle>", - "SVGLength" => "SVGPropertyTearOff<SVGLength>", - "SVGLengthList" => "SVGListPropertyTearOff<SVGLengthList>", - "SVGMatrix" => "SVGMatrixTearOff", - "SVGNumber" => "SVGPropertyTearOff<SVGNumber>", - "SVGNumberList" => "SVGListPropertyTearOff<SVGNumberList>", - "SVGPathSegList" => "SVGPathSegListPropertyTearOff", - "SVGPoint" => "SVGPropertyTearOff<SVGPoint>", - "SVGPointList" => "SVGListPropertyTearOff<SVGPointList>", - "SVGPreserveAspectRatio" => "SVGPropertyTearOff<SVGPreserveAspectRatio>", - "SVGRect" => "SVGPropertyTearOff<SVGRect>", - "SVGStringList" => "SVGStaticListPropertyTearOff<SVGStringList>", - "SVGTransform" => "SVGPropertyTearOff<SVGTransform>", - "SVGTransformList" => "SVGTransformListPropertyTearOff" -); - -my %svgTypeWithWritablePropertiesNeedingTearOff = ( - "SVGPoint" => 1, - "SVGMatrix" => 1 -); - -# Default license header -my $licenseHeader = <<EOF; -/* - * Copyright (C) 2013 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. - */ - -// This file has been auto-generated by code_generator_v8.pm. DO NOT MODIFY! - -EOF - -sub new -{ - my $object = shift; - my $reference = { }; - - $idlDocument = shift; - $idlDirectories = shift; - $preprocessor = shift; - $verbose = shift; - $interfaceIdlFiles = shift; - $writeFileOnlyIfChanged = shift; - - $sourceRoot = dirname(dirname(dirname(Cwd::abs_path($0)))); - - bless($reference, $object); - return $reference; -} - - -sub IDLFileForInterface -{ - my $interfaceName = shift; - - unless ($idlFiles) { - my @directories = map { $_ = "$sourceRoot/$_" if -d "$sourceRoot/$_"; $_ } @$idlDirectories; - push(@directories, "."); - - $idlFiles = { }; - foreach my $idlFile (@$interfaceIdlFiles) { - $idlFiles->{fileparse(basename($idlFile), ".idl")} = $idlFile; - } - - my $wanted = sub { - $idlFiles->{$1} = $File::Find::name if /^([A-Z].*)\.idl$/; - $File::Find::prune = 1 if /^\../; - }; - find($wanted, @directories); - } - - return $idlFiles->{$interfaceName}; -} - -sub ParseInterface -{ - my $interfaceName = shift; - - if (exists $cachedInterfaces->{$interfaceName}) { - return $cachedInterfaces->{$interfaceName}; - } - - # Step #1: Find the IDL file associated with 'interface' - my $filename = IDLFileForInterface($interfaceName) - or die("Could NOT find IDL file for interface \"$interfaceName\" $!\n"); - - print " | |> Parsing parent IDL \"$filename\" for interface \"$interfaceName\"\n" if $verbose; - - # Step #2: Parse the found IDL file (in quiet mode). - my $parser = idl_parser->new(1); - my $document = $parser->Parse($filename, $preprocessor); - - foreach my $interface (@{$document->interfaces}) { - if ($interface->name eq $interfaceName or $interface->isPartial) { - $cachedInterfaces->{$interfaceName} = $interface; - return $interface; - } - } - - die("Could NOT find interface definition for $interfaceName in $filename"); -} - -sub GenerateInterface -{ - my $object = shift; - my $interface = shift; - - %callbackFunctionTypeHash = map { $_->name => $_ } @{$idlDocument->callbackFunctions}; - %enumTypeHash = map { $_->name => $_->values } @{$idlDocument->enumerations}; - my $v8ClassName = GetV8ClassName($interface); - my $defineName = $v8ClassName . "_h"; - my $internalNamespace = GetImplName($interface) . "V8Internal"; - - my $conditionalString = GenerateConditionalString($interface); - my $conditionalIf = ""; - my $conditionalEndif = ""; - if ($conditionalString) { - $conditionalIf = "#if ${conditionalString}"; - $conditionalEndif = "#endif // ${conditionalString}"; - } - - $header{root} = new Block("ROOT", "", ""); - # FIXME: newlines should be generated by Block::toString(). - $header{conditional} = new Block("Conditional", "$conditionalIf", $conditionalEndif ? "$conditionalEndif" : ""); - $header{includes} = new Block("Includes", "", ""); - $header{nameSpaceWebCore} = new Block("Namespace WebCore", "\nnamespace WebCore {\n", "}"); - $header{class} = new Block("Class definition", "", ""); - $header{classPublic} = new Block("Class public:", "public:", ""); - $header{classPrivate} = new Block("Class private:", "private:", ""); - - $header{root}->add($header{conditional}); - $header{conditional}->add($header{includes}); - $header{conditional}->add($header{nameSpaceWebCore}); - $header{nameSpaceWebCore}->add($header{class}); - $header{class}->add($header{classPublic}); - $header{class}->add($header{classPrivate}); - - # - Add default header template - $header{root}->addHeader($licenseHeader); - $header{root}->addHeader("#ifndef $defineName\n#define $defineName\n"); - $header{root}->addFooter("#endif // $defineName"); - - $implementation{root} = new Block("ROOT", "", ""); - $implementation{conditional} = new Block("Conditional", $conditionalIf, $conditionalEndif); - $implementation{includes} = new Block("Includes", "", ""); - - # FIXME: newlines should be generated by Block::toString(). - my $nameSpaceWebCoreBegin = "namespace WebCore {\n"; - my $nameSpaceWebCoreEnd = "} // namespace WebCore"; - $nameSpaceWebCoreBegin = "$nameSpaceWebCoreBegin\n" if !$interface->isCallback; - $implementation{nameSpaceWebCore} = new Block("Namespace WebCore", $nameSpaceWebCoreBegin, $nameSpaceWebCoreEnd); - $implementation{nameSpaceInternal} = new Block("Internal namespace", "namespace $internalNamespace {\n", "} // namespace $internalNamespace\n"); - - $implementation{root}->add($implementation{conditional}); - $implementation{conditional}->add($implementation{includes}); - $implementation{conditional}->add($implementation{nameSpaceWebCore}); - if (!$interface->isCallback) { - $implementation{nameSpaceWebCore}->add($implementation{nameSpaceInternal}); - } - - # - Add default header template - $implementation{root}->addHeader($licenseHeader); - $implementation{root}->addHeader("#include \"config.h\""); - $implementation{includes}->add("#include \"${v8ClassName}.h\"\n\n"); - - # Start actual generation - if ($interface->isCallback) { - $object->GenerateCallbackHeader($interface); - $object->GenerateCallbackImplementation($interface); - } else { - $object->GenerateHeader($interface); - $object->GenerateImplementation($interface); - } -} - -sub AddToImplIncludes -{ - my $header = shift; - $implIncludes{$header} = 1; -} - -sub AddToHeaderIncludes -{ - my @includes = @_; - - for my $include (@includes) { - $headerIncludes{$include} = 1; - } -} - -sub AddIncludesForType -{ - my $type = shift; - - return if IsPrimitiveType($type) or IsEnumType($type) or $type eq "object"; - - $type = $1 if $type =~ /SVG\w+TearOff<(\w+)>/; - - # Default includes - if ($type eq "SerializedScriptValue") { - AddToImplIncludes("bindings/v8/SerializedScriptValue.h"); - } elsif ($type eq "any" || IsCallbackFunctionType($type)) { - AddToImplIncludes("bindings/v8/ScriptValue.h"); - } elsif ($type eq "Promise") { - AddToImplIncludes("bindings/v8/ScriptPromise.h"); - } elsif ($type eq "EventHandler") { - AddToImplIncludes("bindings/v8/V8AbstractEventListener.h"); - AddToImplIncludes("bindings/v8/V8EventListenerList.h"); - } elsif ($type eq "Dictionary") { - AddToImplIncludes("bindings/v8/Dictionary.h"); - } elsif (IsTypedArrayType($type)) { - AddToImplIncludes("bindings/v8/custom/V8${type}Custom.h"); - } elsif (my $arrayType = GetArrayType($type)) { - AddIncludesForType($arrayType); - } else { - AddToImplIncludes("V8${type}.h"); - } -} - -sub HeaderFilesForInterface -{ - my $interfaceName = shift; - my $implClassName = shift; - - my @includes = (); - if (IsPrimitiveType($interfaceName) or IsEnumType($interfaceName) or IsCallbackFunctionType($interfaceName)) { - # Not interface type, no header files - } elsif (IsTypedArrayType($interfaceName)) { - push(@includes, "wtf/${interfaceName}.h"); - } else { - my $idlFilename = Cwd::abs_path(IDLFileForInterface($interfaceName)) or die("Could NOT find IDL file for interface \"$interfaceName\" $!\n"); - my $idlRelPath = File::Spec->abs2rel($idlFilename, $sourceRoot); - push(@includes, dirname($idlRelPath) . "/" . $implClassName . ".h"); - } - return @includes; -} - -sub NeedsVisitDOMWrapper -{ - my $interface = shift; - return $interface->extendedAttributes->{"GenerateVisitDOMWrapper"} || ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "VisitDOMWrapper") || $interface->extendedAttributes->{"SetReference"} || SVGTypeNeedsToHoldContextElement($interface->name); -} - -sub GenerateVisitDOMWrapper -{ - my $interface = shift; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - - if (ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "VisitDOMWrapper")) { - return; - } - - my $nativeType = GetNativeTypeForConversions($interface); - my $code = <<END; -void ${v8ClassName}::visitDOMWrapper(void* object, const v8::Persistent<v8::Object>& wrapper, v8::Isolate* isolate) -{ - ${nativeType}* impl = fromInternalPointer(object); -END - my $needSetWrapperReferenceContext = SVGTypeNeedsToHoldContextElement($interface->name) || $interface->extendedAttributes->{"SetReference"}; - if ($needSetWrapperReferenceContext) { - $code .= <<END; - v8::Local<v8::Object> creationContext = v8::Local<v8::Object>::New(isolate, wrapper); - V8WrapperInstantiationScope scope(creationContext, isolate); -END - } - if (SVGTypeNeedsToHoldContextElement($interface->name)) { - AddToImplIncludes("V8SVGPathElement.h"); - $code .= <<END; - if (impl->contextElement()) { - if (!DOMDataStore::containsWrapper<V8SVGElement>(impl->contextElement(), isolate)) - wrap(impl->contextElement(), creationContext, isolate); - DOMDataStore::setWrapperReference<V8SVGElement>(wrapper, impl->contextElement(), isolate); - } -END - } - for my $setReference (@{$interface->extendedAttributes->{"SetReference"}}) { - my $setReferenceType = $setReference->type; - my $setReferenceV8Type = "V8".$setReferenceType; - - my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($setReferenceType); - if ($svgPropertyType) { - $setReferenceType = $svgNativeType; - } - - my $setReferenceName = $setReference->name; - - AddIncludesForType($setReferenceType); - $code .= <<END; - ${setReferenceType}* ${setReferenceName} = impl->${setReferenceName}(); - if (${setReferenceName}) { - if (!DOMDataStore::containsWrapper<${setReferenceV8Type}>(${setReferenceName}, isolate)) - wrap(${setReferenceName}, creationContext, isolate); - DOMDataStore::setWrapperReference<${setReferenceV8Type}>(wrapper, ${setReferenceName}, isolate); - } -END - } - - my $isReachableMethod = $interface->extendedAttributes->{"GenerateVisitDOMWrapper"}; - if ($isReachableMethod) { - AddToImplIncludes("bindings/v8/V8GCController.h"); - AddToImplIncludes("core/dom/Element.h"); - $code .= <<END; - if (Node* owner = impl->${isReachableMethod}()) { - setObjectGroup(V8GCController::opaqueRootForGC(owner, isolate), wrapper, isolate); - return; - } -END - } - - $code .= <<END; - setObjectGroup(object, wrapper, isolate); -} - -END - $implementation{nameSpaceWebCore}->add($code); -} - -sub GetSVGPropertyTypes -{ - my $implType = shift; - - my $svgPropertyType; - my $svgListPropertyType; - my $svgNativeType; - - return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $implType =~ /SVG/; - - $svgNativeType = GetSVGTypeNeedingTearOff($implType); - return ($svgPropertyType, $svgListPropertyType, $svgNativeType) if not $svgNativeType; - - # Append space to avoid compilation errors when using PassRefPtr<$svgNativeType> - $svgNativeType = "$svgNativeType "; - - my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($implType); - if ($svgNativeType =~ /SVGPropertyTearOff/) { - $svgPropertyType = $svgWrappedNativeType; - AddToHeaderIncludes("core/svg/properties/SVGAnimatedPropertyTearOff.h"); - } elsif ($svgNativeType =~ /SVGMatrixTearOff/) { - $svgPropertyType = $svgWrappedNativeType; - AddToHeaderIncludes("core/svg/properties/SVGMatrixTearOff.h"); - AddToHeaderIncludes("core/svg/properties/SVGAnimatedPropertyTearOff.h"); - } elsif ($svgNativeType =~ /SVGListPropertyTearOff/ or $svgNativeType =~ /SVGStaticListPropertyTearOff/ or $svgNativeType =~ /SVGTransformListPropertyTearOff/) { - $svgListPropertyType = $svgWrappedNativeType; - AddToHeaderIncludes("core/svg/properties/SVGAnimatedListPropertyTearOff.h"); - } elsif ($svgNativeType =~ /SVGPathSegListPropertyTearOff/) { - $svgListPropertyType = $svgWrappedNativeType; - AddToHeaderIncludes("core/svg/properties/SVGPathSegListPropertyTearOff.h"); - } - - return ($svgPropertyType, $svgListPropertyType, $svgNativeType); -} - -sub GetIndexedGetterFunction -{ - my $interface = shift; - - # FIXME: Expose indexed getter of CSSMixFunctionValue by removing this special case - # because CSSValueList(which is parent of CSSMixFunctionValue) has indexed property getter. - if ($interface->name eq "CSSMixFunctionValue") { - return 0; - } - - return GetSpecialAccessorFunctionForType($interface, "getter", "unsigned long", 1); -} - -sub GetIndexedSetterFunction -{ - my $interface = shift; - - return GetSpecialAccessorFunctionForType($interface, "setter", "unsigned long", 2); -} - -sub GetIndexedDeleterFunction -{ - my $interface = shift; - - return GetSpecialAccessorFunctionForType($interface, "deleter", "unsigned long", 1); -} - -sub GetNamedGetterFunction -{ - my $interface = shift; - return GetSpecialAccessorFunctionForType($interface, "getter", "DOMString", 1); -} - -sub GetNamedSetterFunction -{ - my $interface = shift; - return GetSpecialAccessorFunctionForType($interface, "setter", "DOMString", 2); -} - -sub GetNamedDeleterFunction -{ - my $interface = shift; - return GetSpecialAccessorFunctionForType($interface, "deleter", "DOMString", 1); -} - -sub GetSpecialAccessorFunctionForType -{ - my $interface = shift; - my $special = shift; - my $firstParameterType = shift; - my $numberOfParameters = shift; - - foreach my $function (@{$interface->functions}) { - my $specials = $function->specials; - my $specialExists = grep { $_ eq $special } @$specials; - my $parameters = $function->parameters; - if ($specialExists and scalar(@$parameters) == $numberOfParameters and $parameters->[0]->type eq $firstParameterType) { - return $function; - } - } - - return 0; -} - -sub GetV8StringResourceMode -{ - my $extendedAttributes = shift; - - # Blink uses the non-standard identifier NullString instead of Web IDL - # standard EmptyString, in [TreatNullAs=NullString] and [TreatUndefinedAs=NullString], - # and does not support [TreatUndefinedAs=Null] or [TreatUndefinedAs=Missing] - # https://sites.google.com/a/chromium.org/dev/blink/webidl/blink-idl-extended-attributes#TOC-TreatNullAs-a-p-TreatUndefinedAs-a-p- - my $mode = ""; - if (($extendedAttributes->{"TreatNullAs"} and $extendedAttributes->{"TreatNullAs"} eq "NullString") and ($extendedAttributes->{"TreatUndefinedAs"} and $extendedAttributes->{"TreatUndefinedAs"} eq "NullString")) { - $mode = "WithUndefinedOrNullCheck"; - } elsif ($extendedAttributes->{"TreatNullAs"} and $extendedAttributes->{"TreatNullAs"} eq "NullString") { - $mode = "WithNullCheck"; - } - return $mode; -} - -sub GenerateHeader -{ - my $object = shift; - my $interface = shift; - - my $interfaceName = $interface->name; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - - LinkOverloadedFunctions($interface); - - # Ensure the IsDOMNodeType function is in sync. - die("IsDOMNodeType is out of date with respect to $interfaceName") if IsDOMNodeType($interfaceName) != InheritsInterface($interface, "Node"); - - my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($interfaceName); - - my $parentInterface = $interface->parent; - AddToHeaderIncludes("V8${parentInterface}.h") if $parentInterface; - AddToHeaderIncludes("bindings/v8/WrapperTypeInfo.h"); - AddToHeaderIncludes("bindings/v8/V8Binding.h"); - AddToHeaderIncludes("bindings/v8/V8DOMWrapper.h"); - AddToHeaderIncludes(HeaderFilesForInterface($interfaceName, $implClassName)); - foreach my $headerInclude (sort keys(%headerIncludes)) { - $header{includes}->add("#include \"${headerInclude}\"\n"); - } - - $header{nameSpaceWebCore}->addHeader("\ntemplate<typename PropertyType> class SVGPropertyTearOff;\n") if $svgPropertyType; - if ($svgNativeType) { - if ($svgNativeType =~ /SVGStaticListPropertyTearOff/) { - $header{nameSpaceWebCore}->addHeader("\ntemplate<typename PropertyType> class SVGStaticListPropertyTearOff;\n"); - } else { - $header{nameSpaceWebCore}->addHeader("\ntemplate<typename PropertyType> class SVGListPropertyTearOff;\n"); - } - } - - $header{nameSpaceWebCore}->addHeader("\nclass Dictionary;") if $interface->extendedAttributes->{"EventConstructor"}; - - my $nativeType = GetNativeTypeForConversions($interface); - if ($interface->extendedAttributes->{"NamedConstructor"}) { - $header{nameSpaceWebCore}->addHeader(<<END); - -class V8${nativeType}Constructor { -public: - static v8::Handle<v8::FunctionTemplate> domTemplate(v8::Isolate*, WrapperWorldType); - static const WrapperTypeInfo wrapperTypeInfo; -}; -END - } - - $header{class}->addHeader("class $v8ClassName {"); - $header{class}->addFooter("};"); - - $header{classPublic}->add(<<END); - static bool hasInstance(v8::Handle<v8::Value>, v8::Isolate*, WrapperWorldType); - static bool hasInstanceInAnyWorld(v8::Handle<v8::Value>, v8::Isolate*); - static v8::Handle<v8::FunctionTemplate> domTemplate(v8::Isolate*, WrapperWorldType); - static ${nativeType}* toNative(v8::Handle<v8::Object> object) - { - return fromInternalPointer(object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex)); - } - static void derefObject(void*); - static const WrapperTypeInfo wrapperTypeInfo; -END - - if (NeedsVisitDOMWrapper($interface)) { - $header{classPublic}->add(" static void visitDOMWrapper(void*, const v8::Persistent<v8::Object>&, v8::Isolate*);\n"); - } - - if (InheritsExtendedAttribute($interface, "ActiveDOMObject")) { - $header{classPublic}->add(" static ActiveDOMObject* toActiveDOMObject(v8::Handle<v8::Object>);\n"); - } - - if (InheritsInterface($interface, "EventTarget")) { - $header{classPublic}->add(" static EventTarget* toEventTarget(v8::Handle<v8::Object>);\n"); - } - - if ($interfaceName eq "Window") { - $header{classPublic}->add(<<END); - static v8::Handle<v8::ObjectTemplate> GetShadowObjectTemplate(v8::Isolate*, WrapperWorldType); -END - } - - my @perContextEnabledFunctions; - foreach my $function (@{$interface->functions}) { - my $name = $function->name; - next if $name eq ""; - my $attrExt = $function->extendedAttributes; - - if (HasCustomMethod($attrExt) && $function->{overloadIndex} == 1) { - my $conditionalString = GenerateConditionalString($function); - $header{classPublic}->add("#if ${conditionalString}\n") if $conditionalString; - $header{classPublic}->add(<<END); - static void ${name}MethodCustom(const v8::FunctionCallbackInfo<v8::Value>&); -END - $header{classPublic}->add("#endif // ${conditionalString}\n") if $conditionalString; - } - if ($attrExt->{"PerContextEnabled"}) { - push(@perContextEnabledFunctions, $function); - } - } - - if (IsConstructable($interface)) { - $header{classPublic}->add(" static void constructorCallback(const v8::FunctionCallbackInfo<v8::Value>&);\n"); -END - } - if (HasCustomConstructor($interface)) { - $header{classPublic}->add(" static void constructorCustom(const v8::FunctionCallbackInfo<v8::Value>&);\n"); - } - - my @perContextEnabledAttributes; - foreach my $attribute (@{$interface->attributes}) { - my $name = $attribute->name; - my $attrExt = $attribute->extendedAttributes; - my $conditionalString = GenerateConditionalString($attribute); - if (HasCustomGetter($attrExt) && !$attrExt->{"ImplementedBy"}) { - $header{classPublic}->add("#if ${conditionalString}\n") if $conditionalString; - $header{classPublic}->add(<<END); - static void ${name}AttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>&); -END - $header{classPublic}->add("#endif // ${conditionalString}\n") if $conditionalString; - } - if (HasCustomSetter($attribute) && !$attrExt->{"ImplementedBy"}) { - $header{classPublic}->add("#if ${conditionalString}\n") if $conditionalString; - $header{classPublic}->add(<<END); - static void ${name}AttributeSetterCustom(v8::Local<v8::Value>, const v8::PropertyCallbackInfo<void>&); -END - $header{classPublic}->add("#endif // ${conditionalString}\n") if $conditionalString; - } - if ($attrExt->{"PerContextEnabled"}) { - push(@perContextEnabledAttributes, $attribute); - } - } - - GenerateHeaderNamedAndIndexedPropertyAccessors($interface); - GenerateHeaderLegacyCallAsFunction($interface); - GenerateHeaderCustomInternalFieldIndices($interface); - - my $toWrappedType; - my $fromWrappedType; - if ($interface->parent) { - my $v8ParentClassName = "V8" . $interface->parent; - $toWrappedType = "${v8ParentClassName}::toInternalPointer(impl)"; - $fromWrappedType = "static_cast<${nativeType}*>(${v8ParentClassName}::fromInternalPointer(object))"; - } else { - $toWrappedType = "impl"; - $fromWrappedType = "static_cast<${nativeType}*>(object)"; - } - - $header{classPublic}->add(<<END); - static inline void* toInternalPointer(${nativeType}* impl) - { - return $toWrappedType; - } - - static inline ${nativeType}* fromInternalPointer(void* object) - { - return $fromWrappedType; - } -END - - if ($interface->name eq "Window") { - $header{classPublic}->add(<<END); - static bool namedSecurityCheckCustom(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType, v8::Local<v8::Value> data); - static bool indexedSecurityCheckCustom(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data); -END - } - - if (@perContextEnabledAttributes) { - $header{classPublic}->add(<<END); - static void installPerContextEnabledProperties(v8::Handle<v8::Object>, ${nativeType}*, v8::Isolate*); -END - } else { - $header{classPublic}->add(<<END); - static void installPerContextEnabledProperties(v8::Handle<v8::Object>, ${nativeType}*, v8::Isolate*) { } -END - } - - if (@perContextEnabledFunctions) { - $header{classPublic}->add(<<END); - static void installPerContextEnabledMethods(v8::Handle<v8::Object>, v8::Isolate*); -END - } else { - $header{classPublic}->add(<<END); - static void installPerContextEnabledMethods(v8::Handle<v8::Object>, v8::Isolate*) { } -END - } - - if ($interfaceName eq "HTMLElement") { - $header{classPublic}->add(<<END); - friend v8::Handle<v8::Object> createV8HTMLWrapper(HTMLElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*); - friend v8::Handle<v8::Object> createV8HTMLDirectWrapper(HTMLElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*); -END - } elsif ($interfaceName eq "SVGElement") { - $header{classPublic}->add(<<END); - friend v8::Handle<v8::Object> createV8SVGWrapper(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*); - friend v8::Handle<v8::Object> createV8SVGDirectWrapper(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*); - friend v8::Handle<v8::Object> createV8SVGFallbackWrapper(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*); -END - } elsif ($interfaceName eq "HTMLUnknownElement") { - $header{classPublic}->add(<<END); - friend v8::Handle<v8::Object> createV8HTMLFallbackWrapper(HTMLUnknownElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*); -END - } elsif ($interfaceName eq "Element") { - $header{classPublic}->add(<<END); - // This is a performance optimization hack. See V8Element::wrap. - friend v8::Handle<v8::Object> wrap(Node*, v8::Handle<v8::Object> creationContext, v8::Isolate*); -END - } - $header{classPublic}->add("\n"); # blank line to separate classPrivate - - my $customToV8 = ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "ToV8"); - if (!$customToV8) { - my $createWrapperArgumentType = GetPassRefPtrType($nativeType); - $header{classPrivate}->add(<<END); - friend v8::Handle<v8::Object> wrap(${nativeType}*, v8::Handle<v8::Object> creationContext, v8::Isolate*); - static v8::Handle<v8::Object> createWrapper(${createWrapperArgumentType}, v8::Handle<v8::Object> creationContext, v8::Isolate*); -END - } - - $header{nameSpaceWebCore}->add(<<END); - -template<> -class WrapperTypeTraits<${nativeType} > { -public: - static const WrapperTypeInfo* wrapperTypeInfo() { return &${v8ClassName}::wrapperTypeInfo; } -}; -END - - my $customWrap = NeedsSpecialWrap($interface); - if ($customToV8) { - $header{nameSpaceWebCore}->add(<<END); - -class ${nativeType}; -v8::Handle<v8::Value> toV8(${nativeType}*, v8::Handle<v8::Object> creationContext, v8::Isolate*); - -template<class CallbackInfo> -inline void v8SetReturnValue(const CallbackInfo& callbackInfo, ${nativeType}* impl) -{ - v8SetReturnValue(callbackInfo, toV8(impl, callbackInfo.Holder(), callbackInfo.GetIsolate())); -} - -template<class CallbackInfo> -inline void v8SetReturnValueForMainWorld(const CallbackInfo& callbackInfo, ${nativeType}* impl) -{ - v8SetReturnValue(callbackInfo, toV8(impl, callbackInfo.Holder(), callbackInfo.GetIsolate())); -} - -template<class CallbackInfo, class Wrappable> -inline void v8SetReturnValueFast(const CallbackInfo& callbackInfo, ${nativeType}* impl, Wrappable*) -{ - v8SetReturnValue(callbackInfo, toV8(impl, callbackInfo.Holder(), callbackInfo.GetIsolate())); -} -END - } else { - if ($customWrap) { - $header{nameSpaceWebCore}->add(<<END); - -v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate*); -END - } else { - $header{nameSpaceWebCore}->add(<<END); - -inline v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) -{ - ASSERT(impl); - ASSERT(!DOMDataStore::containsWrapper<${v8ClassName}>(impl, isolate)); - return ${v8ClassName}::createWrapper(impl, creationContext, isolate); -} -END - } - - $header{nameSpaceWebCore}->add(<<END); - -inline v8::Handle<v8::Value> toV8(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) -{ - if (UNLIKELY(!impl)) - return v8::Null(isolate); - v8::Handle<v8::Value> wrapper = DOMDataStore::getWrapper<${v8ClassName}>(impl, isolate); - if (!wrapper.IsEmpty()) - return wrapper; - return wrap(impl, creationContext, isolate); -} - -template<typename CallbackInfo> -inline void v8SetReturnValue(const CallbackInfo& callbackInfo, ${nativeType}* impl) -{ - if (UNLIKELY(!impl)) { - v8SetReturnValueNull(callbackInfo); - return; - } - if (DOMDataStore::setReturnValueFromWrapper<${v8ClassName}>(callbackInfo.GetReturnValue(), impl)) - return; - v8::Handle<v8::Object> wrapper = wrap(impl, callbackInfo.Holder(), callbackInfo.GetIsolate()); - v8SetReturnValue(callbackInfo, wrapper); -} - -template<typename CallbackInfo> -inline void v8SetReturnValueForMainWorld(const CallbackInfo& callbackInfo, ${nativeType}* impl) -{ - ASSERT(worldType(callbackInfo.GetIsolate()) == MainWorld); - if (UNLIKELY(!impl)) { - v8SetReturnValueNull(callbackInfo); - return; - } - if (DOMDataStore::setReturnValueFromWrapperForMainWorld<${v8ClassName}>(callbackInfo.GetReturnValue(), impl)) - return; - v8::Handle<v8::Value> wrapper = wrap(impl, callbackInfo.Holder(), callbackInfo.GetIsolate()); - v8SetReturnValue(callbackInfo, wrapper); -} - -template<class CallbackInfo, class Wrappable> -inline void v8SetReturnValueFast(const CallbackInfo& callbackInfo, ${nativeType}* impl, Wrappable* wrappable) -{ - if (UNLIKELY(!impl)) { - v8SetReturnValueNull(callbackInfo); - return; - } - if (DOMDataStore::setReturnValueFromWrapperFast<${v8ClassName}>(callbackInfo.GetReturnValue(), impl, callbackInfo.Holder(), wrappable)) - return; - v8::Handle<v8::Object> wrapper = wrap(impl, callbackInfo.Holder(), callbackInfo.GetIsolate()); - v8SetReturnValue(callbackInfo, wrapper); -} -END - } - - $header{nameSpaceWebCore}->add(<<END); - -inline v8::Handle<v8::Value> toV8(PassRefPtr<${nativeType} > impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) -{ - return toV8(impl.get(), creationContext, isolate); -} - -template<class CallbackInfo> -inline void v8SetReturnValue(const CallbackInfo& callbackInfo, PassRefPtr<${nativeType} > impl) -{ - v8SetReturnValue(callbackInfo, impl.get()); -} - -template<class CallbackInfo> -inline void v8SetReturnValueForMainWorld(const CallbackInfo& callbackInfo, PassRefPtr<${nativeType} > impl) -{ - v8SetReturnValueForMainWorld(callbackInfo, impl.get()); -} - -template<class CallbackInfo, class Wrappable> -inline void v8SetReturnValueFast(const CallbackInfo& callbackInfo, PassRefPtr<${nativeType} > impl, Wrappable* wrappable) -{ - v8SetReturnValueFast(callbackInfo, impl.get(), wrappable); -} - -END - - if ($interface->extendedAttributes->{"EventConstructor"}) { - $header{nameSpaceWebCore}->add("bool initialize${implClassName}(${implClassName}Init&, const Dictionary&, ExceptionState&, const String& = \"\");\n\n"); - } -} - -sub GetInternalFields -{ - my $interface = shift; - - my @customInternalFields = (); - # Event listeners on DOM nodes are explicitly supported in the GC controller. - if (!InheritsInterface($interface, "Node") && - InheritsInterface($interface, "EventTarget")) { - push(@customInternalFields, "eventListenerCacheIndex"); - } - return @customInternalFields; -} - -sub GenerateHeaderCustomInternalFieldIndices -{ - my $interface = shift; - my @customInternalFields = GetInternalFields($interface); - my $customFieldCounter = 0; - foreach my $customInternalField (@customInternalFields) { - $header{classPublic}->add(<<END); - static const int ${customInternalField} = v8DefaultWrapperInternalFieldCount + ${customFieldCounter}; -END - $customFieldCounter++; - } - $header{classPublic}->add(<<END); - static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + ${customFieldCounter}; -END -} - -sub GenerateHeaderNamedAndIndexedPropertyAccessors -{ - my $interface = shift; - - my $indexedGetterFunction = GetIndexedGetterFunction($interface); - my $hasCustomIndexedGetter = $indexedGetterFunction && $indexedGetterFunction->extendedAttributes->{"Custom"}; - - my $indexedSetterFunction = GetIndexedSetterFunction($interface); - my $hasCustomIndexedSetter = $indexedSetterFunction && $indexedSetterFunction->extendedAttributes->{"Custom"}; - - my $indexedDeleterFunction = GetIndexedDeleterFunction($interface); - my $hasCustomIndexedDeleters = $indexedDeleterFunction && $indexedDeleterFunction->extendedAttributes->{"Custom"}; - - my $namedGetterFunction = GetNamedGetterFunction($interface); - my $hasCustomNamedGetter = $namedGetterFunction && $namedGetterFunction->extendedAttributes->{"Custom"}; - - my $namedSetterFunction = GetNamedSetterFunction($interface); - my $hasCustomNamedSetter = $namedSetterFunction && $namedSetterFunction->extendedAttributes->{"Custom"}; - - my $namedDeleterFunction = GetNamedDeleterFunction($interface); - my $hasCustomNamedDeleter = $namedDeleterFunction && $namedDeleterFunction->extendedAttributes->{"Custom"}; - - my $namedEnumeratorFunction = $namedGetterFunction && !$namedGetterFunction->extendedAttributes->{"NotEnumerable"}; - my $hasCustomNamedEnumerator = $namedGetterFunction && $namedGetterFunction->extendedAttributes->{"CustomEnumerateProperty"}; - - if ($hasCustomIndexedGetter) { - $header{classPublic}->add(" static void indexedPropertyGetterCustom(uint32_t, const v8::PropertyCallbackInfo<v8::Value>&);\n"); - } - - if ($hasCustomIndexedSetter) { - $header{classPublic}->add(" static void indexedPropertySetterCustom(uint32_t, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);\n"); - } - - if ($hasCustomIndexedDeleters) { - $header{classPublic}->add(" static void indexedPropertyDeleterCustom(uint32_t, const v8::PropertyCallbackInfo<v8::Boolean>&);\n"); - } - - if ($hasCustomNamedGetter) { - $header{classPublic}->add(" static void namedPropertyGetterCustom(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>&);\n"); - } - - if ($hasCustomNamedSetter) { - $header{classPublic}->add(" static void namedPropertySetterCustom(v8::Local<v8::String>, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&);\n"); - } - - if ($hasCustomNamedDeleter) { - $header{classPublic}->add(" static void namedPropertyDeleterCustom(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Boolean>&);\n"); - } - - if ($hasCustomNamedEnumerator) { - $header{classPublic}->add(" static void namedPropertyEnumeratorCustom(const v8::PropertyCallbackInfo<v8::Array>&);\n"); - $header{classPublic}->add(" static void namedPropertyQueryCustom(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Integer>&);\n"); - } -} - -sub GenerateHeaderLegacyCallAsFunction -{ - my $interface = shift; - - if (ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "LegacyCallAsFunction")) { - $header{classPublic}->add(" static void legacyCallCustom(const v8::FunctionCallbackInfo<v8::Value>&);\n"); - } -} - -sub HasActivityLogging -{ - my $forMainWorldSuffix = shift; - my $attrExt = shift; - my $access = shift; - - if (!$attrExt->{"ActivityLogging"}) { - return 0; - } - my $logAllAccess = ($attrExt->{"ActivityLogging"} =~ /^For/); # No prefix, starts with For*Worlds suffix - my $logGetter = ($attrExt->{"ActivityLogging"} =~ /^Getter/); - my $logSetter = ($attrExt->{"ActivityLogging"} =~ /^Setter/); - my $logOnlyIsolatedWorlds = ($attrExt->{"ActivityLogging"} =~ /ForIsolatedWorlds$/); - - if ($logOnlyIsolatedWorlds && $forMainWorldSuffix eq "ForMainWorld") { - return 0; - } - return $logAllAccess || ($logGetter && $access eq "Getter") || ($logSetter && $access eq "Setter"); -} - -sub IsConstructable -{ - my $interface = shift; - - return $interface->extendedAttributes->{"CustomConstructor"} || $interface->extendedAttributes->{"Constructor"} || $interface->extendedAttributes->{"EventConstructor"}; -} - -sub HasCustomConstructor -{ - my $interface = shift; - - return $interface->extendedAttributes->{"CustomConstructor"}; -} - -sub HasCustomGetter -{ - my $attrExt = shift; - my $custom = $attrExt->{"Custom"}; - return $custom && ($custom eq "VALUE_IS_MISSING" || $custom eq "Getter"); -} - -sub HasCustomSetter -{ - my $attribute = shift; - my $custom = $attribute->extendedAttributes->{"Custom"}; - return $custom && ($custom eq "VALUE_IS_MISSING" || $custom eq "Setter") && !IsReadonly($attribute); -} - -sub HasCustomMethod -{ - my $attrExt = shift; - return $attrExt->{"Custom"}; -} - -sub IsReadonly -{ - my $attribute = shift; - my $attrExt = $attribute->extendedAttributes; - return $attribute->isReadOnly && !$attrExt->{"Replaceable"} && !$attrExt->{"PutForwards"}; -} - -sub GetV8ClassName -{ - my $interface = shift; - return "V8" . $interface->name; -} - -sub GetImplName -{ - my $interfaceOrAttributeOrFunction = shift; - return $interfaceOrAttributeOrFunction->extendedAttributes->{"ImplementedAs"} || $interfaceOrAttributeOrFunction->name; -} - -sub GetImplNameFromImplementedBy -{ - my $implementedBy = shift; - - my $interface = ParseInterface($implementedBy); - - return $interface->extendedAttributes->{"ImplementedAs"} || $implementedBy; -} - -sub GenerateDomainSafeFunctionGetter -{ - my $function = shift; - my $interface = shift; - my $forMainWorldSuffix = shift; - - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - my $funcName = $function->name; - - my $functionLength = GetFunctionLength($function); - my $signature = "v8::Signature::New(info.GetIsolate(), V8PerIsolateData::from(info.GetIsolate())->rawDOMTemplate(&" . $v8ClassName . "::wrapperTypeInfo, currentWorldType))"; - if ($function->extendedAttributes->{"DoNotCheckSignature"}) { - $signature = "v8::Local<v8::Signature>()"; - } - - my $newTemplateParams = "${implClassName}V8Internal::${funcName}MethodCallback${forMainWorldSuffix}, v8Undefined(), $signature"; - - AddToImplIncludes("bindings/v8/BindingSecurity.h"); - $implementation{nameSpaceInternal}->add(<<END); -static void ${funcName}OriginSafeMethodGetter${forMainWorldSuffix}(const v8::PropertyCallbackInfo<v8::Value>& info) -{ - // This is only for getting a unique pointer which we can pass to privateTemplate. - static int privateTemplateUniqueKey; - WrapperWorldType currentWorldType = worldType(info.GetIsolate()); - V8PerIsolateData* data = V8PerIsolateData::from(info.GetIsolate()); - v8::Handle<v8::FunctionTemplate> privateTemplate = data->privateTemplate(currentWorldType, &privateTemplateUniqueKey, $newTemplateParams, $functionLength); - - v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(${v8ClassName}::domTemplate(info.GetIsolate(), currentWorldType)); - if (holder.IsEmpty()) { - // This is only reachable via |object.__proto__.func|, in which case it - // has already passed the same origin security check - v8SetReturnValue(info, privateTemplate->GetFunction()); - return; - } - ${implClassName}* imp = ${v8ClassName}::toNative(holder); - if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame(), DoNotReportSecurityError)) { - static int sharedTemplateUniqueKey; - v8::Handle<v8::FunctionTemplate> sharedTemplate = data->privateTemplate(currentWorldType, &sharedTemplateUniqueKey, $newTemplateParams, $functionLength); - v8SetReturnValue(info, sharedTemplate->GetFunction()); - return; - } - - v8::Local<v8::Value> hiddenValue = info.This()->GetHiddenValue(v8::String::NewFromUtf8(info.GetIsolate(), "${funcName}", v8::String::kInternalizedString)); - if (!hiddenValue.IsEmpty()) { - v8SetReturnValue(info, hiddenValue); - return; - } - - v8SetReturnValue(info, privateTemplate->GetFunction()); -} - -END - $implementation{nameSpaceInternal}->add(<<END); -static void ${funcName}OriginSafeMethodGetterCallback${forMainWorldSuffix}(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info) -{ - TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMGetter"); - ${implClassName}V8Internal::${funcName}OriginSafeMethodGetter${forMainWorldSuffix}(info); - TRACE_EVENT_SET_SAMPLING_STATE("V8", "Execution"); -} - -END -} - -sub GenerateDomainSafeFunctionSetter -{ - my $interface = shift; - - my $interfaceName = $interface->name(); - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - - AddToImplIncludes("bindings/v8/BindingSecurity.h"); - $implementation{nameSpaceInternal}->add(<<END); -static void ${implClassName}OriginSafeMethodSetter(v8::Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info) -{ - v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(${v8ClassName}::domTemplate(info.GetIsolate(), worldType(info.GetIsolate()))); - if (holder.IsEmpty()) - return; - ${implClassName}* imp = ${v8ClassName}::toNative(holder); - v8::String::Utf8Value attributeName(name); - ExceptionState exceptionState(ExceptionState::SetterContext, *attributeName, "${interfaceName}", info.Holder(), info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame(), exceptionState)) { - exceptionState.throwIfNeeded(); - return; - } - - info.This()->SetHiddenValue(name, jsValue); -} - -static void ${implClassName}OriginSafeMethodSetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info) -{ - TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMSetter"); - ${implClassName}V8Internal::${implClassName}OriginSafeMethodSetter(name, jsValue, info); - TRACE_EVENT_SET_SAMPLING_STATE("V8", "Execution"); -} - -END -} - -sub GenerateConstructorGetter -{ - my $interface = shift; - my $implClassName = GetImplName($interface); - - $implementation{nameSpaceInternal}->add(<<END); -static void ${implClassName}ConstructorGetter(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info) -{ - v8::Handle<v8::Value> data = info.Data(); - ASSERT(data->IsExternal()); - V8PerContextData* perContextData = V8PerContextData::from(info.Holder()->CreationContext()); - if (!perContextData) - return; - v8SetReturnValue(info, perContextData->constructorForType(WrapperTypeInfo::unwrap(data))); -} - -END -} - -sub GenerateFeatureObservation -{ - my $measureAs = shift; - - if ($measureAs) { - AddToImplIncludes("core/frame/UseCounter.h"); - return " UseCounter::count(activeDOMWindow(), UseCounter::${measureAs});\n"; - } - - return ""; -} - -sub GenerateDeprecationNotification -{ - my $deprecateAs = shift; - if ($deprecateAs) { - AddToImplIncludes("core/frame/UseCounter.h"); - return " UseCounter::countDeprecation(activeExecutionContext(), UseCounter::${deprecateAs});\n"; - } - return ""; -} - -sub GenerateActivityLogging -{ - my $accessType = shift; - my $interface = shift; - my $propertyName = shift; - - my $interfaceName = $interface->name; - - AddToImplIncludes("bindings/v8/V8DOMActivityLogger.h"); - - my $code = ""; - if ($accessType eq "Method") { - $code .= <<END; - V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->GetCurrentContext()); - if (contextData && contextData->activityLogger()) { - Vector<v8::Handle<v8::Value> > loggerArgs = toNativeArguments<v8::Handle<v8::Value> >(info, 0); - contextData->activityLogger()->log("${interfaceName}.${propertyName}", info.Length(), loggerArgs.data(), "${accessType}"); - } -END - } elsif ($accessType eq "Setter") { - $code .= <<END; - V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->GetCurrentContext()); - if (contextData && contextData->activityLogger()) { - v8::Handle<v8::Value> loggerArg[] = { jsValue }; - contextData->activityLogger()->log("${interfaceName}.${propertyName}", 1, &loggerArg[0], "${accessType}"); - } -END - } elsif ($accessType eq "Getter") { - $code .= <<END; - V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->GetCurrentContext()); - if (contextData && contextData->activityLogger()) - contextData->activityLogger()->log("${interfaceName}.${propertyName}", 0, 0, "${accessType}"); -END - } else { - die "Unrecognized activity logging access type"; - } - - return $code; -} - -sub GenerateNormalAttributeGetterCallback -{ - my $attribute = shift; - my $interface = shift; - my $forMainWorldSuffix = shift; - my $exposeJSAccessors = shift; - - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - my $attrExt = $attribute->extendedAttributes; - my $attrName = $attribute->name; - - my $conditionalString = GenerateConditionalString($attribute); - my $code = ""; - $code .= "#if ${conditionalString}\n" if $conditionalString; - - if ($exposeJSAccessors) { - $code .= "static void ${attrName}AttributeGetterCallback${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8::Value>& info)\n"; - } else { - $code .= "static void ${attrName}AttributeGetterCallback${forMainWorldSuffix}(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; - } - $code .= "{\n"; - $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMGetter\");\n"; - $code .= GenerateFeatureObservation($attrExt->{"MeasureAs"}); - $code .= GenerateDeprecationNotification($attrExt->{"DeprecateAs"}); - if (HasActivityLogging($forMainWorldSuffix, $attrExt, "Getter")) { - $code .= GenerateActivityLogging("Getter", $interface, "${attrName}"); - } - if (HasCustomGetter($attrExt)) { - $code .= " ${v8ClassName}::${attrName}AttributeGetterCustom(info);\n"; - } else { - $code .= " ${implClassName}V8Internal::${attrName}AttributeGetter${forMainWorldSuffix}(info);\n"; - } - $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; - $code .= "}\n"; - $code .= "#endif // ${conditionalString}\n" if $conditionalString; - $code .= "\n"; - - $implementation{nameSpaceInternal}->add($code); -} - -sub GetCachedAttribute -{ - my $attribute = shift; - my $attrExt = $attribute->extendedAttributes; - if (($attribute->type eq "any" || $attribute->type eq "SerializedScriptValue") && $attrExt->{"CachedAttribute"}) { - return $attrExt->{"CachedAttribute"}; - } - return ""; -} - -sub GenerateNormalAttributeGetter -{ - my $attribute = shift; - my $interface = shift; - my $forMainWorldSuffix = shift; - my $exposeJSAccessors = shift; - - my $interfaceName = $interface->name; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - my $attrExt = $attribute->extendedAttributes; - my $attrName = $attribute->name; - my $attrType = $attribute->type; - my $attrCached = GetCachedAttribute($attribute); - - if (HasCustomGetter($attrExt)) { - return; - } - - AssertNotSequenceType($attrType); - my $nativeType = GetNativeType($attribute->type, $attribute->extendedAttributes, ""); - my $svgNativeType = GetSVGTypeNeedingTearOff($interfaceName); - - my $conditionalString = GenerateConditionalString($attribute); - my $code = ""; - $code .= "#if ${conditionalString}\n" if $conditionalString; - if ($exposeJSAccessors) { - $code .= "static void ${attrName}AttributeGetter${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8::Value>& info)\n"; - } else { - $code .= "static void ${attrName}AttributeGetter${forMainWorldSuffix}(const v8::PropertyCallbackInfo<v8::Value>& info)\n"; - } - $code .= "{\n"; - if ($svgNativeType) { - my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfaceName); - if ($svgWrappedNativeType =~ /List/) { - $code .= <<END; - $svgNativeType* imp = ${v8ClassName}::toNative(info.Holder()); -END - } else { - $code .= <<END; - $svgNativeType* wrapper = ${v8ClassName}::toNative(info.Holder()); - $svgWrappedNativeType& impInstance = wrapper->propertyReference(); - $svgWrappedNativeType* imp = &impInstance; -END - } - } elsif ($attrExt->{"OnPrototype"} || $attrExt->{"Unforgeable"}) { - if ($interfaceName eq "Window") { - $code .= <<END; - v8::Handle<v8::Object> holder = info.Holder(); -END - } else { - # perform lookup first - $code .= <<END; - v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(${v8ClassName}::domTemplate(info.GetIsolate(), worldType(info.GetIsolate()))); - if (holder.IsEmpty()) - return; -END - } - $code .= <<END; - ${implClassName}* imp = ${v8ClassName}::toNative(holder); -END - } else { - my $reflect = $attribute->extendedAttributes->{"Reflect"}; - my $url = $attribute->extendedAttributes->{"URL"}; - if ($reflect && !$url && InheritsInterface($interface, "Node") && $attrType eq "DOMString") { - # Generate super-compact call for regular attribute getter: - my ($functionName, @arguments) = GetterExpression($interfaceName, $attribute); - $code .= " Element* imp = V8Element::toNative(info.Holder());\n"; - $code .= " v8SetReturnValueString(info, imp->${functionName}(" . join(", ", @arguments) . "), info.GetIsolate());\n"; - $code .= "}\n"; - $code .= "#endif // ${conditionalString}\n" if $conditionalString; - $code .= "\n"; - $implementation{nameSpaceInternal}->add($code); - return; - # Skip the rest of the function! - } - my $imp = 0; - if ($attrCached) { - $imp = 1; - $code .= <<END; - v8::Handle<v8::String> propertyName = v8::String::NewFromUtf8(info.GetIsolate(), "${attrName}", v8::String::kInternalizedString); - ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()); - if (!imp->$attrCached()) { - v8::Handle<v8::Value> jsValue = info.Holder()->GetHiddenValue(propertyName); - if (!jsValue.IsEmpty()) { - v8SetReturnValue(info, jsValue); - return; - } - } -END - } - if (!$attribute->isStatic && !$imp) { - $code .= <<END; - ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()); -END - } - } - - my $raisesException = $attribute->extendedAttributes->{"RaisesException"}; - my $useExceptions = 1 if $raisesException && ($raisesException eq "VALUE_IS_MISSING" or $raisesException eq "Getter"); - if ($useExceptions || $attribute->extendedAttributes->{"CheckSecurity"}) { - $code .= " ExceptionState exceptionState(ExceptionState::GetterContext, \"${attrName}\", \"${interfaceName}\", info.Holder(), info.GetIsolate());\n"; - } - - # Generate security checks if necessary - if ($attribute->extendedAttributes->{"CheckSecurity"}) { - AddToImplIncludes("bindings/v8/BindingSecurity.h"); - $code .= " if (!BindingSecurity::shouldAllowAccessToNode(imp->" . GetImplName($attribute) . "(), exceptionState)) {\n"; - $code .= " v8SetReturnValueNull(info);\n"; - $code .= " exceptionState.throwIfNeeded();\n"; - $code .= " return;\n"; - $code .= " }\n"; - } - - my $isNullable = $attribute->isNullable; - if ($isNullable) { - $code .= " bool isNull = false;\n"; - } - - my $getterString; - my ($functionName, @arguments) = GetterExpression($interfaceName, $attribute); - push(@arguments, "isNull") if $isNullable; - push(@arguments, "exceptionState") if $useExceptions; - if ($attribute->extendedAttributes->{"ImplementedBy"}) { - my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy"}; - my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy); - AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedByImplName)); - unshift(@arguments, "imp") if !$attribute->isStatic; - $functionName = "${implementedByImplName}::${functionName}"; - } elsif ($attribute->isStatic) { - $functionName = "${implClassName}::${functionName}"; - } else { - $functionName = "imp->${functionName}"; - } - my ($arg, $subCode) = GenerateCallWith($attribute->extendedAttributes->{"CallWith"}, " ", 0); - $code .= $subCode; - unshift(@arguments, @$arg); - $getterString = "${functionName}(" . join(", ", @arguments) . ")"; - - my $expression; - if ($attribute->type eq "EventHandler" && $interface->name eq "Window") { - $code .= " if (!imp->document())\n"; - $code .= " return;\n"; - } - - if ($useExceptions || $isNullable) { - if ($nativeType =~ /^V8StringResource/) { - $code .= " " . ConvertToV8StringResource($attribute, $nativeType, "cppValue", $getterString) . ";\n"; - } else { - $code .= " $nativeType jsValue = $getterString;\n"; - } - - if ($isNullable) { - $code .= " if (isNull) {\n"; - $code .= " v8SetReturnValueNull(info);\n"; - $code .= " return;\n"; - $code .= " }\n"; - } - - if ($useExceptions) { - if ($useExceptions) { - $code .= " if (UNLIKELY(exceptionState.throwIfNeeded()))\n"; - $code .= " return;\n"; - } - - if (ExtendedAttributeContains($attribute->extendedAttributes->{"CallWith"}, "ScriptState")) { - $code .= " if (state.hadException()) {\n"; - $code .= " throwError(state.exception(), info.GetIsolate());\n"; - $code .= " return;\n"; - $code .= " }\n"; - } - } - - $expression = "jsValue"; - $expression .= ".release()" if (IsRefPtrType($attrType)); - } else { - # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary - $expression = $getterString; - # Fix amigious conversion problem, by casting to the base type first ($getterString returns a type that inherits from SVGAnimatedEnumeration, not the base class directly). - $expression = "static_pointer_cast<SVGAnimatedEnumeration>($expression)" if $attrType eq "SVGAnimatedEnumeration"; - } - - if (ShouldKeepAttributeAlive($interface, $attribute, $attrType)) { - my $arrayType = GetArrayType($attrType); - if ($arrayType) { - $code .= " v8SetReturnValue(info, v8Array(${getterString}, info.GetIsolate()));\n"; - $code .= "}\n\n"; - $implementation{nameSpaceInternal}->add($code); - return; - } - - AddToImplIncludes("bindings/v8/V8HiddenPropertyName.h"); - # Check for a wrapper in the wrapper cache. If there is one, we know that a hidden reference has already - # been created. If we don't find a wrapper, we create both a wrapper and a hidden reference. - my $nativeReturnType = GetNativeType($attrType); - my $v8ReturnType = "V8" . $attrType; - $code .= " $nativeReturnType result = ${getterString};\n"; - if ($forMainWorldSuffix) { - $code .= " if (result && DOMDataStore::setReturnValueFromWrapper${forMainWorldSuffix}<${v8ReturnType}>(info.GetReturnValue(), result.get()))\n"; - } else { - $code .= " if (result && DOMDataStore::setReturnValueFromWrapper<${v8ReturnType}>(info.GetReturnValue(), result.get()))\n"; - } - $code .= " return;\n"; - $code .= " v8::Handle<v8::Value> wrapper = toV8(result.get(), info.Holder(), info.GetIsolate());\n"; - $code .= " if (!wrapper.IsEmpty()) {\n"; - $code .= " V8HiddenPropertyName::setNamedHiddenReference(info.Holder(), \"${attrName}\", wrapper);\n"; - $code .= " v8SetReturnValue(info, wrapper);\n"; - $code .= " }\n"; - $code .= "}\n"; - $code .= "#endif // ${conditionalString}\n" if $conditionalString; - $code .= "\n"; - $implementation{nameSpaceInternal}->add($code); - return; - } - - if ((IsSVGAnimatedType($interfaceName) or $interfaceName eq "SVGViewSpec") and IsSVGTypeNeedingTearOff($attrType)) { - AddToImplIncludes("V8$attrType.h"); - my $svgNativeType = GetSVGTypeNeedingTearOff($attrType); - # Convert from abstract SVGProperty to real type, so the right toJS() method can be invoked. - if ($forMainWorldSuffix eq "ForMainWorld") { - $code .= " v8SetReturnValueForMainWorld(info, static_cast<$svgNativeType*>($expression));\n"; - } else { - $code .= " v8SetReturnValueFast(info, static_cast<$svgNativeType*>($expression), imp);\n"; - } - } elsif (IsSVGTypeNeedingTearOff($attrType) and not $interfaceName =~ /List$/) { - AddToImplIncludes("V8$attrType.h"); - AddToImplIncludes("core/svg/properties/SVGPropertyTearOff.h"); - my $tearOffType = GetSVGTypeNeedingTearOff($attrType); - my $wrappedValue; - if (IsSVGTypeWithWritablePropertiesNeedingTearOff($attrType) and not defined $attribute->extendedAttributes->{"Immutable"}) { - my $getter = $expression; - $getter =~ s/imp->//; - $getter =~ s/\(\)//; - - my $updateMethod = "&${implClassName}::update" . FirstLetterToUpperCase($getter); - - my $selfIsTearOffType = IsSVGTypeNeedingTearOff($interfaceName); - if ($selfIsTearOffType) { - AddToImplIncludes("core/svg/properties/SVGMatrixTearOff.h"); - # FIXME: Don't create a new one everytime we access the matrix property. This means, e.g, === won't work. - $wrappedValue = "WTF::getPtr(SVGMatrixTearOff::create(wrapper, $expression))"; - } else { - AddToImplIncludes("core/svg/properties/SVGStaticPropertyTearOff.h"); - $tearOffType =~ s/SVGPropertyTearOff</SVGStaticPropertyTearOff<$implClassName, /; - - $wrappedValue = "WTF::getPtr(${tearOffType}::create(imp, $expression, $updateMethod))"; - } - } elsif ($tearOffType =~ /SVGStaticListPropertyTearOff/) { - $wrappedValue = "WTF::getPtr(${tearOffType}::create(imp, $expression))"; - } elsif ($tearOffType =~ /SVG(Point|PathSeg)List/) { - $wrappedValue = "WTF::getPtr($expression)"; - } else { - $wrappedValue = "WTF::getPtr(${tearOffType}::create($expression))"; - } - if ($forMainWorldSuffix eq "ForMainWorld") { - $code .= " v8SetReturnValueForMainWorld(info, $wrappedValue);\n"; - } else { - $code .= " v8SetReturnValueFast(info, $wrappedValue, imp);\n"; - } - } elsif ($attrCached) { - if ($attribute->type eq "SerializedScriptValue") { - $code .= <<END; - RefPtr<SerializedScriptValue> serialized = $getterString; - ScriptValue jsValue = serialized ? serialized->deserialize() : v8::Handle<v8::Value>(v8::Null(info.GetIsolate())); - info.Holder()->SetHiddenValue(propertyName, jsValue); - v8SetReturnValue(info, jsValue); -END - } else { - if (!$useExceptions && !$isNullable) { - $code .= <<END; - ScriptValue jsValue = $getterString; -END - } - $code .= <<END; - info.Holder()->SetHiddenValue(propertyName, jsValue.v8Value()); - v8SetReturnValue(info, jsValue.v8Value()); -END - } - } elsif ($attribute->type eq "EventHandler") { - AddToImplIncludes("bindings/v8/V8AbstractEventListener.h"); - # FIXME: Pass the main world ID for main-world-only getters. - my ($functionName, @arguments) = GetterExpression($interfaceName, $attribute); - my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy"}; - if ($implementedBy) { - my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy); - $functionName = "${implementedByImplName}::${functionName}"; - push(@arguments, "imp"); - } else { - $functionName = "imp->${functionName}"; - } - push(@arguments, "isolatedWorldForIsolate(info.GetIsolate())"); - $code .= " EventListener* jsValue = ${functionName}(" . join(", ", @arguments) . ");\n"; - $code .= " v8SetReturnValue(info, jsValue ? v8::Handle<v8::Value>(V8AbstractEventListener::cast(jsValue)->getListenerObject(imp->executionContext())) : v8::Handle<v8::Value>(v8::Null(info.GetIsolate())));\n"; - } else { - my $nativeValue = NativeToJSValue($attribute->type, $attribute->extendedAttributes, $expression, " ", "", "info.GetIsolate()", "info", "imp", $forMainWorldSuffix, "return"); - $code .= "${nativeValue}\n"; - } - - $code .= "}\n"; # end of getter - $code .= "#endif // ${conditionalString}\n" if $conditionalString; - $code .= "\n"; - $implementation{nameSpaceInternal}->add($code); -} - -sub ShouldKeepAttributeAlive -{ - my ($interface, $attribute, $returnType) = @_; - my $attrName = $attribute->name; - - # For readonly attributes (including Replaceable), as a general rule, for - # performance reasons we keep the attribute wrapper alive while the owner - # wrapper is alive, because the attribute never changes. - return 0 if !IsWrapperType($returnType); - return 0 if !IsReadonly($attribute) && !$attribute->extendedAttributes->{"Replaceable"}; - - # However, there are a couple of exceptions. - - # Node lifetime is managed by object grouping. - return 0 if InheritsInterface($interface, "Node"); - return 0 if IsDOMNodeType($returnType); - - # To avoid adding a reference to itself. - # FIXME: Introduce [DoNotKeepAttributeAliveForGC] and remove this hack - # depending on the attribute name. - return 0 if $attrName eq "self"; - - # FIXME: Remove these hard-coded hacks. - return 0 if $returnType eq "EventTarget"; - return 0 if $returnType eq "SerializedScriptValue"; - return 0 if $returnType eq "Window"; - return 0 if $returnType =~ /SVG/; - return 0 if $returnType =~ /HTML/; - - return 1; -} - -sub GenerateReplaceableAttributeSetterCallback -{ - my $interface = shift; - my $implClassName = GetImplName($interface); - - my $code = ""; - $code .= "static void ${implClassName}ReplaceableAttributeSetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info)\n"; - $code .= "{\n"; - $code .= GenerateFeatureObservation($interface->extendedAttributes->{"MeasureAs"}); - $code .= GenerateDeprecationNotification($interface->extendedAttributes->{"DeprecateAs"}); - $code .= GenerateCustomElementInvocationScopeIfNeeded($interface->extendedAttributes); - if (HasActivityLogging("", $interface->extendedAttributes, "Setter")) { - die "IDL error: ActivityLog attribute cannot exist on a ReplacableAttributeSetterCallback"; - } - $code .= " ${implClassName}V8Internal::${implClassName}ReplaceableAttributeSetter(name, jsValue, info);\n"; - $code .= "}\n\n"; - $implementation{nameSpaceInternal}->add($code); -} - -sub GenerateReplaceableAttributeSetter -{ - my $interface = shift; - - my $interfaceName = $interface->name(); - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - - my $code = ""; - $code .= <<END; -static void ${implClassName}ReplaceableAttributeSetter(v8::Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info) -{ -END - if ($interface->extendedAttributes->{"CheckSecurity"}) { - AddToImplIncludes("bindings/v8/BindingSecurity.h"); - $code .= <<END; - ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()); - v8::String::Utf8Value attributeName(name); - ExceptionState exceptionState(ExceptionState::SetterContext, *attributeName, "${interfaceName}", info.Holder(), info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame(), exceptionState)) { - exceptionState.throwIfNeeded(); - return; - } -END - } - - $code .= <<END; - info.This()->ForceSet(name, jsValue); -} - -END - $implementation{nameSpaceInternal}->add($code); -} - -sub GenerateCustomElementInvocationScopeIfNeeded -{ - my $code = ""; - my $ext = shift; - - if ($ext->{"CustomElementCallbacks"} or $ext->{"Reflect"}) { - AddToImplIncludes("core/dom/custom/CustomElementCallbackDispatcher.h"); - $code .= <<END; - CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope; -END - } - return $code; -} - -sub GenerateNormalAttributeSetterCallback -{ - my $attribute = shift; - my $interface = shift; - my $forMainWorldSuffix = shift; - my $exposeJSAccessors = shift; - - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - my $attrExt = $attribute->extendedAttributes; - my $attrName = $attribute->name; - - my $conditionalString = GenerateConditionalString($attribute); - my $code = ""; - $code .= "#if ${conditionalString}\n" if $conditionalString; - - if ($exposeJSAccessors) { - $code .= "static void ${attrName}AttributeSetterCallback${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8::Value>& info)\n"; - $code .= "{\n"; - $code .= " v8::Local<v8::Value> jsValue = info[0];\n"; - } else { - $code .= "static void ${attrName}AttributeSetterCallback${forMainWorldSuffix}(v8::Local<v8::String>, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info)\n"; - $code .= "{\n"; - } - $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMSetter\");\n"; - $code .= GenerateFeatureObservation($attrExt->{"MeasureAs"}); - $code .= GenerateDeprecationNotification($attrExt->{"DeprecateAs"}); - if (HasActivityLogging($forMainWorldSuffix, $attrExt, "Setter")) { - $code .= GenerateActivityLogging("Setter", $interface, "${attrName}"); - } - $code .= GenerateCustomElementInvocationScopeIfNeeded($attrExt); - if (HasCustomSetter($attribute)) { - $code .= " ${v8ClassName}::${attrName}AttributeSetterCustom(jsValue, info);\n"; - } else { - $code .= " ${implClassName}V8Internal::${attrName}AttributeSetter${forMainWorldSuffix}(jsValue, info);\n"; - } - $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; - $code .= "}\n"; - $code .= "#endif // ${conditionalString}\n" if $conditionalString; - $code .= "\n"; - $implementation{nameSpaceInternal}->add($code); -} - -sub FindAttributeWithName -{ - my $interface = shift; - my $attrName = shift; - - foreach my $attribute (@{$interface->attributes}) { - if ($attribute->name eq $attrName) { - return $attribute; - } - } -} - -sub GenerateNormalAttributeSetter -{ - my $attribute = shift; - my $interface = shift; - my $forMainWorldSuffix = shift; - my $exposeJSAccessors = shift; - - my $interfaceName = $interface->name; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - my $attrName = $attribute->name; - my $attrExt = $attribute->extendedAttributes; - my $attrType = $attribute->type; - my $attrCached = GetCachedAttribute($attribute); - - if (HasCustomSetter($attribute)) { - return; - } - - my $conditionalString = GenerateConditionalString($attribute); - my $code = ""; - $code .= "#if ${conditionalString}\n" if $conditionalString; - if ($exposeJSAccessors) { - $code .= "static void ${attrName}AttributeSetter${forMainWorldSuffix}(v8::Local<v8::Value> jsValue, const v8::FunctionCallbackInfo<v8::Value>& info)\n"; - } else { - $code .= "static void ${attrName}AttributeSetter${forMainWorldSuffix}(v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info)\n"; - } - $code .= "{\n"; - - my $raisesException = $attribute->extendedAttributes->{"RaisesException"}; - my $useExceptions = 1 if $raisesException && ($raisesException eq "VALUE_IS_MISSING" or $raisesException eq "Setter"); - my $hasStrictTypeChecking = 1 if $attribute->extendedAttributes->{"StrictTypeChecking"} && IsWrapperType($attrType); # Currently only actually check interface types - - # We throw exceptions using 'ExceptionState' if the attribute explicitly - # claims that exceptions may be raised, or if a strict type check might - # fail, or if we're dealing with SVG, which does strange things with - # tearoffs and read-only wrappers. - if ($useExceptions or $hasStrictTypeChecking or GetSVGTypeNeedingTearOff($interfaceName) or GetSVGTypeNeedingTearOff($attrType)) { - $code .= " ExceptionState exceptionState(ExceptionState::SetterContext, \"${attrName}\", \"${interfaceName}\", info.Holder(), info.GetIsolate());\n"; - } - - # If the "StrictTypeChecking" extended attribute is present, and the - # attribute's type is an interface type, then if the incoming value does not - # implement that interface, a TypeError is thrown rather than silently - # passing NULL to the C++ code. - # Per the Web IDL and ECMAScript specifications, incoming values can always - # be converted to both strings and numbers, so do not throw TypeError if the - # attribute is of these types. - if ($hasStrictTypeChecking) { - $code .= " if (!isUndefinedOrNull(jsValue) && !V8${attrType}::hasInstance(jsValue, info.GetIsolate(), worldType(info.GetIsolate()))) {\n"; - $code .= " exceptionState.throwTypeError(\"The provided value is not of type '${attrType}'.\");\n"; - $code .= " exceptionState.throwIfNeeded();\n"; - $code .= " return;\n"; - $code .= " }\n"; - } - - my $svgNativeType = GetSVGTypeNeedingTearOff($interfaceName); - if ($svgNativeType) { - my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfaceName); - if ($svgWrappedNativeType =~ /List$/) { - $code .= <<END; - $svgNativeType* imp = ${v8ClassName}::toNative(info.Holder()); -END - } else { - $code .= " $svgNativeType* wrapper = ${v8ClassName}::toNative(info.Holder());\n"; - $code .= " if (wrapper->isReadOnly()) {\n"; - $code .= " exceptionState.throwDOMException(NoModificationAllowedError, \"The attribute is read-only.\");\n"; - $code .= " exceptionState.throwIfNeeded();\n"; - $code .= " return;\n"; - $code .= " }\n"; - $code .= " $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n"; - $code .= " $svgWrappedNativeType* imp = &impInstance;\n"; - } - } elsif ($attrExt->{"OnPrototype"}) { - $code .= <<END; - ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()); -END - } elsif($attrExt->{"PutForwards"}) { - my $destinationAttrName = $attrExt->{"PutForwards"}; - my $destinationInterface = ParseInterface($attrType); - die "[PutForwards=x] value must be a wrapper type" unless $destinationInterface; - my $destinationAttribute = FindAttributeWithName($destinationInterface, $destinationAttrName); - die "[PutForwards=x] could not find $destinationAttrName in interface $attrType" unless $destinationAttribute; - $code .= <<END; - ${implClassName}* proxyImp = ${v8ClassName}::toNative(info.Holder()); - RefPtr<${attrType}> imp = proxyImp->${attrName}(); - if (!imp) - return; -END - # Override attribute and fall through to forward setter call. - $attribute = $destinationAttribute; - $attrName = $attribute->name; - $attrType = $attribute->type; - $attrExt = $attribute->extendedAttributes; - } else { - my $reflect = $attribute->extendedAttributes->{"Reflect"}; - if ($reflect && InheritsInterface($interface, "Node") && $attrType eq "DOMString") { - # Generate super-compact call for regular attribute setter: - my $contentAttributeName = $reflect eq "VALUE_IS_MISSING" ? lc $attrName : $reflect; - my $namespace = NamespaceForAttributeName($interfaceName, $contentAttributeName); - my $mode = GetV8StringResourceMode($attribute->extendedAttributes); - AddToImplIncludes("${namespace}.h"); - $code .= " Element* imp = V8Element::toNative(info.Holder());\n"; - $code .= " V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<$mode>, stringResource, jsValue);\n"; - # Attr (not Attribute) used in content attributes - $code .= " imp->setAttribute(${namespace}::${contentAttributeName}Attr, stringResource);\n"; - $code .= "}\n"; - $code .= "#endif // ${conditionalString}\n" if $conditionalString; - $code .= "\n"; - $implementation{nameSpaceInternal}->add($code); - return; - # Skip the rest of the function! - } - - if (!$attribute->isStatic) { - $code .= <<END; - ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()); -END - } - } - - my $nativeType = GetNativeType($attribute->type, $attribute->extendedAttributes, "parameter"); - if ($attribute->type eq "EventHandler") { - if ($interface->name eq "Window") { - $code .= " if (!imp->document())\n"; - $code .= " return;\n"; - } - } else { - my $asSetterValue = 0; - $code .= JSValueToNativeStatement($attribute->type, $attribute->extendedAttributes, $asSetterValue, "jsValue", "cppValue", " ", "info.GetIsolate()"); - } - - if (IsEnumType($attrType)) { - # setter ignores invalid enumeration values - my @enumValues = ValidEnumValues($attrType); - my @validEqualities = (); - foreach my $enumValue (@enumValues) { - push(@validEqualities, "string == \"$enumValue\""); - } - my $enumValidationExpression = join(" || ", @validEqualities); - $code .= <<END; - String string = cppValue; - if (!($enumValidationExpression)) - return; -END - } - - my $expression = "cppValue"; - my $returnType = $attribute->type; - if (IsRefPtrType($returnType) && !GetArrayType($returnType)) { - $expression = "WTF::getPtr(" . $expression . ")"; - } - - $code .= GenerateCustomElementInvocationScopeIfNeeded($attribute->extendedAttributes); - - my $returnSvgNativeType = GetSVGTypeNeedingTearOff($returnType); - if ($returnSvgNativeType) { - $code .= <<END; - if (!$expression) { - exceptionState.throwTypeError(\"The provided value is not of type '$returnType'.\"); - exceptionState.throwIfNeeded(); - return; - } -END - $expression = $expression . "->propertyReference()"; - } - - if ($attribute->type eq "EventHandler") { - my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy"}; - my $implementedByImplName; - if ($implementedBy) { - $implementedByImplName = GetImplNameFromImplementedBy($implementedBy); - } - if (!InheritsInterface($interface, "Node")) { - my $attrImplName = GetImplName($attribute); - my @arguments; - if ($implementedBy) { - $attrImplName = "${implementedByImplName}::${attrImplName}"; - push(@arguments, "imp"); - } else { - $attrImplName = "imp->${attrImplName}"; - } - push(@arguments, "isolatedWorldForIsolate(info.GetIsolate())"); - $code .= " transferHiddenDependency(info.Holder(), ${attrImplName}(" . join(", ", @arguments) . "), jsValue, ${v8ClassName}::eventListenerCacheIndex, info.GetIsolate());\n"; - } - my ($functionName, @arguments) = SetterExpression($interfaceName, $attribute); - if ($implementedBy) { - $functionName = "${implementedByImplName}::${functionName}"; - push(@arguments, "imp"); - } else { - $functionName = "imp->${functionName}"; - } - if (($interfaceName eq "Window" or $interfaceName eq "WorkerGlobalScope") and $attribute->name eq "onerror") { - AddToImplIncludes("bindings/v8/V8ErrorHandler.h"); - push(@arguments, "V8EventListenerList::findOrCreateWrapper<V8ErrorHandler>(jsValue, true, info.GetIsolate())"); - } else { - push(@arguments, "V8EventListenerList::getEventListener(jsValue, true, ListenerFindOrCreate)"); - } - push(@arguments, "isolatedWorldForIsolate(info.GetIsolate())"); - $code .= " ${functionName}(" . join(", ", @arguments) . ");\n"; - } else { - my ($functionName, @arguments) = SetterExpression($interfaceName, $attribute); - push(@arguments, $expression); - push(@arguments, "exceptionState") if $useExceptions; - if ($attribute->extendedAttributes->{"ImplementedBy"}) { - my $implementedBy = $attribute->extendedAttributes->{"ImplementedBy"}; - my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy); - AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedByImplName)); - unshift(@arguments, "imp") if !$attribute->isStatic; - $functionName = "${implementedByImplName}::${functionName}"; - } elsif ($attribute->isStatic) { - $functionName = "${implClassName}::${functionName}"; - } else { - $functionName = "imp->${functionName}"; - } - my ($arg, $subCode) = GenerateCallWith($attribute->extendedAttributes->{"SetterCallWith"} || $attribute->extendedAttributes->{"CallWith"}, " ", 1); - $code .= $subCode; - unshift(@arguments, @$arg); - $code .= " ${functionName}(" . join(", ", @arguments) . ");\n"; - } - - if ($useExceptions) { - $code .= " exceptionState.throwIfNeeded();\n"; - } - - if (ExtendedAttributeContains($attribute->extendedAttributes->{"CallWith"}, "ScriptState")) { - $code .= " if (state.hadException())\n"; - $code .= " throwError(state.exception(), info.GetIsolate());\n"; - } - - if ($svgNativeType) { - if ($useExceptions) { - $code .= " if (!exceptionState.hadException())\n"; - $code .= " wrapper->commitChange();\n"; - } else { - $code .= " wrapper->commitChange();\n"; - } - } - - if ($attrCached) { - $code .= <<END; - info.Holder()->DeleteHiddenValue(v8::String::NewFromUtf8(info.GetIsolate(), "${attrName}", v8::String::kInternalizedString)); // Invalidate the cached value. -END - } - - $code .= "}\n"; # end of setter - $code .= "#endif // ${conditionalString}\n" if $conditionalString; - $code .= "\n"; - $implementation{nameSpaceInternal}->add($code); -} - -sub GenerateParametersCheckExpression -{ - my $numParameters = shift; - my $function = shift; - - my @andExpression = (); - push(@andExpression, "info.Length() == $numParameters"); - my $parameterIndex = 0; - foreach my $parameter (@{$function->parameters}) { - last if $parameterIndex >= $numParameters; - my $value = "info[$parameterIndex]"; - my $type = $parameter->type; - - # Only DOMString or wrapper types are checked. - # For DOMString with StrictTypeChecking only Null, Undefined and Object - # are accepted for compatibility. Otherwise, no restrictions are made to - # match the non-overloaded behavior. - # FIXME: Implement WebIDL overload resolution algorithm. - if ($type eq "DOMString") { - if ($parameter->extendedAttributes->{"StrictTypeChecking"}) { - push(@andExpression, "${value}->IsNull() || ${value}->IsUndefined() || ${value}->IsString() || ${value}->IsObject()"); - } - } elsif (IsCallbackInterface($parameter->type)) { - # For Callbacks only checks if the value is null or object. - push(@andExpression, "${value}->IsNull() || ${value}->IsFunction()"); - } elsif (GetArrayOrSequenceType($type)) { - if ($parameter->isNullable) { - push(@andExpression, "${value}->IsNull() || ${value}->IsArray()"); - } else { - push(@andExpression, "${value}->IsArray()"); - } - } elsif (IsWrapperType($type)) { - if ($parameter->isNullable) { - push(@andExpression, "${value}->IsNull() || V8${type}::hasInstance($value, info.GetIsolate(), worldType(info.GetIsolate()))"); - } else { - push(@andExpression, "V8${type}::hasInstance($value, info.GetIsolate(), worldType(info.GetIsolate()))"); - } - } - - $parameterIndex++; - } - @andExpression = map { "($_)" } @andExpression; - my $res = "(" . join(" && ", @andExpression) . ")"; - return $res; -} - -# As per Web IDL specification, the length of a function Object is -# its number of mandatory parameters. -sub GetFunctionLength -{ - my $function = shift; - - my $numMandatoryParams = 0; - foreach my $parameter (@{$function->parameters}) { - # Abort as soon as we find the first optional parameter as no mandatory - # parameter can follow an optional one. - last if $parameter->isOptional; - $numMandatoryParams++; - } - return $numMandatoryParams; -} - -sub GenerateFunctionParametersCheck -{ - my $function = shift; - - my @orExpression = (); - my $numParameters = 0; - my $hasVariadic = 0; - my $numMandatoryParams = @{$function->parameters}; - foreach my $parameter (@{$function->parameters}) { - if ($parameter->isOptional) { - push(@orExpression, GenerateParametersCheckExpression($numParameters, $function)); - $numMandatoryParams--; - } - if ($parameter->isVariadic) { - $hasVariadic = 1; - last; - } - $numParameters++; - } - if (!$hasVariadic) { - push(@orExpression, GenerateParametersCheckExpression($numParameters, $function)); - } - return ($numMandatoryParams, join(" || ", @orExpression)); -} - -sub GenerateOverloadedFunction -{ - my $function = shift; - my $interface = shift; - my $forMainWorldSuffix = shift; - - # Generate code for choosing the correct overload to call. Overloads are - # chosen based on the total number of arguments passed and the type of - # values passed in non-primitive argument slots. When more than a single - # overload is applicable, precedence is given according to the order of - # declaration in the IDL. - - my $name = $function->name; - my $interfaceName = $interface->name; - my $implClassName = GetImplName($interface); - - my $conditionalString = GenerateConditionalString($function); - my $leastNumMandatoryParams = 255; - - my $code = ""; - $code .= "#if ${conditionalString}\n\n" if $conditionalString; - $code .= <<END; -static void ${name}Method${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8::Value>& info) -{ -END - $code .= GenerateFeatureObservation($function->extendedAttributes->{"MeasureAs"}); - $code .= GenerateDeprecationNotification($function->extendedAttributes->{"DeprecateAs"}); - - foreach my $overload (@{$function->{overloads}}) { - my ($numMandatoryParams, $parametersCheck) = GenerateFunctionParametersCheck($overload); - $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams < $leastNumMandatoryParams); - $code .= " if ($parametersCheck) {\n"; - my $overloadedIndexString = $overload->{overloadIndex}; - $code .= " ${name}${overloadedIndexString}Method${forMainWorldSuffix}(info);\n"; - $code .= " return;\n"; - $code .= " }\n"; - } - if ($leastNumMandatoryParams >= 1) { - $code .= " ExceptionState exceptionState(ExceptionState::ExecutionContext, \"${name}\", \"${interfaceName}\", info.Holder(), info.GetIsolate());\n"; - $code .= " if (UNLIKELY(info.Length() < $leastNumMandatoryParams)) {\n"; - $code .= " exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments($leastNumMandatoryParams, info.Length()));\n"; - $code .= " exceptionState.throwIfNeeded();\n"; - $code .= " return;\n"; - $code .= " }\n"; - $code .= <<END; - exceptionState.throwTypeError(\"No function was found that matched the signature provided.\"); - exceptionState.throwIfNeeded(); -END - } else { - $code .=<<END; - throwTypeError(ExceptionMessages::failedToExecute(\"${name}\", \"${interfaceName}\", \"No function was found that matched the signature provided.\"), info.GetIsolate()); -END - } - $code .= "}\n\n"; - $code .= "#endif // ${conditionalString}\n\n" if $conditionalString; - $implementation{nameSpaceInternal}->add($code); -} - -sub GenerateFunctionCallback -{ - my $function = shift; - my $interface = shift; - my $forMainWorldSuffix = shift; - - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - my $name = $function->name; - - if ($name eq "") { - return; - } - - my $conditionalString = GenerateConditionalString($function); - my $code = ""; - $code .= "#if ${conditionalString}\n" if $conditionalString; - $code .= <<END; -static void ${name}MethodCallback${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8::Value>& info) -{ -END - $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMMethod\");\n"; - $code .= GenerateFeatureObservation($function->extendedAttributes->{"MeasureAs"}); - $code .= GenerateDeprecationNotification($function->extendedAttributes->{"DeprecateAs"}); - if (HasActivityLogging($forMainWorldSuffix, $function->extendedAttributes, "Access")) { - $code .= GenerateActivityLogging("Method", $interface, "${name}"); - } - if (HasCustomMethod($function->extendedAttributes)) { - $code .= " ${v8ClassName}::${name}MethodCustom(info);\n"; - } else { - $code .= " ${implClassName}V8Internal::${name}Method${forMainWorldSuffix}(info);\n"; - } - $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; - $code .= "}\n"; - $code .= "#endif // ${conditionalString}\n" if $conditionalString; - $code .= "\n"; - $implementation{nameSpaceInternal}->add($code); -} - -sub GenerateFunction -{ - my $function = shift; - my $interface = shift; - my $forMainWorldSuffix = shift; - - my $interfaceName = $interface->name; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - my $name = $function->name; - my $unoverloadedName = $function->name; - my $implName = GetImplName($function); - my $funcExt = $function->extendedAttributes; - - if (HasCustomMethod($funcExt) || $name eq "") { - return; - } - - if (@{$function->{overloads}} > 1) { - # Append a number to an overloaded method's name to make it unique: - $name = $name . $function->{overloadIndex}; - } - - my $conditionalString = GenerateConditionalString($function); - my $code = ""; - $code .= "#if ${conditionalString}\n" if $conditionalString; - $code .= "static void ${name}Method${forMainWorldSuffix}(const v8::FunctionCallbackInfo<v8::Value>& info)\n"; - $code .= "{\n"; - - # We throw exceptions using 'ExceptionState' if the function explicitly claims that exceptions - # may be raised, or for event listeners, or for security-checking, and for weird SVG stuff. - my $isEventListener = $name eq "addEventListener" || $name eq "removeEventListener"; - my $isEventDispatcher = $name eq "dispatchEvent"; - my $isSecurityCheckNecessary = $interface->extendedAttributes->{"CheckSecurity"} && !$function->extendedAttributes->{"DoNotCheckSecurity"}; - my $raisesExceptions = $function->extendedAttributes->{"RaisesException"}; - my ($svgPropertyType, $svgListPropertyType, $svgNativeType) = GetSVGPropertyTypes($interfaceName); - my $isNonListSVGType = $svgNativeType && !($interfaceName =~ /List$/); - - my $hasExceptionState = 0; - if ($raisesExceptions || $isEventListener || $isSecurityCheckNecessary || $isNonListSVGType) { - $code .= " ExceptionState exceptionState(ExceptionState::ExecutionContext, \"${unoverloadedName}\", \"${interfaceName}\", info.Holder(), info.GetIsolate());\n"; - $hasExceptionState = 1; - } - - if ($isEventListener || $isEventDispatcher) { - AddToImplIncludes("bindings/v8/BindingSecurity.h"); - AddToImplIncludes("bindings/v8/V8EventListenerList.h"); - AddToImplIncludes("core/frame/DOMWindow.h"); - $code .= <<END; - EventTarget* impl = ${v8ClassName}::toNative(info.Holder()); - if (DOMWindow* window = impl->toDOMWindow()) { - if (!BindingSecurity::shouldAllowAccessToFrame(window->frame(), exceptionState)) { - exceptionState.throwIfNeeded(); - return; - } - if (!window->document()) - return; - } -END - } - if ($isEventListener) { - my $lookupType = ($name eq "addEventListener") ? "OrCreate" : "Only"; - my $passRefPtrHandling = ($name eq "addEventListener") ? "" : ".get()"; - my $hiddenDependencyAction = ($name eq "addEventListener") ? "create" : "remove"; - - $code .= <<END; - RefPtr<EventListener> listener = V8EventListenerList::getEventListener(info[1], false, ListenerFind${lookupType}); - if (listener) { - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, eventName, info[0]); - impl->${implName}(eventName, listener${passRefPtrHandling}, info[2]->BooleanValue()); - if (!impl->toNode()) - ${hiddenDependencyAction}HiddenDependency(info.Holder(), info[1], ${v8ClassName}::eventListenerCacheIndex, info.GetIsolate()); - } -} -END - $code .= "#endif // ${conditionalString}\n" if $conditionalString; - $code .= "\n"; - $implementation{nameSpaceInternal}->add($code); - return; - } - - $code .= GenerateArgumentsCountCheck($function, $interface, $hasExceptionState); - - if ($svgNativeType) { - my $nativeClassName = GetNativeType($interfaceName); - if ($interfaceName =~ /List$/) { - $code .= " $nativeClassName imp = ${v8ClassName}::toNative(info.Holder());\n"; - } else { - AddToImplIncludes("core/dom/ExceptionCode.h"); - $code .= " $nativeClassName wrapper = ${v8ClassName}::toNative(info.Holder());\n"; - $code .= " if (wrapper->isReadOnly()) {\n"; - $code .= " exceptionState.throwDOMException(NoModificationAllowedError, \"The object is read-only.\");\n"; - $code .= " exceptionState.throwIfNeeded();\n"; - $code .= " return;\n"; - $code .= " }\n"; - my $svgWrappedNativeType = GetSVGWrappedTypeNeedingTearOff($interfaceName); - $code .= " $svgWrappedNativeType& impInstance = wrapper->propertyReference();\n"; - $code .= " $svgWrappedNativeType* imp = &impInstance;\n"; - } - } elsif (!$function->isStatic) { - $code .= <<END; - ${implClassName}* imp = ${v8ClassName}::toNative(info.Holder()); -END - } - - $code .= GenerateCustomElementInvocationScopeIfNeeded($funcExt); - - # Check domain security if needed - if ($isSecurityCheckNecessary) { - # We have not find real use cases yet. - AddToImplIncludes("bindings/v8/BindingSecurity.h"); - $code .= <<END; - if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame(), exceptionState)) { - exceptionState.throwIfNeeded(); - return; - } -END - } - - if ($function->extendedAttributes->{"CheckSecurity"}) { - AddToImplIncludes("bindings/v8/BindingSecurity.h"); - $code .= " if (!BindingSecurity::shouldAllowAccessToNode(imp->" . GetImplName($function) . "(exceptionState), exceptionState)) {\n"; - $code .= " v8SetReturnValueNull(info);\n"; - $code .= " exceptionState.throwIfNeeded();\n"; - $code .= " return;\n"; - $code .= " }\n"; -END - } - - my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $interface, $forMainWorldSuffix); - $code .= $parameterCheckString; - - # Build the function call string. - $code .= GenerateFunctionCallString($function, $paramIndex, " ", $interface, $forMainWorldSuffix, %replacements); - $code .= "}\n"; - $code .= "#endif // ${conditionalString}\n" if $conditionalString; - $code .= "\n"; - $implementation{nameSpaceInternal}->add($code); -} - -sub GenerateCallWith -{ - my $callWith = shift; - return ([], "") unless $callWith; - my $indent = shift; - my $returnVoid = shift; - my $function = shift; - my $code = ""; - - my @callWithArgs; - if (ExtendedAttributeContains($callWith, "ScriptState")) { - $code .= $indent . "ScriptState* currentState = ScriptState::current();\n"; - $code .= $indent . "if (!currentState)\n"; - $code .= $indent . " return" . ($returnVoid ? "" : " v8Undefined()") . ";\n"; - $code .= $indent . "ScriptState& state = *currentState;\n"; - push(@callWithArgs, "&state"); - AddToImplIncludes("bindings/v8/ScriptState.h"); - } - if (ExtendedAttributeContains($callWith, "ExecutionContext")) { - $code .= $indent . "ExecutionContext* scriptContext = getExecutionContext();\n"; - push(@callWithArgs, "scriptContext"); - } - if ($function and ExtendedAttributeContains($callWith, "ScriptArguments")) { - $code .= $indent . "RefPtr<ScriptArguments> scriptArguments(createScriptArguments(info, " . @{$function->parameters} . "));\n"; - push(@callWithArgs, "scriptArguments.release()"); - AddToImplIncludes("bindings/v8/ScriptCallStackFactory.h"); - AddToImplIncludes("core/inspector/ScriptArguments.h"); - } - if (ExtendedAttributeContains($callWith, "ActiveWindow")) { - push(@callWithArgs, "activeDOMWindow()"); - } - if (ExtendedAttributeContains($callWith, "FirstWindow")) { - push(@callWithArgs, "firstDOMWindow()"); - } - return ([@callWithArgs], $code); -} - -sub GenerateArgumentsCountCheck -{ - my $function = shift; - my $interface = shift; - my $hasExceptionState = shift; - - my $functionName = $function->name; - my $interfaceName = $interface->name; - my $implClassName = GetImplName($interface); - - my $numMandatoryParams = 0; - my $allowNonOptional = 1; - foreach my $param (@{$function->parameters}) { - if ($param->isOptional or $param->isVariadic) { - $allowNonOptional = 0; - } else { - die "An argument must not be declared to be optional unless all subsequent arguments to the operation are also optional." if !$allowNonOptional; - $numMandatoryParams++; - } - } - - my $argumentsCountCheckString = ""; - if ($numMandatoryParams >= 1) { - $argumentsCountCheckString .= " if (UNLIKELY(info.Length() < $numMandatoryParams)) {\n"; - if ($hasExceptionState) { - $argumentsCountCheckString .= " exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments($numMandatoryParams, info.Length()));\n"; - $argumentsCountCheckString .= " exceptionState.throwIfNeeded();\n"; - } else { - $argumentsCountCheckString .= " throwTypeError(ExceptionMessages::failedToExecute(\"$functionName\", \"$interfaceName\", ExceptionMessages::notEnoughArguments($numMandatoryParams, info.Length())), info.GetIsolate());\n"; - } - $argumentsCountCheckString .= " return;\n"; - $argumentsCountCheckString .= " }\n"; - } - return $argumentsCountCheckString; -} - -sub GenerateParametersCheck -{ - my $function = shift; - my $interface = shift; - my $forMainWorldSuffix = shift; - my $style = shift || "new"; - - my $functionName = $function->name; - my $interfaceName = $interface->name; - my $implClassName = GetImplName($interface); - - my $parameterCheckString = ""; - my $paramIndex = 0; - my %replacements = (); - - foreach my $parameter (@{$function->parameters}) { - my $humanFriendlyIndex = $paramIndex + 1; - my $nativeType = GetNativeType($parameter->type, $parameter->extendedAttributes, "parameter"); - - # Optional arguments without [Default=...] should generate an early call with fewer arguments. - # Optional Dictionary arguments always considered to have default of empty dictionary. - if ($parameter->isOptional && !$parameter->extendedAttributes->{"Default"} && $nativeType ne "Dictionary" && !IsCallbackInterface($parameter->type)) { - $parameterCheckString .= <<END; - if (UNLIKELY(info.Length() <= $paramIndex)) { -END - $parameterCheckString .= GenerateFunctionCallString($function, $paramIndex, " " x 2, $interface, $forMainWorldSuffix, %replacements); - $parameterCheckString .= <<END; - return; - } -END - } - - my $parameterName = $parameter->name; - if (IsCallbackInterface($parameter->type)) { - my $v8ClassName = "V8" . $parameter->type; - AddToImplIncludes("$v8ClassName.h"); - if ($parameter->isOptional) { - $parameterCheckString .= " OwnPtr<" . $parameter->type . "> $parameterName;\n"; - $parameterCheckString .= " if (info.Length() > $paramIndex && !info[$paramIndex]->IsNull() && !info[$paramIndex]->IsUndefined()) {\n"; - $parameterCheckString .= " if (!info[$paramIndex]->IsFunction()) {\n"; - $parameterCheckString .= " throwTypeError(ExceptionMessages::failedToExecute(\"$functionName\", \"$interfaceName\", \"The callback provided as parameter $humanFriendlyIndex is not a function.\"), info.GetIsolate());\n"; - $parameterCheckString .= " return;\n"; - $parameterCheckString .= " }\n"; - $parameterCheckString .= " $parameterName = ${v8ClassName}::create(v8::Handle<v8::Function>::Cast(info[$paramIndex]), getExecutionContext());\n"; - $parameterCheckString .= " }\n"; - } else { - $parameterCheckString .= " if (info.Length() <= $paramIndex || "; - if ($parameter->isNullable) { - $parameterCheckString .= "!(info[$paramIndex]->IsFunction() || info[$paramIndex]->IsNull())"; - } else { - $parameterCheckString .= "!info[$paramIndex]->IsFunction()"; - } - $parameterCheckString .= ") {\n"; - $parameterCheckString .= " throwTypeError(ExceptionMessages::failedToExecute(\"$functionName\", \"$interfaceName\", \"The callback provided as parameter $humanFriendlyIndex is not a function.\"), info.GetIsolate());\n"; - $parameterCheckString .= " return;\n"; - $parameterCheckString .= " }\n"; - $parameterCheckString .= " OwnPtr<" . $parameter->type . "> $parameterName = "; - $parameterCheckString .= "info[$paramIndex]->IsNull() ? nullptr : " if $parameter->isNullable; - $parameterCheckString .= "${v8ClassName}::create(v8::Handle<v8::Function>::Cast(info[$paramIndex]), getExecutionContext());\n"; - } - } elsif ($parameter->extendedAttributes->{"Clamp"}) { - my $nativeValue = "${parameterName}NativeValue"; - my $idlType = $parameter->type; - $parameterCheckString .= " $nativeType $parameterName = 0;\n"; - $parameterCheckString .= " V8TRYCATCH_VOID(double, $nativeValue, info[$paramIndex]->NumberValue());\n"; - $parameterCheckString .= " if (!std::isnan($nativeValue))\n"; - $parameterCheckString .= " $parameterName = clampTo<$idlType>($nativeValue);\n"; - } elsif ($parameter->type eq "SerializedScriptValue") { - AddToImplIncludes("bindings/v8/SerializedScriptValue.h"); - $parameterCheckString .= " bool ${parameterName}DidThrow = false;\n"; - $parameterCheckString .= " $nativeType $parameterName = SerializedScriptValue::create(info[$paramIndex], 0, 0, ${parameterName}DidThrow, info.GetIsolate());\n"; - $parameterCheckString .= " if (${parameterName}DidThrow)\n"; - $parameterCheckString .= " return;\n"; - } elsif ($parameter->isVariadic) { - my $nativeElementType = GetNativeType($parameter->type); - if ($nativeElementType =~ />$/) { - $nativeElementType .= " "; - } - - my $argType = $parameter->type; - if (IsWrapperType($argType)) { - $parameterCheckString .= " Vector<$nativeElementType> $parameterName;\n"; - $parameterCheckString .= " for (int i = $paramIndex; i < info.Length(); ++i) {\n"; - $parameterCheckString .= " if (!V8${argType}::hasInstance(info[i], info.GetIsolate(), worldType(info.GetIsolate()))) {\n"; - $parameterCheckString .= " throwTypeError(ExceptionMessages::failedToExecute(\"$functionName\", \"$interfaceName\", \"parameter $humanFriendlyIndex is not of type \'$argType\'.\"), info.GetIsolate());\n"; - $parameterCheckString .= " return;\n"; - $parameterCheckString .= " }\n"; - $parameterCheckString .= " $parameterName.append(V8${argType}::toNative(v8::Handle<v8::Object>::Cast(info[i])));\n"; - $parameterCheckString .= " }\n"; - } else { - $parameterCheckString .= " V8TRYCATCH_VOID(Vector<$nativeElementType>, $parameterName, toNativeArguments<$nativeElementType>(info, $paramIndex));\n"; - } - } elsif ($nativeType =~ /^V8StringResource/) { - my $default = defined $parameter->extendedAttributes->{"Default"} ? $parameter->extendedAttributes->{"Default"} : ""; - my $jsValue = $parameter->isOptional && $default eq "NullString" ? "argumentOrNull(info, $paramIndex)" : "info[$paramIndex]"; - my $stringResourceParameterName = $parameterName; - my $isNullable = IsNullableParameter($parameter); - if ($isNullable) { - $parameterCheckString .= " bool ${parameterName}IsNull = $jsValue->IsNull();\n"; - $stringResourceParameterName .= "StringResource"; - } - $parameterCheckString .= JSValueToNativeStatement($parameter->type, $parameter->extendedAttributes, $humanFriendlyIndex, $jsValue, $stringResourceParameterName, " ", "info.GetIsolate()"); - $parameterCheckString .= " String $parameterName = $stringResourceParameterName;\n" if $isNullable; - if (IsEnumType($parameter->type)) { - my @enumValues = ValidEnumValues($parameter->type); - my @validEqualities = (); - foreach my $enumValue (@enumValues) { - push(@validEqualities, "string == \"$enumValue\""); - } - my $enumValidationExpression = join(" || ", @validEqualities); - $parameterCheckString .= " String string = $parameterName;\n"; - $parameterCheckString .= " if (!($enumValidationExpression)) {\n"; - $parameterCheckString .= " throwTypeError(ExceptionMessages::failedToExecute(\"$functionName\", \"$interfaceName\", \"parameter $humanFriendlyIndex (\'\" + string + \"\') is not a valid enum value.\"), info.GetIsolate());\n"; - $parameterCheckString .= " return;\n"; - $parameterCheckString .= " }\n"; - } - } else { - # If the "StrictTypeChecking" extended attribute is present, and the argument's type is an - # interface type, then if the incoming value does not implement that interface, a TypeError - # is thrown rather than silently passing NULL to the C++ code. - # Per the Web IDL and ECMAScript specifications, incoming values can always be converted - # to both strings and numbers, so do not throw TypeError if the argument is of these - # types. - if ($function->extendedAttributes->{"StrictTypeChecking"}) { - my $argValue = "info[$paramIndex]"; - my $argType = $parameter->type; - if (IsWrapperType($argType)) { - $parameterCheckString .= " if (info.Length() > $paramIndex && !isUndefinedOrNull($argValue) && !V8${argType}::hasInstance($argValue, info.GetIsolate(), worldType(info.GetIsolate()))) {\n"; - $parameterCheckString .= " throwTypeError(ExceptionMessages::failedToExecute(\"$functionName\", \"$interfaceName\", \"parameter $humanFriendlyIndex is not of type \'$argType\'.\"), info.GetIsolate());\n"; - $parameterCheckString .= " return;\n"; - $parameterCheckString .= " }\n"; - } - } - my $default = defined $parameter->extendedAttributes->{"Default"} ? $parameter->extendedAttributes->{"Default"} : ""; - my $jsValue = $parameter->isOptional && $default eq "NullString" ? "argumentOrNull(info, $paramIndex)" : "info[$paramIndex]"; - my $isNullable = IsNullableParameter($parameter); - $parameterCheckString .= " bool ${parameterName}IsNull = $jsValue->IsNull();\n" if $isNullable; - $parameterCheckString .= JSValueToNativeStatement($parameter->type, $parameter->extendedAttributes, $humanFriendlyIndex, $jsValue, $parameterName, " ", "info.GetIsolate()"); - if ($nativeType eq 'Dictionary' or $nativeType eq 'ScriptPromise') { - $parameterCheckString .= " if (!$parameterName.isUndefinedOrNull() && !$parameterName.isObject()) {\n"; - if ($functionName eq "Constructor") { - $parameterCheckString .= " throwTypeError(ExceptionMessages::failedToConstruct(\"$interfaceName\", \"parameter ${humanFriendlyIndex} ('${parameterName}') is not an object.\"), info.GetIsolate());\n"; - } else { - $parameterCheckString .= " throwTypeError(ExceptionMessages::failedToExecute(\"$functionName\", \"$interfaceName\", \"parameter ${humanFriendlyIndex} ('${parameterName}') is not an object.\"), info.GetIsolate());\n"; - } - $parameterCheckString .= " return;\n"; - $parameterCheckString .= " }\n"; - } - } - - $paramIndex++; - } - return ($parameterCheckString, $paramIndex, %replacements); -} - -sub GenerateOverloadedConstructorCallback -{ - my $interface = shift; - my $interfaceName = $interface->name; - my $implClassName = GetImplName($interface); - - my $code .= <<END; -static void constructor(const v8::FunctionCallbackInfo<v8::Value>& info) -{ -END - my $leastNumMandatoryParams = 255; - foreach my $constructor (@{$interface->constructors}) { - my $name = "constructor" . $constructor->overloadedIndex; - my ($numMandatoryParams, $parametersCheck) = GenerateFunctionParametersCheck($constructor); - $leastNumMandatoryParams = $numMandatoryParams if ($numMandatoryParams < $leastNumMandatoryParams); - $code .= " if ($parametersCheck) {\n"; - $code .= " ${implClassName}V8Internal::${name}(info);\n"; - $code .= " return;\n"; - $code .= " }\n"; - } - if ($leastNumMandatoryParams >= 1) { - $code .= <<END; - ExceptionState exceptionState(ExceptionState::ConstructionContext, \"${interfaceName}\", info.Holder(), info.GetIsolate()); - if (UNLIKELY(info.Length() < $leastNumMandatoryParams)) { - exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments($leastNumMandatoryParams, info.Length())); - exceptionState.throwIfNeeded(); - return; - } - exceptionState.throwTypeError(\"No matching constructor signature.\"); - exceptionState.throwIfNeeded(); -END - } else { - $code .= <<END; - throwTypeError(ExceptionMessages::failedToConstruct(\"${interfaceName}\", \"No matching constructor signature.\"), info.GetIsolate()); -END - } - $code .= "}\n\n"; - $implementation{nameSpaceInternal}->add($code); -} - -sub GenerateSingleConstructorCallback -{ - my $interface = shift; - my $function = shift; - - my $interfaceName = $interface->name; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - my $overloadedIndexString = ""; - if ($function->overloadedIndex > 0) { - $overloadedIndexString .= $function->overloadedIndex; - } - - my $constructorRaisesException = $interface->extendedAttributes->{"RaisesException"} && $interface->extendedAttributes->{"RaisesException"} eq "Constructor"; - my $raisesExceptions = $function->extendedAttributes->{"RaisesException"} || $constructorRaisesException; - - my @beforeArgumentList; - my @afterArgumentList; - my $code = ""; - $code .= <<END; -static void constructor${overloadedIndexString}(const v8::FunctionCallbackInfo<v8::Value>& info) -{ -END - - if ($function->overloadedIndex == 0) { - my $hasExceptionState = 0; - $code .= GenerateArgumentsCountCheck($function, $interface, $hasExceptionState); - } - - if ($raisesExceptions) { - $code .= " ExceptionState exceptionState(ExceptionState::ConstructionContext, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n"; - } - - # FIXME: Currently [Constructor(...)] does not yet support optional arguments without [Default=...] - my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $interface, ""); - $code .= $parameterCheckString; - - if ($interface->extendedAttributes->{"ConstructorCallWith"}) { - if (ExtendedAttributeContains($interface->extendedAttributes->{"ConstructorCallWith"}, "ExecutionContext")) { - push(@beforeArgumentList, "context"); - $code .= " ExecutionContext* context = getExecutionContext();\n"; - } - if (ExtendedAttributeContains($interface->extendedAttributes->{"ConstructorCallWith"}, "Document")) { - push(@beforeArgumentList, "document"); - $code .= " Document& document = *toDocument(getExecutionContext());\n"; - } - } - - if ($constructorRaisesException) { - push(@afterArgumentList, "exceptionState"); - } - - my @argumentList; - my $index = 0; - foreach my $parameter (@{$function->parameters}) { - last if $index eq $paramIndex; - if ($replacements{$parameter->name}) { - push(@argumentList, $replacements{$parameter->name}); - } else { - push(@argumentList, $parameter->name); - } - $index++; - } - - my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterArgumentList); - $code .= " RefPtr<${implClassName}> impl = ${implClassName}::create(${argumentString});\n"; - $code .= " v8::Handle<v8::Object> wrapper = info.Holder();\n"; - - if ($constructorRaisesException) { - $code .= " if (exceptionState.throwIfNeeded())\n"; - $code .= " return;\n"; - } - - $code .= <<END; - - V8DOMWrapper::associateObjectWithWrapper<${v8ClassName}>(impl.release(), &${v8ClassName}::wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent); - v8SetReturnValue(info, wrapper); -} - -END - $implementation{nameSpaceInternal}->add($code); -} - -# The Web IDL specification states that Interface objects for interfaces MUST have a property named -# "length" that returns the length of the shortest argument list of the entries in the effective -# overload set for constructors. In other words, use the lowest number of mandatory arguments among -# all constructors. -sub GetInterfaceLength -{ - my $interface = shift; - - my $leastConstructorLength = 0; - if ($interface->extendedAttributes->{"EventConstructor"}) { - $leastConstructorLength = 1; - } elsif ($interface->extendedAttributes->{"Constructor"} || $interface->extendedAttributes->{"CustomConstructor"}) { - my @constructors = @{$interface->constructors}; - my @customConstructors = @{$interface->customConstructors}; - $leastConstructorLength = 255; - foreach my $constructor (@constructors, @customConstructors) { - my $constructorLength = GetFunctionLength($constructor); - $leastConstructorLength = $constructorLength if ($constructorLength < $leastConstructorLength); - } - } - - return $leastConstructorLength; -} - -sub GenerateConstructorCallback -{ - my $interface = shift; - - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - my $code = ""; - $code .= "void ${v8ClassName}::constructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info)\n"; - $code .= "{\n"; - $code .= " TRACE_EVENT_SCOPED_SAMPLING_STATE(\"Blink\", \"DOMConstructor\");\n"; - $code .= GenerateFeatureObservation($interface->extendedAttributes->{"MeasureAs"}); - $code .= GenerateDeprecationNotification($interface->extendedAttributes->{"DeprecateAs"}); - $code .= GenerateConstructorHeader($interface->name); - if (HasCustomConstructor($interface)) { - $code .= " ${v8ClassName}::constructorCustom(info);\n"; - } else { - $code .= " ${implClassName}V8Internal::constructor(info);\n"; - } - $code .= "}\n\n"; - $implementation{nameSpaceWebCore}->add($code); -} - -sub GenerateConstructor -{ - my $interface = shift; - - if (@{$interface->constructors} == 1) { - GenerateSingleConstructorCallback($interface, @{$interface->constructors}[0]); - } else { - foreach my $constructor (@{$interface->constructors}) { - GenerateSingleConstructorCallback($interface, $constructor); - } - GenerateOverloadedConstructorCallback($interface); - } -} - -sub GenerateEventConstructor -{ - my $interface = shift; - - my $interfaceName = $interface->name; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - - my $constructorRaisesException = $interface->extendedAttributes->{"RaisesException"} && $interface->extendedAttributes->{"RaisesException"} eq "Constructor"; - - my @anyAttributeNames; - foreach my $attribute (@{$interface->attributes}) { - if ($attribute->type eq "any") { - push(@anyAttributeNames, $attribute->name); - } - } - - AddToImplIncludes("bindings/v8/Dictionary.h"); - $implementation{nameSpaceInternal}->add(<<END); -static void constructor(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - ExceptionState exceptionState(ExceptionState::ConstructionContext, \"${interfaceName}\", info.Holder(), info.GetIsolate()); - if (info.Length() < 1) { - exceptionState.throwTypeError("An event name must be provided."); - exceptionState.throwIfNeeded(); - return; - } - - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, info[0]); -END - - foreach my $attrName (@anyAttributeNames) { - $implementation{nameSpaceInternal}->add(" v8::Local<v8::Value> ${attrName};\n"); - } - - $implementation{nameSpaceInternal}->add(<<END); - ${implClassName}Init eventInit; - if (info.Length() >= 2) { - V8TRYCATCH_VOID(Dictionary, options, Dictionary(info[1], info.GetIsolate())); - if (!initialize${implClassName}(eventInit, options, exceptionState)) { - exceptionState.throwIfNeeded(); - return; - } -END - - # Store 'any'-typed properties on the wrapper to avoid leaking them between isolated worlds. - foreach my $attrName (@anyAttributeNames) { - $implementation{nameSpaceInternal}->add(<<END); - options.get("${attrName}", ${attrName}); - if (!${attrName}.IsEmpty()) - info.Holder()->SetHiddenValue(V8HiddenPropertyName::${attrName}(info.GetIsolate()), ${attrName}); -END - } - - $implementation{nameSpaceInternal}->add(<<END); - } -END - - my $exceptionStateArgument = ""; - if ($constructorRaisesException) { - ${exceptionStateArgument} = ", exceptionState"; - } - - $implementation{nameSpaceInternal}->add(<<END); - RefPtr<${implClassName}> event = ${implClassName}::create(type, eventInit${exceptionStateArgument}); -END - - if ($constructorRaisesException) { - $implementation{nameSpaceInternal}->add(<<END); - if (exceptionState.throwIfNeeded()) - return; -END - } - - if (@anyAttributeNames) { - # Separate check to simplify Python code - AddToImplIncludes("bindings/v8/SerializedScriptValue.h"); - } - if (@anyAttributeNames && $interface->name ne 'ErrorEvent') { - # If we're in an isolated world, create a SerializedScriptValue andi - # store it in the event for later cloning if the property is accessed - # from another world. - # The main world case is handled lazily (in Custom code). - # - # We do not clone Error objects (exceptions), for 2 reasons: - # 1) Errors carry a reference to the isolated world's global object, - # and thus passing it around would cause leakage. - # 2) Errors cannot be cloned (or serialized): - # http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#safe-passing-of-structured-data - $implementation{nameSpaceInternal}->add(" if (isolatedWorldForIsolate(info.GetIsolate())) {\n"); - foreach my $attrName (@anyAttributeNames) { - my $setter = "setSerialized" . FirstLetterToUpperCase($attrName); - $implementation{nameSpaceInternal}->add(<<END); - if (!${attrName}.IsEmpty()) - event->${setter}(SerializedScriptValue::createAndSwallowExceptions(${attrName}, info.GetIsolate())); -END - } - $implementation{nameSpaceInternal}->add(" }\n\n"); - } - - $implementation{nameSpaceInternal}->add(<<END); - v8::Handle<v8::Object> wrapper = info.Holder(); - V8DOMWrapper::associateObjectWithWrapper<${v8ClassName}>(event.release(), &${v8ClassName}::wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent); - v8SetReturnValue(info, wrapper); -} - -END - - my $code = ""; - $code .= <<END; -bool initialize${implClassName}(${implClassName}Init& eventInit, const Dictionary& options, ExceptionState& exceptionState, const String& forEventName) -{ - Dictionary::ConversionContext conversionContext(forEventName.isEmpty() ? String("${interfaceName}") : forEventName, "", exceptionState); -END - - if ($interface->parent) { - my $interfaceBase = $interface->parent; - $code .= <<END; - if (!initialize${interfaceBase}(eventInit, options, exceptionState, forEventName.isEmpty() ? String("${interfaceName}") : forEventName)) - return false; - -END - } - - foreach my $attribute (@{$interface->attributes}) { - if ($attribute->extendedAttributes->{"InitializedByEventConstructor"}) { - if ($attribute->type ne "any") { - my $attributeName = $attribute->name; - my $attributeImplName = GetImplName($attribute); - - my $isNullable = $attribute->isNullable ? "true" : "false"; - my $dictionaryGetter = "options.convert(conversionContext.setConversionType(\"" . $attribute->type . "\", $isNullable), \"$attributeName\", eventInit.$attributeImplName)"; - my $deprecation = $attribute->extendedAttributes->{"DeprecateAs"}; - if ($deprecation) { - $code .= " if ($dictionaryGetter) {\n"; - $code .= " if (options.hasProperty(\"$attributeName\"))\n"; - $code .= " " . GenerateDeprecationNotification($deprecation); - $code .= " } else {\n"; - $code .= " return false;\n"; - $code .= " }\n"; - } else { - $code .= " if (!$dictionaryGetter)\n"; - $code .= " return false;\n"; - } - } - } - } - - $code .= <<END; - return true; -} - -END - $implementation{nameSpaceWebCore}->add($code); -} - -sub GenerateNamedConstructor -{ - my $function = shift; - my $interface = shift; - - my $interfaceName = $interface->name; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - my $constructorRaisesException = $interface->extendedAttributes->{"RaisesException"} && $interface->extendedAttributes->{"RaisesException"} eq "Constructor"; - my $raisesExceptions = $function->extendedAttributes->{"RaisesException"} || $constructorRaisesException; - - my $maybeObserveFeature = GenerateFeatureObservation($function->extendedAttributes->{"MeasureAs"}); - my $maybeDeprecateFeature = GenerateDeprecationNotification($function->extendedAttributes->{"DeprecateAs"}); - - my @beforeArgumentList; - my @afterArgumentList; - - my $toActiveDOMObject = "0"; - if (InheritsExtendedAttribute($interface, "ActiveDOMObject")) { - $toActiveDOMObject = "${v8ClassName}::toActiveDOMObject"; - } - - my $toEventTarget = "0"; - if (InheritsInterface($interface, "EventTarget")) { - $toEventTarget = "${v8ClassName}::toEventTarget"; - } - - $implementation{nameSpaceWebCore}->add(<<END); -const WrapperTypeInfo ${v8ClassName}Constructor::wrapperTypeInfo = { gin::kEmbedderBlink, ${v8ClassName}Constructor::domTemplate, ${v8ClassName}::derefObject, $toActiveDOMObject, $toEventTarget, 0, ${v8ClassName}::installPerContextEnabledMethods, 0, WrapperTypeObjectPrototype }; - -END - - my $code = ""; - $code .= <<END; -static void ${v8ClassName}ConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info) -{ -END - $code .= $maybeObserveFeature if $maybeObserveFeature; - $code .= $maybeDeprecateFeature if $maybeDeprecateFeature; - $code .= GenerateConstructorHeader($function->extendedAttributes->{"NamedConstructor"}); - $code .= <<END; - Document* document = currentDocument(); - ASSERT(document); - - // Make sure the document is added to the DOM Node map. Otherwise, the ${implClassName} instance - // may end up being the only node in the map and get garbage-collected prematurely. - toV8(document, info.Holder(), info.GetIsolate()); - -END - - if ($raisesExceptions) { - $code .= " ExceptionState exceptionState(ExceptionState::ConstructionContext, \"${interfaceName}\", info.Holder(), info.GetIsolate());\n"; - } - - my $hasExceptionState = $raisesExceptions; - $code .= GenerateArgumentsCountCheck($function, $interface, $hasExceptionState); - - my ($parameterCheckString, $paramIndex, %replacements) = GenerateParametersCheck($function, $interface); - $code .= $parameterCheckString; - - push(@beforeArgumentList, "*document"); - - if ($constructorRaisesException) { - push(@afterArgumentList, "exceptionState"); - } - - my @argumentList; - my $index = 0; - foreach my $parameter (@{$function->parameters}) { - last if $index eq $paramIndex; - if ($replacements{$parameter->name}) { - push(@argumentList, $replacements{$parameter->name}); - } else { - push(@argumentList, $parameter->name); - } - $index++; - } - - my $argumentString = join(", ", @beforeArgumentList, @argumentList, @afterArgumentList); - $code .= " RefPtr<${implClassName}> impl = ${implClassName}::createForJSConstructor(${argumentString});\n"; - $code .= " v8::Handle<v8::Object> wrapper = info.Holder();\n"; - - if ($constructorRaisesException) { - $code .= " if (exceptionState.throwIfNeeded())\n"; - $code .= " return;\n"; - } - - $code .= <<END; - - V8DOMWrapper::associateObjectWithWrapper<${v8ClassName}>(impl.release(), &${v8ClassName}Constructor::wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent); - v8SetReturnValue(info, wrapper); -} - -END - $implementation{nameSpaceWebCore}->add($code); - - $code = <<END; -v8::Handle<v8::FunctionTemplate> ${v8ClassName}Constructor::domTemplate(v8::Isolate* isolate, WrapperWorldType currentWorldType) -{ - // This is only for getting a unique pointer which we can pass to privateTemplate. - static int privateTemplateUniqueKey; - V8PerIsolateData* data = V8PerIsolateData::from(isolate); - v8::Local<v8::FunctionTemplate> result = data->privateTemplateIfExists(currentWorldType, &privateTemplateUniqueKey); - if (!result.IsEmpty()) - return result; - - TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); - v8::EscapableHandleScope scope(isolate); - result = v8::FunctionTemplate::New(isolate, ${v8ClassName}ConstructorCallback); - - v8::Local<v8::ObjectTemplate> instanceTemplate = result->InstanceTemplate(); - instanceTemplate->SetInternalFieldCount(${v8ClassName}::internalFieldCount); - result->SetClassName(v8::String::NewFromUtf8(isolate, "${implClassName}", v8::String::kInternalizedString)); - result->Inherit(${v8ClassName}::domTemplate(isolate, currentWorldType)); - data->setPrivateTemplate(currentWorldType, &privateTemplateUniqueKey, result); - - return scope.Escape(result); -} - -END - $implementation{nameSpaceWebCore}->add($code); -} - -sub GenerateConstructorHeader -{ - my $constructorName = shift; - - AddToImplIncludes("bindings/v8/V8ObjectConstructor.h"); - my $content = <<END; - if (!info.IsConstructCall()) { - throwTypeError(ExceptionMessages::failedToConstruct("$constructorName", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate()); - return; - } - - if (ConstructorMode::current() == ConstructorMode::WrapExistingObject) { - v8SetReturnValue(info, info.Holder()); - return; - } - -END - return $content; -} - -sub GenerateAttributeConfigurationArray -{ - my $interface = shift; - my $attributes = shift; - my $exposeJSAccessors = shift; - - my $code = ""; - foreach my $attribute (@$attributes) { - my $conditionalString = GenerateConditionalString($attribute); - my $subCode = ""; - $subCode .= "#if ${conditionalString}\n" if $conditionalString; - $subCode .= GenerateAttributeConfiguration($interface, $attribute, ",", "", $exposeJSAccessors); - $subCode .= "#endif // ${conditionalString}\n" if $conditionalString; - $code .= $subCode; - } - return $code; -} - -sub GenerateAttributeConfigurationParameters -{ - my $interface = shift; - my $attribute = shift; - my $attrName = $attribute->name; - my $attrExt = $attribute->extendedAttributes; - my $implClassName = GetImplName($interface); - - my @accessControlList; - if (my $doNotCheckSecurity = $attrExt->{"DoNotCheckSecurity"}) { - if ($doNotCheckSecurity eq "Getter") { - push(@accessControlList, "v8::ALL_CAN_READ"); - } elsif ($doNotCheckSecurity eq "Setter") { - push(@accessControlList, "v8::ALL_CAN_WRITE"); - } else { - push(@accessControlList, "v8::ALL_CAN_READ"); - if (!IsReadonly($attribute)) { - push(@accessControlList, "v8::ALL_CAN_WRITE"); - } - } - } - if ($attrExt->{"Unforgeable"}) { - push(@accessControlList, "v8::PROHIBITS_OVERWRITING"); - } - @accessControlList = ("v8::DEFAULT") unless @accessControlList; - my $accessControl = "static_cast<v8::AccessControl>(" . join(" | ", @accessControlList) . ")"; - - my $customAccessor = HasCustomGetter($attrExt) || HasCustomSetter($attribute) || ""; - if ($customAccessor eq "VALUE_IS_MISSING") { - # use the naming convension, interface + (capitalize) attr name - $customAccessor = $implClassName . "::" . $attrName; - } - - my $getter; - my $setter; - my $getterForMainWorld; - my $setterForMainWorld; - - my $isConstructor = ($attribute->type =~ /Constructor$/); - - # Check attributes. - # As per Web IDL specification, constructor properties on the ECMAScript global object should be - # configurable and should not be enumerable. - my @propAttributeList; - if ($attrExt->{"NotEnumerable"} || $isConstructor) { - push(@propAttributeList, "v8::DontEnum"); - } - if ($attrExt->{"Unforgeable"} && !$isConstructor) { - push(@propAttributeList, "v8::DontDelete"); - } - @propAttributeList = ("v8::None") unless @propAttributeList; - my $propAttribute = join(" | ", @propAttributeList); - - my $onProto = "0 /* on instance */"; - my $data = "0"; # no data - - # Constructor - if ($isConstructor) { - my $constructorType = $attribute->type; - $constructorType =~ s/Constructor$//; - - # For NamedConstructors we do not generate a header file. The code for the NamedConstructor - # gets generated when we generate the code for its interface. - if ($constructorType !~ /Constructor$/) { - AddToImplIncludes("V8${constructorType}.h"); - } - $data = "const_cast<WrapperTypeInfo*>(&V8${constructorType}::wrapperTypeInfo)"; - $getter = "${implClassName}V8Internal::${implClassName}ConstructorGetter"; - $setter = "${implClassName}V8Internal::${implClassName}ReplaceableAttributeSetterCallback"; - $getterForMainWorld = "0"; - $setterForMainWorld = "0"; - } else { - # Default Getter and Setter - $getter = "${implClassName}V8Internal::${attrName}AttributeGetterCallback"; - $setter = "${implClassName}V8Internal::${attrName}AttributeSetterCallback"; - $getterForMainWorld = "${getter}ForMainWorld"; - $setterForMainWorld = "${setter}ForMainWorld"; - - if (!HasCustomSetter($attribute) && !$attrExt->{"PutForwards"} && $attrExt->{"Replaceable"}) { - $setter = "${implClassName}V8Internal::${implClassName}ReplaceableAttributeSetterCallback"; - $setterForMainWorld = "0"; - } - } - - # Read only attributes - if (IsReadonly($attribute)) { - $setter = "0"; - $setterForMainWorld = "0"; - } - - # An accessor can be installed on the prototype - if ($attrExt->{"OnPrototype"}) { - $onProto = "1 /* on prototype */"; - } - - if (!$attrExt->{"PerWorldBindings"}) { - $getterForMainWorld = "0"; - $setterForMainWorld = "0"; - } - - return ($attrName, $getter, $setter, $getterForMainWorld, $setterForMainWorld, $data, $accessControl, "static_cast<v8::PropertyAttribute>($propAttribute)", $onProto); -} - -sub GenerateAttributeConfiguration -{ - my $interface = shift; - my $attribute = shift; - my $delimiter = shift; - my $indent = shift; - my $exposeJSAccessors = shift; - - my $code = ""; - - my ($attrName, $getter, $setter, $getterForMainWorld, $setterForMainWorld, $data, $accessControl, $propAttribute, $onProto) = GenerateAttributeConfigurationParameters($interface, $attribute, $exposeJSAccessors); - if ($exposeJSAccessors) { - $code .= $indent . " {\"$attrName\", $getter, $setter, $getterForMainWorld, $setterForMainWorld, $data, $accessControl, $propAttribute}" . $delimiter . "\n"; - } else { - $code .= $indent . " {\"$attrName\", $getter, $setter, $getterForMainWorld, $setterForMainWorld, $data, $accessControl, $propAttribute, $onProto}" . $delimiter . "\n"; - } - return $code; -} - -sub GenerateStaticAttribute -{ - my $interface = shift; - my $attribute = shift; - my $attrExt = $attribute->extendedAttributes; - my $code = ""; - - my ($attrName, $getter, $setter, $getterForMainWorld, $setterForMainWorld, $data, $accessControl, $propAttribute, $onProto) = GenerateAttributeConfigurationParameters($interface, $attribute); - - die "Static attributes do not support optimized getters or setters for the main world" if $getterForMainWorld || $setterForMainWorld; - - my $conditionalString = GenerateConditionalString($attribute); - - $code .= "#if ${conditionalString}\n" if $conditionalString; - $code .= " functionTemplate->SetNativeDataProperty(v8::String::NewFromUtf8(isolate, \"$attrName\", v8::String::kInternalizedString), $getter, $setter, v8::External::New(isolate, $data), $propAttribute, v8::Handle<v8::AccessorSignature>(), $accessControl);\n"; - $code .= "#endif // ${conditionalString}\n" if $conditionalString; - - return $code; -} - -sub IsStandardFunction -{ - my $interface = shift; - my $function = shift; - - my $interfaceName = $interface->name; - my $attrExt = $function->extendedAttributes; - return 0 if $attrExt->{"Unforgeable"}; - return 0 if $function->isStatic; - return 0 if $attrExt->{"RuntimeEnabled"}; - return 0 if $attrExt->{"PerContextEnabled"}; - return 0 if RequiresCustomSignature($function); - return 0 if $attrExt->{"DoNotCheckSignature"}; - return 0 if ($attrExt->{"DoNotCheckSecurity"} && ($interface->extendedAttributes->{"CheckSecurity"} || $interfaceName eq "Window")); - return 0 if $attrExt->{"NotEnumerable"}; - return 0 if $attrExt->{"ReadOnly"}; - return 1; -} - -sub GenerateNonStandardFunction -{ - my $interface = shift; - my $function = shift; - my $code = ""; - - my $implClassName = GetImplName($interface); - my $attrExt = $function->extendedAttributes; - my $name = $function->name; - - my $property_attributes = "v8::DontDelete"; - if ($attrExt->{"NotEnumerable"}) { - $property_attributes .= " | v8::DontEnum"; - } - if ($attrExt->{"ReadOnly"}) { - $property_attributes .= " | v8::ReadOnly"; - } - - my $commentInfo = "Function '$name' (Extended Attributes: '" . join(' ', keys(%{$attrExt})) . "')"; - - my $template = "prototypeTemplate"; - if ($attrExt->{"Unforgeable"}) { - $template = "instanceTemplate"; - } - if ($function->isStatic) { - $template = "functionTemplate"; - } - - my $conditional4 = ""; # 4 space indent context - my $conditional8 = ""; # 8 space indent context - if ($attrExt->{"RuntimeEnabled"}) { - # Only call Set()/SetAccessor() if this method should be enabled - my $runtimeEnabledFunction = GetRuntimeEnabledFunctionName($function); - $conditional4 = "if (${runtimeEnabledFunction}())\n "; - } - if ($attrExt->{"PerContextEnabled"}) { - # Only call Set()/SetAccessor() if this method should be enabled - my $contextEnabledFunction = GetContextEnabledFunctionName($function); - $conditional4 = "if (${contextEnabledFunction}(impl->document()))\n "; - } - $conditional8 = $conditional4 . " " if $conditional4 ne ""; - - if ($interface->extendedAttributes->{"CheckSecurity"} && $attrExt->{"DoNotCheckSecurity"}) { - my $setter = $attrExt->{"ReadOnly"} ? "0" : "${implClassName}V8Internal::${implClassName}OriginSafeMethodSetterCallback"; - # Functions that are marked DoNotCheckSecurity are always readable but if they are changed - # and then accessed on a different domain we do not return the underlying value but instead - # return a new copy of the original function. This is achieved by storing the changed value - # as hidden property. - if ($function->extendedAttributes->{"PerWorldBindings"}) { - $code .= <<END; - if (currentWorldType == MainWorld) { - ${conditional8}$template->SetAccessor(v8::String::NewFromUtf8(isolate, "$name", v8::String::kInternalizedString), ${implClassName}V8Internal::${name}OriginSafeMethodGetterCallbackForMainWorld, ${setter}, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>($property_attributes)); - } else { - ${conditional8}$template->SetAccessor(v8::String::NewFromUtf8(isolate, "$name", v8::String::kInternalizedString), ${implClassName}V8Internal::${name}OriginSafeMethodGetterCallback, ${setter}, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>($property_attributes)); - } -END - } else { - $code .= " ${conditional4}$template->SetAccessor(v8::String::NewFromUtf8(isolate, \"$name\", v8::String::kInternalizedString), ${implClassName}V8Internal::${name}OriginSafeMethodGetterCallback, ${setter}, v8Undefined(), v8::ALL_CAN_READ, static_cast<v8::PropertyAttribute>($property_attributes));\n"; - } - - return $code; - } - - my $signature = "defaultSignature"; - if ($attrExt->{"DoNotCheckSignature"} || $function->isStatic) { - $signature = "v8::Local<v8::Signature>()"; - } - - my $conditionalString = GenerateConditionalString($function); - $code .= "#if ${conditionalString}\n" if $conditionalString; - if (RequiresCustomSignature($function)) { - $signature = "${name}Signature"; - $code .= "\n // Custom Signature '$name'\n" . CreateCustomSignature($function); - } - - if ($property_attributes eq "v8::DontDelete") { - $property_attributes = ""; - } else { - $property_attributes = ", static_cast<v8::PropertyAttribute>($property_attributes)"; - } - - if ($template eq "prototypeTemplate" && $conditional4 eq "" && $signature eq "defaultSignature" && $property_attributes eq "") { - die "This shouldn't happen: Class '$implClassName' $commentInfo\n"; - } - - my $functionLength = GetFunctionLength($function); - - if ($function->extendedAttributes->{"PerWorldBindings"}) { - $code .= " if (currentWorldType == MainWorld) {\n"; - $code .= " ${conditional8}$template->Set(v8::String::NewFromUtf8(isolate, \"$name\", v8::String::kInternalizedString), v8::FunctionTemplate::New(isolate, ${implClassName}V8Internal::${name}MethodCallbackForMainWorld, v8Undefined(), ${signature}, $functionLength)$property_attributes);\n"; - $code .= " } else {\n"; - $code .= " ${conditional8}$template->Set(v8::String::NewFromUtf8(isolate, \"$name\", v8::String::kInternalizedString), v8::FunctionTemplate::New(isolate, ${implClassName}V8Internal::${name}MethodCallback, v8Undefined(), ${signature}, $functionLength)$property_attributes);\n"; - $code .= " }\n"; - } else { - $code .= " ${conditional4}$template->Set(v8::String::NewFromUtf8(isolate, \"$name\", v8::String::kInternalizedString), v8::FunctionTemplate::New(isolate, ${implClassName}V8Internal::${name}MethodCallback, v8Undefined(), ${signature}, $functionLength)$property_attributes);\n"; - } - $code .= "#endif // ${conditionalString}\n" if $conditionalString; - return $code; -} - -sub GenerateIsNullExpression -{ - my $type = shift; - my $variableName = shift; - if (IsUnionType($type)) { - my $types = $type->unionMemberTypes; - my @expression = (); - for my $i (0 .. scalar(@$types)-1) { - my $unionMemberType = $types->[$i]; - my $unionMemberVariable = $variableName . $i; - my $isNull = GenerateIsNullExpression($unionMemberType, $unionMemberVariable); - push @expression, $isNull; - } - return join " && ", @expression; - } - if (IsRefPtrType($type)) { - return "!${variableName}"; - } elsif ($type eq "DOMString") { - return "${variableName}.isNull()"; - } elsif ($type eq "Promise") { - return "${variableName}.isNull()"; - } else { - return ""; - } -} - -sub GenerateIfElseStatement -{ - my $type = shift; - my $outputVariableName = shift; - my $conditions = shift; - my $statements = shift; - - my $code = ""; - if (@$conditions == 1) { - $code .= " ${type} ${outputVariableName} = " . $statements->[0] . "\n"; - } else { - $code .= " ${type} ${outputVariableName};\n"; - for my $i (0 .. @$conditions - 1) { - my $token = "else if"; - $token = "if" if $i == 0; - $token = "else" if $i == @$conditions - 1; - $code .= " ${token}"; - $code .= " (" . $conditions->[$i] . ")" if $conditions->[$i]; - $code .= "\n"; - $code .= " ${outputVariableName} = " . $statements->[$i] . "\n"; - } - } - return $code; -} - -sub GenerateImplementationIndexedPropertyAccessors -{ - my $interface = shift; - my $interfaceName = $interface->name; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - - my $indexedGetterFunction = GetIndexedGetterFunction($interface); - if ($indexedGetterFunction) { - my $hasCustomIndexedGetter = $indexedGetterFunction->extendedAttributes->{"Custom"}; - if (!$hasCustomIndexedGetter) { - GenerateImplementationIndexedPropertyGetter($interface, $indexedGetterFunction); - } - GenerateImplementationIndexedPropertyGetterCallback($interface, $hasCustomIndexedGetter); - } - - my $indexedSetterFunction = GetIndexedSetterFunction($interface); - if ($indexedSetterFunction) { - my $hasCustomIndexedSetter = $indexedSetterFunction->extendedAttributes->{"Custom"}; - if (!$hasCustomIndexedSetter) { - GenerateImplementationIndexedPropertySetter($interface, $indexedSetterFunction); - } - GenerateImplementationIndexedPropertySetterCallback($interface, $hasCustomIndexedSetter); - } - - my $indexedDeleterFunction = GetIndexedDeleterFunction($interface); - if ($indexedDeleterFunction) { - my $hasCustomIndexedDeleter = $indexedDeleterFunction->extendedAttributes->{"Custom"}; - if (!$hasCustomIndexedDeleter) { - GenerateImplementationIndexedPropertyDeleter($interface, $indexedDeleterFunction); - } - GenerateImplementationIndexedPropertyDeleterCallback($interface, $hasCustomIndexedDeleter); - } - - my $indexedEnumeratorFunction = $indexedGetterFunction; - $indexedEnumeratorFunction = 0 if $indexedGetterFunction && $indexedGetterFunction->extendedAttributes->{"NotEnumerable"}; - - my $indexedQueryFunction = 0; - # If there is an enumerator, there MUST be a query method to properly communicate property attributes. - my $hasQuery = $indexedQueryFunction || $indexedEnumeratorFunction; - - my $setOn = "Instance"; - - # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on Window - # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to - # get implementation straight out of the Window prototype regardless of what prototype is actually set - # on the object. - if ($interfaceName eq "Window") { - $setOn = "Prototype"; - } - - my $code = ""; - if ($indexedGetterFunction || $indexedSetterFunction || $indexedDeleterFunction || $indexedEnumeratorFunction || $hasQuery) { - $code .= " functionTemplate->${setOn}Template()->SetIndexedPropertyHandler(${implClassName}V8Internal::indexedPropertyGetterCallback"; - $code .= $indexedSetterFunction ? ", ${implClassName}V8Internal::indexedPropertySetterCallback" : ", 0"; - $code .= ", 0"; # IndexedPropertyQuery -- not being used at the moment. - $code .= $indexedDeleterFunction ? ", ${implClassName}V8Internal::indexedPropertyDeleterCallback" : ", 0"; - $code .= $indexedEnumeratorFunction ? ", indexedPropertyEnumerator<${implClassName}>" : ", 0"; - $code .= ");\n"; - } - - return $code; -} - -sub GenerateImplementationIndexedPropertyGetter -{ - my $interface = shift; - my $indexedGetterFunction = shift; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - my $methodName = GetImplName($indexedGetterFunction); - - my $returnType = $indexedGetterFunction->type; - my $nativeType = GetNativeType($returnType); - my $nativeValue = "element"; - $nativeValue .= ".release()" if (IsRefPtrType($returnType)); - my $isNull = GenerateIsNullExpression($returnType, "element"); - my $returnJSValueCode = NativeToJSValue($indexedGetterFunction->type, $indexedGetterFunction->extendedAttributes, $nativeValue, " ", "", "info.GetIsolate()", "info", "collection", "", "return"); - my $raisesExceptions = $indexedGetterFunction->extendedAttributes->{"RaisesException"}; - my $methodCallCode = GenerateMethodCall($returnType, "element", "collection->${methodName}", "index", $raisesExceptions); - my $getterCode = "static void indexedPropertyGetter(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; - $getterCode .= "{\n"; - $getterCode .= " ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder()));\n"; - $getterCode .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder());\n"; - if ($raisesExceptions) { - $getterCode .= " ExceptionState exceptionState(info.Holder(), info.GetIsolate());\n"; - } - $getterCode .= $methodCallCode . "\n"; - if ($raisesExceptions) { - $getterCode .= " if (exceptionState.throwIfNeeded())\n"; - $getterCode .= " return;\n"; - } - if (IsUnionType($returnType)) { - $getterCode .= "${returnJSValueCode}\n"; - $getterCode .= " return;\n"; - } else { - $getterCode .= " if (${isNull})\n"; - $getterCode .= " return;\n"; - $getterCode .= $returnJSValueCode . "\n"; - } - $getterCode .= "}\n\n"; - $implementation{nameSpaceInternal}->add($getterCode); -} - -sub GenerateImplementationIndexedPropertyGetterCallback -{ - my $interface = shift; - my $hasCustom = shift; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - - my $code = "static void indexedPropertyGetterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; - $code .= "{\n"; - $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty\");\n"; - if ($hasCustom) { - $code .= " ${v8ClassName}::indexedPropertyGetterCustom(index, info);\n"; - } else { - $code .= " ${implClassName}V8Internal::indexedPropertyGetter(index, info);\n"; - } - $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; - $code .= "}\n\n"; - $implementation{nameSpaceInternal}->add($code); -} - -sub GenerateImplementationIndexedPropertySetterCallback -{ - my $interface = shift; - my $hasCustom = shift; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - - my $code = "static void indexedPropertySetterCallback(uint32_t index, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; - $code .= "{\n"; - $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty\");\n"; - if ($hasCustom) { - $code .= " ${v8ClassName}::indexedPropertySetterCustom(index, jsValue, info);\n"; - } else { - $code .= " ${implClassName}V8Internal::indexedPropertySetter(index, jsValue, info);\n"; - } - $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; - $code .= "}\n\n"; - $implementation{nameSpaceInternal}->add($code); -} - -sub GenerateImplementationIndexedPropertyDeleterCallback -{ - my $interface = shift; - my $hasCustom = shift; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - - my $code = "static void indexedPropertyDeleterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info)\n"; - $code .= "{\n"; - $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMIndexedProperty\");\n"; - if ($hasCustom) { - $code .= " ${v8ClassName}::indexedPropertyDeleterCustom(index, info);\n"; - } else { - $code .= " ${implClassName}V8Internal::indexedPropertyDeleter(index, info);\n"; - } - $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; - $code .= "}\n\n"; - $implementation{nameSpaceInternal}->add($code); -} - -sub GenerateImplementationIndexedPropertySetter -{ - my $interface = shift; - my $indexedSetterFunction = shift; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - my $methodName = GetImplName($indexedSetterFunction); - - my $type = $indexedSetterFunction->parameters->[1]->type; - my $raisesExceptions = $indexedSetterFunction->extendedAttributes->{"RaisesException"}; - my $treatNullAs = $indexedSetterFunction->parameters->[1]->extendedAttributes->{"TreatNullAs"}; - my $treatUndefinedAs = $indexedSetterFunction->parameters->[1]->extendedAttributes->{"TreatUndefinedAs"}; - my $asSetterValue = 0; - - my $code = "static void indexedPropertySetter(uint32_t index, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; - $code .= "{\n"; - $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder());\n"; - $code .= JSValueToNativeStatement($indexedSetterFunction->parameters->[1]->type, $indexedSetterFunction->extendedAttributes, $asSetterValue, "jsValue", "propertyValue", " ", "info.GetIsolate()"); - - my $extraArguments = ""; - if ($raisesExceptions) { - $code .= " ExceptionState exceptionState(info.Holder(), info.GetIsolate());\n"; - $extraArguments = ", exceptionState"; - } - my @conditions = (); - my @statements = (); - if ($treatNullAs && $treatNullAs ne "NullString") { - push @conditions, "jsValue->IsNull()"; - push @statements, "collection->${treatNullAs}(index$extraArguments);"; - } - if ($treatUndefinedAs && $treatUndefinedAs ne "NullString") { - push @conditions, "jsValue->IsUndefined()"; - push @statements, "collection->${treatUndefinedAs}(index$extraArguments);"; - } - push @conditions, ""; - push @statements, "collection->${methodName}(index, propertyValue$extraArguments);"; - $code .= GenerateIfElseStatement("bool", "result", \@conditions, \@statements); - - if ($raisesExceptions) { - $code .= " if (exceptionState.throwIfNeeded())\n"; - $code .= " return;\n"; - } - $code .= " if (!result)\n"; - $code .= " return;\n"; - $code .= " v8SetReturnValue(info, jsValue);\n"; - $code .= "}\n\n"; - $implementation{nameSpaceInternal}->add($code); -} - -sub GenerateImplementationNamedPropertyAccessors -{ - my $interface = shift; - - my $interfaceName = $interface->name; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - - my $namedGetterFunction = GetNamedGetterFunction($interface); - if ($namedGetterFunction) { - my $hasCustomNamedGetter = $namedGetterFunction->extendedAttributes->{"Custom"}; - if (!$hasCustomNamedGetter) { - GenerateImplementationNamedPropertyGetter($interface, $namedGetterFunction); - } - GenerateImplementationNamedPropertyGetterCallback($interface, $hasCustomNamedGetter); - } - - my $namedSetterFunction = GetNamedSetterFunction($interface); - if ($namedSetterFunction) { - my $hasCustomNamedSetter = $namedSetterFunction->extendedAttributes->{"Custom"}; - if (!$hasCustomNamedSetter) { - GenerateImplementationNamedPropertySetter($interface, $namedSetterFunction); - } - GenerateImplementationNamedPropertySetterCallback($interface, $hasCustomNamedSetter); - } - - my $namedDeleterFunction = GetNamedDeleterFunction($interface); - if ($namedDeleterFunction) { - my $hasCustomNamedDeleter = $namedDeleterFunction->extendedAttributes->{"Custom"}; - if (!$hasCustomNamedDeleter) { - GenerateImplementationNamedPropertyDeleter($interface, $namedDeleterFunction); - } - GenerateImplementationNamedPropertyDeleterCallback($interface, $hasCustomNamedDeleter); - } - - my $namedEnumeratorFunction = $namedGetterFunction && !$namedGetterFunction->extendedAttributes->{"NotEnumerable"}; - if ($namedEnumeratorFunction) { - my $hasCustomNamedEnumerator = $namedGetterFunction->extendedAttributes->{"CustomEnumerateProperty"}; - if (!$hasCustomNamedEnumerator) { - GenerateImplementationNamedPropertyEnumerator($interface); - GenerateImplementationNamedPropertyQuery($interface); - } - GenerateImplementationNamedPropertyEnumeratorCallback($interface, $hasCustomNamedEnumerator); - GenerateImplementationNamedPropertyQueryCallback($interface, $hasCustomNamedEnumerator); - } - - my $subCode = ""; - if ($namedGetterFunction || $namedSetterFunction || $namedDeleterFunction || $namedEnumeratorFunction) { - my $setOn = "Instance"; - - # V8 has access-check callback API (see ObjectTemplate::SetAccessCheckCallbacks) and it's used on Window - # instead of deleters or enumerators. In addition, the getter should be set on prototype template, to - # get implementation straight out of the Window prototype regardless of what prototype is actually set - # on the object. - if ($interfaceName eq "Window") { - $setOn = "Prototype"; - } - - $subCode .= " functionTemplate->${setOn}Template()->SetNamedPropertyHandler("; - $subCode .= $namedGetterFunction ? "${implClassName}V8Internal::namedPropertyGetterCallback, " : "0, "; - $subCode .= $namedSetterFunction ? "${implClassName}V8Internal::namedPropertySetterCallback, " : "0, "; - $subCode .= $namedEnumeratorFunction ? "${implClassName}V8Internal::namedPropertyQueryCallback, " : "0, "; - $subCode .= $namedDeleterFunction ? "${implClassName}V8Internal::namedPropertyDeleterCallback, " : "0, "; - $subCode .= $namedEnumeratorFunction ? "${implClassName}V8Internal::namedPropertyEnumeratorCallback" : "0"; - $subCode .= ");\n"; - } - - return $subCode; -} - -sub GenerateImplementationNamedPropertyGetterCallback -{ - my $interface = shift; - my $hasCustom = shift; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - - my $code = "static void namedPropertyGetterCallback(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; - $code .= "{\n"; - $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\");\n"; - if ($hasCustom) { - $code .= " ${v8ClassName}::namedPropertyGetterCustom(name, info);\n"; - } else { - $code .= " ${implClassName}V8Internal::namedPropertyGetter(name, info);\n"; - } - $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; - $code .= "}\n\n"; - $implementation{nameSpaceInternal}->add($code); -} - -sub GenerateImplementationNamedPropertySetterCallback -{ - my $interface = shift; - my $hasCustom = shift; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - - my $code = "static void namedPropertySetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; - $code .= "{\n"; - $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\");\n"; - if ($hasCustom) { - $code .= " ${v8ClassName}::namedPropertySetterCustom(name, jsValue, info);\n"; - } else { - $code .= " ${implClassName}V8Internal::namedPropertySetter(name, jsValue, info);\n"; - } - $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; - $code .= "}\n\n"; - $implementation{nameSpaceInternal}->add($code); -} - -sub GenerateImplementationNamedPropertyDeleterCallback -{ - my $interface = shift; - my $hasCustom = shift; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - - my $code = "static void namedPropertyDeleterCallback(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Boolean>& info)\n"; - $code .= "{\n"; - $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\");\n"; - if ($hasCustom) { - $code .= " ${v8ClassName}::namedPropertyDeleterCustom(name, info);\n"; - } else { - $code .= " ${implClassName}V8Internal::namedPropertyDeleter(name, info);\n"; - } - $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; - $code .= "}\n\n"; - $implementation{nameSpaceInternal}->add($code); -} - -sub GenerateImplementationNamedPropertyEnumeratorCallback -{ - my $interface = shift; - my $hasCustom = shift; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - - my $code = "static void namedPropertyEnumeratorCallback(const v8::PropertyCallbackInfo<v8::Array>& info)\n"; - $code .= "{\n"; - $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\");\n"; - if ($hasCustom) { - $code .= " ${v8ClassName}::namedPropertyEnumeratorCustom(info);\n"; - } else { - $code .= " ${implClassName}V8Internal::namedPropertyEnumerator(info);\n"; - } - $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; - $code .= "}\n\n"; - $implementation{nameSpaceInternal}->add($code); -} - -sub GenerateImplementationNamedPropertyQueryCallback -{ - my $interface = shift; - my $hasCustom = shift; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - - my $code = "static void namedPropertyQueryCallback(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Integer>& info)\n"; - $code .= "{\n"; - $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"Blink\", \"DOMNamedProperty\");\n"; - if ($hasCustom) { - $code .= " ${v8ClassName}::namedPropertyQueryCustom(name, info);\n"; - } else { - $code .= " ${implClassName}V8Internal::namedPropertyQuery(name, info);\n"; - } - $code .= " TRACE_EVENT_SET_SAMPLING_STATE(\"V8\", \"Execution\");\n"; - $code .= "}\n\n"; - $implementation{nameSpaceInternal}->add($code); -} - -sub GenerateMethodCall -{ - my $returnType = shift; # string or UnionType - my $returnName = shift; - my $functionExpression = shift; - my $firstArgument = shift; - my $raisesExceptions = shift; - - my @arguments = (); - push @arguments, $firstArgument; - if ($raisesExceptions) { - push @arguments, "exceptionState"; - } - - if (IsUnionType($returnType)) { - my $code = ""; - my @extraArguments = (); - for my $i (0..scalar(@{$returnType->unionMemberTypes})-1) { - my $unionMemberType = $returnType->unionMemberTypes->[$i]; - my $nativeType = GetNativeType($unionMemberType); - my $unionMemberVariable = $returnName . $i; - my $unionMemberEnabledVariable = $returnName . $i . "Enabled"; - $code .= " bool ${unionMemberEnabledVariable} = false;\n"; - $code .= " ${nativeType} ${unionMemberVariable};\n"; - push @extraArguments, $unionMemberEnabledVariable; - push @extraArguments, $unionMemberVariable; - } - push @arguments, @extraArguments; - $code .= " ${functionExpression}(" . (join ", ", @arguments) . ");"; - return $code; - } else { - my $nativeType = GetNativeType($returnType); - return " ${nativeType} element = ${functionExpression}(" . (join ", ", @arguments) . ");" - } -} - -sub GenerateImplementationNamedPropertyGetter -{ - my $interface = shift; - my $namedGetterFunction = shift; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - my $methodName = GetImplName($namedGetterFunction); - - my $returnType = $namedGetterFunction->type; - my $isNull = GenerateIsNullExpression($returnType, "element"); - my $nativeValue = "element"; - $nativeValue .= ".release()" if (IsRefPtrType($returnType)); - my $returnJSValueCode = NativeToJSValue($namedGetterFunction->type, $namedGetterFunction->extendedAttributes, $nativeValue, " ", "", "info.GetIsolate()", "info", "collection", "", "return"); - my $raisesExceptions = $namedGetterFunction->extendedAttributes->{"RaisesException"}; - my $methodCallCode = GenerateMethodCall($returnType, "element", "collection->${methodName}", "propertyName", $raisesExceptions); - - my $code = "static void namedPropertyGetter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; - $code .= "{\n"; - if (!$namedGetterFunction->extendedAttributes->{"OverrideBuiltins"}) { - $code .= " if (!info.Holder()->GetRealNamedPropertyInPrototypeChain(name).IsEmpty())\n"; - $code .= " return;\n"; - $code .= " if (info.Holder()->HasRealNamedCallbackProperty(name))\n"; - $code .= " return;\n"; - $code .= " if (info.Holder()->HasRealNamedProperty(name))\n"; - $code .= " return;\n"; - } - $code .= "\n"; - $code .= " ASSERT(V8DOMWrapper::maybeDOMWrapper(info.Holder()));\n"; - $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder());\n"; - $code .= " AtomicString propertyName = toCoreAtomicString(name);\n"; - if ($raisesExceptions) { - $code .= " ExceptionState exceptionState(info.Holder(), info.GetIsolate());\n"; - } - $code .= $methodCallCode . "\n"; - if ($raisesExceptions) { - $code .= " if (exceptionState.throwIfNeeded())\n"; - $code .= " return;\n"; - } - if (IsUnionType($returnType)) { - $code .= "${returnJSValueCode}\n"; - $code .= " return;\n"; - } else { - $code .= " if (${isNull})\n"; - $code .= " return;\n"; - $code .= $returnJSValueCode . "\n"; - } - $code .= "}\n\n"; - $implementation{nameSpaceInternal}->add($code); -} - -sub GenerateImplementationNamedPropertySetter -{ - my $interface = shift; - my $namedSetterFunction = shift; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - my $methodName = GetImplName($namedSetterFunction); - - my $raisesExceptions = $namedSetterFunction->extendedAttributes->{"RaisesException"}; - my $treatNullAs = $namedSetterFunction->parameters->[1]->extendedAttributes->{"TreatNullAs"}; - my $treatUndefinedAs = $namedSetterFunction->parameters->[1]->extendedAttributes->{"TreatUndefinedAs"}; - my $asSetterValue = 0; - - my $code = "static void namedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<v8::Value>& info)\n"; - $code .= "{\n"; - if (!$namedSetterFunction->extendedAttributes->{"OverrideBuiltins"}) { - $code .= " if (!info.Holder()->GetRealNamedPropertyInPrototypeChain(name).IsEmpty())\n"; - $code .= " return;\n"; - $code .= " if (info.Holder()->HasRealNamedCallbackProperty(name))\n"; - $code .= " return;\n"; - $code .= " if (info.Holder()->HasRealNamedProperty(name))\n"; - $code .= " return;\n"; - } - $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder());\n"; - $code .= JSValueToNativeStatement($namedSetterFunction->parameters->[0]->type, $namedSetterFunction->extendedAttributes, $asSetterValue, "name", "propertyName", " ", "info.GetIsolate()"); - $code .= JSValueToNativeStatement($namedSetterFunction->parameters->[1]->type, $namedSetterFunction->extendedAttributes, $asSetterValue, "jsValue", "propertyValue", " ", "info.GetIsolate()"); - my $extraArguments = ""; - if ($raisesExceptions) { - $code .= " ExceptionState exceptionState(info.Holder(), info.GetIsolate());\n"; - $extraArguments = ", exceptionState"; - } - - my @conditions = (); - my @statements = (); - if ($treatNullAs && $treatNullAs ne "NullString") { - push @conditions, "jsValue->IsNull()"; - push @statements, "collection->${treatNullAs}(propertyName$extraArguments);"; - } - if ($treatUndefinedAs && $treatUndefinedAs ne "NullString") { - push @conditions, "jsValue->IsUndefined()"; - push @statements, "collection->${treatUndefinedAs}(propertyName$extraArguments);"; - } - push @conditions, ""; - push @statements, "collection->${methodName}(propertyName, propertyValue$extraArguments);"; - $code .= GenerateIfElseStatement("bool", "result", \@conditions, \@statements); - - $code .= " if (!result)\n"; - $code .= " return;\n"; - if ($raisesExceptions) { - $code .= " if (exceptionState.throwIfNeeded())\n"; - $code .= " return;\n"; - } - $code .= " v8SetReturnValue(info, jsValue);\n"; - $code .= "}\n\n"; - $implementation{nameSpaceInternal}->add($code); -} - -sub GenerateImplementationIndexedPropertyDeleter -{ - my $interface = shift; - my $indexedDeleterFunction = shift; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - my $methodName = GetImplName($indexedDeleterFunction); - - my $raisesExceptions = $indexedDeleterFunction->extendedAttributes->{"RaisesException"}; - - my $code = "static void indexedPropertyDeleter(unsigned index, const v8::PropertyCallbackInfo<v8::Boolean>& info)\n"; - $code .= "{\n"; - $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder());\n"; - my $extraArguments = ""; - if ($raisesExceptions) { - $code .= " ExceptionState exceptionState(info.Holder(), info.GetIsolate());\n"; - $extraArguments = ", exceptionState"; - } - $code .= " bool result = collection->${methodName}(index$extraArguments);\n"; - if ($raisesExceptions) { - $code .= " if (exceptionState.throwIfNeeded())\n"; - $code .= " return;\n"; - } - $code .= " return v8SetReturnValueBool(info, result);\n"; - $code .= "}\n\n"; - $implementation{nameSpaceInternal}->add($code); -} - -sub GenerateImplementationNamedPropertyDeleter -{ - my $interface = shift; - my $namedDeleterFunction = shift; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - my $methodName = GetImplName($namedDeleterFunction); - - my $raisesExceptions = $namedDeleterFunction->extendedAttributes->{"RaisesException"}; - - my $code = "static void namedPropertyDeleter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Boolean>& info)\n"; - $code .= "{\n"; - $code .= " ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder());\n"; - $code .= " AtomicString propertyName = toCoreAtomicString(name);\n"; - my $extraArguments = ""; - if ($raisesExceptions) { - $code .= " ExceptionState exceptionState(info.Holder(), info.GetIsolate());\n"; - $extraArguments = ", exceptionState"; - } - $code .= " bool result = collection->${methodName}(propertyName$extraArguments);\n"; - if ($raisesExceptions) { - $code .= " if (exceptionState.throwIfNeeded())\n"; - $code .= " return;\n"; - } - $code .= " return v8SetReturnValueBool(info, result);\n"; - $code .= "}\n\n"; - $implementation{nameSpaceInternal}->add($code); -} - -sub GenerateImplementationNamedPropertyEnumerator -{ - my $interface = shift; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - - $implementation{nameSpaceInternal}->add(<<END); -static void namedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) -{ - ExceptionState exceptionState(info.Holder(), info.GetIsolate()); - ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder()); - Vector<String> names; - collection->namedPropertyEnumerator(names, exceptionState); - if (exceptionState.throwIfNeeded()) - return; - v8::Handle<v8::Array> v8names = v8::Array::New(info.GetIsolate(), names.size()); - for (size_t i = 0; i < names.size(); ++i) - v8names->Set(v8::Integer::New(info.GetIsolate(), i), v8String(info.GetIsolate(), names[i])); - v8SetReturnValue(info, v8names); -} - -END -} - -sub GenerateImplementationNamedPropertyQuery -{ - my $interface = shift; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - - $implementation{nameSpaceInternal}->add(<<END); -static void namedPropertyQuery(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Integer>& info) -{ - ${implClassName}* collection = ${v8ClassName}::toNative(info.Holder()); - AtomicString propertyName = toCoreAtomicString(name); - ExceptionState exceptionState(info.Holder(), info.GetIsolate()); - bool result = collection->namedPropertyQuery(propertyName, exceptionState); - if (exceptionState.throwIfNeeded()) - return; - if (!result) - return; - v8SetReturnValueInt(info, v8::None); -} - -END -} - -sub GenerateImplementationLegacyCallAsFunction -{ - my $interface = shift; - my $code = ""; - - my $v8ClassName = GetV8ClassName($interface); - - if (ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "LegacyCallAsFunction")) { - $code .= " functionTemplate->InstanceTemplate()->SetCallAsFunctionHandler(${v8ClassName}::legacyCallCustom);\n"; - } - return $code; -} - -sub GenerateImplementationMarkAsUndetectable -{ - my $interface = shift; - my $code = ""; - - # Needed for legacy support of document.all - if ($interface->name eq "HTMLAllCollection") - { - $code .= " functionTemplate->InstanceTemplate()->MarkAsUndetectable();\n"; - } - return $code; -} - -sub GenerateImplementation -{ - my $object = shift; - my $interface = shift; - my $interfaceName = $interface->name; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - my $nativeType = GetNativeTypeForConversions($interface); - - AddToImplIncludes("RuntimeEnabledFeatures.h"); - AddToImplIncludes("bindings/v8/ExceptionState.h"); - AddToImplIncludes("core/dom/ContextFeatures.h"); - AddToImplIncludes("core/dom/Document.h"); - AddToImplIncludes("platform/TraceEvent.h"); - - AddIncludesForType($interfaceName); - if ($interface->extendedAttributes->{"CheckSecurity"}) { - AddToImplIncludes("bindings/v8/BindingSecurity.h"); - } - - my $toActiveDOMObject = InheritsExtendedAttribute($interface, "ActiveDOMObject") ? "${v8ClassName}::toActiveDOMObject" : "0"; - my $toEventTarget = InheritsInterface($interface, "EventTarget") ? "${v8ClassName}::toEventTarget" : "0"; - my $visitDOMWrapper = NeedsVisitDOMWrapper($interface) ? "${v8ClassName}::visitDOMWrapper" : "0"; - - # Find the super descriptor. - my $parentClass = ""; - my $parentClassTemplate = ""; - if ($interface->parent) { - my $parent = $interface->parent; - $parentClass = "V8" . $parent; - $parentClassTemplate = $parentClass . "::domTemplate(isolate, currentWorldType)"; - } - - my $parentClassInfo = $parentClass ? "&${parentClass}::wrapperTypeInfo" : "0"; - my $WrapperTypePrototype = $interface->isException ? "WrapperTypeErrorPrototype" : "WrapperTypeObjectPrototype"; - - if (!IsSVGTypeNeedingTearOff($interfaceName)) { - my $code = <<END; -static void initializeScriptWrappableForInterface(${implClassName}* object) -{ - if (ScriptWrappable::wrapperCanBeStoredInObject(object)) - ScriptWrappable::setTypeInfoInObject(object, &${v8ClassName}::wrapperTypeInfo); - else - ASSERT_NOT_REACHED(); -} - -} // namespace WebCore - -// In ScriptWrappable::init, the use of a local function declaration has an issue on Windows: -// the local declaration does not pick up the surrounding namespace. Therefore, we provide this function -// in the global namespace. -// (More info on the MSVC bug here: http://connect.microsoft.com/VisualStudio/feedback/details/664619/the-namespace-of-local-function-declarations-in-c) -END - - if (GetNamespaceForInterface($interface) eq "WebCore") { - $code .= "void webCoreInitializeScriptWrappableForInterface(WebCore::${implClassName}* object)\n"; - } else { - $code .= "void webCoreInitializeScriptWrappableForInterface(${implClassName}* object)\n"; - } - - $code .= <<END; -{ - WebCore::initializeScriptWrappableForInterface(object); -} - -namespace WebCore { -END - $implementation{nameSpaceWebCore}->addHeader($code); - } - - my $code = "const WrapperTypeInfo ${v8ClassName}::wrapperTypeInfo = { gin::kEmbedderBlink, ${v8ClassName}::domTemplate, ${v8ClassName}::derefObject, $toActiveDOMObject, $toEventTarget, "; - $code .= "$visitDOMWrapper, ${v8ClassName}::installPerContextEnabledMethods, $parentClassInfo, $WrapperTypePrototype };\n"; - $implementation{nameSpaceWebCore}->addHeader($code); - - $implementation{nameSpaceInternal}->add("template <typename T> void V8_USE(T) { }\n\n"); - - my $hasConstructors = 0; - my $hasReplaceable = 0; - - # Generate property accessors for attributes. - for (my $index = 0; $index < @{$interface->attributes}; $index++) { - my $attribute = @{$interface->attributes}[$index]; - my $attrType = $attribute->type; - my $attrExt = $attribute->extendedAttributes; - - # Generate special code for the constructor attributes. - if ($attrType =~ /Constructor$/) { - if (!HasCustomGetter($attrExt)) { - $hasConstructors = 1; - } - next; - } - - AddIncludesForType($attrType); - - if ($attrType eq "EventHandler" && $interfaceName eq "Window") { - $attrExt->{"OnPrototype"} = 1; - } - - if ($attrType eq "SerializedScriptValue") { - AddToImplIncludes("bindings/v8/SerializedScriptValue.h"); - } - - my $isReplaceable = 0; - if (!HasCustomSetter($attribute) && !$attrExt->{"PutForwards"} && $attrExt->{"Replaceable"}) { - $isReplaceable = 1; - $hasReplaceable = 1; - } - - my $exposeJSAccessors = $attrExt->{"ExposeJSAccessors"}; - my @worldSuffixes = (""); - if ($attrExt->{"PerWorldBindings"}) { - push(@worldSuffixes, "ForMainWorld"); - } - foreach my $worldSuffix (@worldSuffixes) { - GenerateNormalAttributeGetter($attribute, $interface, $worldSuffix, $exposeJSAccessors); - GenerateNormalAttributeGetterCallback($attribute, $interface, $worldSuffix, $exposeJSAccessors); - if (!$isReplaceable && !IsReadonly($attribute)) { - GenerateNormalAttributeSetter($attribute, $interface, $worldSuffix, $exposeJSAccessors); - GenerateNormalAttributeSetterCallback($attribute, $interface, $worldSuffix, $exposeJSAccessors); - } - } - } - - if ($hasConstructors) { - GenerateConstructorGetter($interface); - } - - if ($hasConstructors || $hasReplaceable) { - GenerateReplaceableAttributeSetter($interface); - GenerateReplaceableAttributeSetterCallback($interface); - } - - if (NeedsVisitDOMWrapper($interface)) { - GenerateVisitDOMWrapper($interface); - } - - if ($interface->extendedAttributes->{"CheckSecurity"} && $interface->name ne "Window") { - GenerateSecurityCheckFunctions($interface); - } - - my @perContextEnabledFunctions; - my @normalFunctions; - my $needsDomainSafeFunctionSetter = 0; - # Generate methods for functions. - foreach my $function (@{$interface->functions}) { - next if $function->name eq ""; - my @worldSuffixes = (""); - if ($function->extendedAttributes->{"PerWorldBindings"}) { - push(@worldSuffixes, "ForMainWorld"); - } - foreach my $worldSuffix (@worldSuffixes) { - GenerateFunction($function, $interface, $worldSuffix); - if ($function->{overloadIndex} == @{$function->{overloads}}) { - if ($function->{overloadIndex} > 1) { - GenerateOverloadedFunction($function, $interface, $worldSuffix); - } - GenerateFunctionCallback($function, $interface, $worldSuffix); - } - - # If the function does not need domain security check, we need to - # generate an access getter that returns different function objects - # for different calling context. - if ($interface->extendedAttributes->{"CheckSecurity"} && $function->extendedAttributes->{"DoNotCheckSecurity"} && (!HasCustomMethod($function->extendedAttributes) || $function->{overloadIndex} == 1)) { - GenerateDomainSafeFunctionGetter($function, $interface, $worldSuffix); - if (!$function->extendedAttributes->{"ReadOnly"}) { - $needsDomainSafeFunctionSetter = 1; - } - } - } - - # Separate out functions that are enabled per context so we can process them specially. - if ($function->extendedAttributes->{"PerContextEnabled"}) { - push(@perContextEnabledFunctions, $function); - } else { - push(@normalFunctions, $function); - } - } - - if ($needsDomainSafeFunctionSetter) { - GenerateDomainSafeFunctionSetter($interface); - } - - # Attributes - my $attributes = $interface->attributes; - - # For the Window interface we partition the attributes into the - # ones that disallows shadowing and the rest. - my @disallowsShadowing; - # Also separate out attributes that are enabled at runtime so we can process them specially. - my @runtimeEnabledAttributes; - my @perContextEnabledAttributes; - my @normalAttributes; - my @normalAccessors; - my @staticAttributes; - foreach my $attribute (@$attributes) { - - if ($attribute->isStatic) { - push(@staticAttributes, $attribute); - } elsif ($interfaceName eq "Window" && $attribute->extendedAttributes->{"Unforgeable"}) { - push(@disallowsShadowing, $attribute); - } elsif ($attribute->extendedAttributes->{"PerContextEnabled"}) { - push(@perContextEnabledAttributes, $attribute); - } elsif ($attribute->extendedAttributes->{"RuntimeEnabled"}) { - push(@runtimeEnabledAttributes, $attribute); - } elsif ($attribute->extendedAttributes->{"ExposeJSAccessors"}) { - push(@normalAccessors, $attribute); - } else { - push(@normalAttributes, $attribute); - } - } - AddToImplIncludes("bindings/v8/V8DOMConfiguration.h"); - # Put the attributes that disallow shadowing on the shadow object. - if (@disallowsShadowing) { - my $code = ""; - $code .= "static const V8DOMConfiguration::AttributeConfiguration shadowAttributes[] = {\n"; - $code .= GenerateAttributeConfigurationArray($interface, \@disallowsShadowing); - $code .= "};\n\n"; - $implementation{nameSpaceWebCore}->add($code); - } - - my $hasAttributes = 0; - if (@normalAttributes) { - $hasAttributes = 1; - my $code = ""; - $code .= "static const V8DOMConfiguration::AttributeConfiguration ${v8ClassName}Attributes[] = {\n"; - $code .= GenerateAttributeConfigurationArray($interface, \@normalAttributes); - $code .= "};\n\n"; - $implementation{nameSpaceWebCore}->add($code); - } - - my $hasAccessors = 0; - if (@normalAccessors) { - $hasAccessors = 1; - my $code = ""; - $code .= "static const V8DOMConfiguration::AccessorConfiguration ${v8ClassName}Accessors[] = {\n"; - $code .= GenerateAttributeConfigurationArray($interface, \@normalAccessors, "accessor"); - $code .= "};\n\n"; - $implementation{nameSpaceWebCore}->add($code); - } - - # Setup table of standard callback functions - my $hasFunctions = 0; - $code = ""; - foreach my $function (@normalFunctions) { - # Only one table entry is needed for overloaded functions: - next if $function->{overloadIndex} > 1; - # Don't put any nonstandard functions into this table: - next if !IsStandardFunction($interface, $function); - next if $function->name eq ""; - if (!$hasFunctions) { - $hasFunctions = 1; - $code .= "static const V8DOMConfiguration::MethodConfiguration ${v8ClassName}Methods[] = {\n"; - } - my $name = $function->name; - my $methodForMainWorld = "0"; - if ($function->extendedAttributes->{"PerWorldBindings"}) { - $methodForMainWorld = "${implClassName}V8Internal::${name}MethodCallbackForMainWorld"; - } - my $functionLength = GetFunctionLength($function); - my $conditionalString = GenerateConditionalString($function); - $code .= "#if ${conditionalString}\n" if $conditionalString; - $code .= <<END; - {"$name", ${implClassName}V8Internal::${name}MethodCallback, ${methodForMainWorld}, ${functionLength}}, -END - $code .= "#endif // ${conditionalString}\n" if $conditionalString; - } - $code .= "};\n\n" if $hasFunctions; - $implementation{nameSpaceWebCore}->add($code); - - my $hasConstants = 0; - if (@{$interface->constants}) { - $hasConstants = 1; - } - - if (!HasCustomConstructor($interface)) { - if ($interface->extendedAttributes->{"NamedConstructor"}) { - GenerateNamedConstructor(@{$interface->constructors}[0], $interface); - } elsif ($interface->extendedAttributes->{"Constructor"}) { - GenerateConstructor($interface); - } elsif ($interface->extendedAttributes->{"EventConstructor"}) { - GenerateEventConstructor($interface); - } - } - if (IsConstructable($interface)) { - GenerateConstructorCallback($interface); - } - - my $accessCheck = ""; - if ($interface->extendedAttributes->{"CheckSecurity"} && $interfaceName ne "Window") { - $accessCheck = "instanceTemplate->SetAccessCheckCallbacks(${implClassName}V8Internal::namedSecurityCheck, ${implClassName}V8Internal::indexedSecurityCheck, v8::External::New(isolate, const_cast<WrapperTypeInfo*>(&${v8ClassName}::wrapperTypeInfo)));"; - } - - # For the Window interface, generate the shadow object template - # configuration method. - if ($interfaceName eq "Window") { - $implementation{nameSpaceWebCore}->add(<<END); -static void ConfigureShadowObjectTemplate(v8::Handle<v8::ObjectTemplate> templ, v8::Isolate* isolate, WrapperWorldType currentWorldType) -{ - V8DOMConfiguration::installAttributes(templ, v8::Handle<v8::ObjectTemplate>(), shadowAttributes, WTF_ARRAY_LENGTH(shadowAttributes), isolate, currentWorldType); - - // Install a security handler with V8. - templ->SetAccessCheckCallbacks(V8Window::namedSecurityCheckCustom, V8Window::indexedSecurityCheckCustom, v8::External::New(isolate, const_cast<WrapperTypeInfo*>(&V8Window::wrapperTypeInfo))); - templ->SetInternalFieldCount(V8Window::internalFieldCount); -} -END - } - - if (!$parentClassTemplate) { - $parentClassTemplate = "v8::Local<v8::FunctionTemplate>()"; - } - - # Generate the template configuration method - $code = <<END; -static v8::Handle<v8::FunctionTemplate> Configure${v8ClassName}Template(v8::Handle<v8::FunctionTemplate> functionTemplate, v8::Isolate* isolate, WrapperWorldType currentWorldType) -{ - functionTemplate->ReadOnlyPrototype(); - - v8::Local<v8::Signature> defaultSignature; -END - - # Define constants, attributes, accessors and operations. - my $runtimeEnabledIndent = ""; - if ($interface->extendedAttributes->{"RuntimeEnabled"}) { - my $runtimeEnabledFunction = GetRuntimeEnabledFunctionName($interface); - $runtimeEnabledIndent = " "; - $code .= <<END; - if (!${runtimeEnabledFunction}()) - defaultSignature = V8DOMConfiguration::installDOMClassTemplate(functionTemplate, \"\", $parentClassTemplate, ${v8ClassName}::internalFieldCount, 0, 0, 0, 0, 0, 0, isolate, currentWorldType); - else -END - } - $code .= $runtimeEnabledIndent . " defaultSignature = V8DOMConfiguration::installDOMClassTemplate(functionTemplate, \"${interfaceName}\", $parentClassTemplate, ${v8ClassName}::internalFieldCount,\n"; - $code .= $runtimeEnabledIndent . " " . ($hasAttributes ? "${v8ClassName}Attributes, WTF_ARRAY_LENGTH(${v8ClassName}Attributes),\n" : "0, 0,\n"); - $code .= $runtimeEnabledIndent . " " . ($hasAccessors ? "${v8ClassName}Accessors, WTF_ARRAY_LENGTH(${v8ClassName}Accessors),\n" : "0, 0,\n"); - $code .= $runtimeEnabledIndent . " " . ($hasFunctions ? "${v8ClassName}Methods, WTF_ARRAY_LENGTH(${v8ClassName}Methods),\n" : "0, 0,\n"); - $code .= $runtimeEnabledIndent . " isolate, currentWorldType);\n"; - - if (IsConstructable($interface)) { - $code .= " functionTemplate->SetCallHandler(${v8ClassName}::constructorCallback);\n"; - my $interfaceLength = GetInterfaceLength($interface); - $code .= " functionTemplate->SetLength(${interfaceLength});\n"; - } - - $code .= <<END; - v8::Local<v8::ObjectTemplate> ALLOW_UNUSED instanceTemplate = functionTemplate->InstanceTemplate(); - v8::Local<v8::ObjectTemplate> ALLOW_UNUSED prototypeTemplate = functionTemplate->PrototypeTemplate(); -END - - if ($accessCheck) { - $code .= " $accessCheck\n"; - } - - # Define runtime enabled attributes. - foreach my $runtimeEnabledAttribute (@runtimeEnabledAttributes) { - my $runtimeEnabledFunction = GetRuntimeEnabledFunctionName($runtimeEnabledAttribute); - my $conditionalString = GenerateConditionalString($runtimeEnabledAttribute); - $code .= "#if ${conditionalString}\n" if $conditionalString; - $code .= " if (${runtimeEnabledFunction}()) {\n"; - $code .= " static const V8DOMConfiguration::AttributeConfiguration attributeConfiguration =\\\n"; - $code .= GenerateAttributeConfiguration($interface, $runtimeEnabledAttribute, ";", " "); - $code .= <<END; - V8DOMConfiguration::installAttribute(instanceTemplate, prototypeTemplate, attributeConfiguration, isolate, currentWorldType); - } -END - $code .= "#endif // ${conditionalString}\n" if $conditionalString; - } - - my @runtimeEnabledConstants; - if ($hasConstants) { - # Define constants. - $code .= " static const V8DOMConfiguration::ConstantConfiguration ${v8ClassName}Constants[] = {\n"; - foreach my $constant (@{$interface->constants}) { - my $name = $constant->name; - my $value = $constant->value; - my $attrExt = $constant->extendedAttributes; - my $implementedBy = $attrExt->{"ImplementedBy"}; - if ($implementedBy) { - my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy); - AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedByImplName)); - } - if ($attrExt->{"RuntimeEnabled"}) { - push(@runtimeEnabledConstants, $constant); - } else { - $code .= <<END; - {"${name}", $value}, -END - } - } - $code .= " };\n"; - $code .= <<END; - V8DOMConfiguration::installConstants(functionTemplate, prototypeTemplate, ${v8ClassName}Constants, WTF_ARRAY_LENGTH(${v8ClassName}Constants), isolate); -END - # Define runtime enabled constants. - foreach my $runtimeEnabledConstant (@runtimeEnabledConstants) { - my $runtimeEnabledFunction = GetRuntimeEnabledFunctionName($runtimeEnabledConstant); - my $name = $runtimeEnabledConstant->name; - my $value = $runtimeEnabledConstant->value; - $code .= " if (${runtimeEnabledFunction}()) {\n"; - $code .= <<END; - static const V8DOMConfiguration::ConstantConfiguration constantConfiguration = {"${name}", static_cast<signed int>(${value})}; - V8DOMConfiguration::installConstants(functionTemplate, prototypeTemplate, &constantConfiguration, 1, isolate); -END - $code .= " }\n"; - } - $code .= join "", GenerateCompileTimeCheckForEnumsIfNeeded($interface); - } - - $code .= GenerateImplementationIndexedPropertyAccessors($interface); - $code .= GenerateImplementationNamedPropertyAccessors($interface); - $code .= GenerateImplementationLegacyCallAsFunction($interface); - $code .= GenerateImplementationMarkAsUndetectable($interface); - - # Define operations. - my $total_functions = 0; - foreach my $function (@normalFunctions) { - # Only one accessor is needed for overloaded operations. - next if $function->{overloadIndex} > 1; - next if $function->name eq ""; - - $total_functions++; - next if IsStandardFunction($interface, $function); - $code .= GenerateNonStandardFunction($interface, $function); - } - - # Define static attributes. - foreach my $attribute (@staticAttributes) { - $code .= GenerateStaticAttribute($interface, $attribute); - } - - # Special cases - if ($interfaceName eq "Window") { - $code .= <<END; - - prototypeTemplate->SetInternalFieldCount(V8Window::internalFieldCount); - functionTemplate->SetHiddenPrototype(true); - instanceTemplate->SetInternalFieldCount(V8Window::internalFieldCount); - // Set access check callbacks, but turned off initially. - // When a context is detached from a frame, turn on the access check. - // Turning on checks also invalidates inline caches of the object. - instanceTemplate->SetAccessCheckCallbacks(V8Window::namedSecurityCheckCustom, V8Window::indexedSecurityCheckCustom, v8::External::New(isolate, const_cast<WrapperTypeInfo*>(&V8Window::wrapperTypeInfo)), false); -END - } - if ($interfaceName eq "HTMLDocument" or $interfaceName eq "DedicatedWorkerGlobalScope" or $interfaceName eq "SharedWorkerGlobalScope" or $interfaceName eq "ServiceWorkerGlobalScope") { - $code .= <<END; - functionTemplate->SetHiddenPrototype(true); -END - } - - $code .= <<END; - - // Custom toString template - functionTemplate->Set(v8::String::NewFromUtf8(isolate, "toString", v8::String::kInternalizedString), V8PerIsolateData::current()->toStringTemplate()); - return functionTemplate; -} - -END - $implementation{nameSpaceWebCore}->add($code); - - $implementation{nameSpaceWebCore}->add(<<END); -v8::Handle<v8::FunctionTemplate> ${v8ClassName}::domTemplate(v8::Isolate* isolate, WrapperWorldType currentWorldType) -{ - V8PerIsolateData* data = V8PerIsolateData::from(isolate); - V8PerIsolateData::TemplateMap::iterator result = data->templateMap(currentWorldType).find(&wrapperTypeInfo); - if (result != data->templateMap(currentWorldType).end()) - return result->value.newLocal(isolate); - - TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); - v8::EscapableHandleScope handleScope(isolate); - v8::Local<v8::FunctionTemplate> templ = - Configure${v8ClassName}Template(data->rawDOMTemplate(&wrapperTypeInfo, currentWorldType), isolate, currentWorldType); - data->templateMap(currentWorldType).add(&wrapperTypeInfo, UnsafePersistent<v8::FunctionTemplate>(isolate, templ)); - return handleScope.Escape(templ); -} - -END - $implementation{nameSpaceWebCore}->add(<<END); -bool ${v8ClassName}::hasInstance(v8::Handle<v8::Value> jsValue, v8::Isolate* isolate, WrapperWorldType currentWorldType) -{ - return V8PerIsolateData::from(isolate)->hasInstance(&wrapperTypeInfo, jsValue, currentWorldType); -} - -END - $implementation{nameSpaceWebCore}->add(<<END); -bool ${v8ClassName}::hasInstanceInAnyWorld(v8::Handle<v8::Value> jsValue, v8::Isolate* isolate) -{ - return V8PerIsolateData::from(isolate)->hasInstance(&wrapperTypeInfo, jsValue, MainWorld) - || V8PerIsolateData::from(isolate)->hasInstance(&wrapperTypeInfo, jsValue, IsolatedWorld) - || V8PerIsolateData::from(isolate)->hasInstance(&wrapperTypeInfo, jsValue, WorkerWorld); -} - -END - - if (@perContextEnabledAttributes) { - my $code = ""; - $code .= <<END; -void ${v8ClassName}::installPerContextEnabledProperties(v8::Handle<v8::Object> instanceTemplate, ${nativeType}* impl, v8::Isolate* isolate) -{ - v8::Local<v8::Object> prototypeTemplate = v8::Local<v8::Object>::Cast(instanceTemplate->GetPrototype()); -END - - # Define per-context enabled attributes. - foreach my $perContextEnabledAttribute (@perContextEnabledAttributes) { - my $contextEnabledFunction = GetContextEnabledFunctionName($perContextEnabledAttribute); - $code .= " if (${contextEnabledFunction}(impl->document())) {\n"; - - $code .= " static const V8DOMConfiguration::AttributeConfiguration attributeConfiguration =\\\n"; - $code .= GenerateAttributeConfiguration($interface, $perContextEnabledAttribute, ";", " "); - $code .= <<END; - V8DOMConfiguration::installAttribute(instanceTemplate, prototypeTemplate, attributeConfiguration, isolate); -END - $code .= " }\n"; - } - $code .= <<END; -} - -END - $implementation{nameSpaceWebCore}->add($code); - } - - if (@perContextEnabledFunctions) { - my $code = ""; - $code .= <<END; -void ${v8ClassName}::installPerContextEnabledMethods(v8::Handle<v8::Object> prototypeTemplate, v8::Isolate* isolate) -{ -END - # Define per-context enabled operations. - $code .= <<END; - v8::Local<v8::Signature> defaultSignature = v8::Signature::New(isolate, domTemplate(isolate, worldType(isolate))); - - ExecutionContext* context = toExecutionContext(prototypeTemplate->CreationContext()); -END - - foreach my $perContextEnabledFunction (@perContextEnabledFunctions) { - my $contextEnabledFunction = GetContextEnabledFunctionName($perContextEnabledFunction); - my $functionLength = GetFunctionLength($perContextEnabledFunction); - my $conditionalString = GenerateConditionalString($perContextEnabledFunction); - $code .= "\n#if ${conditionalString}\n" if $conditionalString; - $code .= " if (context && context->isDocument() && ${contextEnabledFunction}(toDocument(context)))\n"; - my $name = $perContextEnabledFunction->name; - $code .= <<END; - prototypeTemplate->Set(v8::String::NewFromUtf8(isolate, "${name}", v8::String::kInternalizedString), v8::FunctionTemplate::New(isolate, ${implClassName}V8Internal::${name}MethodCallback, v8Undefined(), defaultSignature, $functionLength)->GetFunction()); -END - $code .= "#endif // ${conditionalString}\n" if $conditionalString; - } - - $code .= <<END; -} - -END - $implementation{nameSpaceWebCore}->add($code); - } - - if (InheritsExtendedAttribute($interface, "ActiveDOMObject")) { - $implementation{nameSpaceWebCore}->add(<<END); -ActiveDOMObject* ${v8ClassName}::toActiveDOMObject(v8::Handle<v8::Object> wrapper) -{ - return toNative(wrapper); -} - -END - } - - if (InheritsInterface($interface, "EventTarget")) { - $implementation{nameSpaceWebCore}->add(<<END); -EventTarget* ${v8ClassName}::toEventTarget(v8::Handle<v8::Object> object) -{ - return toNative(object); -} - -END - } - - if ($interfaceName eq "Window") { - $implementation{nameSpaceWebCore}->add(<<END); -v8::Handle<v8::ObjectTemplate> V8Window::GetShadowObjectTemplate(v8::Isolate* isolate, WrapperWorldType currentWorldType) -{ - if (currentWorldType == MainWorld) { - DEFINE_STATIC_LOCAL(v8::Persistent<v8::ObjectTemplate>, V8WindowShadowObjectCacheForMainWorld, ()); - if (V8WindowShadowObjectCacheForMainWorld.IsEmpty()) { - TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); - v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate); - ConfigureShadowObjectTemplate(templ, isolate, currentWorldType); - V8WindowShadowObjectCacheForMainWorld.Reset(isolate, templ); - return templ; - } - return v8::Local<v8::ObjectTemplate>::New(isolate, V8WindowShadowObjectCacheForMainWorld); - } else { - DEFINE_STATIC_LOCAL(v8::Persistent<v8::ObjectTemplate>, V8WindowShadowObjectCacheForNonMainWorld, ()); - if (V8WindowShadowObjectCacheForNonMainWorld.IsEmpty()) { - TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); - v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate); - ConfigureShadowObjectTemplate(templ, isolate, currentWorldType); - V8WindowShadowObjectCacheForNonMainWorld.Reset(isolate, templ); - return templ; - } - return v8::Local<v8::ObjectTemplate>::New(isolate, V8WindowShadowObjectCacheForNonMainWorld); - } -} - -END - } - - GenerateSpecialWrap($interface, $v8ClassName, $nativeType); - GenerateToV8Converters($interface, $v8ClassName, $nativeType); - - $implementation{nameSpaceWebCore}->add(<<END); -void ${v8ClassName}::derefObject(void* object) -{ - fromInternalPointer(object)->deref(); -} - -template<> -v8::Handle<v8::Value> toV8NoInline(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) -{ - return toV8(impl, creationContext, isolate); -} - -END -} - -sub GenerateHeaderContentHeader -{ - my $interface = shift; - my $v8ClassName = GetV8ClassName($interface); - my $conditionalString = GenerateConditionalString($interface); - - my @headerContentHeader = split("\r", $licenseHeader); - - push(@headerContentHeader, "#ifndef ${v8ClassName}" . "_h\n"); - push(@headerContentHeader, "#define ${v8ClassName}" . "_h\n\n"); - push(@headerContentHeader, "#if ${conditionalString}\n") if $conditionalString; - return join "", @headerContentHeader; -} - -sub GenerateCallbackHeader -{ - my $object = shift; - my $interface = shift; - - my $interfaceName = $interface->name; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - - my @includes = (); - push(@includes, "bindings/v8/ActiveDOMCallback.h"); - push(@includes, "bindings/v8/DOMWrapperWorld.h"); - push(@includes, "bindings/v8/ScopedPersistent.h"); - push(@includes, HeaderFilesForInterface($interfaceName, $implClassName)); - for my $include (sort @includes) { - $header{includes}->add("#include \"$include\"\n"); - } - $header{nameSpaceWebCore}->addHeader("\nclass ExecutionContext;\n"); - $header{class}->addHeader("class $v8ClassName : public $implClassName, public ActiveDOMCallback {"); - $header{class}->addFooter("};\n"); - - $header{classPublic}->add(<<END); - static PassOwnPtr<${v8ClassName}> create(v8::Handle<v8::Function> callback, ExecutionContext* context) - { - ASSERT(context); - return adoptPtr(new ${v8ClassName}(callback, context)); - } - - virtual ~${v8ClassName}(); - -END - - # Functions - my $numFunctions = @{$interface->functions}; - if ($numFunctions > 0) { - foreach my $function (@{$interface->functions}) { - my $code = " virtual " . GetNativeTypeForCallbacks($function->type) . " " . $function->name . "("; - - my @args = (); - if (ExtendedAttributeContains($function->extendedAttributes->{"CallWith"}, "ThisValue")) { - push(@args, GetNativeType("any") . " thisValue"); - } - my @params = @{$function->parameters}; - foreach my $param (@params) { - push(@args, GetNativeTypeForCallbacks($param->type) . " " . $param->name); - } - $code .= join(", ", @args); - $code .= ");\n"; - $header{classPublic}->add($code); - } - } - - $header{classPrivate}->add(<<END); - ${v8ClassName}(v8::Handle<v8::Function>, ExecutionContext*); - - ScopedPersistent<v8::Function> m_callback; - RefPtr<DOMWrapperWorld> m_world; -END -} - -sub GenerateCallbackImplementation -{ - my $object = shift; - my $interface = shift; - my $v8ClassName = GetV8ClassName($interface); - - AddToImplIncludes("core/dom/ExecutionContext.h"); - AddToImplIncludes("bindings/v8/V8Binding.h"); - AddToImplIncludes("bindings/v8/V8Callback.h"); - AddToImplIncludes("wtf/Assertions.h"); - - $implementation{nameSpaceWebCore}->add(<<END); -${v8ClassName}::${v8ClassName}(v8::Handle<v8::Function> callback, ExecutionContext* context) - : ActiveDOMCallback(context) - , m_callback(toIsolate(context), callback) - , m_world(DOMWrapperWorld::current()) -{ -} - -END - - $implementation{nameSpaceWebCore}->add(<<END); -${v8ClassName}::~${v8ClassName}() -{ -} - -END - - # Functions - my $numFunctions = @{$interface->functions}; - if ($numFunctions > 0) { - foreach my $function (@{$interface->functions}) { - my $code = ""; - my @params = @{$function->parameters}; - next if $function->extendedAttributes->{"Custom"}; - - AddIncludesForType($function->type); - die "We only support callbacks that return boolean or void values.\n" unless ($function->type eq "boolean" || $function->type eq "void"); - my $defaultReturn = $function->type eq "boolean" ? " true" : ""; - $code .= GetNativeTypeForCallbacks($function->type) . " ${v8ClassName}::" . $function->name . "("; - my $callWithThisValue = ExtendedAttributeContains($function->extendedAttributes->{"CallWith"}, "ThisValue"); - - my @args = (); - if ($callWithThisValue) { - push(@args, GetNativeTypeForCallbacks("any") . " thisValue"); - } - foreach my $param (@params) { - my $paramName = $param->name; - my $type = $param->type; - my $arrayOrSequenceType = GetArrayOrSequenceType($type); - - if ($arrayOrSequenceType) { - if (IsRefPtrType($arrayOrSequenceType)) { - AddIncludesForType($arrayOrSequenceType); - } - } else { - AddIncludesForType($type); - } - - push(@args, GetNativeTypeForCallbacks($type) . " " . $paramName); - } - $code .= join(", ", @args); - - $code .= ")\n"; - $code .= "{\n"; - $code .= " if (!canInvokeCallback())\n"; - $code .= " return${defaultReturn};\n\n"; - $code .= " v8::Isolate* isolate = v8::Isolate::GetCurrent();\n"; - $code .= " v8::HandleScope handleScope(isolate);\n\n"; - $code .= " v8::Handle<v8::Context> v8Context = toV8Context(executionContext(), m_world.get());\n"; - $code .= " if (v8Context.IsEmpty())\n"; - $code .= " return${defaultReturn};\n\n"; - $code .= " v8::Context::Scope scope(v8Context);\n"; - - my $thisObjectHandle = ""; - if ($callWithThisValue) { - $code .= " v8::Handle<v8::Value> thisHandle = thisValue.v8Value();\n"; - $code .= " if (thisHandle.IsEmpty()) {\n"; - $code .= " if (!isScriptControllerTerminating())\n"; - $code .= " CRASH();\n"; - $code .= " return${defaultReturn};\n"; - $code .= " }\n"; - $code .= " ASSERT(thisHandle->IsObject());\n"; - $thisObjectHandle = "v8::Handle<v8::Object>::Cast(thisHandle), "; - } - @args = (); - foreach my $param (@params) { - my $paramName = $param->name; - $code .= NativeToJSValue($param->type, $param->extendedAttributes, $paramName, " ", "v8::Handle<v8::Value> ${paramName}Handle =", "isolate", "") . "\n"; - $code .= " if (${paramName}Handle.IsEmpty()) {\n"; - $code .= " if (!isScriptControllerTerminating())\n"; - $code .= " CRASH();\n"; - $code .= " return${defaultReturn};\n"; - $code .= " }\n"; - push(@args, "${paramName}Handle"); - } - - if (scalar(@args) > 0) { - $code .= " v8::Handle<v8::Value> argv[] = { "; - $code .= join(", ", @args); - $code .= " };\n\n"; - } else { - $code .= " v8::Handle<v8::Value> *argv = 0;\n\n"; - } - $code .= " "; - if ($function->type eq "boolean") { - $code .= "return "; - } - $code .= "invokeCallback(m_callback.newLocal(isolate), ${thisObjectHandle}" . scalar(@args) . ", argv, executionContext(), isolate);\n"; - $code .= "}\n\n"; - $implementation{nameSpaceWebCore}->add($code); - } - } -} - -sub GenerateSpecialWrap -{ - my $interface = shift; - my $v8ClassName = shift; - my $nativeType = shift; - - my $specialWrap = $interface->extendedAttributes->{"SpecialWrapFor"}; - my $isDocument = InheritsInterface($interface, "Document"); - if (!$specialWrap && !$isDocument) { - return; - } - - my $code = ""; - $code .= <<END; -v8::Handle<v8::Object> wrap(${nativeType}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) -{ - ASSERT(impl); -END - if ($specialWrap) { - foreach my $type (split(/\s*\|\s*/, $specialWrap)) { - AddToImplIncludes("V8${type}.h"); - $code .= <<END; - if (impl->is${type}()) - return wrap(to${type}(impl), creationContext, isolate); -END - } - } - $code .= <<END; - v8::Handle<v8::Object> wrapper = ${v8ClassName}::createWrapper(impl, creationContext, isolate); -END - if ($isDocument) { - AddToImplIncludes("bindings/v8/ScriptController.h"); - AddToImplIncludes("bindings/v8/V8WindowShell.h"); - $code .= <<END; - if (wrapper.IsEmpty()) - return wrapper; - if (!isolatedWorldForEnteredContext(isolate)) { - if (Frame* frame = impl->frame()) - frame->script().windowShell(mainThreadNormalWorld())->updateDocumentWrapper(wrapper); - } -END - } - $code .= <<END; - return wrapper; -} - -END - $implementation{nameSpaceWebCore}->add($code); -} - -sub GenerateToV8Converters -{ - my $interface = shift; - my $v8ClassName = shift; - my $nativeType = shift; - my $interfaceName = $interface->name; - - if (ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "ToV8")) { - return; - } - - my $createWrapperArgumentType = GetPassRefPtrType($nativeType); - - # FIXME: Do we really need to treat /SVG/ as dependent DOM objects? - my $wrapperConfiguration = "WrapperConfiguration::Independent"; - if (InheritsExtendedAttribute($interface, "ActiveDOMObject") - || InheritsExtendedAttribute($interface, "DependentLifetime") - || NeedsVisitDOMWrapper($interface) - || $v8ClassName =~ /SVG/) { - $wrapperConfiguration = "WrapperConfiguration::Dependent"; - } - - my $code = ""; - $code .= <<END; -v8::Handle<v8::Object> ${v8ClassName}::createWrapper(${createWrapperArgumentType} impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) -{ - ASSERT(impl); - ASSERT(!DOMDataStore::containsWrapper<${v8ClassName}>(impl.get(), isolate)); - if (ScriptWrappable::wrapperCanBeStoredInObject(impl.get())) { - const WrapperTypeInfo* actualInfo = ScriptWrappable::getTypeInfoFromObject(impl.get()); - // Might be a XXXConstructor::wrapperTypeInfo instead of an XXX::wrapperTypeInfo. These will both have - // the same object de-ref functions, though, so use that as the basis of the check. - RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(actualInfo->derefObjectFunction == wrapperTypeInfo.derefObjectFunction); - } - -END - - if (InheritsInterface($interface, "Document")) { - AddToImplIncludes("bindings/v8/ScriptController.h"); - AddToImplIncludes("core/frame/Frame.h"); - $code .= <<END; - if (Frame* frame = impl->frame()) { - if (frame->script().initializeMainWorld()) { - // initializeMainWorld may have created a wrapper for the object, retry from the start. - v8::Handle<v8::Object> wrapper = DOMDataStore::getWrapper<${v8ClassName}>(impl.get(), isolate); - if (!wrapper.IsEmpty()) - return wrapper; - } - } -END - } - - $code .= <<END; - v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationContext, &wrapperTypeInfo, toInternalPointer(impl.get()), isolate); - if (UNLIKELY(wrapper.IsEmpty())) - return wrapper; - -END - if (IsTypedArrayType($interface->name)) { - AddToImplIncludes("bindings/v8/custom/V8ArrayBufferCustom.h"); - $code .= <<END; - impl->buffer()->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instanceTemplate()); -END - } - - if (InheritsInterface($interface, "AudioBuffer")) { - AddToImplIncludes("modules/webaudio/AudioBuffer.h"); - $code .= <<END; - for (unsigned i = 0, n = impl->numberOfChannels(); i < n; i++) { - Float32Array* channelData = impl->getChannelData(i); - channelData->buffer()->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instanceTemplate()); - } -END - } - - - $code .= <<END; - installPerContextEnabledProperties(wrapper, impl.get(), isolate); - V8DOMWrapper::associateObjectWithWrapper<$v8ClassName>(impl, &wrapperTypeInfo, wrapper, isolate, $wrapperConfiguration); - return wrapper; -} - -END - $implementation{nameSpaceWebCore}->add($code); -} - -sub GenerateSecurityCheckFunctions -{ - my $interface = shift; - my $implClassName = GetImplName($interface); - my $v8ClassName = GetV8ClassName($interface); - - AddToImplIncludes("bindings/v8/BindingSecurity.h"); - $implementation{nameSpaceInternal}->add(<<END); -bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value>) -{ - $implClassName* imp = ${v8ClassName}::toNative(host); - return BindingSecurity::shouldAllowAccessToFrame(imp->frame(), DoNotReportSecurityError); -} - -END - $implementation{nameSpaceInternal}->add(<<END); -bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value>) -{ - $implClassName* imp = ${v8ClassName}::toNative(host); - return BindingSecurity::shouldAllowAccessToFrame(imp->frame(), DoNotReportSecurityError); -} - -END -} - -sub GetNativeTypeForConversions -{ - my $interface = shift; - my $implClassName = GetImplName($interface); - $implClassName = GetSVGTypeNeedingTearOff($interface->name) if IsSVGTypeNeedingTearOff($interface->name); - return $implClassName; -} - -sub GetNamespaceForInterface -{ - my $interface = shift; - return "WTF" if IsTypedArrayType($interface->name); - return "WebCore"; -} - -sub GenerateFunctionCallString -{ - my $function = shift; - my $numberOfParameters = shift; - my $indent = shift; - my $interface = shift; - my $forMainWorldSuffix = shift; - my %replacements = @_; - - my $interfaceName = $interface->name; - my $implClassName = GetImplName($interface); - my $name = GetImplName($function); - my $returnType = $function->type; - my $nativeReturnType = GetNativeType($returnType, {}, ""); - my $code = ""; - - my $isSVGTearOffType = (IsSVGTypeNeedingTearOff($returnType) and not $interfaceName =~ /List$/); - $nativeReturnType = GetSVGWrappedTypeNeedingTearOff($returnType) if $isSVGTearOffType; - - my $index = 0; - my $humanFriendlyIndex = $index + 1; - - my @arguments; - my $functionName; - my $implementedBy = $function->extendedAttributes->{"ImplementedBy"}; - if ($implementedBy) { - my $implementedByImplName = GetImplNameFromImplementedBy($implementedBy); - AddToImplIncludes(HeaderFilesForInterface($implementedBy, $implementedByImplName)); - unshift(@arguments, "imp") if !$function->isStatic; - $functionName = "${implementedByImplName}::${name}"; - } elsif ($function->isStatic) { - $functionName = "${implClassName}::${name}"; - } else { - $functionName = "imp->${name}"; - } - - my $callWith = $function->extendedAttributes->{"CallWith"}; - my ($callWithArgs, $subCode) = GenerateCallWith($callWith, $indent, 1, $function); - $code .= $subCode; - unshift(@arguments, @$callWithArgs); - $index += @$callWithArgs; - $humanFriendlyIndex = $index + 1; - - $numberOfParameters += @$callWithArgs; - - foreach my $parameter (@{$function->parameters}) { - if ($index eq $numberOfParameters) { - last; - } - my $paramName = $parameter->name; - my $paramType = $parameter->type; - - if ($replacements{$paramName}) { - push @arguments, $replacements{$paramName}; - } elsif (IsSVGTypeNeedingTearOff($parameter->type) and not $interfaceName =~ /List$/) { - push @arguments, "$paramName->propertyReference()"; - $code .= <<END; - if (!$paramName) { - throwTypeError(ExceptionMessages::failedToExecute(\"$name\", \"$interfaceName\", \"parameter $humanFriendlyIndex is not of type '${ \$parameter->type }'.\"), info.GetIsolate()); - return; - } -END - } elsif ($parameter->type eq "SVGMatrix" and $interfaceName eq "SVGTransformList") { - push @arguments, "$paramName.get()"; - } elsif (IsNullableParameter($parameter)) { - push @arguments, "${paramName}IsNull ? 0 : &$paramName"; - } elsif (IsCallbackInterface($paramType) or $paramType eq "NodeFilter" or $paramType eq "XPathNSResolver") { - push @arguments, "$paramName.release()"; - } else { - push @arguments, $paramName; - } - $index++; - $humanFriendlyIndex = $index + 1; - } - - if ($function->extendedAttributes->{"RaisesException"}) { - push @arguments, "exceptionState"; - } - - my $functionString = "$functionName(" . join(", ", @arguments) . ")"; - - my $return = "result"; - my $returnIsRef = IsRefPtrType($returnType); - - if ($returnType eq "void") { - $code .= $indent . "$functionString;\n"; - } elsif (ExtendedAttributeContains($callWith, "ScriptState") or $function->extendedAttributes->{"RaisesException"}) { - $code .= $indent . $nativeReturnType . " result = $functionString;\n"; - } else { - # Can inline the function call into the return statement to avoid overhead of using a Ref<> temporary - $return = $functionString; - $returnIsRef = 0; - - if ($interfaceName eq "SVGTransformList" and IsRefPtrType($returnType)) { - $return = "WTF::getPtr(" . $return . ")"; - } - } - - if ($function->extendedAttributes->{"RaisesException"}) { - $code .= $indent . "if (exceptionState.throwIfNeeded())\n"; - $code .= $indent . " return;\n"; - } - - if (ExtendedAttributeContains($callWith, "ScriptState")) { - $code .= $indent . "if (state.hadException()) {\n"; - $code .= $indent . " v8::Local<v8::Value> exception = state.exception();\n"; - $code .= $indent . " state.clearException();\n"; - $code .= $indent . " throwError(exception, info.GetIsolate());\n"; - $code .= $indent . " return;\n"; - $code .= $indent . "}\n"; - } - - if ($isSVGTearOffType) { - AddToImplIncludes("V8$returnType.h"); - AddToImplIncludes("core/svg/properties/SVGPropertyTearOff.h"); - my $svgNativeType = GetSVGTypeNeedingTearOff($returnType); - # FIXME: Update for all ScriptWrappables. - if (IsDOMNodeType($interfaceName)) { - if ($forMainWorldSuffix eq "ForMainWorld") { - $code .= $indent . "v8SetReturnValueForMainWorld(info, WTF::getPtr(${svgNativeType}::create($return)));\n"; - } else { - $code .= $indent . "v8SetReturnValueFast(info, WTF::getPtr(${svgNativeType}::create($return)), imp);\n"; - } - } else { - $code .= $indent . "v8SetReturnValue${forMainWorldSuffix}(info, WTF::getPtr(${svgNativeType}::create($return)));\n"; - } - return $code; - } - - # If the implementing class is a POD type, commit changes - if (IsSVGTypeNeedingTearOff($interfaceName) and not $interfaceName =~ /List$/) { - $code .= $indent . "wrapper->commitChange();\n"; - } - - $return .= ".release()" if ($returnIsRef); - - my $nativeValue; - # FIXME: Update for all ScriptWrappables. - if (IsDOMNodeType($interfaceName)) { - $nativeValue = NativeToJSValue($function->type, $function->extendedAttributes, $return, $indent, "", "info.GetIsolate()", "info", "imp", $forMainWorldSuffix, "return"); - } else { - $nativeValue = NativeToJSValue($function->type, $function->extendedAttributes, $return, $indent, "", "info.GetIsolate()", "info", 0, $forMainWorldSuffix, "return"); - } - - $code .= $nativeValue . "\n" if $nativeValue; # Skip blank line for void return type - - return $code; -} - -sub GetNativeType -{ - my $type = shift; - my $extendedAttributes = shift; - my $isParameter = shift; - - my $svgNativeType = GetSVGTypeNeedingTearOff($type); - if ($svgNativeType) { - if ($svgNativeType =~ /List$/) { - return "${svgNativeType}*"; - } else { - return "RefPtr<${svgNativeType} >"; - } - } - - return "float" if $type eq "float"; - return "double" if $type eq "double"; - return "int" if $type eq "long" or $type eq "int" or $type eq "short" or $type eq "byte"; - if ($type eq "unsigned long" or $type eq "unsigned int" or $type eq "unsigned short" or $type eq "octet") { - return "unsigned"; - } - return "long long" if $type eq "long long"; - return "unsigned long long" if $type eq "unsigned long long"; - return "bool" if $type eq "boolean"; - - if (($type eq "DOMString" || IsEnumType($type)) and $isParameter) { - my $mode = GetV8StringResourceMode($extendedAttributes); - # FIXME: Add the case for 'elsif ($attributeOrParameter->extendedAttributes->{"TreatUndefinedAs"} and $attributeOrParameter->extendedAttributes->{"TreatUndefinedAs"} eq "NullString"))'. - return "V8StringResource<$mode>"; - } - - return "String" if $type eq "DOMString" or IsEnumType($type); - - return "ScriptPromise" if $type eq "Promise"; - - return "Range::CompareHow" if $type eq "CompareHow"; - return "DOMTimeStamp" if $type eq "DOMTimeStamp"; - return "double" if $type eq "Date"; - return "ScriptValue" if $type eq "any" or IsCallbackFunctionType($type); - return "Dictionary" if $type eq "Dictionary"; - - die "UnionType is not supported" if IsUnionType($type); - - if (IsTypedArrayType($type)) { - return $isParameter ? "${type}*" : "RefPtr<${type}>"; - } - - # We need to check [ImplementedAs] extended attribute for wrapper types. - return "RefPtr<$type>" if $type eq "XPathNSResolver"; # FIXME: can this be put in nonWrapperTypes instead? - if (IsWrapperType($type)) { - my $interface = ParseInterface($type); - my $implClassName = GetImplName($interface); - return $isParameter ? "${implClassName}*" : "RefPtr<${implClassName}>"; - } - return "RefPtr<$type>" if IsRefPtrType($type) and (not $isParameter or $nonWrapperTypes{$type}); - - my $arrayOrSequenceType = GetArrayOrSequenceType($type); - - if ($arrayOrSequenceType) { - my $nativeType = GetNativeType($arrayOrSequenceType); - $nativeType .= " " if ($nativeType =~ />$/); - return "Vector<${nativeType}>"; - } - - # Default, assume native type is a pointer with same type name as idl type - return "${type}*"; -} - -sub GetNativeTypeForCallbacks -{ - my $type = shift; - return "const String&" if $type eq "DOMString"; - return "PassRefPtr<SerializedScriptValue>" if $type eq "SerializedScriptValue"; - return "void" if $type eq "void"; - - # Callbacks use raw pointers, so pass isParameter = 1 - my $nativeType = GetNativeType($type, {}, "parameter"); - return "const $nativeType&" if $nativeType =~ /^Vector/; - return $nativeType; -} - -sub JSValueToNativeStatement -{ - my $type = shift; - my $extendedAttributes = shift; - my $argIndexOrZero = shift; - my $jsValue = shift; - my $variableName = shift; - my $indent = shift; - my $getIsolate = shift; - - my $nativeType = GetNativeType($type, $extendedAttributes, "parameter"); - my $native_value = JSValueToNative($type, $extendedAttributes, $argIndexOrZero, $jsValue, $getIsolate); - my $code = ""; - if ($type eq "DOMString" || IsEnumType($type)) { - die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8StringResource/; - if ($type eq "DOMString" or IsEnumType($type)) { - $code .= $indent . "V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID($nativeType, $variableName, $native_value);\n" - } else { - $code .= $indent . "$nativeType $variableName($native_value, true);\n"; - } - } elsif ($extendedAttributes->{"EnforceRange"}) { - $code .= $indent . "V8TRYCATCH_WITH_TYPECHECK_VOID($nativeType, $variableName, $native_value, $getIsolate);\n"; - } else { - $code .= $indent . "V8TRYCATCH_VOID($nativeType, $variableName, $native_value);\n"; - } - return $code; -} - - -sub JSValueToNative -{ - my $type = shift; - my $extendedAttributes = shift; - # Argument position (1-indexed) or 0 if for a setter's value. - my $argIndexOrZero = shift; - my $value = shift; - my $getIsolate = shift; - - my $intConversion = $extendedAttributes->{"EnforceRange"} ? "EnforceRange" : "NormalConversion"; - - return "$value->BooleanValue()" if $type eq "boolean"; - return "static_cast<$type>($value->NumberValue())" if $type eq "float" or $type eq "double"; - - if ($intConversion ne "NormalConversion") { - return "toInt8($value, $intConversion, ok)" if $type eq "byte"; - return "toUInt8($value, $intConversion, ok)" if $type eq "octet"; - return "toInt16($value, $intConversion, ok)" if $type eq "short"; - return "toUInt16($value, $intConversion, ok)" if $type eq "unsigned short"; - return "toInt32($value, $intConversion, ok)" if $type eq "long"; - return "toUInt32($value, $intConversion, ok)" if $type eq "unsigned long"; - return "toInt64($value, $intConversion, ok)" if $type eq "long long"; - return "toUInt64($value, $intConversion, ok)" if $type eq "unsigned long long"; - } else { - return "toInt8($value)" if $type eq "byte"; - return "toUInt8($value)" if $type eq "octet"; - return "toInt16($value)" if $type eq "short"; - return "toUInt16($value)" if $type eq "unsigned short"; - return "toInt32($value)" if $type eq "long"; - return "toUInt32($value)" if $type eq "unsigned long"; - return "toInt64($value)" if $type eq "long long"; - return "toUInt64($value)" if $type eq "unsigned long long"; - } - return "static_cast<Range::CompareHow>($value->Int32Value())" if $type eq "CompareHow"; - return "toWebCoreDate($value)" if $type eq "Date"; - - if ($type eq "DOMString" or IsEnumType($type)) { - return $value; - } - - if ($type eq "SerializedScriptValue") { - AddToImplIncludes("bindings/v8/SerializedScriptValue.h"); - return "SerializedScriptValue::create($value, $getIsolate)"; - } - - if ($type eq "Dictionary") { - AddToImplIncludes("bindings/v8/Dictionary.h"); - return "Dictionary($value, $getIsolate)"; - } - - if ($type eq "any" || IsCallbackFunctionType($type)) { - AddToImplIncludes("bindings/v8/ScriptValue.h"); - return "ScriptValue($value, $getIsolate)"; - } - - if ($type eq "Promise") { - AddToImplIncludes("bindings/v8/ScriptPromise.h"); - return "ScriptPromise($value)"; - } - - if ($type eq "NodeFilter") { - return "toNodeFilter($value, $getIsolate)"; - } - - if ($type eq "MediaQueryListListener") { - AddToImplIncludes("core/css/MediaQueryListListener.h"); - return "MediaQueryListListener::create(ScriptValue(" . $value . ", $getIsolate))"; - } - - if ($type eq "EventTarget") { - return "V8DOMWrapper::isDOMWrapper($value) ? toWrapperTypeInfo(v8::Handle<v8::Object>::Cast($value))->toEventTarget(v8::Handle<v8::Object>::Cast($value)) : 0"; - } - - if (IsTypedArrayType($type)) { - AddIncludesForType($type); - return "$value->Is${type}() ? V8${type}::toNative(v8::Handle<v8::${type}>::Cast($value)) : 0" - } - - if ($type eq "XPathNSResolver") { - return "toXPathNSResolver($value, $getIsolate)"; - } - - my $arrayOrSequenceType = GetArrayOrSequenceType($type); - - if ($arrayOrSequenceType) { - if (IsRefPtrType($arrayOrSequenceType)) { - AddToImplIncludes("V8${arrayOrSequenceType}.h"); - return "(toRefPtrNativeArray<${arrayOrSequenceType}, V8${arrayOrSequenceType}>($value, $argIndexOrZero, $getIsolate))"; - } - return "toNativeArray<" . GetNativeType($arrayOrSequenceType) . ">($value, $argIndexOrZero, $getIsolate)"; - } - - AddIncludesForType($type); - - AddToImplIncludes("V8${type}.h"); - return "V8${type}::hasInstance($value, $getIsolate, worldType($getIsolate)) ? V8${type}::toNative(v8::Handle<v8::Object>::Cast($value)) : 0"; -} - -sub CreateCustomSignature -{ - my $function = shift; - my $count = @{$function->parameters}; - my $name = $function->name; - my $code = " const int ${name}Argc = ${count};\n" . - " v8::Handle<v8::FunctionTemplate> ${name}Argv[${name}Argc] = { "; - my $first = 1; - foreach my $parameter (@{$function->parameters}) { - if ($first) { $first = 0; } - else { $code .= ", "; } - if (IsWrapperType($parameter->type) && not IsTypedArrayType($parameter->type)) { - if ($parameter->type eq "XPathNSResolver") { - # Special case for XPathNSResolver. All other browsers accepts a callable, - # so, even though it's against IDL, accept objects here. - $code .= "v8::Handle<v8::FunctionTemplate>()"; - } else { - my $type = $parameter->type; - my $arrayOrSequenceType = GetArrayOrSequenceType($type); - - if ($arrayOrSequenceType) { - if (IsRefPtrType($arrayOrSequenceType)) { - AddIncludesForType($arrayOrSequenceType); - } else { - $code .= "v8::Handle<v8::FunctionTemplate>()"; - next; - } - } else { - AddIncludesForType($type); - } - $code .= "V8PerIsolateData::from(isolate)->rawDOMTemplate(&V8${type}::wrapperTypeInfo, currentWorldType)"; - } - } else { - $code .= "v8::Handle<v8::FunctionTemplate>()"; - } - } - $code .= " };\n"; - $code .= " v8::Handle<v8::Signature> ${name}Signature = v8::Signature::New(isolate, functionTemplate, ${name}Argc, ${name}Argv);\n"; - return $code; -} - - -sub RequiresCustomSignature -{ - my $function = shift; - # No signature needed for Custom function - if (HasCustomMethod($function->extendedAttributes)) { - return 0; - } - # No signature needed for overloaded function - if (@{$function->{overloads}} > 1) { - return 0; - } - if ($function->isStatic) { - return 0; - } - # Type checking is performed in the generated code - if ($function->extendedAttributes->{"StrictTypeChecking"}) { - return 0; - } - foreach my $parameter (@{$function->parameters}) { - if (($parameter->isOptional && !$parameter->extendedAttributes->{"Default"}) || IsCallbackInterface($parameter->type)) { - return 0; - } - } - - foreach my $parameter (@{$function->parameters}) { - if (IsWrapperType($parameter->type)) { - return 1; - } - } - return 0; -} - -sub IsUnionType -{ - my $type = shift; # string or UnionType - if(ref($type) eq "UnionType") { - die "Currently only 2 values of non-union type is supported as union type.\n" unless @{$type->unionMemberTypes} == 2; - return 1; - } - return 0; -} - -sub IsWrapperType -{ - my $type = shift; - return 0 if GetArrayType($type); - return 0 if GetSequenceType($type); - return 0 if IsCallbackFunctionType($type); - return 0 if IsEnumType($type); - return 0 if IsPrimitiveType($type); - return 0 if $type eq "Promise"; - return !$nonWrapperTypes{$type}; -} - -sub IsCallbackInterface -{ - my $type = shift; - return 0 unless IsWrapperType($type); - return 0 if IsTypedArrayType($type); - - my $idlFile = IDLFileForInterface($type) - or die("Could NOT find IDL file for interface \"$type\"!\n"); - - open FILE, "<", $idlFile; - my @lines = <FILE>; - close FILE; - - my $fileContents = join('', @lines); - return ($fileContents =~ /callback\s+interface\s+(\w+)/gs); -} - -sub GetNativeTypeOfTypedArray -{ - my $interface = shift; - my $interfaceName = $interface->name; - die "TypedArray of unknown type is found" unless $typedArrayHash{$interface->name}; - return @{$typedArrayHash{$interface->name}}; -} - -sub IsDOMNodeType -{ - my $type = shift; - - return 1 if $type eq 'Attr'; - return 1 if $type eq 'CDATASection'; - return 1 if $type eq 'CharacterData'; - return 1 if $type eq 'Comment'; - return 1 if $type eq 'Document'; - return 1 if $type eq 'DocumentFragment'; - return 1 if $type eq 'DocumentType'; - return 1 if $type eq 'Element'; - return 1 if $type eq 'Entity'; - return 1 if $type eq 'HTMLDocument'; - return 1 if $type eq 'Node'; - return 1 if $type eq 'Notation'; - return 1 if $type eq 'ProcessingInstruction'; - return 1 if $type eq 'ShadowRoot'; - return 1 if $type eq 'SVGDocument'; - return 1 if $type eq 'Text'; - - return 1 if $type =~ /^HTML.*Element$/; - return 1 if $type =~ /^SVG.*Element$/; - - return 1 if $type eq 'TestNode'; - - return 0; -} - - -sub NativeToJSValue -{ - my $type = shift; - my $extendedAttributes = shift; - my $nativeValue = shift; - my $indent = shift; # added before every line - my $receiver = shift; # "return" or "<variableName> =" - my $getIsolate = shift; - die "An Isolate is mandatory for native value => JS value conversion." unless $getIsolate; - my $getCallbackInfo = shift || ""; - my $creationContext = $getCallbackInfo ? "${getCallbackInfo}.Holder()" : "v8::Handle<v8::Object>()"; - my $getScriptWrappable = shift || ""; - my $forMainWorldSuffix = shift || ""; - my $returnValueArg = shift || 0; - my $isReturnValue = $returnValueArg eq "return"; - - if (IsUnionType($type)) { - my $types = $type->unionMemberTypes; - my @codes = (); - for my $i (0 .. scalar(@$types)-1) { - my $unionMemberType = $types->[$i]; - my $unionMemberNumber = $i + 1; - my $unionMemberVariable = $nativeValue . $i; - my $unionMemberEnabledVariable = $nativeValue . $i . "Enabled"; - my $unionMemberNativeValue = $unionMemberVariable; - $unionMemberNativeValue .= ".release()" if (IsRefPtrType($unionMemberType)); - my $returnJSValueCode = NativeToJSValue($unionMemberType, $extendedAttributes, $unionMemberNativeValue, $indent . " ", $receiver, $getIsolate, $getCallbackInfo, $getScriptWrappable, $forMainWorldSuffix, $returnValueArg); - my $code = ""; - if ($isReturnValue) { - $code .= "${indent}if (${unionMemberEnabledVariable}) {\n"; - $code .= "${returnJSValueCode}\n"; - $code .= "${indent} return;\n"; - $code .= "${indent}}\n"; - } else { - $code .= "${indent}if (${unionMemberEnabledVariable})\n"; - $code .= "${returnJSValueCode}"; - } - push @codes, $code; - } - return join "\n", @codes; - } - - if ($type eq "boolean") { - return "${indent}v8SetReturnValueBool(${getCallbackInfo}, ${nativeValue});" if $isReturnValue; - return "$indent$receiver v8Boolean($nativeValue, $getIsolate);"; - } - - if ($type eq "void") { # equivalent to v8Undefined() - return "" if $isReturnValue; - return "$indent$receiver v8Undefined();" - } - - # HTML5 says that unsigned reflected attributes should be in the range - # [0, 2^31). When a value isn't in this range, a default value (or 0) - # should be returned instead. - if ($extendedAttributes->{"Reflect"} and ($type eq "unsigned long" or $type eq "unsigned short")) { - $nativeValue =~ s/getUnsignedIntegralAttribute/getIntegralAttribute/g; - return "${indent}v8SetReturnValueUnsigned(${getCallbackInfo}, std::max(0, ${nativeValue}));" if $isReturnValue; - return "$indent$receiver v8::Integer::NewFromUnsigned($getIsolate, std::max(0, " . $nativeValue . "));"; - } - - my $nativeType = GetNativeType($type); - if ($nativeType eq "int") { - return "${indent}v8SetReturnValueInt(${getCallbackInfo}, ${nativeValue});" if $isReturnValue; - return "$indent$receiver v8::Integer::New($getIsolate, $nativeValue);"; - } - - if ($nativeType eq "unsigned") { - return "${indent}v8SetReturnValueUnsigned(${getCallbackInfo}, ${nativeValue});" if $isReturnValue; - return "$indent$receiver v8::Integer::NewFromUnsigned($getIsolate, $nativeValue);"; - } - - if ($type eq "Date") { - return "${indent}v8SetReturnValue(${getCallbackInfo}, v8DateOrNull($nativeValue, $getIsolate));" if $isReturnValue; - return "$indent$receiver v8DateOrNull($nativeValue, $getIsolate);" - } - - # long long and unsigned long long are not representable in ECMAScript. - if ($type eq "long long" or $type eq "unsigned long long" or $type eq "DOMTimeStamp") { - return "${indent}v8SetReturnValue(${getCallbackInfo}, static_cast<double>($nativeValue));" if $isReturnValue; - return "$indent$receiver v8::Number::New($getIsolate, static_cast<double>($nativeValue));"; - } - - my $conv = $extendedAttributes->{"TreatReturnedNullStringAs"}; - if (($type eq "DOMString" || IsEnumType($type)) && $isReturnValue) { - my $functionSuffix = ""; - if (defined $conv) { - if ($conv eq "Null") { - $functionSuffix = "OrNull"; - } elsif ($conv eq "Undefined") { - $functionSuffix = "OrUndefined"; - } else { - die "Unknown value for TreatReturnedNullStringAs extended attribute"; - } - } - return "${indent}v8SetReturnValueString${functionSuffix}(${getCallbackInfo}, $nativeValue, $getIsolate);"; - } - - if ($type eq "DOMString" or IsEnumType($type)) { - my $returnValue = ""; - if (defined $conv) { - if ($conv eq "Null") { - $returnValue = "v8StringOrNull($nativeValue, $getIsolate)"; - } elsif ($conv eq "Undefined") { - $returnValue = "v8StringOrUndefined($nativeValue, $getIsolate)"; - } else { - die "Unknown value for TreatReturnedNullStringAs extended attribute"; - } - } else { - $returnValue = "v8String($getIsolate, $nativeValue)"; - } - return "$indent$receiver $returnValue;"; - } - - if (IsPrimitiveType($type)) { - die "unexpected type $type" if not ($type eq "float" or $type eq "double"); - return "${indent}v8SetReturnValue(${getCallbackInfo}, ${nativeValue});" if $isReturnValue; - return "$indent$receiver v8::Number::New($getIsolate, $nativeValue);"; - } - - if ($nativeType eq "ScriptValue" or $nativeType eq "ScriptPromise") { - return "${indent}v8SetReturnValue(${getCallbackInfo}, ${nativeValue}.v8Value());" if $isReturnValue; - return "$indent$receiver $nativeValue.v8Value();"; - } - - my $arrayOrSequenceType = GetArrayOrSequenceType($type); - - if ($arrayOrSequenceType) { - if (IsRefPtrType($arrayOrSequenceType)) { - AddIncludesForType($arrayOrSequenceType); - } - return "${indent}v8SetReturnValue(${getCallbackInfo}, v8Array($nativeValue, $getIsolate));" if $isReturnValue; - return "$indent$receiver v8Array($nativeValue, $getIsolate);"; - } - - AddIncludesForType($type); - - if ($type eq "SerializedScriptValue") { - my $returnValue = "$nativeValue ? $nativeValue->deserialize() : v8::Handle<v8::Value>(v8::Null($getIsolate))"; - return "${indent}v8SetReturnValue(${getCallbackInfo}, $returnValue);" if $isReturnValue; - return "$indent$receiver $returnValue;"; - } - - AddToImplIncludes("wtf/RefPtr.h"); - AddToImplIncludes("wtf/GetPtr.h"); - - if ($getScriptWrappable) { - # FIXME: Use safe handles - if ($isReturnValue) { - if ($forMainWorldSuffix eq "ForMainWorld") { - return "${indent}v8SetReturnValueForMainWorld(${getCallbackInfo}, $nativeValue);"; - } - return "${indent}v8SetReturnValueFast(${getCallbackInfo}, $nativeValue, $getScriptWrappable);"; - } - } - # FIXME: Use safe handles - return "${indent}v8SetReturnValue(${getCallbackInfo}, $nativeValue);" if $isReturnValue; - return "$indent$receiver toV8($nativeValue, $creationContext, $getIsolate);"; -} - -sub WriteData -{ - my $object = shift; - my $interface = shift; - my $outputDirectory = shift; - - my $name = $interface->name; - my $headerFileName = "$outputDirectory/V8$name.h"; - my $implFileName = "$outputDirectory/V8$name.cpp"; - - my @includes = (); - foreach my $include (keys %implIncludes) { - push @includes, "\"$include\""; - } - - #FIXME: do not treat main header special - my $mainInclude = "\"V8$name.h\""; - foreach my $include (sort @includes) { - $implementation{includes}->add("#include $include\n") unless $include eq $mainInclude; - } - $implementation{includes}->add("\n") unless $interface->isCallback; - WriteFileIfChanged($implFileName, $implementation{root}->toString()); - - %implIncludes = (); - - WriteFileIfChanged($headerFileName, $header{root}->toString()); -} - -sub ConvertToV8StringResource -{ - my $attributeOrParameter = shift; - my $nativeType = shift; - my $variableName = shift; - my $value = shift; - - die "Wrong native type passed: $nativeType" unless $nativeType =~ /^V8StringResource/; - if ($attributeOrParameter->type eq "DOMString" or IsEnumType($attributeOrParameter->type)) { - return "V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID($nativeType, $variableName, $value);" - } else { - return "$nativeType $variableName($value, true);"; - } -} - -# Returns the RuntimeEnabledFeatures function name that is hooked up to check if a method/attribute is enabled. -sub GetRuntimeEnabledFunctionName -{ - my $signature = shift; - - # Given [RuntimeEnabled=FeatureName], - # return RuntimeEnabledFeatures::{featureName}Enabled; - my $featureName = ToMethodName($signature->extendedAttributes->{"RuntimeEnabled"}); - return "RuntimeEnabledFeatures::${featureName}Enabled"; -} - -sub GetContextEnabledFunctionName -{ - my $signature = shift; - - # Given [PerContextEnabled=FeatureName], - # return ContextFeatures::{featureName}Enabled - my $featureName = ToMethodName($signature->extendedAttributes->{"PerContextEnabled"}); - return "ContextFeatures::${featureName}Enabled"; -} - -sub GetPassRefPtrType -{ - my $v8ClassName = shift; - - my $angleBracketSpace = $v8ClassName =~ />$/ ? " " : ""; - return "PassRefPtr<${v8ClassName}${angleBracketSpace}>"; -} - -sub WriteFileIfChanged -{ - my $fileName = shift; - my $contents = shift; - - if (-f $fileName && $writeFileOnlyIfChanged) { - open FH, "<", $fileName or die "Couldn't open $fileName: $!\n"; - my @lines = <FH>; - my $oldContents = join "", @lines; - close FH; - return if $contents eq $oldContents; - } - open FH, ">", $fileName or die "Couldn't open $fileName: $!\n"; - print FH $contents; - close FH; -} - -sub ForAllParents -{ - my $interface = shift; - my $beforeRecursion = shift; - my $afterRecursion = shift; - - my $recurse; - $recurse = sub { - my $currentInterface = shift; - - if ($currentInterface->parent) { - my $parentInterface = ParseInterface($currentInterface->parent); - if ($beforeRecursion) { - &$beforeRecursion($parentInterface) eq 'prune' and return; - } - &$recurse($parentInterface); - &$afterRecursion($parentInterface) if $afterRecursion; - } - }; - - &$recurse($interface); -} - -sub IsPrimitiveType -{ - my $type = shift; - - return 1 if $primitiveTypeHash{$type}; - return 0; -} - -sub IsIntegerType -{ - my $type = shift; - - return 1 if $integerTypeHash{$type}; - return 0; -} - -sub IsCallbackFunctionType -{ - my $type = shift; - - return 1 if $callbackFunctionTypeHash{$type}; - return 0; -} - -sub IsEnumType -{ - my $type = shift; - - return 1 if $enumTypeHash{$type}; - return 0; -} - -sub ValidEnumValues -{ - my $type = shift; - - return @{$enumTypeHash{$type}}; -} - -sub IsSVGTypeNeedingTearOff -{ - my $type = shift; - - return 1 if $svgTypeNeedingTearOff{$type}; - return 0; -} - -sub IsSVGTypeWithWritablePropertiesNeedingTearOff -{ - my $type = shift; - - return 1 if $svgTypeWithWritablePropertiesNeedingTearOff{$type}; - return 0; -} - -sub IsTypedArrayType -{ - my $type = shift; - return 1 if $typedArrayHash{$type}; - return 0; -} - -sub IsRefPtrType -{ - my $type = shift; - - return 0 if $type eq "any"; - return 0 if IsPrimitiveType($type); - return 0 if GetArrayType($type); - return 0 if GetSequenceType($type); - return 0 if $type eq "Promise"; - return 0 if IsCallbackFunctionType($type); - return 0 if IsEnumType($type); - return 0 if IsUnionType($type); - return 0 if $type eq "Dictionary"; - - return 1; -} - -sub IsNullableParameter -{ - my $parameter = shift; - - return $parameter->isNullable && !IsRefPtrType($parameter->type) && $parameter->type ne "Dictionary"; -} - -sub GetSVGTypeNeedingTearOff -{ - my $type = shift; - - return $svgTypeNeedingTearOff{$type} if exists $svgTypeNeedingTearOff{$type}; - return undef; -} - -sub GetSVGWrappedTypeNeedingTearOff -{ - my $type = shift; - - my $svgTypeNeedingTearOff = GetSVGTypeNeedingTearOff($type); - return $svgTypeNeedingTearOff if not $svgTypeNeedingTearOff; - - if ($svgTypeNeedingTearOff =~ /SVGPropertyTearOff/) { - $svgTypeNeedingTearOff =~ s/SVGPropertyTearOff<//; - } elsif ($svgTypeNeedingTearOff =~ /SVGListPropertyTearOff/) { - $svgTypeNeedingTearOff =~ s/SVGListPropertyTearOff<//; - } elsif ($svgTypeNeedingTearOff =~ /SVGStaticListPropertyTearOff/) { - $svgTypeNeedingTearOff =~ s/SVGStaticListPropertyTearOff<//; - } elsif ($svgTypeNeedingTearOff =~ /SVGTransformListPropertyTearOff/) { - $svgTypeNeedingTearOff =~ s/SVGTransformListPropertyTearOff<//; - } elsif ($svgTypeNeedingTearOff =~ /SVGMatrixTearOff/) { - $svgTypeNeedingTearOff = 'SVGMatrix'; - } - - $svgTypeNeedingTearOff =~ s/>//; - return $svgTypeNeedingTearOff; -} - -sub IsSVGAnimatedType -{ - my $type = shift; - - return $type =~ /^SVGAnimated/; -} - -sub SVGTypeNeedsToHoldContextElement -{ - my $type = shift; - - return IsSVGTypeNeedingTearOff($type) || IsSVGAnimatedType($type); -} - -sub GetSequenceType -{ - my $type = shift; - - return $1 if $type =~ /^sequence<([\w\d_\s]+)>.*/; - return ""; -} - -sub GetArrayType -{ - my $type = shift; - - return $1 if $type =~ /^([\w\d_\s]+)\[\]/; - return ""; -} - -sub GetArrayOrSequenceType -{ - my $type = shift; - - return GetArrayType($type) || GetSequenceType($type); -} - -sub AssertNotSequenceType -{ - my $type = shift; - die "Sequences must not be used as the type of an attribute, constant or exception field." if GetSequenceType($type); -} - -sub FirstLetterToUpperCase -{ - my $param = shift; - my $ret = ucfirst($param); - # Capitalize initial acronym, e.g., xml -> setXML - $ret =~ s/Xml/XML/ if $ret =~ /^Xml/; - $ret =~ s/Css/CSS/ if $ret =~ /^Css/; - $ret =~ s/Html/HTML/ if $ret =~ /^Html/; - $ret =~ s/Ime/IME/ if $ret =~ /^Ime/; - $ret =~ s/Svg/SVG/ if $ret =~ /^Svg/; - return $ret; -} - -# URL becomes url, but SetURL becomes setURL. -sub ToMethodName -{ - my $param = shift; - my $ret = lcfirst($param); - $ret =~ s/hTML/html/ if $ret =~ /^hTML/; - $ret =~ s/iME/ime/ if $ret =~ /^iME/; - $ret =~ s/uRL/url/ if $ret =~ /^uRL/; - $ret =~ s/jS/js/ if $ret =~ /^jS/; - $ret =~ s/xML/xml/ if $ret =~ /^xML/; - $ret =~ s/xSLT/xslt/ if $ret =~ /^xSLT/; - $ret =~ s/cSS/css/ if $ret =~ /^cSS/; - - # For HTML5 FileSystem API Flags attributes. - # (create is widely used to instantiate an object and must be avoided.) - $ret =~ s/^create/isCreate/ if $ret =~ /^create$/; - $ret =~ s/^exclusive/isExclusive/ if $ret =~ /^exclusive$/; - - return $ret; -} - -sub NamespaceForAttributeName -{ - my ($interfaceName, $attributeName) = @_; - return "SVGNames" if $interfaceName =~ /^SVG/ && !$svgAttributesInHTMLHash{$attributeName}; - return "HTMLNames"; -} - -# Identifies overloaded functions and for each function adds an array with -# links to its respective overloads (including itself). -sub LinkOverloadedFunctions -{ - my $interface = shift; - - my %nameToFunctionsMap = (); - foreach my $function (@{$interface->functions}) { - my $name = $function->name; - $nameToFunctionsMap{$name} = [] if !exists $nameToFunctionsMap{$name} or !$name; # Nameless functions cannot be overloaded - push(@{$nameToFunctionsMap{$name}}, $function); - $function->{overloads} = $nameToFunctionsMap{$name}; - $function->{overloadIndex} = @{$nameToFunctionsMap{$name}}; - } -} - -sub AttributeNameForGetterAndSetter -{ - my $attribute = shift; - - my $attributeName = GetImplName($attribute); - if ($attribute->extendedAttributes->{"ImplementedAs"}) { - $attributeName = $attribute->extendedAttributes->{"ImplementedAs"}; - } - my $attributeType = $attribute->type; - - return $attributeName; -} - -sub ContentAttributeName -{ - my ($interfaceName, $attribute) = @_; - - my $contentAttributeName = $attribute->extendedAttributes->{"Reflect"}; - return undef if !$contentAttributeName; - - $contentAttributeName = lc AttributeNameForGetterAndSetter($attribute) if $contentAttributeName eq "VALUE_IS_MISSING"; - - my $namespace = NamespaceForAttributeName($interfaceName, $contentAttributeName); - - AddToImplIncludes("${namespace}.h"); - # Attr (not Attribute) used in core content attributes - return "${namespace}::${contentAttributeName}Attr"; -} - -sub GetterExpression -{ - my ($interfaceName, $attribute) = @_; - - my $contentAttributeName = ContentAttributeName($interfaceName, $attribute); - - if (!$contentAttributeName) { - return (ToMethodName(AttributeNameForGetterAndSetter($attribute))); - } - - my $functionName; - if ($attribute->extendedAttributes->{"URL"}) { - $functionName = "getURLAttribute"; - } elsif ($attribute->type eq "boolean") { - $functionName = "fastHasAttribute"; - } elsif ($attribute->type eq "long") { - $functionName = "getIntegralAttribute"; - } elsif ($attribute->type eq "unsigned long") { - $functionName = "getUnsignedIntegralAttribute"; - } else { - if ($contentAttributeName eq "HTMLNames::idAttr") { - $functionName = "getIdAttribute"; - $contentAttributeName = ""; - } elsif ($contentAttributeName eq "HTMLNames::nameAttr") { - $functionName = "getNameAttribute"; - $contentAttributeName = ""; - } elsif ($contentAttributeName eq "HTMLNames::classAttr") { - $functionName = "getClassAttribute"; - $contentAttributeName = ""; - } else { - # We cannot use fast attributes for animated SVG types. - $functionName = IsSVGAnimatedType($attribute->type) ? "getAttribute" : "fastGetAttribute"; - } - } - - return ($functionName, $contentAttributeName); -} - -sub SetterExpression -{ - my ($interfaceName, $attribute) = @_; - - my $contentAttributeName = ContentAttributeName($interfaceName, $attribute); - - if (!$contentAttributeName) { - return ("set" . FirstLetterToUpperCase(AttributeNameForGetterAndSetter($attribute))); - } - - my $functionName; - if ($attribute->type eq "boolean") { - $functionName = "setBooleanAttribute"; - } elsif ($attribute->type eq "long") { - $functionName = "setIntegralAttribute"; - } elsif ($attribute->type eq "unsigned long") { - $functionName = "setUnsignedIntegralAttribute"; - } else { - $functionName = "setAttribute"; - } - - return ($functionName, $contentAttributeName); -} - -sub GenerateConditionalString -{ - my $node = shift; - - my $conditional = $node->extendedAttributes->{"Conditional"}; - if ($conditional) { - return GenerateConditionalStringFromAttributeValue($conditional); - } else { - return ""; - } -} - -sub GenerateConditionalStringFromAttributeValue -{ - my $conditional = shift; - - my $operator = ($conditional =~ /&/ ? '&' : ($conditional =~ /\|/ ? '|' : '')); - if ($operator) { - # Avoid duplicated conditions. - my %conditions; - map { $conditions{$_} = 1 } split('\\' . $operator, $conditional); - return "ENABLE(" . join(") $operator$operator ENABLE(", sort keys %conditions) . ")"; - } else { - return "ENABLE(" . $conditional . ")"; - } -} - -sub GenerateCompileTimeCheckForEnumsIfNeeded -{ - my $interface = shift; - my $implClassName = GetImplName($interface); - my @checks = (); - # If necessary, check that all constants are available as enums with the same value. - if (!$interface->extendedAttributes->{"DoNotCheckConstants"} && @{$interface->constants}) { - foreach my $constant (@{$interface->constants}) { - my $reflect = $constant->extendedAttributes->{"Reflect"}; - my $name = $reflect ? $reflect : $constant->name; - my $value = $constant->value; - - if ($constant->extendedAttributes->{"ImplementedBy"}) { - my $implementedByImplName = GetImplNameFromImplementedBy($constant->extendedAttributes->{"ImplementedBy"}); - push(@checks, " COMPILE_ASSERT($value == " . $implementedByImplName . "::$name, TheValueOf${implClassName}_${name}DoesntMatchWithImplementation);\n"); - } else { - push(@checks, " COMPILE_ASSERT($value == ${implClassName}::$name, TheValueOf${implClassName}_${name}DoesntMatchWithImplementation);\n"); - } - } - } - return @checks; -} - -sub ExtendedAttributeContains -{ - my $extendedAttributeValue = shift; - return 0 unless $extendedAttributeValue; - my $keyword = shift; - - my @extendedAttributeValues = split /\s*(\&|\|)\s*/, $extendedAttributeValue; - return grep { $_ eq $keyword } @extendedAttributeValues; -} - -sub InheritsInterface -{ - my $interface = shift; - my $interfaceName = shift; - my $found = 0; - - return 1 if $interfaceName eq $interface->name; - ForAllParents($interface, sub { - my $currentInterface = shift; - if ($currentInterface->name eq $interfaceName) { - $found = 1; - } - return 1 if $found; - }, 0); - - return $found; -} - -sub InheritsExtendedAttribute -{ - my $interface = shift; - my $extendedAttribute = shift; - my $found = 0; - - return 1 if $interface->extendedAttributes->{$extendedAttribute}; - ForAllParents($interface, sub { - my $currentInterface = shift; - if ($currentInterface->extendedAttributes->{$extendedAttribute}) { - $found = 1; - } - return 1 if $found; - }, 0); - - return $found; -} - -sub NeedsSpecialWrap -{ - my $interface = shift; - - return 1 if ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "ToV8"); - return 1 if ExtendedAttributeContains($interface->extendedAttributes->{"Custom"}, "Wrap"); - return 1 if $interface->extendedAttributes->{"SpecialWrapFor"}; - return 1 if InheritsInterface($interface, "Document"); - - return 0; -} - -1; diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/code_generator_v8.py b/chromium/third_party/WebKit/Source/bindings/scripts/code_generator_v8.py new file mode 100644 index 00000000000..778a87ec79b --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/code_generator_v8.py @@ -0,0 +1,222 @@ +# Copyright (C) 2013 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. + +"""Generate Blink V8 bindings (.h and .cpp files). + +If run itself, caches Jinja templates (and creates dummy file for build, +since cache filenames are unpredictable and opaque). + +This module is *not* concurrency-safe without care: bytecode caching creates +a race condition on cache *write* (crashes if one process tries to read a +partially-written cache). However, if you pre-cache the templates (by running +the module itself), then you can parallelize compiling individual files, since +cache *reading* is safe. + +Input: An object of class IdlDefinitions, containing an IDL interface X +Output: V8X.h and V8X.cpp + +Design doc: http://www.chromium.org/developers/design-documents/idl-compiler +""" + +import os +import posixpath +import re +import sys + +# Path handling for libraries and templates +# Paths have to be normalized because Jinja uses the exact template path to +# determine the hash used in the cache filename, and we need a pre-caching step +# to be concurrency-safe. Use absolute path because __file__ is absolute if +# module is imported, and relative if executed directly. +# If paths differ between pre-caching and individual file compilation, the cache +# is regenerated, which causes a race condition and breaks concurrent build, +# since some compile processes will try to read the partially written cache. +module_path, module_filename = os.path.split(os.path.realpath(__file__)) +third_party_dir = os.path.normpath(os.path.join( + module_path, os.pardir, os.pardir, os.pardir, os.pardir)) +templates_dir = os.path.normpath(os.path.join( + module_path, os.pardir, 'templates')) +# Make sure extension is .py, not .pyc or .pyo, so doesn't depend on caching +module_pyname = os.path.splitext(module_filename)[0] + '.py' + +# jinja2 is in chromium's third_party directory. +# Insert at 1 so at front to override system libraries, and +# after path[0] == invoking script dir +sys.path.insert(1, third_party_dir) +import jinja2 + +import idl_types +from idl_types import IdlType +import v8_callback_interface +from v8_globals import includes, interfaces +import v8_interface +import v8_types +from v8_utilities import capitalize, cpp_name, conditional_string, v8_class_name + + +class CodeGeneratorV8(object): + def __init__(self, interfaces_info, cache_dir): + interfaces_info = interfaces_info or {} + self.interfaces_info = interfaces_info + self.jinja_env = initialize_jinja_env(cache_dir) + + # Set global type info + idl_types.set_ancestors(dict( + (interface_name, interface_info['ancestors']) + for interface_name, interface_info in interfaces_info.iteritems() + if interface_info['ancestors'])) + IdlType.set_callback_interfaces(set( + interface_name + for interface_name, interface_info in interfaces_info.iteritems() + if interface_info['is_callback_interface'])) + IdlType.set_implemented_as_interfaces(dict( + (interface_name, interface_info['implemented_as']) + for interface_name, interface_info in interfaces_info.iteritems() + if interface_info['implemented_as'])) + IdlType.set_garbage_collected_types(set( + interface_name + for interface_name, interface_info in interfaces_info.iteritems() + if 'GarbageCollected' in interface_info['inherited_extended_attributes'])) + IdlType.set_will_be_garbage_collected_types(set( + interface_name + for interface_name, interface_info in interfaces_info.iteritems() + if 'WillBeGarbageCollected' in interface_info['inherited_extended_attributes'])) + v8_types.set_component_dirs(dict( + (interface_name, interface_info['component_dir']) + for interface_name, interface_info in interfaces_info.iteritems())) + + def generate_code(self, definitions, interface_name): + """Returns .h/.cpp code as (header_text, cpp_text).""" + try: + interface = definitions.interfaces[interface_name] + except KeyError: + raise Exception('%s not in IDL definitions' % interface_name) + + # Store other interfaces for introspection + interfaces.update(definitions.interfaces) + + # Set local type info + IdlType.set_callback_functions(definitions.callback_functions.keys()) + IdlType.set_enums((enum.name, enum.values) + for enum in definitions.enumerations.values()) + + # Select appropriate Jinja template and contents function + if interface.is_callback: + header_template_filename = 'callback_interface.h' + cpp_template_filename = 'callback_interface.cpp' + generate_contents = v8_callback_interface.generate_callback_interface + else: + header_template_filename = 'interface.h' + cpp_template_filename = 'interface.cpp' + generate_contents = v8_interface.generate_interface + header_template = self.jinja_env.get_template(header_template_filename) + cpp_template = self.jinja_env.get_template(cpp_template_filename) + + # Generate contents (input parameters for Jinja) + template_contents = generate_contents(interface) + template_contents['code_generator'] = module_pyname + + # Add includes for interface itself and any dependencies + interface_info = self.interfaces_info[interface_name] + template_contents['header_includes'].add(interface_info['include_path']) + template_contents['header_includes'] = sorted(template_contents['header_includes']) + includes.update(interface_info.get('dependencies_include_paths', [])) + template_contents['cpp_includes'] = sorted(includes) + + # Render Jinja templates + header_text = header_template.render(template_contents) + cpp_text = cpp_template.render(template_contents) + return header_text, cpp_text + + +def initialize_jinja_env(cache_dir): + jinja_env = jinja2.Environment( + loader=jinja2.FileSystemLoader(templates_dir), + # Bytecode cache is not concurrency-safe unless pre-cached: + # if pre-cached this is read-only, but writing creates a race condition. + bytecode_cache=jinja2.FileSystemBytecodeCache(cache_dir), + keep_trailing_newline=True, # newline-terminate generated files + lstrip_blocks=True, # so can indent control flow tags + trim_blocks=True) + jinja_env.filters.update({ + 'blink_capitalize': capitalize, + 'conditional': conditional_if_endif, + 'runtime_enabled': runtime_enabled_if, + }) + return jinja_env + + +# [Conditional] +def conditional_if_endif(code, conditional_string): + # Jinja2 filter to generate if/endif directive blocks + if not conditional_string: + return code + return ('#if %s\n' % conditional_string + + code + + '#endif // %s\n' % conditional_string) + + +# [RuntimeEnabled] +def runtime_enabled_if(code, runtime_enabled_function_name): + if not runtime_enabled_function_name: + return code + # Indent if statement to level of original code + indent = re.match(' *', code).group(0) + return ('%sif (%s()) {\n' % (indent, runtime_enabled_function_name) + + ' %s\n' % '\n '.join(code.splitlines()) + + '%s}\n' % indent) + + +################################################################################ + +def main(argv): + # If file itself executed, cache templates + try: + cache_dir = argv[1] + dummy_filename = argv[2] + except IndexError as err: + print 'Usage: %s CACHE_DIR DUMMY_FILENAME' % argv[0] + return 1 + + # Cache templates + jinja_env = initialize_jinja_env(cache_dir) + template_filenames = [filename for filename in os.listdir(templates_dir) + # Skip .svn, directories, etc. + if filename.endswith(('.cpp', '.h'))] + for template_filename in template_filenames: + jinja_env.get_template(template_filename) + + # Create a dummy file as output for the build system, + # since filenames of individual cache files are unpredictable and opaque + # (they are hashes of the template path, which varies based on environment) + with open(dummy_filename, 'w') as dummy_file: + pass # |open| creates or touches the file + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/compute_dependencies.py b/chromium/third_party/WebKit/Source/bindings/scripts/compute_dependencies.py deleted file mode 100755 index b358ae60e01..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/scripts/compute_dependencies.py +++ /dev/null @@ -1,404 +0,0 @@ -#!/usr/bin/python -# -# Copyright (C) 2013 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. - -import optparse -import os -import posixpath -import re -import string - - -class IdlBadFilenameError(Exception): - """Raised if an IDL filename disagrees with the interface name in the file.""" - pass - - -class IdlInterfaceFileNotFoundError(Exception): - """Raised if the IDL file implementing an interface cannot be found.""" - pass - - -def parse_options(): - parser = optparse.OptionParser() - parser.add_option('--event-names-file', help='output file') - parser.add_option('--main-idl-files-list', help='file listing main (compiled to Blink) IDL files') - parser.add_option('--support-idl-files-list', help='file listing support IDL files (not compiled to Blink, e.g. testing)') - parser.add_option('--interface-dependencies-file', help='output file') - parser.add_option('--bindings-derived-sources-file', help='output file') - parser.add_option('--window-constructors-file', help='output file') - parser.add_option('--workerglobalscope-constructors-file', help='output file') - parser.add_option('--sharedworkerglobalscope-constructors-file', help='output file') - parser.add_option('--dedicatedworkerglobalscope-constructors-file', help='output file') - parser.add_option('--serviceworkerglobalscope-constructors-file', help='output file') - parser.add_option('--write-file-only-if-changed', type='int', help='if true, do not write an output file if it would be identical to the existing one, which avoids unnecessary rebuilds in ninja') - options, args = parser.parse_args() - if options.event_names_file is None: - parser.error('Must specify an output file using --event-names-file.') - if options.interface_dependencies_file is None: - parser.error('Must specify an output file using --interface-dependencies-file.') - if options.bindings_derived_sources_file is None: - parser.error('Must specify an output file using --bindings-derived-sources-file.') - if options.window_constructors_file is None: - parser.error('Must specify an output file using --window-constructors-file.') - if options.workerglobalscope_constructors_file is None: - parser.error('Must specify an output file using --workerglobalscope-constructors-file.') - if options.sharedworkerglobalscope_constructors_file is None: - parser.error('Must specify an output file using --sharedworkerglobalscope-constructors-file.') - if options.dedicatedworkerglobalscope_constructors_file is None: - parser.error('Must specify an output file using --dedicatedworkerglobalscope-constructors-file.') - if options.serviceworkerglobalscope_constructors_file is None: - parser.error('Must specify an output file using --serviceworkerglobalscope-constructors-file.') - if options.main_idl_files_list is None: - parser.error('Must specify a file listing main IDL files using --main-idl-files-list.') - if options.support_idl_files_list is None: - parser.error('Must specify a file listing support IDL files using --support-idl-files-list.') - if options.write_file_only_if_changed is None: - parser.error('Must specify whether file is only written if changed using --write-file-only-if-changed.') - options.write_file_only_if_changed = bool(options.write_file_only_if_changed) - if args: - parser.error('No arguments taken, but "%s" given.' % ' '.join(args)) - return options - - -def get_file_contents(idl_filename): - with open(idl_filename) as idl_file: - lines = idl_file.readlines() - return ''.join(lines) - - -def write_file(new_lines, destination_filename, only_if_changed): - if only_if_changed and os.path.isfile(destination_filename): - with open(destination_filename) as destination_file: - old_lines = destination_file.readlines() - if old_lines == new_lines: - return - with open(destination_filename, 'w') as destination_file: - destination_file.write(''.join(new_lines)) - - -def get_partial_interface_name_from_idl(file_contents): - match = re.search(r'partial\s+interface\s+(\w+)', file_contents) - return match and match.group(1) - - -# identifier-A implements identifier-B; -# http://www.w3.org/TR/WebIDL/#idl-implements-statements -def get_implemented_interfaces_from_idl(file_contents, interface_name): - def get_implemented(left_identifier, right_identifier): - # identifier-A must be the current interface - if left_identifier != interface_name: - raise IdlBadFilenameError("Identifier on the left of the 'implements' statement should be %s in %s.idl, but found %s" % (interface_name, interface_name, left_identifier)) - return right_identifier - - implements_re = r'^\s*(\w+)\s+implements\s+(\w+)\s*;' - implements_matches = re.finditer(implements_re, file_contents, re.MULTILINE) - implements_pairs = [(match.group(1), match.group(2)) - for match in implements_matches] - return [get_implemented(left, right) for left, right in implements_pairs] - - -def is_callback_interface_from_idl(file_contents): - match = re.search(r'callback\s+interface\s+\w+', file_contents) - return bool(match) - - -def get_parent_interface(file_contents): - match = re.search(r'interface\s+\w+\s*:\s*(\w+)\s*', file_contents) - return match and match.group(1) - - -def get_interface_extended_attributes_from_idl(file_contents): - match = re.search(r'\[(.*)\]\s+(callback\s+)?(interface|exception)\s+(\w+)', - file_contents, flags=re.DOTALL) - if not match: - return {} - # Strip comments - # re.compile needed b/c Python 2.6 doesn't support flags in re.sub - single_line_comment_re = re.compile(r'//.*$', flags=re.MULTILINE) - block_comment_re = re.compile(r'/\*.*?\*/', flags=re.MULTILINE | re.DOTALL) - extended_attributes_string = re.sub(single_line_comment_re, '', match.group(1)) - extended_attributes_string = re.sub(block_comment_re, '', extended_attributes_string) - extended_attributes = {} - # FIXME: this splitting is WRONG: it fails on ExtendedAttributeArgList like - # 'NamedConstructor=Foo(a, b)' - parts = [extended_attribute.strip() - for extended_attribute in extended_attributes_string.split(',') - # Discard empty parts, which may exist due to trailing comma - if extended_attribute.strip()] - for part in parts: - name, _, value = map(string.strip, part.partition('=')) - extended_attributes[name] = value - return extended_attributes - - -def generate_constructor_attribute_list(interface_name, extended_attributes): - extended_attributes_list = [ - name + '=' + extended_attributes[name] - for name in 'Conditional', 'PerContextEnabled', 'RuntimeEnabled' - if name in extended_attributes] - if extended_attributes_list: - extended_string = '[%s] ' % ', '.join(extended_attributes_list) - else: - extended_string = '' - - attribute_string = 'attribute {interface_name}Constructor {interface_name}'.format(interface_name=interface_name) - attributes_list = [extended_string + attribute_string] - - # In addition to the regular property, for every [NamedConstructor] - # extended attribute on an interface, a corresponding property MUST exist - # on the ECMAScript global object. - if 'NamedConstructor' in extended_attributes: - named_constructor = extended_attributes['NamedConstructor'] - # Extract function name, namely everything before opening '(' - constructor_name = re.sub(r'\(.*', '', named_constructor) - # Note the reduplicated 'ConstructorConstructor' - attribute_string = 'attribute %sConstructorConstructor %s' % (interface_name, constructor_name) - attributes_list.append(extended_string + attribute_string) - - return attributes_list - - -def generate_event_names_file(destination_filename, event_names, only_if_changed): - def extended_attribute_string(name): - value = extended_attributes[name] - if name == 'RuntimeEnabled': - value += 'Enabled' - return name + '=' + value - - source_dir, _ = os.path.split(os.getcwd()) - lines = [] - lines.append('namespace="Event"\n') - lines.append('\n') - for filename, extended_attributes in sorted(event_names.iteritems()): - refined_filename, _ = os.path.splitext(os.path.relpath(filename, source_dir)) - refined_filename = refined_filename.replace(os.sep, posixpath.sep) - extended_attributes_list = [ - extended_attribute_string(name) - for name in 'Conditional', 'ImplementedAs', 'RuntimeEnabled' - if name in extended_attributes] - lines.append('%s %s\n' % (refined_filename, ', '.join(extended_attributes_list))) - write_file(lines, destination_filename, only_if_changed) - - -def generate_global_constructors_partial_interface(interface_name, destination_filename, constructor_attributes_list, only_if_changed): - lines = (['partial interface %s {\n' % interface_name] + - [' %s;\n' % constructor_attribute - for constructor_attribute in sorted(constructor_attributes_list)] + - ['};\n']) - write_file(lines, destination_filename, only_if_changed) - - -def generate_dependencies(idl_file_name, interfaces, dependencies, partial_interface_files, implements_interfaces, implemented_somewhere): - interface_name, _ = os.path.splitext(os.path.basename(idl_file_name)) - full_path = os.path.realpath(idl_file_name) - idl_file_contents = get_file_contents(full_path) - - # Handle partial interfaces - partial_interface_name = get_partial_interface_name_from_idl(idl_file_contents) - if partial_interface_name: - partial_interface_files[partial_interface_name].append(full_path) - return partial_interface_name - - interfaces.add(interface_name) - # Non-partial interfaces default to having bindings generated - dependencies[full_path] = [] - - # Parse 'identifier-A implements identifier-B;' statements - implemented_interfaces = get_implemented_interfaces_from_idl(idl_file_contents, interface_name) - implements_interfaces[interface_name] = implemented_interfaces - implemented_somewhere |= set(implemented_interfaces) - - return partial_interface_name - - -def remove_interfaces_implemented_somewhere(dependencies, interface_name_to_idl_file, implemented_somewhere): - # Interfaces that are implemented by another interface do not have - # their own bindings generated, as this would be redundant with the - # actual implementation. - for implemented_interface in implemented_somewhere: - full_path = interface_name_to_idl_file[implemented_interface] - del dependencies[full_path] - - -def record_global_constructors_and_extended_attribute(idl_file_name, global_constructors, interface_extended_attribute, parent_interface): - interface_name, _ = os.path.splitext(os.path.basename(idl_file_name)) - full_path = os.path.realpath(idl_file_name) - idl_file_contents = get_file_contents(full_path) - extended_attributes = get_interface_extended_attributes_from_idl(idl_file_contents) - - # Record global constructors - if not is_callback_interface_from_idl(idl_file_contents) and 'NoInterfaceObject' not in extended_attributes: - global_contexts = extended_attributes.get('GlobalContext', 'Window').split('&') - new_constructor_list = generate_constructor_attribute_list(interface_name, extended_attributes) - for global_object in global_contexts: - global_constructors[global_object].extend(new_constructor_list) - - # Record parents and extended attributes for generating event names - if interface_name == 'Event': - interface_extended_attribute[interface_name] = extended_attributes - parent = get_parent_interface(idl_file_contents) - if parent: - parent_interface[interface_name] = parent - interface_extended_attribute[interface_name] = extended_attributes - - -def parse_idl_files(main_idl_files, support_idl_files, global_constructors_filenames): - """Return dependencies between IDL files, constructors on global objects, and events. - - Returns: - interfaces: - set of all interfaces - bindings_derived_sources: - list of main IDL file names (except support IDL file names) - dependencies: - dict of main IDL filename (for a given interface) -> list of partial IDL filenames (for that interface) - The keys (main IDL files) are the files for which bindings are - generated. This does not include IDL files for interfaces - implemented by another interface. - global_constructors: - dict of global objects -> list of constructors on that object - event_names: - dict of interfaces that inherit from Event -> list of extended attributes for the interface - """ - interfaces = set() - dependencies = {} - partial_interface_files = {} - implements_interfaces = {} - implemented_somewhere = set() - - global_constructors = {} - for global_object in global_constructors_filenames.keys(): - global_constructors[global_object] = [] - - # Parents and extended attributes (of interfaces with parents) are - # used in generating event names - parent_interface = {} - interface_extended_attribute = {} - - interface_name_to_idl_file = {} - for idl_file_name in main_idl_files + support_idl_files: - full_path = os.path.realpath(idl_file_name) - interface_name, _ = os.path.splitext(os.path.basename(idl_file_name)) - interface_name_to_idl_file[interface_name] = full_path - partial_interface_files[interface_name] = [] - - # Generate dependencies, global_constructors and interface_extended_attributes for main IDL files - for idl_file_name in main_idl_files: - if not generate_dependencies(idl_file_name, interfaces, dependencies, partial_interface_files, implements_interfaces, implemented_somewhere): - record_global_constructors_and_extended_attribute(idl_file_name, global_constructors, interface_extended_attribute, parent_interface) - - bindings_derived_sources = dependencies.copy() - remove_interfaces_implemented_somewhere(bindings_derived_sources, interface_name_to_idl_file, implemented_somewhere) - - # Add constructors on global objects to partial interfaces - for global_object, filename in global_constructors_filenames.iteritems(): - if global_object in interfaces: - partial_interface_files[global_object].append(filename) - - # Add support IDL files to the dependencies for supporting partial interface - for idl_file_name in support_idl_files: - generate_dependencies(idl_file_name, interfaces, dependencies, partial_interface_files, implements_interfaces, implemented_somewhere) - remove_interfaces_implemented_somewhere(dependencies, interface_name_to_idl_file, implemented_somewhere) - - # An IDL file's dependencies are partial interface files that extend it, - # and files for other interfaces that this interfaces implements. - for idl_file_path in dependencies.iterkeys(): - interface_name, _ = os.path.splitext(os.path.basename(idl_file_path)) - implemented_interfaces = implements_interfaces[interface_name] - try: - interface_paths = map(lambda x: interface_name_to_idl_file[x], implemented_interfaces) - except KeyError as key_name: - raise IdlInterfaceFileNotFoundError('Could not find the IDL file where the following implemented interface is defined: %s' % key_name) - dependencies[idl_file_path] = sorted(partial_interface_files[interface_name] + interface_paths) - - # Generate event names for all interfaces that inherit from Event, - # including Event itself. - event_names = {} - if 'Event' in interfaces: - event_names[interface_name_to_idl_file['Event']] = interface_extended_attribute['Event'] - for interface, parent in parent_interface.iteritems(): - while parent in parent_interface: - parent = parent_interface[parent] - if parent == 'Event': - event_names[interface_name_to_idl_file[interface]] = interface_extended_attribute[interface] - - return interfaces, dependencies, bindings_derived_sources, global_constructors, event_names - - -def write_dependency_file(filename, dependencies, only_if_changed): - """Write the interface dependencies file. - - The format is as follows: - - Document.idl P.idl - Event.idl - Window.idl Q.idl R.idl S.idl - ... - - The above indicates that: - Document.idl depends on P.idl, - Event.idl depends on no other IDL files, and - Window.idl depends on Q.idl, R.idl, and S.idl. - - An IDL that is a dependency of another IDL (e.g. P.idl) does not have its - own line in the dependency file. - """ - lines = ['%s %s\n' % (idl_file, ' '.join(sorted(dependency_files))) - for idl_file, dependency_files in sorted(dependencies.iteritems())] - write_file(lines, filename, only_if_changed) - - -def main(): - options = parse_options() - with open(options.main_idl_files_list) as idl_files_list: - main_idl_files = [string.rstrip(line, '\n') for line in idl_files_list] - with open(options.support_idl_files_list) as idl_files_list: - support_idl_files = [string.rstrip(line, '\n') for line in idl_files_list] - only_if_changed = options.write_file_only_if_changed - global_constructors_filenames = { - 'Window': options.window_constructors_file, - 'WorkerGlobalScope': options.workerglobalscope_constructors_file, - 'SharedWorkerGlobalScope': options.sharedworkerglobalscope_constructors_file, - 'DedicatedWorkerGlobalScope': options.dedicatedworkerglobalscope_constructors_file, - 'ServiceWorkerGlobalScope': options.serviceworkerglobalscope_constructors_file, - } - - interfaces, dependencies, bindings_derived_sources, global_constructors, event_names = parse_idl_files(main_idl_files, support_idl_files, global_constructors_filenames) - - write_dependency_file(options.interface_dependencies_file, dependencies, only_if_changed) - write_dependency_file(options.bindings_derived_sources_file, bindings_derived_sources, only_if_changed) - for interface_name, filename in global_constructors_filenames.iteritems(): - if interface_name in interfaces: - generate_global_constructors_partial_interface(interface_name, filename, global_constructors[interface_name], only_if_changed) - generate_event_names_file(options.event_names_file, event_names, only_if_changed) - - -if __name__ == '__main__': - main() diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/compute_global_objects.py b/chromium/third_party/WebKit/Source/bindings/scripts/compute_global_objects.py new file mode 100755 index 00000000000..93d2eed5db3 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/compute_global_objects.py @@ -0,0 +1,113 @@ +#!/usr/bin/python +# +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Compute global objects. + +Global objects are defined by interfaces with [Global] or [PrimaryGlobal] on +their definition: http://heycam.github.io/webidl/#Global + +Design document: http://www.chromium.org/developers/design-documents/idl-build +""" + +import optparse +import os +import cPickle as pickle +import sys + +from utilities import get_file_contents, idl_filename_to_interface_name, get_interface_extended_attributes_from_idl, read_file_to_list, read_pickle_files, write_pickle_file + +GLOBAL_EXTENDED_ATTRIBUTES = frozenset([ + 'Global', + 'PrimaryGlobal', +]) + + +def parse_options(): + usage = 'Usage: %prog [options] [GlobalObjectsComponent.pickle]... [GlobalObjects.pickle]' + parser = optparse.OptionParser(usage=usage) + parser.add_option('--idl-files-list', help='file listing IDL files') + parser.add_option('--write-file-only-if-changed', type='int', help='if true, do not write an output file if it would be identical to the existing one, which avoids unnecessary rebuilds in ninja') + + options, args = parser.parse_args() + + if options.idl_files_list is None: + parser.error('Must specify a file listing IDL files using --idl-files-list.') + if options.write_file_only_if_changed is None: + parser.error('Must specify whether output files are only written if changed using --write-file-only-if-changed.') + options.write_file_only_if_changed = bool(options.write_file_only_if_changed) + if not args: + parser.error('Must specify an output pickle filename as argument, ' + 'optionally preceeded by input pickle filenames.') + + return options, args + + +def dict_union(dicts): + return dict((k, v) for d in dicts for k, v in d.iteritems()) + + +def idl_file_to_global_names(idl_filename): + """Returns global names, if any, for an IDL file. + + If the [Global] or [PrimaryGlobal] extended attribute is declared with an + identifier list argument, then those identifiers are the interface's global + names; otherwise, the interface has a single global name, which is the + interface's identifier (http://heycam.github.io/webidl/#Global). + """ + interface_name = idl_filename_to_interface_name(idl_filename) + full_path = os.path.realpath(idl_filename) + idl_file_contents = get_file_contents(full_path) + extended_attributes = get_interface_extended_attributes_from_idl(idl_file_contents) + + global_keys = GLOBAL_EXTENDED_ATTRIBUTES.intersection( + extended_attributes.iterkeys()) + if not global_keys: + return + if len(global_keys) > 1: + raise ValueError('The [Global] and [PrimaryGlobal] extended attributes ' + 'MUST NOT be declared on the same interface.') + global_key = next(iter(global_keys)) + + global_value = extended_attributes[global_key] + if global_value: + # FIXME: In spec names are comma-separated, which makes parsing very + # difficult (https://www.w3.org/Bugs/Public/show_bug.cgi?id=24959). + return global_value.split('&') + return [interface_name] + + +def idl_files_to_interface_name_global_names(idl_files): + """Yields pairs (interface_name, global_names) found in IDL files.""" + for idl_filename in idl_files: + interface_name = idl_filename_to_interface_name(idl_filename) + global_names = idl_file_to_global_names(idl_filename) + if global_names: + yield interface_name, global_names + + +################################################################################ + +def main(): + options, args = parse_options() + # args = Input1, Input2, ..., Output + output_global_objects_filename = args.pop() + interface_name_global_names = dict_union( + existing_interface_name_global_names + for existing_interface_name_global_names in read_pickle_files(args)) + + # Input IDL files are passed in a file, due to OS command line length + # limits. This is generated at GYP time, which is ok b/c files are static. + idl_files = read_file_to_list(options.idl_files_list) + interface_name_global_names.update( + idl_files_to_interface_name_global_names(idl_files)) + + write_pickle_file(output_global_objects_filename, + interface_name_global_names, + options.write_file_only_if_changed) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/compute_interfaces_info_individual.py b/chromium/third_party/WebKit/Source/bindings/scripts/compute_interfaces_info_individual.py new file mode 100755 index 00000000000..c3671d9ebdf --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/compute_interfaces_info_individual.py @@ -0,0 +1,192 @@ +#!/usr/bin/python +# +# Copyright (C) 2013 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. + +"""Compute global interface information for individual IDL files. + +Auxiliary module for compute_interfaces_info_overall, which consolidates +this individual information, computing info that spans multiple files +(dependencies and ancestry). + +This distinction is so that individual interface info can be computed +separately for each component (avoiding duplicated reading of individual +files), then consolidated using *only* the info visible to a given component. + +Design doc: http://www.chromium.org/developers/design-documents/idl-build +""" + +from collections import defaultdict +import optparse +import os +import posixpath +import sys + +from utilities import get_file_contents, read_file_to_list, idl_filename_to_interface_name, write_pickle_file, get_interface_extended_attributes_from_idl, is_callback_interface_from_idl, get_partial_interface_name_from_idl, get_implements_from_idl, get_parent_interface, get_put_forward_interfaces_from_idl + +module_path = os.path.dirname(__file__) +source_path = os.path.normpath(os.path.join(module_path, os.pardir, os.pardir)) + +# Global variables (filled in and exported) +interfaces_info = {} +partial_interface_files = defaultdict(lambda: { + 'full_paths': [], + 'include_paths': [], +}) + + +def parse_options(): + usage = 'Usage: %prog [options] [generated1.idl]...' + parser = optparse.OptionParser(usage=usage) + parser.add_option('--component-dir', help='component directory') + parser.add_option('--idl-files-list', help='file listing IDL files') + parser.add_option('--interfaces-info-file', help='output pickle file') + parser.add_option('--write-file-only-if-changed', type='int', help='if true, do not write an output file if it would be identical to the existing one, which avoids unnecessary rebuilds in ninja') + + options, args = parser.parse_args() + if options.component_dir is None: + parser.error('Must specify a component directory using --component-dir.') + if options.interfaces_info_file is None: + parser.error('Must specify an output file using --interfaces-info-file.') + if options.idl_files_list is None: + parser.error('Must specify a file listing IDL files using --idl-files-list.') + if options.write_file_only_if_changed is None: + parser.error('Must specify whether file is only written if changed using --write-file-only-if-changed.') + options.write_file_only_if_changed = bool(options.write_file_only_if_changed) + return options, args + + +################################################################################ +# Computations +################################################################################ + +def include_path(idl_filename, implemented_as=None): + """Returns relative path to header file in POSIX format; used in includes. + + POSIX format is used for consistency of output, so reference tests are + platform-independent. + """ + relative_path_local = os.path.relpath(idl_filename, source_path) + relative_dir_local = os.path.dirname(relative_path_local) + relative_dir_posix = relative_dir_local.replace(os.path.sep, posixpath.sep) + + # IDL file basename is used even if only a partial interface file + idl_file_basename, _ = os.path.splitext(os.path.basename(idl_filename)) + cpp_class_name = implemented_as or idl_file_basename + + return posixpath.join(relative_dir_posix, cpp_class_name + '.h') + + +def add_paths_to_partials_dict(partial_interface_name, full_path, this_include_path=None): + paths_dict = partial_interface_files[partial_interface_name] + paths_dict['full_paths'].append(full_path) + if this_include_path: + paths_dict['include_paths'].append(this_include_path) + + +def compute_info_individual(idl_filename, component_dir): + full_path = os.path.realpath(idl_filename) + idl_file_contents = get_file_contents(full_path) + + extended_attributes = get_interface_extended_attributes_from_idl(idl_file_contents) + implemented_as = extended_attributes.get('ImplementedAs') + this_include_path = include_path(idl_filename, implemented_as) + + # Handle partial interfaces + partial_interface_name = get_partial_interface_name_from_idl(idl_file_contents) + if partial_interface_name: + add_paths_to_partials_dict(partial_interface_name, full_path, this_include_path) + return + + # If not a partial interface, the basename is the interface name + interface_name = idl_filename_to_interface_name(idl_filename) + + # 'implements' statements can be included in either the file for the + # implement*ing* interface (lhs of 'implements') or implement*ed* interface + # (rhs of 'implements'). Store both for now, then merge to implement*ing* + # interface later. + left_interfaces, right_interfaces = get_implements_from_idl(idl_file_contents, interface_name) + + interfaces_info[interface_name] = { + 'component_dir': component_dir, + 'extended_attributes': extended_attributes, + 'full_path': full_path, + 'implemented_as': implemented_as, + 'implemented_by_interfaces': left_interfaces, # private, merged to next + 'implements_interfaces': right_interfaces, + 'include_path': this_include_path, + # FIXME: temporary private field, while removing old treatement of + # 'implements': http://crbug.com/360435 + 'is_legacy_treat_as_partial_interface': 'LegacyTreatAsPartialInterface' in extended_attributes, + 'is_callback_interface': is_callback_interface_from_idl(idl_file_contents), + 'parent': get_parent_interface(idl_file_contents), + # Interfaces that are referenced (used as types) and that we introspect + # during code generation (beyond interface-level data ([ImplementedAs], + # is_callback_interface, ancestors, and inherited extended attributes): + # deep dependencies. + # These cause rebuilds of referrers, due to the dependency, so these + # should be minimized; currently only targets of [PutForwards]. + 'referenced_interfaces': get_put_forward_interfaces_from_idl(idl_file_contents), + } + + +def info_individual(): + """Returns info packaged as a dict.""" + return { + 'interfaces_info': interfaces_info, + # Can't pickle defaultdict, convert to dict + 'partial_interface_files': dict(partial_interface_files), + } + + +################################################################################ + +def main(): + options, args = parse_options() + + # Static IDL files are passed in a file (generated at GYP time), due to OS + # command line length limits + idl_files = read_file_to_list(options.idl_files_list) + # Generated IDL files are passed at the command line, since these are in the + # build directory, which is determined at build time, not GYP time, so these + # cannot be included in the file listing static files + idl_files.extend(args) + + # Compute information for individual files + # Information is stored in global variables interfaces_info and + # partial_interface_files. + for idl_filename in idl_files: + compute_info_individual(idl_filename, options.component_dir) + + write_pickle_file(options.interfaces_info_file, + info_individual(), + options.write_file_only_if_changed) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/compute_interfaces_info_overall.py b/chromium/third_party/WebKit/Source/bindings/scripts/compute_interfaces_info_overall.py new file mode 100755 index 00000000000..658ccfade6f --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/compute_interfaces_info_overall.py @@ -0,0 +1,264 @@ +#!/usr/bin/python +# +# Copyright (C) 2013 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. + +"""Compute global interface information, including public information, dependencies, and inheritance. + +Computed data is stored in a global variable, |interfaces_info|, and written as +output (concretely, exported as a pickle). This is then used by the IDL compiler +itself, so it does not need to compute global information itself, and so that +inter-IDL dependencies are clear, since they are all computed here. + +The |interfaces_info| pickle is a *global* dependency: any changes cause a full +rebuild. This is to avoid having to compute which public data is visible by +which IDL files on a file-by-file basis, which is very complex for little +benefit. +|interfaces_info| should thus only contain data about an interface that +contains paths or is needed by *other* interfaces, e.g., path data (to abstract +the compiler from OS-specific file paths) or public data (to avoid having to +read other interfaces unnecessarily). +It should *not* contain full information about an interface (e.g., all +extended attributes), as this would cause unnecessary rebuilds. + +|interfaces_info| is a dict, keyed by |interface_name|. + +Current keys are: +* dependencies: + 'implements_interfaces': targets of 'implements' statements + 'referenced_interfaces': reference interfaces that are introspected + (currently just targets of [PutForwards]) + +* inheritance: + 'ancestors': all ancestor interfaces + 'inherited_extended_attributes': inherited extended attributes + (all controlling memory management) + +* public: + 'is_callback_interface': bool, callback interface or not + 'implemented_as': value of [ImplementedAs=...] on interface (C++ class name) + +* paths: + 'full_path': path to the IDL file, so can lookup an IDL by interface name + 'include_path': path for use in C++ #include directives + 'dependencies_full_paths': paths to dependencies (for merging into main) + 'dependencies_include_paths': paths for use in C++ #include directives + +Note that all of these are stable information, unlikely to change without +moving or deleting files (hence requiring a full rebuild anyway) or significant +code changes (for inherited extended attributes). + +Design doc: http://www.chromium.org/developers/design-documents/idl-build +""" + +from collections import defaultdict +import cPickle as pickle +import optparse +import sys + +from utilities import read_pickle_files, write_pickle_file + +INHERITED_EXTENDED_ATTRIBUTES = set([ + 'ActiveDOMObject', + 'DependentLifetime', + 'GarbageCollected', + 'WillBeGarbageCollected', +]) + +# Main variable (filled in and exported) +interfaces_info = {} + +# Auxiliary variables (not visible to future build steps) +partial_interface_files = defaultdict(lambda: { + 'full_paths': [], + 'include_paths': [], +}) +parent_interfaces = {} +inherited_extended_attributes_by_interface = {} # interface name -> extended attributes + + +class IdlInterfaceFileNotFoundError(Exception): + """Raised if the IDL file implementing an interface cannot be found.""" + pass + + +def parse_options(): + usage = 'Usage: %prog [InfoIndividual.pickle]... [Info.pickle]' + parser = optparse.OptionParser(usage=usage) + parser.add_option('--write-file-only-if-changed', type='int', help='if true, do not write an output file if it would be identical to the existing one, which avoids unnecessary rebuilds in ninja') + + options, args = parser.parse_args() + if options.write_file_only_if_changed is None: + parser.error('Must specify whether file is only written if changed using --write-file-only-if-changed.') + options.write_file_only_if_changed = bool(options.write_file_only_if_changed) + return options, args + + +def dict_of_dicts_of_lists_update_or_append(existing, other): + """Updates an existing dict of dicts of lists, or appends to lists if key already present. + + Needed for merging partial_interface_files across components. + """ + for key, value in other.iteritems(): + if key not in existing: + existing[key] = value + continue + existing_value = existing[key] + for inner_key, inner_value in value.iteritems(): + existing_value[inner_key].extend(inner_value) + + +################################################################################ +# Computations +################################################################################ + +def compute_inheritance_info(interface_name): + """Compute inheritance information, namely ancestors and inherited extended attributes.""" + def generate_ancestors(interface_name): + while interface_name in parent_interfaces: + interface_name = parent_interfaces[interface_name] + yield interface_name + + ancestors = list(generate_ancestors(interface_name)) + inherited_extended_attributes = inherited_extended_attributes_by_interface[interface_name] + for ancestor in ancestors: + # Ancestors may not be present, notably if an ancestor is a generated + # IDL file and we are running this script from run-bindings-tests, + # where we don't generate these files. + ancestor_extended_attributes = inherited_extended_attributes_by_interface.get(ancestor, {}) + inherited_extended_attributes.update(ancestor_extended_attributes) + + interfaces_info[interface_name].update({ + 'ancestors': ancestors, + 'inherited_extended_attributes': inherited_extended_attributes, + }) + + +def compute_interfaces_info_overall(info_individuals): + """Compute information about IDL files. + + Information is stored in global interfaces_info. + """ + for info in info_individuals: + # No overlap between interface names, so ok to use dict.update + interfaces_info.update(info['interfaces_info']) + # Interfaces in one component may have partial interfaces in + # another component. This is ok (not a layering violation), since + # partial interfaces are used to *extend* interfaces. + # We thus need to update or append if already present + dict_of_dicts_of_lists_update_or_append( + partial_interface_files, info['partial_interface_files']) + + # Record inheritance information individually + for interface_name, interface_info in interfaces_info.iteritems(): + extended_attributes = interface_info['extended_attributes'] + inherited_extended_attributes_by_interface[interface_name] = dict( + (key, value) + for key, value in extended_attributes.iteritems() + if key in INHERITED_EXTENDED_ATTRIBUTES) + parent = interface_info['parent'] + if parent: + parent_interfaces[interface_name] = parent + + # Once all individual files handled, can compute inheritance information + # and dependencies + + # Compute inheritance info + for interface_name in interfaces_info: + compute_inheritance_info(interface_name) + + # Compute dependencies + # Move implements info from implement*ed* interface (rhs of 'implements') + # to implement*ing* interface (lhs of 'implements'). + # Note that moving an 'implements' statement between implementing and + # implemented files does not change the info (or hence cause a rebuild)! + for right_interface_name, interface_info in interfaces_info.iteritems(): + for left_interface_name in interface_info['implemented_by_interfaces']: + interfaces_info[left_interface_name]['implements_interfaces'].append(right_interface_name) + del interface_info['implemented_by_interfaces'] + + # An IDL file's dependencies are partial interface files that extend it, + # and files for other interfaces that this interfaces implements. + for interface_name, interface_info in interfaces_info.iteritems(): + partial_interface_paths = partial_interface_files[interface_name] + partial_interfaces_full_paths = partial_interface_paths['full_paths'] + # Partial interface definitions each need an include, as they are + # implemented in separate classes from the main interface. + partial_interfaces_include_paths = partial_interface_paths['include_paths'] + + implemented_interfaces = interface_info['implements_interfaces'] + try: + implemented_interfaces_info = [ + interfaces_info[interface] + for interface in implemented_interfaces] + except KeyError as key_name: + raise IdlInterfaceFileNotFoundError('Could not find the IDL file where the following implemented interface is defined: %s' % key_name) + implemented_interfaces_full_paths = [ + implemented_interface_info['full_path'] + for implemented_interface_info in implemented_interfaces_info] + # Implemented interfaces don't need includes, as this is handled in + # the Blink implementation (they are implemented on |impl| itself, + # hence header is included in implementing class). + # However, they are needed for legacy implemented interfaces that + # are being treated as partial interfaces, until we remove these. + # http://crbug.com/360435 + implemented_interfaces_include_paths = [ + implemented_interface_info['include_path'] + for implemented_interface_info in implemented_interfaces_info + if implemented_interface_info['is_legacy_treat_as_partial_interface']] + + interface_info.update({ + 'dependencies_full_paths': (partial_interfaces_full_paths + + implemented_interfaces_full_paths), + 'dependencies_include_paths': (partial_interfaces_include_paths + + implemented_interfaces_include_paths), + }) + + # Clean up temporary private information + for interface_info in interfaces_info.itervalues(): + del interface_info['extended_attributes'] + del interface_info['is_legacy_treat_as_partial_interface'] + del interface_info['parent'] + + +################################################################################ + +def main(): + options, args = parse_options() + # args = Input1, Input2, ..., Output + interfaces_info_filename = args.pop() + info_individuals = read_pickle_files(args) + + compute_interfaces_info_overall(info_individuals) + write_pickle_file(interfaces_info_filename, + interfaces_info, + options.write_file_only_if_changed) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/generate_bindings.pl b/chromium/third_party/WebKit/Source/bindings/scripts/generate_bindings.pl deleted file mode 100755 index 68f36800403..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/scripts/generate_bindings.pl +++ /dev/null @@ -1,309 +0,0 @@ -#!/usr/bin/perl -w -# -# Copyright (C) 2005 Apple Computer, Inc. -# Copyright (C) 2006 Anders Carlsson <andersca@mac.com> -# -# This file is part of WebKit -# -# 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. -# - -use strict; - -use File::Path; -use File::Basename; -use Getopt::Long; -use Text::ParseWords; -use Cwd; - -use idl_parser; -use code_generator_v8; -use idl_serializer; - -my @idlDirectories; -my $outputDirectory; -my $preprocessor; -my $verbose; -my $interfaceDependenciesFile; -my $additionalIdlFiles; -my $idlAttributesFile; -my $writeFileOnlyIfChanged; - -GetOptions('include=s@' => \@idlDirectories, - 'outputDir=s' => \$outputDirectory, - 'preprocessor=s' => \$preprocessor, - 'verbose' => \$verbose, - 'interfaceDependenciesFile=s' => \$interfaceDependenciesFile, - 'additionalIdlFiles=s' => \$additionalIdlFiles, - 'idlAttributesFile=s' => \$idlAttributesFile, - 'write-file-only-if-changed=s' => \$writeFileOnlyIfChanged); - -my $targetIdlFile = $ARGV[0]; - -die('Must specify input file.') unless defined($targetIdlFile); -die('Must specify output directory.') unless defined($outputDirectory); - -$targetIdlFile = Cwd::realpath($targetIdlFile); -if ($verbose) { - print "$targetIdlFile\n"; -} -my $targetInterfaceName = fileparse(basename($targetIdlFile), ".idl"); - -my $idlFound = 0; -my @dependencyIdlFiles; -if ($interfaceDependenciesFile) { - # The format of the interface dependencies file: - # - # Window.idl P.idl Q.idl R.idl - # Document.idl S.idl - # Event.idl - # ... - # - # The above indicates that Window.idl depends on P.idl, Q.idl, and R.idl, - # Document.idl depends on S.idl, and Event.idl depends on no IDLs. - # A dependency IDL file (one that is depended on by another IDL, e.g. P.idl - # in the above) does not have its own entry in the dependency file. - open FH, "< $interfaceDependenciesFile" or die "Cannot open $interfaceDependenciesFile\n"; - while (my $line = <FH>) { - my ($idlFile, @followingIdlFiles) = split(/\s+/, $line); - if ($idlFile and basename($idlFile) eq basename($targetIdlFile)) { - $idlFound = 1; - # We sort the dependency IDL files so that the corresponding code is generated - # in a consistent order. This is important for the bindings tests. - @dependencyIdlFiles = sort @followingIdlFiles; - } - } - close FH; - - # $additionalIdlFiles is for IDL files not listed in the interface - # dependencies file, namely generated IDL files for interfaces - # (not partial interfaces), so we need to generate .h and .cpp files. - if (!$idlFound and $additionalIdlFiles) { - my @idlFiles = shellwords($additionalIdlFiles); - $idlFound = grep { $_ and basename($_) eq basename($targetIdlFile) } @idlFiles; - } - - if (!$idlFound) { - # IDL files for dependencies (partial interfaces and interfaces - # implemented elsewhere). We generate empty .h and .cpp files just to - # tell build scripts that outputs have been created. - generateEmptyHeaderAndCpp($targetInterfaceName, $outputDirectory); - exit 0; - } -} - -# Parse the target IDL file. -my $targetParser = idl_parser->new(!$verbose); -my $targetDocument = $targetParser->Parse($targetIdlFile, $preprocessor); - -if ($idlAttributesFile) { - my $idlAttributes = loadIDLAttributes($idlAttributesFile); - checkIDLAttributes($idlAttributes, $targetDocument, basename($targetIdlFile)); -} - -foreach my $idlFile (@dependencyIdlFiles) { - next if $idlFile eq $targetIdlFile; - - my $interfaceName = fileparse(basename($idlFile), ".idl"); - my $parser = idl_parser->new(!$verbose); - my $document = $parser->Parse($idlFile, $preprocessor); - - foreach my $interface (@{$document->interfaces}) { - if (!$interface->isPartial || $interface->name eq $targetInterfaceName) { - my $targetDataNode; - foreach my $interface (@{$targetDocument->interfaces}) { - if ($interface->name eq $targetInterfaceName) { - $targetDataNode = $interface; - last; - } - } - die "Not found an interface ${targetInterfaceName} in ${targetInterfaceName}.idl." unless defined $targetDataNode; - - # Support for attributes of partial interfaces. - foreach my $attribute (@{$interface->attributes}) { - # Record that this attribute is implemented by $interfaceName. - $attribute->extendedAttributes->{"ImplementedBy"} = $interfaceName unless $interface->extendedAttributes->{"LegacyImplementedInBaseClass"}; - - # Add interface-wide extended attributes to each attribute. - applyInterfaceExtendedAttributes($interface, $attribute->extendedAttributes); - - push(@{$targetDataNode->attributes}, $attribute); - } - - # Support for methods of partial interfaces. - foreach my $function (@{$interface->functions}) { - # Record that this method is implemented by $interfaceName. - $function->extendedAttributes->{"ImplementedBy"} = $interfaceName unless $interface->extendedAttributes->{"LegacyImplementedInBaseClass"}; - - # Add interface-wide extended attributes to each method. - applyInterfaceExtendedAttributes($interface, $function->extendedAttributes); - - push(@{$targetDataNode->functions}, $function); - } - - # Support for constants of partial interfaces. - foreach my $constant (@{$interface->constants}) { - # Record that this constant is implemented by $interfaceName. - $constant->extendedAttributes->{"ImplementedBy"} = $interfaceName unless $interface->extendedAttributes->{"LegacyImplementedInBaseClass"}; - - # Add interface-wide extended attributes to each constant. - applyInterfaceExtendedAttributes($interface, $constant->extendedAttributes); - - push(@{$targetDataNode->constants}, $constant); - } - } else { - die "$idlFile is not a dependency of $targetIdlFile. There maybe a bug in the dependency computer (compute_dependencies.py).\n"; - } - } -} - -# Serialize to and from JSON to ensure Perl and Python parsers are equivalent, -# as part of porting compiler to Python. See http://crbug.com/242795 -$targetDocument = deserializeJSON(serializeJSON($targetDocument)); - -# Generate desired output for the target IDL file. -my @interfaceIdlFiles = ($targetDocument->fileName(), @dependencyIdlFiles); -my $codeGenerator = code_generator_v8->new($targetDocument, \@idlDirectories, $preprocessor, $verbose, \@interfaceIdlFiles, $writeFileOnlyIfChanged); -my $interfaces = $targetDocument->interfaces; -foreach my $interface (@$interfaces) { - print "Generating bindings code for IDL interface \"" . $interface->name . "\"...\n" if $verbose; - $codeGenerator->GenerateInterface($interface); - $codeGenerator->WriteData($interface, $outputDirectory); -} - -sub generateEmptyHeaderAndCpp -{ - my ($targetInterfaceName, $outputDirectory) = @_; - - my $headerName = "V8${targetInterfaceName}.h"; - my $cppName = "V8${targetInterfaceName}.cpp"; - my $contents = "/* - This file is generated just to tell build scripts that $headerName and - $cppName are created for ${targetInterfaceName}.idl, and thus - prevent the build scripts from trying to generate $headerName and - $cppName at every build. This file must not be tried to compile. -*/ -"; - open FH, "> ${outputDirectory}/${headerName}" or die "Cannot open $headerName\n"; - print FH $contents; - close FH; - - open FH, "> ${outputDirectory}/${cppName}" or die "Cannot open $cppName\n"; - print FH $contents; - close FH; -} - -sub loadIDLAttributes -{ - my $idlAttributesFile = shift; - - my %idlAttributes; - open FH, "<", $idlAttributesFile or die "Couldn't open $idlAttributesFile: $!"; - while (my $line = <FH>) { - chomp $line; - next if $line =~ /^\s*#/; - next if $line =~ /^\s*$/; - - if ($line =~ /^\s*([^=\s]*)\s*=?\s*(.*)/) { - my $name = $1; - $idlAttributes{$name} = {}; - if ($2) { - foreach my $rightValue (split /\|/, $2) { - $rightValue =~ s/^\s*|\s*$//g; - $rightValue = "VALUE_IS_MISSING" unless $rightValue; - $idlAttributes{$name}{$rightValue} = 1; - } - } else { - $idlAttributes{$name}{"VALUE_IS_MISSING"} = 1; - } - } else { - die "The format of " . basename($idlAttributesFile) . " is wrong: line $.\n"; - } - } - close FH; - - return \%idlAttributes; -} - -sub checkIDLAttributes -{ - my $idlAttributes = shift; - my $document = shift; - my $idlFile = shift; - - foreach my $interface (@{$document->interfaces}) { - checkIfIDLAttributesExists($idlAttributes, $interface->extendedAttributes, $idlFile); - - foreach my $attribute (@{$interface->attributes}) { - checkIfIDLAttributesExists($idlAttributes, $attribute->extendedAttributes, $idlFile); - } - - foreach my $function (@{$interface->functions}) { - checkIfIDLAttributesExists($idlAttributes, $function->extendedAttributes, $idlFile); - foreach my $parameter (@{$function->parameters}) { - checkIfIDLAttributesExists($idlAttributes, $parameter->extendedAttributes, $idlFile); - } - } - } -} - -sub applyInterfaceExtendedAttributes -{ - my $interface = shift; - my $extendedAttributes = shift; - - foreach my $extendedAttributeName (keys %{$interface->extendedAttributes}) { - next if $extendedAttributeName eq "ImplementedAs"; - $extendedAttributes->{$extendedAttributeName} = $interface->extendedAttributes->{$extendedAttributeName}; - } -} - -sub checkIfIDLAttributesExists -{ - my $idlAttributes = shift; - my $extendedAttributes = shift; - my $idlFile = shift; - - my $error; - OUTER: for my $name (keys %$extendedAttributes) { - if (!exists $idlAttributes->{$name}) { - $error = "Invalid IDL attribute [$name] found in $idlFile."; - last; - } - # Check no argument first, since "*" means "some argument (not missing)". - if ($extendedAttributes->{$name} eq "VALUE_IS_MISSING" and not exists $idlAttributes->{$name}{"VALUE_IS_MISSING"}) { - $error = "Missing required argument for IDL attribute [$name] in file $idlFile."; - last; - } - if (exists $idlAttributes->{$name}{"*"}) { - next; - } - for my $rightValue (split /\s*[|&]\s*/, $extendedAttributes->{$name}) { - if (!(exists $idlAttributes->{$name}{$rightValue})) { - $error = "Invalid IDL attribute value [$name=" . $extendedAttributes->{$name} . "] found in $idlFile."; - last OUTER; - } - } - } - if ($error) { - die "IDL ATTRIBUTE CHECKER ERROR: $error -If you want to add a new IDL extended attribute, please add it to: - bindings/IDLExtendedAttributes.txt -and add an explanation to the Blink IDL documentation at: - http://www.chromium.org/blink/webidl/blink-idl-extended-attributes -"; - } -} diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/generate_event_interfaces.py b/chromium/third_party/WebKit/Source/bindings/scripts/generate_event_interfaces.py new file mode 100755 index 00000000000..b222cb4a64b --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/generate_event_interfaces.py @@ -0,0 +1,122 @@ +#!/usr/bin/python +# +# Copyright (C) 2013 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. + +"""Generate event interfaces .in file (EventInterfaces.in). + +The event interfaces .in file contains a list of all Event interfaces, i.e., +all interfaces that inherit from Event, including Event itself, +together with certain extended attributes. + +Paths are in POSIX format, and relative to Source/. + +This list is used in core/ to generate EventFactory and EventNames. +The .in format is documented in build/scripts/in_file.py. +""" + +from optparse import OptionParser +import os +import posixpath +import sys + +from utilities import get_file_contents, read_file_to_list, write_file, get_interface_extended_attributes_from_idl + +EXPORTED_EXTENDED_ATTRIBUTES = ( + 'Conditional', + 'ImplementedAs', + 'RuntimeEnabled', +) +module_path = os.path.dirname(os.path.realpath(__file__)) +source_dir = os.path.normpath(os.path.join(module_path, os.pardir, os.pardir)) + + +def parse_options(): + parser = OptionParser() + parser.add_option('--event-idl-files-list', help='file listing event IDL files') + parser.add_option('--event-interfaces-file', help='output file') + parser.add_option('--write-file-only-if-changed', type='int', help='if true, do not write an output file if it would be identical to the existing one, which avoids unnecessary rebuilds in ninja') + parser.add_option('--suffix', help='specify a suffix to the namespace, i.e., "Modules". Default is None.') + + options, args = parser.parse_args() + if options.event_idl_files_list is None: + parser.error('Must specify a file listing event IDL files using --event-idl-files-list.') + if options.event_interfaces_file is None: + parser.error('Must specify an output file using --event-interfaces-file.') + if options.write_file_only_if_changed is None: + parser.error('Must specify whether file is only written if changed using --write-file-only-if-changed.') + options.write_file_only_if_changed = bool(options.write_file_only_if_changed) + if args: + parser.error('No arguments allowed, but %d given.' % len(args)) + return options + + +def write_event_interfaces_file(event_idl_files, destination_filename, only_if_changed, suffix): + def extended_attribute_string(name, value): + if name == 'RuntimeEnabled': + value += 'Enabled' + return name + '=' + value + + def interface_line(full_path): + relative_path_local, _ = os.path.splitext(os.path.relpath(full_path, source_dir)) + relative_path_posix = relative_path_local.replace(os.sep, posixpath.sep) + + idl_file_contents = get_file_contents(full_path) + extended_attributes = get_interface_extended_attributes_from_idl(idl_file_contents) + extended_attributes_list = [ + extended_attribute_string(name, extended_attributes[name]) + for name in EXPORTED_EXTENDED_ATTRIBUTES + if name in extended_attributes] + + return '%s %s\n' % (relative_path_posix, + ', '.join(extended_attributes_list)) + + lines = ['namespace="Event"\n'] + if suffix: + lines.append('suffix="' + suffix + '"\n') + lines.append('\n') + interface_lines = [interface_line(event_idl_file) + for event_idl_file in event_idl_files] + interface_lines.sort() + lines.extend(interface_lines) + write_file(''.join(lines), destination_filename, only_if_changed) + + +################################################################################ + +def main(): + options = parse_options() + event_idl_files = read_file_to_list(options.event_idl_files_list) + write_event_interfaces_file(event_idl_files, + options.event_interfaces_file, + options.write_file_only_if_changed, + options.suffix) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/generate_global_constructors.py b/chromium/third_party/WebKit/Source/bindings/scripts/generate_global_constructors.py new file mode 100755 index 00000000000..81838fe1865 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/generate_global_constructors.py @@ -0,0 +1,184 @@ +#!/usr/bin/python +# +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Generates interface properties on global objects. + +Concretely these are implemented as "constructor attributes", meaning +"attributes whose name ends with Constructor" (special-cased by code generator), +hence "global constructors" for short. + +For reference on global objects, see: +http://heycam.github.io/webidl/#Global +http://heycam.github.io/webidl/#Exposed + +Design document: http://www.chromium.org/developers/design-documents/idl-build +""" + +import itertools +import optparse +import os +import cPickle as pickle +import re +import sys + +from collections import defaultdict +from utilities import get_file_contents, idl_filename_to_interface_name, read_file_to_list, write_file, get_interface_extended_attributes_from_idl, is_callback_interface_from_idl + +interface_name_to_global_names = {} +global_name_to_constructors = defaultdict(list) + + +HEADER_FORMAT = """// Stub header file for {{idl_basename}} +// Required because the IDL compiler assumes that a corresponding header file +// exists for each IDL file. +""" + +def parse_options(): + parser = optparse.OptionParser() + parser.add_option('--idl-files-list', help='file listing IDL files') + parser.add_option('--global-objects-file', help='pickle file of global objects') + parser.add_option('--write-file-only-if-changed', type='int', help='if true, do not write an output file if it would be identical to the existing one, which avoids unnecessary rebuilds in ninja') + + options, args = parser.parse_args() + + if options.idl_files_list is None: + parser.error('Must specify a file listing IDL files using --idl-files-list.') + if options.global_objects_file is None: + parser.error('Must specify a pickle file of global objects using --global-objects-file.') + if options.write_file_only_if_changed is None: + parser.error('Must specify whether output files are only written if changed using --write-file-only-if-changed.') + options.write_file_only_if_changed = bool(options.write_file_only_if_changed) + + return options, args + + +def flatten_list(iterable): + return list(itertools.chain.from_iterable(iterable)) + + +def interface_name_to_constructors(interface_name): + """Returns constructors for an interface.""" + global_names = interface_name_to_global_names[interface_name] + return flatten_list(global_name_to_constructors[global_name] + for global_name in global_names) + + +def record_global_constructors(idl_filename): + interface_name = idl_filename_to_interface_name(idl_filename) + full_path = os.path.realpath(idl_filename) + idl_file_contents = get_file_contents(full_path) + extended_attributes = get_interface_extended_attributes_from_idl(idl_file_contents) + + # An interface property is produced for every non-callback interface + # that does not have [NoInterfaceObject]. + # Callback interfaces with constants also have interface properties, + # but there are none of these in Blink. + # http://heycam.github.io/webidl/#es-interfaces + if (is_callback_interface_from_idl(idl_file_contents) or + 'NoInterfaceObject' in extended_attributes): + return + + # The [Exposed] extended attribute MUST take an identifier list. Each + # identifier in the list MUST be a global name. An interface or interface + # member the extended attribute applies to will be exposed only on objects + # associated with ECMAScript global environments whose global object + # implements an interface that has a matching global name. + # FIXME: In spec names are comma-separated, but that makes parsing very + # difficult (https://www.w3.org/Bugs/Public/show_bug.cgi?id=24959). + exposed_global_names = extended_attributes.get('Exposed', 'Window').split('&') + new_constructors_list = generate_global_constructors_list(interface_name, extended_attributes) + for exposed_global_name in exposed_global_names: + global_name_to_constructors[exposed_global_name].extend(new_constructors_list) + + +def generate_global_constructors_list(interface_name, extended_attributes): + extended_attributes_list = [ + name + '=' + extended_attributes[name] + for name in 'Conditional', 'PerContextEnabled', 'RuntimeEnabled' + if name in extended_attributes] + if extended_attributes_list: + extended_string = '[%s] ' % ', '.join(extended_attributes_list) + else: + extended_string = '' + + attribute_string = 'attribute {interface_name}Constructor {interface_name}'.format(interface_name=interface_name) + attributes_list = [extended_string + attribute_string] + + # In addition to the usual interface property, for every [NamedConstructor] + # extended attribute on an interface, a corresponding property MUST exist + # on the ECMAScript global object. + # http://heycam.github.io/webidl/#NamedConstructor + if 'NamedConstructor' in extended_attributes: + named_constructor = extended_attributes['NamedConstructor'] + # Extract function name, namely everything before opening '(' + constructor_name = re.sub(r'\(.*', '', named_constructor) + # Note the reduplicated 'ConstructorConstructor' + # FIXME: rename to NamedConstructor + attribute_string = 'attribute %sConstructorConstructor %s' % (interface_name, constructor_name) + attributes_list.append(extended_string + attribute_string) + + return attributes_list + + +def write_global_constructors_partial_interface(interface_name, idl_filename, constructor_attributes_list, only_if_changed): + # FIXME: replace this with a simple Jinja template + lines = (['partial interface %s {\n' % interface_name] + + [' %s;\n' % constructor_attribute + # FIXME: sort by interface name (not first by extended attributes) + for constructor_attribute in sorted(constructor_attributes_list)] + + ['};\n']) + write_file(''.join(lines), idl_filename, only_if_changed) + header_filename = os.path.splitext(idl_filename)[0] + '.h' + idl_basename = os.path.basename(idl_filename) + write_file(HEADER_FORMAT.format(idl_basename=idl_basename), + header_filename, only_if_changed) + + +################################################################################ + +def main(): + options, args = parse_options() + + # Input IDL files are passed in a file, due to OS command line length + # limits. This is generated at GYP time, which is ok b/c files are static. + idl_files = read_file_to_list(options.idl_files_list) + + # Output IDL files (to generate) are passed at the command line, since + # these are in the build directory, which is determined at build time, not + # GYP time. + # These are passed as pairs of GlobalObjectName, GlobalObject.idl + interface_name_idl_filename = [(args[i], args[i + 1]) + for i in range(0, len(args), 2)] + + with open(options.global_objects_file) as global_objects_file: + interface_name_to_global_names.update(pickle.load(global_objects_file)) + + for idl_filename in idl_files: + record_global_constructors(idl_filename) + + # Check for [Exposed] / [Global] mismatch. + known_global_names = frozenset(itertools.chain.from_iterable(interface_name_to_global_names.values())) + exposed_global_names = frozenset(global_name_to_constructors) + if not exposed_global_names.issubset(known_global_names): + unknown_global_names = exposed_global_names.difference(known_global_names) + raise ValueError('The following global names were used in ' + '[Exposed=xxx] but do not match any [Global] / ' + '[PrimaryGlobal] interface: %s' + % list(unknown_global_names)) + + # Write partial interfaces containing constructor attributes for each + # global interface. + for interface_name, idl_filename in interface_name_idl_filename: + constructors = interface_name_to_constructors(interface_name) + write_global_constructors_partial_interface( + interface_name, + idl_filename, + constructors, + options.write_file_only_if_changed) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/global_constructors.gypi b/chromium/third_party/WebKit/Source/bindings/scripts/global_constructors.gypi new file mode 100644 index 00000000000..58073e70923 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/global_constructors.gypi @@ -0,0 +1,73 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# This file is meant to be included into a target to provide an action +# to compute global objects in a component. +# +# To use this, create a gyp target with the following form: +# { +# 'target_name': 'core_global_constructors_idls', +# 'dependencies': [ +# 'component_global_objects', +# ], +# 'variables': { +# 'idl_files': '<(list_of_idl_files)', +# 'global_objects_file': '<(some_dir)/GlobalObjectsComponent.pickle', +# 'global_names_idl_files': [ +# 'GlobalName', +# '<(blink_core_output_dir)/GlobalScopeComponentConstructors.idl', +# # ... +# ], +# 'outputs': [ +# '<@(component_global_constructors_generated_idl_files)', +# '<@(component_global_constructors_generated_header_files)', +# ], +# }, +# 'includes': ['path/to/this/gypi/file'], +# }, +# +# Required variables: +# idl_files - List of .idl files that will be searched in. +# This should *only* contain main IDL files, excluding dependencies and +# testing, which should not appear on global objects. +# global_objects - Pickle file of global objects. +# global_names_idl_files - pairs (GlobalName, Constructors.idl) +# outputs - List of output files. +# Passed as a variable here, included by the template in the action. +# +# Spec: http://heycam.github.io/webidl/#Global +# http://heycam.github.io/webidl/#Exposed +# Design document: http://www.chromium.org/developers/design-documents/idl-build + +{ + 'type': 'none', + 'actions': [{ + 'action_name': 'generate_<(_target_name)', + 'message': 'Generating IDL files for constructors on global objects for <(_target_name)', + 'variables': { + 'idl_files_list': '<|(<(_target_name)_idl_files_list.tmp <@(idl_files))', + }, + 'includes': ['scripts.gypi'], + 'inputs': [ + '<(bindings_scripts_dir)/generate_global_constructors.py', + '<(bindings_scripts_dir)/utilities.py', + '<(idl_files_list)', + '<@(idl_files)', + '<(global_objects_file)', + ], + 'outputs': ['<@(outputs)'], + 'action': [ + 'python', + '<(bindings_scripts_dir)/generate_global_constructors.py', + '--idl-files-list', + '<(idl_files_list)', + '--global-objects-file', + '<(global_objects_file)', + '--write-file-only-if-changed', + '<(write_file_only_if_changed)', + '--', + '<@(global_names_idl_files)', + ], + }], +} diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/global_objects.gypi b/chromium/third_party/WebKit/Source/bindings/scripts/global_objects.gypi new file mode 100644 index 00000000000..fa812ee0a8b --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/global_objects.gypi @@ -0,0 +1,64 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# This file is meant to be included into a target to provide an action +# to compute global objects in a component. +# +# To use this, create a gyp target with the following form: +# { +# 'target_name': 'component_global_objects', +# 'variables': { +# 'idl_files': '<(list_of_idl_files)', +# 'input_files': ['<(some_dir)/GlobalObjectBaseComponent.pickle'], +# 'output_file': '<(some_dir)/GlobalObjectsComponent.pickle', +# }, +# 'includes': ['path/to/this/gypi/file'], +# }, +# +# Required variables: +# idl_files - List of .idl files that will be searched in. +# This should *only* contain main IDL files, excluding dependencies and +# testing, which should not define global objects. +# output_file - Pickle file of output. +# +# Optional variables: +# input_files - List of input pickle files of global objects in base +# components. In this case make sure to include a dependencies section +# in the target to ensure this is generated. +# +# Spec: http://heycam.github.io/webidl/#Global +# Design document: http://www.chromium.org/developers/design-documents/idl-build + +{ + 'type': 'none', + 'actions': [{ + 'action_name': 'compute_<(_target_name)', + 'message': 'Computing global objects for <(_target_name)', + 'variables': { + 'input_files%': [], + 'idl_files_list': '<|(<(_target_name)_idl_files_list.tmp <@(idl_files))', + }, + 'includes': ['scripts.gypi'], + 'inputs': [ + '<(bindings_scripts_dir)/compute_global_objects.py', + '<(bindings_scripts_dir)/utilities.py', + '<(idl_files_list)', + '<@(idl_files)', + ], + 'outputs': [ + '<(output_file)', + ], + 'action': [ + 'python', + '<(bindings_scripts_dir)/compute_global_objects.py', + '--idl-files-list', + '<(idl_files_list)', + '--write-file-only-if-changed', + '<(write_file_only_if_changed)', + '--', + '<@(input_files)', + '<(output_file)', + ], + }], +} diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/idl_compiler.py b/chromium/third_party/WebKit/Source/bindings/scripts/idl_compiler.py new file mode 100755 index 00000000000..6728aff45c1 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/idl_compiler.py @@ -0,0 +1,143 @@ +#!/usr/bin/python +# Copyright (C) 2013 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. + +"""Compile an .idl file to Blink V8 bindings (.h and .cpp files). + +Design doc: http://www.chromium.org/developers/design-documents/idl-compiler +""" + +import abc +from optparse import OptionParser +import os +import cPickle as pickle +import sys + +from code_generator_v8 import CodeGeneratorV8 +from idl_reader import IdlReader +from utilities import write_file + + +def parse_options(): + parser = OptionParser() + parser.add_option('--cache-directory', + help='cache directory, defaults to output directory') + parser.add_option('--output-directory') + parser.add_option('--interfaces-info-file') + parser.add_option('--write-file-only-if-changed', type='int') + # ensure output comes last, so command line easy to parse via regexes + parser.disable_interspersed_args() + + options, args = parser.parse_args() + if options.output_directory is None: + parser.error('Must specify output directory using --output-directory.') + options.write_file_only_if_changed = bool(options.write_file_only_if_changed) + if len(args) != 1: + parser.error('Must specify exactly 1 input file as argument, but %d given.' % len(args)) + idl_filename = os.path.realpath(args[0]) + return options, idl_filename + + +def idl_filename_to_interface_name(idl_filename): + basename = os.path.basename(idl_filename) + interface_name, _ = os.path.splitext(basename) + return interface_name + + +class IdlCompiler(object): + """Abstract Base Class for IDL compilers. + + In concrete classes: + * self.code_generator must be set, implementing generate_code() + (returning a list of output code), and + * compile_file() must be implemented (handling output filenames). + """ + __metaclass__ = abc.ABCMeta + + def __init__(self, output_directory, cache_directory='', + code_generator=None, interfaces_info=None, + interfaces_info_filename='', only_if_changed=False): + """ + Args: + interfaces_info: + interfaces_info dict + (avoids auxiliary file in run-bindings-tests) + interfaces_info_file: filename of pickled interfaces_info + """ + cache_directory = cache_directory or output_directory + self.cache_directory = cache_directory + self.code_generator = code_generator + if interfaces_info_filename: + with open(interfaces_info_filename) as interfaces_info_file: + interfaces_info = pickle.load(interfaces_info_file) + self.interfaces_info = interfaces_info + self.only_if_changed = only_if_changed + self.output_directory = output_directory + self.reader = IdlReader(interfaces_info, cache_directory) + + def compile_and_write(self, idl_filename, output_filenames): + interface_name = idl_filename_to_interface_name(idl_filename) + definitions = self.reader.read_idl_definitions(idl_filename) + output_code_list = self.code_generator.generate_code( + definitions, interface_name) + for output_code, output_filename in zip(output_code_list, + output_filenames): + write_file(output_code, output_filename, self.only_if_changed) + + @abc.abstractmethod + def compile_file(self, idl_filename): + pass + + +class IdlCompilerV8(IdlCompiler): + def __init__(self, *args, **kwargs): + IdlCompiler.__init__(self, *args, **kwargs) + self.code_generator = CodeGeneratorV8(self.interfaces_info, + self.cache_directory) + + def compile_file(self, idl_filename): + interface_name = idl_filename_to_interface_name(idl_filename) + header_filename = os.path.join(self.output_directory, + 'V8%s.h' % interface_name) + cpp_filename = os.path.join(self.output_directory, + 'V8%s.cpp' % interface_name) + self.compile_and_write(idl_filename, (header_filename, cpp_filename)) + + +def main(): + options, idl_filename = parse_options() + idl_compiler = IdlCompilerV8( + options.output_directory, + cache_directory=options.cache_directory, + interfaces_info_filename=options.interfaces_info_file, + only_if_changed=options.write_file_only_if_changed) + idl_compiler.compile_file(idl_filename) + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/idl_definitions.py b/chromium/third_party/WebKit/Source/bindings/scripts/idl_definitions.py new file mode 100644 index 00000000000..50664ba12ef --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/idl_definitions.py @@ -0,0 +1,756 @@ +# Copyright (C) 2013 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. + +"""Blink IDL Intermediate Representation (IR) classes. + +Classes are primarily constructors, which build an IdlDefinitions object +(and various contained objects) from an AST (produced by blink_idl_parser). + +This is in two steps: +* Constructors walk the AST, creating objects. +* Typedef resolution. + +Typedefs are all resolved here, and not stored in IR. + +Typedef resolution uses some auxiliary classes and OOP techniques to make this +a generic call, via the resolve_typedefs() method. + +Class hierarchy (mostly containment, '<' for inheritance): + +IdlDefinitions + IdlCallbackFunction < TypedObject + IdlEnum :: FIXME: remove, just use a dict for enums + IdlInterface + IdlAttribute < TypedObject + IdlConstant < TypedObject + IdlOperation < TypedObject + IdlArgument < TypedObject + IdlException < IdlInterface + (same contents as IdlInterface) + +TypedObject :: mixin for typedef resolution + +Design doc: http://www.chromium.org/developers/design-documents/idl-compiler +""" + +import abc + +from idl_types import IdlType, IdlUnionType + +SPECIAL_KEYWORD_LIST = ['GETTER', 'SETTER', 'DELETER'] +STANDARD_TYPEDEFS = { + # http://www.w3.org/TR/WebIDL/#common-DOMTimeStamp + 'DOMTimeStamp': 'unsigned long long', +} + + +################################################################################ +# TypedObject (mixin for typedef resolution) +################################################################################ + +class TypedObject(object): + """Object with a type, such as an Attribute or Operation (return value). + + The type can be an actual type, or can be a typedef, which must be resolved + before passing data to the code generator. + """ + __metaclass__ = abc.ABCMeta + idl_type = None + + def resolve_typedefs(self, typedefs): + """Resolve typedefs to actual types in the object.""" + # Constructors don't have their own return type, because it's the + # interface itself. + if not self.idl_type: + return + # Need to re-assign self.idl_type, not just mutate idl_type, + # since type(idl_type) may change. + self.idl_type = self.idl_type.resolve_typedefs(typedefs) + + +################################################################################ +# Definitions (main container class) +################################################################################ + +class IdlDefinitions(object): + def __init__(self, node): + """Args: node: AST root node, class == 'File'""" + self.callback_functions = {} + self.dictionaries = {} + self.enumerations = {} + self.interfaces = {} + + node_class = node.GetClass() + if node_class != 'File': + raise ValueError('Unrecognized node class: %s' % node_class) + + typedefs = dict((typedef_name, IdlType(type_name)) + for typedef_name, type_name in + STANDARD_TYPEDEFS.iteritems()) + + children = node.GetChildren() + for child in children: + child_class = child.GetClass() + if child_class == 'Interface': + interface = IdlInterface(child) + self.interfaces[interface.name] = interface + elif child_class == 'Exception': + exception = IdlException(child) + # For simplicity, treat exceptions as interfaces + self.interfaces[exception.name] = exception + elif child_class == 'Typedef': + type_name = child.GetName() + typedefs[type_name] = typedef_node_to_type(child) + elif child_class == 'Enum': + enumeration = IdlEnum(child) + self.enumerations[enumeration.name] = enumeration + elif child_class == 'Callback': + callback_function = IdlCallbackFunction(child) + self.callback_functions[callback_function.name] = callback_function + elif child_class == 'Implements': + # Implements is handled at the interface merging step + pass + elif child_class == 'Dictionary': + dictionary = IdlDictionary(child) + self.dictionaries[dictionary.name] = dictionary + else: + raise ValueError('Unrecognized node class: %s' % child_class) + + # Typedefs are not stored in IR: + # Resolve typedefs with the actual types and then discard the Typedefs. + # http://www.w3.org/TR/WebIDL/#idl-typedefs + self.resolve_typedefs(typedefs) + + def resolve_typedefs(self, typedefs): + for callback_function in self.callback_functions.itervalues(): + callback_function.resolve_typedefs(typedefs) + for interface in self.interfaces.itervalues(): + interface.resolve_typedefs(typedefs) + + def update(self, other): + """Update with additional IdlDefinitions.""" + for interface_name, new_interface in other.interfaces.iteritems(): + if not new_interface.is_partial: + # Add as new interface + self.interfaces[interface_name] = new_interface + continue + + # Merge partial to existing interface + try: + self.interfaces[interface_name].merge(new_interface) + except KeyError: + raise Exception('Tried to merge partial interface for {0}, ' + 'but no existing interface by that name' + .format(interface_name)) + + # Merge callbacks and enumerations + self.enumerations.update(other.enumerations) + self.callback_functions.update(other.callback_functions) + + +################################################################################ +# Callback Functions +################################################################################ + +class IdlCallbackFunction(TypedObject): + def __init__(self, node): + children = node.GetChildren() + num_children = len(children) + if num_children != 2: + raise ValueError('Expected 2 children, got %s' % num_children) + type_node, arguments_node = children + arguments_node_class = arguments_node.GetClass() + if arguments_node_class != 'Arguments': + raise ValueError('Expected Arguments node, got %s' % arguments_node_class) + + self.name = node.GetName() + self.idl_type = type_node_to_type(type_node) + self.arguments = arguments_node_to_arguments(arguments_node) + + def resolve_typedefs(self, typedefs): + TypedObject.resolve_typedefs(self, typedefs) + for argument in self.arguments: + argument.resolve_typedefs(typedefs) + + +################################################################################ +# Dictionary +################################################################################ + +class IdlDictionary(object): + def __init__(self, node): + self.parent = None + self.name = node.GetName() + self.members = [] + for child in node.GetChildren(): + child_class = child.GetClass() + if child_class == 'Inherit': + self.parent = child.GetName() + elif child_class == 'Key': + self.members.append(IdlDictionaryMember(child)) + else: + raise ValueError('Unrecognized node class: %s' % child_class) + + +class IdlDictionaryMember(object): + def __init__(self, node): + self.default_value = None + self.extended_attributes = {} + self.idl_type = None + self.name = node.GetName() + for child in node.GetChildren(): + child_class = child.GetClass() + if child_class == 'Type': + self.idl_type = type_node_to_type(child) + elif child_class == 'Default': + self.default_value = child.GetProperty('VALUE') + elif child_class == 'ExtAttributes': + self.extended_attributes = ext_attributes_node_to_extended_attributes(child) + else: + raise ValueError('Unrecognized node class: %s' % child_class) + + +################################################################################ +# Enumerations +################################################################################ + +class IdlEnum(object): + # FIXME: remove, just treat enums as a dictionary + def __init__(self, node): + self.name = node.GetName() + self.values = [] + for child in node.GetChildren(): + self.values.append(child.GetName()) + + +################################################################################ +# Interfaces and Exceptions +################################################################################ + +class IdlInterface(object): + def __init__(self, node=None): + self.attributes = [] + self.constants = [] + self.constructors = [] + self.custom_constructors = [] + self.extended_attributes = {} + self.operations = [] + self.parent = None + if not node: # Early exit for IdlException.__init__ + return + + self.is_callback = node.GetProperty('CALLBACK') or False + self.is_exception = False + # FIXME: uppercase 'Partial' => 'PARTIAL' in base IDL parser + self.is_partial = node.GetProperty('Partial') or False + self.name = node.GetName() + + children = node.GetChildren() + for child in children: + child_class = child.GetClass() + if child_class == 'Attribute': + self.attributes.append(IdlAttribute(child)) + elif child_class == 'Const': + self.constants.append(IdlConstant(child)) + elif child_class == 'ExtAttributes': + extended_attributes = ext_attributes_node_to_extended_attributes(child) + self.constructors, self.custom_constructors = ( + extended_attributes_to_constructors(extended_attributes)) + clear_constructor_attributes(extended_attributes) + self.extended_attributes = extended_attributes + elif child_class == 'Operation': + self.operations.append(IdlOperation(child)) + elif child_class == 'Inherit': + self.parent = child.GetName() + else: + raise ValueError('Unrecognized node class: %s' % child_class) + + def resolve_typedefs(self, typedefs): + for attribute in self.attributes: + attribute.resolve_typedefs(typedefs) + for constant in self.constants: + constant.resolve_typedefs(typedefs) + for constructor in self.constructors: + constructor.resolve_typedefs(typedefs) + for custom_constructor in self.custom_constructors: + custom_constructor.resolve_typedefs(typedefs) + for operation in self.operations: + operation.resolve_typedefs(typedefs) + + def merge(self, other): + """Merge in another interface's members (e.g., partial interface)""" + self.attributes.extend(other.attributes) + self.constants.extend(other.constants) + self.operations.extend(other.operations) + + +class IdlException(IdlInterface): + # Properly exceptions and interfaces are distinct, and thus should inherit a + # common base class (say, "IdlExceptionOrInterface"). + # However, there is only one exception (DOMException), and new exceptions + # are not expected. Thus it is easier to implement exceptions as a + # restricted subclass of interfaces. + # http://www.w3.org/TR/WebIDL/#idl-exceptions + def __init__(self, node): + # Exceptions are similar to Interfaces, but simpler + IdlInterface.__init__(self) + self.is_callback = False + self.is_exception = True + self.is_partial = False + self.name = node.GetName() + + children = node.GetChildren() + for child in children: + child_class = child.GetClass() + if child_class == 'Attribute': + attribute = IdlAttribute(child) + self.attributes.append(attribute) + elif child_class == 'Const': + self.constants.append(IdlConstant(child)) + elif child_class == 'ExtAttributes': + self.extended_attributes = ext_attributes_node_to_extended_attributes(child) + elif child_class == 'ExceptionOperation': + self.operations.append(IdlOperation.from_exception_operation_node(child)) + else: + raise ValueError('Unrecognized node class: %s' % child_class) + + +################################################################################ +# Attributes +################################################################################ + +class IdlAttribute(TypedObject): + def __init__(self, node): + self.is_read_only = node.GetProperty('READONLY') or False + self.is_static = node.GetProperty('STATIC') or False + self.name = node.GetName() + # Defaults, overridden below + self.idl_type = None + self.extended_attributes = {} + + children = node.GetChildren() + for child in children: + child_class = child.GetClass() + if child_class == 'Type': + self.idl_type = type_node_to_type(child) + elif child_class == 'ExtAttributes': + self.extended_attributes = ext_attributes_node_to_extended_attributes(child) + else: + raise ValueError('Unrecognized node class: %s' % child_class) + + +################################################################################ +# Constants +################################################################################ + +class IdlConstant(TypedObject): + def __init__(self, node): + children = node.GetChildren() + num_children = len(children) + if num_children < 2 or num_children > 3: + raise ValueError('Expected 2 or 3 children, got %s' % num_children) + type_node = children[0] + value_node = children[1] + value_node_class = value_node.GetClass() + if value_node_class != 'Value': + raise ValueError('Expected Value node, got %s' % value_node_class) + + self.name = node.GetName() + # ConstType is more limited than Type, so subtree is smaller and + # we don't use the full type_node_to_type function. + self.idl_type = type_node_inner_to_type(type_node) + self.value = value_node.GetName() + + if num_children == 3: + ext_attributes_node = children[2] + self.extended_attributes = ext_attributes_node_to_extended_attributes(ext_attributes_node) + else: + self.extended_attributes = {} + + +################################################################################ +# Literals +################################################################################ + +class IdlLiteral(object): + def __init__(self, idl_type, value): + self.idl_type = idl_type + self.value = value + self.is_null = False + + def __str__(self): + if self.idl_type == 'DOMString': + return 'String("%s")' % self.value + if self.idl_type == 'integer': + return '%d' % self.value + if self.idl_type == 'float': + return '%g' % self.value + if self.idl_type == 'boolean': + return 'true' if self.value else 'false' + raise ValueError('Unsupported literal type: %s' % self.idl_type) + + +class IdlLiteralNull(IdlLiteral): + def __init__(self): + self.idl_type = 'NULL' + self.value = None + self.is_null = True + + def __str__(self): + return 'nullptr' + + +def default_node_to_idl_literal(node): + # FIXME: This code is unnecessarily complicated due to the rather + # inconsistent way the upstream IDL parser outputs default values. + # http://crbug.com/374178 + idl_type = node.GetProperty('TYPE') + if idl_type == 'DOMString': + value = node.GetProperty('NAME') + if '"' in value or '\\' in value: + raise ValueError('Unsupported string value: %r' % value) + return IdlLiteral(idl_type, value) + if idl_type == 'integer': + return IdlLiteral(idl_type, int(node.GetProperty('NAME'))) + if idl_type == 'float': + return IdlLiteral(idl_type, float(node.GetProperty('VALUE'))) + if idl_type == 'boolean': + return IdlLiteral(idl_type, node.GetProperty('VALUE')) + if idl_type == 'NULL': + return IdlLiteralNull() + raise ValueError('Unrecognized default value type: %s' % idl_type) + + +################################################################################ +# Operations +################################################################################ + +class IdlOperation(TypedObject): + def __init__(self, node=None): + self.arguments = [] + self.extended_attributes = {} + self.specials = [] + self.is_constructor = False + + if not node: + self.is_static = False + return + self.name = node.GetName() # FIXME: should just be: or '' + # FIXME: AST should use None internally + if self.name == '_unnamed_': + self.name = '' + + self.is_static = node.GetProperty('STATIC') or False + property_dictionary = node.GetProperties() + for special_keyword in SPECIAL_KEYWORD_LIST: + if special_keyword in property_dictionary: + self.specials.append(special_keyword.lower()) + + self.idl_type = None + children = node.GetChildren() + for child in children: + child_class = child.GetClass() + if child_class == 'Arguments': + self.arguments = arguments_node_to_arguments(child) + elif child_class == 'Type': + self.idl_type = type_node_to_type(child) + elif child_class == 'ExtAttributes': + self.extended_attributes = ext_attributes_node_to_extended_attributes(child) + else: + raise ValueError('Unrecognized node class: %s' % child_class) + + @classmethod + def from_exception_operation_node(cls, node): + # Needed to handle one case in DOMException.idl: + # // Override in a Mozilla compatible format + # [NotEnumerable] DOMString toString(); + # FIXME: can we remove this? replace with a stringifier? + operation = cls() + operation.name = node.GetName() + children = node.GetChildren() + if len(children) < 1 or len(children) > 2: + raise ValueError('ExceptionOperation node with %s children, expected 1 or 2' % len(children)) + + type_node = children[0] + operation.idl_type = type_node_to_type(type_node) + + if len(children) > 1: + ext_attributes_node = children[1] + operation.extended_attributes = ext_attributes_node_to_extended_attributes(ext_attributes_node) + + return operation + + @classmethod + def constructor_from_arguments_node(cls, name, arguments_node): + constructor = cls() + constructor.name = name + constructor.arguments = arguments_node_to_arguments(arguments_node) + constructor.is_constructor = True + return constructor + + def resolve_typedefs(self, typedefs): + TypedObject.resolve_typedefs(self, typedefs) + for argument in self.arguments: + argument.resolve_typedefs(typedefs) + + +################################################################################ +# Arguments +################################################################################ + +class IdlArgument(TypedObject): + def __init__(self, node): + self.extended_attributes = {} + self.idl_type = None + self.is_optional = node.GetProperty('OPTIONAL') # syntax: (optional T) + self.is_variadic = False # syntax: (T...) + self.name = node.GetName() + self.default_value = None + + children = node.GetChildren() + for child in children: + child_class = child.GetClass() + if child_class == 'Type': + self.idl_type = type_node_to_type(child) + elif child_class == 'ExtAttributes': + self.extended_attributes = ext_attributes_node_to_extended_attributes(child) + elif child_class == 'Argument': + child_name = child.GetName() + if child_name != '...': + raise ValueError('Unrecognized Argument node; expected "...", got "%s"' % child_name) + self.is_variadic = child.GetProperty('ELLIPSIS') or False + elif child_class == 'Default': + self.default_value = default_node_to_idl_literal(child) + else: + raise ValueError('Unrecognized node class: %s' % child_class) + + +def arguments_node_to_arguments(node): + # [Constructor] and [CustomConstructor] without arguments (the bare form) + # have None instead of an arguments node, but have the same meaning as using + # an empty argument list, [Constructor()], so special-case this. + # http://www.w3.org/TR/WebIDL/#Constructor + if node is None: + return [] + return [IdlArgument(argument_node) + for argument_node in node.GetChildren()] + + +################################################################################ +# Extended attributes +################################################################################ + +def ext_attributes_node_to_extended_attributes(node): + """ + Returns: + Dictionary of {ExtAttributeName: ExtAttributeValue}. + Value is usually a string, with three exceptions: + Constructors: value is a list of Arguments nodes, corresponding to + possible signatures of the constructor. + CustomConstructors: value is a list of Arguments nodes, corresponding to + possible signatures of the custom constructor. + NamedConstructor: value is a Call node, corresponding to the single + signature of the named constructor. + """ + # Primarily just make a dictionary from the children. + # The only complexity is handling various types of constructors: + # Constructors and Custom Constructors can have duplicate entries due to + # overloading, and thus are stored in temporary lists. + # However, Named Constructors cannot be overloaded, and thus do not have + # a list. + # FIXME: move Constructor logic into separate function, instead of modifying + # extended attributes in-place. + constructors = [] + custom_constructors = [] + extended_attributes = {} + + def child_node(extended_attribute_node): + children = extended_attribute_node.GetChildren() + if not children: + return None + if len(children) > 1: + raise ValueError('ExtAttributes node with %s children, expected at most 1' % len(children)) + return children[0] + + extended_attribute_node_list = node.GetChildren() + for extended_attribute_node in extended_attribute_node_list: + name = extended_attribute_node.GetName() + child = child_node(extended_attribute_node) + child_class = child and child.GetClass() + if name == 'Constructor': + if child_class and child_class != 'Arguments': + raise ValueError('Constructor only supports Arguments as child, but has child of class: %s' % child_class) + constructors.append(child) + elif name == 'CustomConstructor': + if child_class and child_class != 'Arguments': + raise ValueError('[CustomConstructor] only supports Arguments as child, but has child of class: %s' % child_class) + custom_constructors.append(child) + elif name == 'NamedConstructor': + if child_class and child_class != 'Call': + raise ValueError('[NamedConstructor] only supports Call as child, but has child of class: %s' % child_class) + extended_attributes[name] = child + elif name == 'SetWrapperReferenceTo': + if not child: + raise ValueError('[SetWrapperReferenceTo] requires a child, but has none.') + if child_class != 'Arguments': + raise ValueError('[SetWrapperReferenceTo] only supports Arguments as child, but has child of class: %s' % child_class) + extended_attributes[name] = arguments_node_to_arguments(child) + elif child: + raise ValueError('ExtAttributes node with unexpected children: %s' % name) + else: + value = extended_attribute_node.GetProperty('VALUE') + extended_attributes[name] = value + + # Store constructors and custom constructors in special list attributes, + # which are deleted later. Note plural in key. + if constructors: + extended_attributes['Constructors'] = constructors + if custom_constructors: + extended_attributes['CustomConstructors'] = custom_constructors + + return extended_attributes + + +def extended_attributes_to_constructors(extended_attributes): + """Returns constructors and custom_constructors (lists of IdlOperations). + + Auxiliary function for IdlInterface.__init__. + """ + + constructor_list = extended_attributes.get('Constructors', []) + constructors = [ + IdlOperation.constructor_from_arguments_node('Constructor', arguments_node) + for arguments_node in constructor_list] + + custom_constructor_list = extended_attributes.get('CustomConstructors', []) + custom_constructors = [ + IdlOperation.constructor_from_arguments_node('CustomConstructor', arguments_node) + for arguments_node in custom_constructor_list] + + if 'NamedConstructor' in extended_attributes: + # FIXME: support overloaded named constructors, and make homogeneous + name = 'NamedConstructor' + call_node = extended_attributes['NamedConstructor'] + extended_attributes['NamedConstructor'] = call_node.GetName() + children = call_node.GetChildren() + if len(children) != 1: + raise ValueError('NamedConstructor node expects 1 child, got %s.' % len(children)) + arguments_node = children[0] + named_constructor = IdlOperation.constructor_from_arguments_node('NamedConstructor', arguments_node) + # FIXME: should return named_constructor separately; appended for Perl + constructors.append(named_constructor) + + return constructors, custom_constructors + + +def clear_constructor_attributes(extended_attributes): + # Deletes Constructor*s* (plural), sets Constructor (singular) + if 'Constructors' in extended_attributes: + del extended_attributes['Constructors'] + extended_attributes['Constructor'] = None + if 'CustomConstructors' in extended_attributes: + del extended_attributes['CustomConstructors'] + extended_attributes['CustomConstructor'] = None + + +################################################################################ +# Types +################################################################################ + +def type_node_to_type(node): + children = node.GetChildren() + if len(children) < 1 or len(children) > 2: + raise ValueError('Type node expects 1 or 2 children (type + optional array []), got %s (multi-dimensional arrays are not supported).' % len(children)) + + type_node_child = children[0] + + if len(children) == 2: + array_node = children[1] + array_node_class = array_node.GetClass() + if array_node_class != 'Array': + raise ValueError('Expected Array node as TypeSuffix, got %s node.' % array_node_class) + # FIXME: use IdlArrayType instead of is_array, once have that + is_array = True + else: + is_array = False + + is_nullable = node.GetProperty('NULLABLE') or False # syntax: T? + + return type_node_inner_to_type(type_node_child, is_array=is_array, is_nullable=is_nullable) + + +def type_node_inner_to_type(node, is_array=False, is_nullable=False): + # FIXME: remove is_array and is_nullable once have IdlArrayType and IdlNullableType + node_class = node.GetClass() + # Note Type*r*ef, not Typedef, meaning the type is an identifier, thus + # either a typedef shorthand (but not a Typedef declaration itself) or an + # interface type. We do not distinguish these, and just use the type name. + if node_class in ['PrimitiveType', 'Typeref']: + # unrestricted syntax: unrestricted double | unrestricted float + is_unrestricted = node.GetProperty('UNRESTRICTED') or False + return IdlType(node.GetName(), is_array=is_array, is_nullable=is_nullable, is_unrestricted=is_unrestricted) + elif node_class == 'Any': + return IdlType('any', is_array=is_array, is_nullable=is_nullable) + elif node_class == 'Sequence': + if is_array: + raise ValueError('Arrays of sequences are not supported') + return sequence_node_to_type(node, is_nullable=is_nullable) + elif node_class == 'UnionType': + if is_array: + raise ValueError('Arrays of unions are not supported') + return union_type_node_to_idl_union_type(node, is_nullable=is_nullable) + raise ValueError('Unrecognized node class: %s' % node_class) + + +def sequence_node_to_type(node, is_nullable=False): + children = node.GetChildren() + if len(children) != 1: + raise ValueError('Sequence node expects exactly 1 child, got %s' % len(children)) + sequence_child = children[0] + sequence_child_class = sequence_child.GetClass() + if sequence_child_class != 'Type': + raise ValueError('Unrecognized node class: %s' % sequence_child_class) + element_type = type_node_to_type(sequence_child).base_type + return IdlType(element_type, is_sequence=True, is_nullable=is_nullable) + + +def typedef_node_to_type(node): + children = node.GetChildren() + if len(children) != 1: + raise ValueError('Typedef node with %s children, expected 1' % len(children)) + child = children[0] + child_class = child.GetClass() + if child_class != 'Type': + raise ValueError('Unrecognized node class: %s' % child_class) + return type_node_to_type(child) + + +def union_type_node_to_idl_union_type(node, is_nullable=False): + member_types = [type_node_to_type(member_type_node) + for member_type_node in node.GetChildren()] + return IdlUnionType(member_types, is_nullable=is_nullable) diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/idl_parser.pm b/chromium/third_party/WebKit/Source/bindings/scripts/idl_parser.pm deleted file mode 100644 index a216c242c71..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/scripts/idl_parser.pm +++ /dev/null @@ -1,2222 +0,0 @@ -# -# KDOM IDL parser -# -# Copyright (C) 2005 Nikolas Zimmermann <wildfox@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. -# - -package idl_parser; - -use strict; - -use preprocessor; -use Class::Struct; - -use constant StringToken => 0; -use constant IntegerToken => 1; -use constant FloatToken => 2; -use constant IdentifierToken => 3; -use constant OtherToken => 4; -use constant EmptyToken => 5; - -# Used to represent a parsed IDL document -struct( idlDocument => { - fileName => '$', # file name - callbackFunctions => '@', - enumerations => '@', # All parsed enumerations - interfaces => '@', # All parsed interfaces -}); - -struct( callbackFunction => { - name => '$', - type => '$', - parameters => '@', -}); - -# Used to represent 'interface' blocks -struct( domInterface => { - name => '$', # Class identifier - parent => '$', # Parent class identifier - constants => '@', # List of 'domConstant' - functions => '@', # List of 'domFunction' - attributes => '@', # List of 'domAttribute' - extendedAttributes => '$', # Extended attributes - constructors => '@', # Constructors, list of 'domFunction' - customConstructors => '@', # Custom constructors, list of 'domFunction' - isException => '$', # Used for exception interfaces - isCallback => '$', # Used for callback interfaces - isPartial => '$', # Used for partial interfaces -}); - -# Used to represent domInterface contents -struct( domFunction => { - isStatic => '$', - name => '$', - type => '$', - extendedAttributes => '$', # Extended attributes - specials => '@', # Specials - parameters => '@', # List of 'domParameter' - overloadedIndex => '$', -}); - -# Used to represent domInterface contents -struct( domAttribute => { - type => '$', # Attribute type (including namespace) (string or UnionType) - name => '$', - isNullable => '$', # Is variable type Nullable (T?) - isStatic => '$', - isReadOnly => '$', - getterExceptions => '@', # Possibly raised exceptions. - setterExceptions => '@', # Possibly raised exceptions. - extendedAttributes => '$', # Extended attributes -}); - -# Used to represent a map of 'variable name' <-> 'variable type' -struct( domParameter => { - name => '$', # Variable name - type => '$', # Variable type (string or UnionType) - extendedAttributes => '$', # Extended attributes - isOptional => '$', # Is variable optional (optional T) - isNullable => '$', # Is variable type Nullable (T?) - isVariadic => '$' # Is variable variadic (long... numbers) -}); - -# Used to represent string constants -struct( domConstant => { - name => '$', # DOM Constant identifier - type => '$', # Type of data - value => '$', # Constant value - extendedAttributes => '$', # Extended attributes -}); - -# Used to represent 'enum' definitions -struct( domEnum => { - name => '$', # Enumeration identifier - values => '@', # Enumeration values (list of unique strings) -}); - -struct( Token => { - type => '$', # type of token - value => '$' # value of token -}); - -struct( UnionType => { - unionMemberTypes => '@', # (UnionType or string)[] -}); - -# Maps 'typedef name' -> 'type' -my %typedefs = (); - -sub new { - my $class = shift; - - my $emptyToken = Token->new(); - $emptyToken->type(EmptyToken); - $emptyToken->value("empty"); - - my $self = { - DocumentContent => "", - EmptyToken => $emptyToken, - NextToken => $emptyToken, - Token => $emptyToken, - Line => "", - LineNumber => 1 - }; - return bless $self, $class; -} - -sub assertTokenValue -{ - my $self = shift; - my $token = shift; - my $value = shift; - my $line = shift; - my $msg = "Next token should be " . $value . ", but " . $token->value() . " at " . $self->{Line}; - if (defined ($line)) { - $msg .= " idl_parser.pm:" . $line; - } - die $msg unless $token->value() eq $value; -} - -sub assertTokenType -{ - my $self = shift; - my $token = shift; - my $type = shift; - die "Next token's type should be " . $type . ", but " . $token->type() . " at " . $self->{Line} unless $token->type() eq $type; -} - -sub assertUnexpectedToken -{ - my $self = shift; - my $token = shift; - my $line = shift; - my $msg = "Unexpected token " . $token . " at " . $self->{Line}; - if (defined ($line)) { - $msg .= " idl_parser.pm:" . $line; - } - die $msg; -} - -sub Parse -{ - my $self = shift; - my $fileName = shift; - my $preprocessor = shift; - my $defines = ""; - - my @definitions = (); - - my @lines = applyPreprocessor($fileName, $defines, $preprocessor); - $self->{Line} = $lines[0]; - $self->{DocumentContent} = join(' ', @lines); - - $self->getToken(); - eval { - my $result = $self->parseDefinitions(); - push(@definitions, @{$result}); - - my $next = $self->nextToken(); - $self->assertTokenType($next, EmptyToken); - }; - die $@ . " in $fileName" if $@; - - my $document = idlDocument->new(); - $document->fileName($fileName); - foreach my $definition (@definitions) { - if (ref($definition) eq "domInterface") { - push(@{$document->interfaces}, $definition); - } elsif (ref($definition) eq "domEnum") { - push(@{$document->enumerations}, $definition); - } elsif (ref($definition) eq "callbackFunction") { - push(@{$document->callbackFunctions}, $definition); - } else { - die "Unrecognized IDL definition kind: \"" . ref($definition) . "\""; - } - } - # Sort so output independent of order in IDL file (e.g., for JSON output) - @{$document->callbackFunctions} = sort {$a->name cmp $b->name} @{$document->callbackFunctions}; - @{$document->enumerations} = sort {$a->name cmp $b->name} @{$document->enumerations}; - @{$document->interfaces} = sort {$a->name cmp $b->name} @{$document->interfaces}; - return $document; -} - -sub nextToken -{ - my $self = shift; - return $self->{NextToken}; -} - -sub getToken -{ - my $self = shift; - $self->{Token} = $self->{NextToken}; - $self->{NextToken} = $self->getTokenInternal(); - return $self->{Token}; -} - -my $whitespaceTokenPattern = '^[\t\n\r ]*[\n\r]'; -my $floatTokenPattern = '^(-?(([0-9]+\.[0-9]*|[0-9]*\.[0-9]+)([Ee][+-]?[0-9]+)?|[0-9]+[Ee][+-]?[0-9]+))'; -my $integerTokenPattern = '^(-?[1-9][0-9]*|-?0[Xx][0-9A-Fa-f]+|-?0[0-7]*)'; -my $stringTokenPattern = '^(\"[^\"]*\")'; -my $identifierTokenPattern = '^([A-Z_a-z][0-9A-Z_a-z]*)'; -my $otherTokenPattern = '^(::|\.\.\.|[^\t\n\r 0-9A-Z_a-z])'; - -sub getTokenInternal -{ - my $self = shift; - - if ($self->{DocumentContent} =~ /$whitespaceTokenPattern/) { - $self->{DocumentContent} =~ s/($whitespaceTokenPattern)//; - my $skipped = $1; - $self->{LineNumber}++ while ($skipped =~ /\n/g); - if ($self->{DocumentContent} =~ /^([^\n\r]+)/) { - $self->{Line} = $self->{LineNumber} . ":" . $1; - } else { - $self->{Line} = "Unknown"; - } - } - $self->{DocumentContent} =~ s/^([\t\n\r ]+)//; - if ($self->{DocumentContent} eq "") { - return $self->{EmptyToken}; - } - - my $token = Token->new(); - if ($self->{DocumentContent} =~ /$floatTokenPattern/) { - $token->type(FloatToken); - $token->value($1); - $self->{DocumentContent} =~ s/$floatTokenPattern//; - return $token; - } - if ($self->{DocumentContent} =~ /$integerTokenPattern/) { - $token->type(IntegerToken); - $token->value($1); - $self->{DocumentContent} =~ s/$integerTokenPattern//; - return $token; - } - if ($self->{DocumentContent} =~ /$stringTokenPattern/) { - $token->type(StringToken); - $token->value($1); - $self->{DocumentContent} =~ s/$stringTokenPattern//; - return $token; - } - if ($self->{DocumentContent} =~ /$identifierTokenPattern/) { - $token->type(IdentifierToken); - (my $value = $1) =~ s/^_//; # strip leading underscore, used to strope reserved words - $token->value($value); - $self->{DocumentContent} =~ s/$identifierTokenPattern//; - return $token; - } - if ($self->{DocumentContent} =~ /$otherTokenPattern/) { - $token->type(OtherToken); - $token->value($1); - $self->{DocumentContent} =~ s/$otherTokenPattern//; - return $token; - } - die "Failed in tokenizing at " . $self->{Line}; -} - -sub unquoteString -{ - my $self = shift; - my $quotedString = shift; - if ($quotedString =~ /^"([^"]*)"$/) { - return $1; - } - die "Failed to parse string (" . $quotedString . ") at " . $self->{Line}; -} - -sub typeHasNullableSuffix -{ - my $type = shift; - return $type =~ /\?$/; -} - -sub typeRemoveNullableSuffix -{ - my $type = shift; - $type =~ s/\?$//g; - return $type; -} - -# Promise is not yet in the Web IDL spec but is going to be speced -# as primitive types in the future. -my $nextAttribute_1 = '^(attribute|inherit|readonly)$'; -my $nextPrimitiveType_1 = '^(int|long|short|unsigned)$'; -my $nextPrimitiveType_2 = '^(double|float|unrestricted)$'; -my $nextArgumentList_1 = '^(\(|::|ByteString|DOMString|Promise|Date|\[|any|boolean|byte|double|float|in|int|long|object|octet|optional|sequence|short|unrestricted|unsigned)$'; -my $nextNonAnyType_1 = '^(boolean|byte|double|float|int|long|octet|short|unrestricted|unsigned)$'; -my $nextInterfaceMember_1 = '^(\(|::|ByteString|DOMString|Promise|Date|any|attribute|boolean|byte|creator|deleter|double|float|getter|inherit|int|legacycaller|long|object|octet|readonly|sequence|serializer|setter|short|static|stringifier|unrestricted|unsigned|void)$'; -my $nextOptionalIteratorInterfaceOrObject_1 = '^(;|=)$'; -my $nextAttributeOrOperationOrIterator_1 = '^(static|stringifier)$'; -my $nextAttributeOrOperationOrIterator_2 = '^(\(|::|ByteString|DOMString|Promise|Date|any|boolean|byte|creator|deleter|double|float|getter|int|legacycaller|long|object|octet|sequence|setter|short|unrestricted|unsigned|void)$'; -my $nextUnrestrictedFloatType_1 = '^(double|float)$'; -my $nextExtendedAttributeRest3_1 = '^(\,|::|\])$'; -my $nextExceptionField_1 = '^(\(|::|ByteString|DOMString|Promise|Date|any|boolean|byte|double|float|int|long|object|octet|sequence|short|unrestricted|unsigned)$'; -my $nextType_1 = '^(::|ByteString|DOMString|Promise|Date|any|boolean|byte|double|float|int|long|object|octet|sequence|short|unrestricted|unsigned)$'; -my $nextSpecials_1 = '^(creator|deleter|getter|legacycaller|setter)$'; -my $nextDefinitions_1 = '^(::|callback|dictionary|enum|exception|interface|partial|typedef)$'; -my $nextExceptionMembers_1 = '^(\(|::|ByteString|DOMString|Promise|Date|\[|any|boolean|byte|const|double|float|int|long|object|octet|optional|sequence|short|unrestricted|unsigned)$'; -my $nextAttributeRest_1 = '^(attribute|readonly)$'; -my $nextInterfaceMembers_1 = '^(\(|::|ByteString|DOMString|Promise|Date|any|attribute|boolean|byte|const|creator|deleter|double|float|getter|inherit|int|legacycaller|long|object|octet|readonly|sequence|serializer|setter|short|static|stringifier|unrestricted|unsigned|void)$'; -my $nextSingleType_1 = '^(::|ByteString|DOMString|Promise|Date|boolean|byte|double|float|int|long|object|octet|sequence|short|unrestricted|unsigned)$'; -my $nextArgumentName_1 = '^(attribute|callback|const|creator|deleter|dictionary|enum|exception|getter|implements|inherit|interface|legacycaller|partial|serializer|setter|static|stringifier|typedef|unrestricted)$'; -my $nextConstValue_1 = '^(false|true)$'; -my $nextConstValue_2 = '^(-|Infinity|NaN)$'; -my $nextDefinition_1 = '^(callback|interface)$'; -my $nextAttributeOrOperationRest_1 = '^(\(|::|ByteString|DOMString|Promise|Date|any|boolean|byte|double|float|int|long|object|octet|sequence|short|unrestricted|unsigned|void)$'; -my $nextUnsignedIntegerType_1 = '^(int|long|short)$'; -my $nextDefaultValue_1 = '^(-|Infinity|NaN|false|null|true)$'; - - -sub parseDefinitions -{ - my $self = shift; - my @definitions = (); - - while (1) { - my $extendedAttributeList = $self->parseExtendedAttributeListAllowEmpty(); - my $next = $self->nextToken(); - my $definition; - if ($next->type() == IdentifierToken || $next->value() =~ /$nextDefinitions_1/) { - $definition = $self->parseDefinition($extendedAttributeList); - } else { - last; - } - if (defined ($definition)) { - push(@definitions, $definition); - } - } - $self->applyTypedefs(\@definitions); - return \@definitions; -} - -sub applyTypedefs -{ - my $self = shift; - my $definitions = shift; - - if (!%typedefs) { - return; - } - foreach my $definition (@$definitions) { - if (ref($definition) eq "domInterface") { - foreach my $constant (@{$definition->constants}) { - $self->applyTypedefsForTypedObject($constant); - } - foreach my $attribute (@{$definition->attributes}) { - $self->applyTypedefsForTypedObject($attribute); - } - foreach my $function (@{$definition->functions}, @{$definition->constructors}, @{$definition->customConstructors}) { - $self->applyTypedefsForTypedObject($function); - foreach my $parameter (@{$function->parameters}) { - $self->applyTypedefsForTypedObject($parameter); - } - } - } - } -} - -sub applyTypedefsForTypedObject -{ - my $self = shift; - my $typedObject = shift; - - if (!defined ($typedObject->type)) { - return; - } - - my $type = $typedObject->type; - $type =~ s/[\?\[\]]+$//g; - my $typeSuffix = $typedObject->type; - $typeSuffix =~ s/^[^\?\[\]]+//g; - if (exists $typedefs{$type}) { - $typedObject->type($typedefs{$type} . $typeSuffix); - } - - # Handle union types, sequences and etc. - foreach my $name (%typedefs) { - if (!exists $typedefs{$name}) { - next; - } - my $regex = '\\b' . $name . '\\b'; - my $replacement = $typedefs{$name}; - my $type = $typedObject->type; - $type =~ s/($regex)/$replacement/g; - $typedObject->type($type); - } -} - -sub parseDefinition -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() =~ /$nextDefinition_1/) { - return $self->parseCallbackOrInterface($extendedAttributeList); - } - if ($next->value() eq "partial") { - return $self->parsePartial($extendedAttributeList); - } - if ($next->value() eq "dictionary") { - return $self->parseDictionary($extendedAttributeList); - } - if ($next->value() eq "exception") { - return $self->parseException($extendedAttributeList); - } - if ($next->value() eq "enum") { - return $self->parseEnum($extendedAttributeList); - } - if ($next->value() eq "typedef") { - return $self->parseTypedef($extendedAttributeList); - } - if ($next->type() == IdentifierToken || $next->value() eq "::") { - return $self->parseImplementsStatement($extendedAttributeList); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseCallbackOrInterface -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() eq "callback") { - $self->assertTokenValue($self->getToken(), "callback", __LINE__); - return $self->parseCallbackRestOrInterface($extendedAttributeList); - } - if ($next->value() eq "interface") { - return $self->parseInterface($extendedAttributeList); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseCallbackRestOrInterface -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() eq "interface") { - my $interface = $self->parseInterface($extendedAttributeList); - $interface->isCallback(1); - return $interface; - } - if ($next->type() == IdentifierToken) { - return $self->parseCallbackRest($extendedAttributeList); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseInterface -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() eq "interface") { - my $interface = domInterface->new(); - $self->assertTokenValue($self->getToken(), "interface", __LINE__); - my $interfaceNameToken = $self->getToken(); - $self->assertTokenType($interfaceNameToken, IdentifierToken); - $interface->name($interfaceNameToken->value()); - $interface->parent($self->parseInheritance()); - $self->assertTokenValue($self->getToken(), "{", __LINE__); - my $interfaceMembers = $self->parseInterfaceMembers(); - $self->assertTokenValue($self->getToken(), "}", __LINE__); - $self->assertTokenValue($self->getToken(), ";", __LINE__); - applyMemberList($interface, $interfaceMembers); - applyExtendedAttributeList($interface, $extendedAttributeList); - return $interface; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parsePartial -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() eq "partial") { - $self->assertTokenValue($self->getToken(), "partial", __LINE__); - return $self->parsePartialDefinition($extendedAttributeList); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parsePartialDefinition -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() eq "interface") { - my $interface = $self->parseInterface($extendedAttributeList); - $interface->isPartial(1); - return $interface; - } - if ($next->value() eq "dictionary") { - return $self->parsePartialDictionary($extendedAttributeList); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parsePartialInterface -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() eq "interface") { - $self->assertTokenValue($self->getToken(), "interface", __LINE__); - $self->assertTokenType($self->getToken(), IdentifierToken); - $self->assertTokenValue($self->getToken(), "{", __LINE__); - $self->parseInterfaceMembers(); - $self->assertTokenValue($self->getToken(), "}", __LINE__); - $self->assertTokenValue($self->getToken(), ";", __LINE__); - return; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseInterfaceMembers -{ - my $self = shift; - my @interfaceMembers = (); - - while (1) { - my $extendedAttributeList = $self->parseExtendedAttributeListAllowEmpty(); - my $next = $self->nextToken(); - my $interfaceMember; - if ($next->type() == IdentifierToken || $next->value() =~ /$nextInterfaceMembers_1/) { - $interfaceMember = $self->parseInterfaceMember($extendedAttributeList); - } else { - last; - } - if (defined $interfaceMember) { - push(@interfaceMembers, $interfaceMember); - } - } - return \@interfaceMembers; -} - -sub parseInterfaceMember -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() eq "const") { - return $self->parseConst($extendedAttributeList); - } - if ($next->type() == IdentifierToken || $next->value() =~ /$nextInterfaceMember_1/) { - return $self->parseAttributeOrOperationOrIterator($extendedAttributeList); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseDictionary -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() eq "dictionary") { - $self->assertTokenValue($self->getToken(), "dictionary", __LINE__); - $self->assertTokenType($self->getToken(), IdentifierToken); - $self->parseInheritance(); - $self->assertTokenValue($self->getToken(), "{", __LINE__); - $self->parseDictionaryMembers(); - $self->assertTokenValue($self->getToken(), "}", __LINE__); - $self->assertTokenValue($self->getToken(), ";", __LINE__); - return; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseDictionaryMembers -{ - my $self = shift; - - while (1) { - my $extendedAttributeList = $self->parseExtendedAttributeListAllowEmpty(); - my $next = $self->nextToken(); - if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) { - $self->parseDictionaryMember($extendedAttributeList); - } else { - last; - } - } -} - -sub parseDictionaryMember -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) { - $self->parseType(); - $self->assertTokenType($self->getToken(), IdentifierToken); - $self->parseDefault(); - $self->assertTokenValue($self->getToken(), ";", __LINE__); - return; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parsePartialDictionary -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "dictionary") { - $self->assertTokenValue($self->getToken(), "dictionary", __LINE__); - $self->assertTokenType($self->getToken(), IdentifierToken); - $self->assertTokenValue($self->getToken(), "{", __LINE__); - $self->parseDictionaryMembers(); - $self->assertTokenValue($self->getToken(), "}", __LINE__); - $self->assertTokenValue($self->getToken(), ";", __LINE__); - return; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseDefault -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "=") { - $self->assertTokenValue($self->getToken(), "=", __LINE__); - return $self->parseDefaultValue(); - } -} - -sub parseDefaultValue -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->type() == FloatToken || $next->type() == IntegerToken || $next->value() =~ /$nextDefaultValue_1/) { - return $self->parseConstValue(); - } - if ($next->type() == StringToken) { - return $self->getToken()->value(); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseException -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() eq "exception") { - my $interface = domInterface->new(); - $self->assertTokenValue($self->getToken(), "exception", __LINE__); - my $exceptionNameToken = $self->getToken(); - $self->assertTokenType($exceptionNameToken, IdentifierToken); - $interface->name($exceptionNameToken->value()); - $interface->isException(1); - $interface->parent($self->parseInheritance()); - $self->assertTokenValue($self->getToken(), "{", __LINE__); - my $exceptionMembers = $self->parseExceptionMembers(); - $self->assertTokenValue($self->getToken(), "}", __LINE__); - $self->assertTokenValue($self->getToken(), ";", __LINE__); - applyMemberList($interface, $exceptionMembers); - applyExtendedAttributeList($interface, $extendedAttributeList); - return $interface; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseExceptionMembers -{ - my $self = shift; - my @members = (); - - while (1) { - my $next = $self->nextToken(); - if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionMembers_1/) { - my $extendedAttributeList = $self->parseExtendedAttributeListAllowEmpty(); - #my $member = $self->parseExceptionMember($extendedAttributeList); - my $member = $self->parseInterfaceMember($extendedAttributeList); - if (defined ($member)) { - push(@members, $member); - } - } else { - last; - } - } - return \@members; -} - -sub parseInheritance -{ - my $self = shift; - my $parent; - - my $next = $self->nextToken(); - if ($next->value() eq ":") { - $self->assertTokenValue($self->getToken(), ":", __LINE__); - $parent = $self->parseScopedName(); - } - return $parent; -} - -sub parseEnum -{ - my $self = shift; - my $extendedAttributeList = shift; # ignored: Extended attributes are not applicable to enumerations - - my $next = $self->nextToken(); - if ($next->value() eq "enum") { - my $enum = domEnum->new(); - $self->assertTokenValue($self->getToken(), "enum", __LINE__); - my $enumNameToken = $self->getToken(); - $self->assertTokenType($enumNameToken, IdentifierToken); - $enum->name($enumNameToken->value()); - $self->assertTokenValue($self->getToken(), "{", __LINE__); - push(@{$enum->values}, @{$self->parseEnumValueList()}); - $self->assertTokenValue($self->getToken(), "}", __LINE__); - $self->assertTokenValue($self->getToken(), ";", __LINE__); - return $enum; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseEnumValueList -{ - my $self = shift; - my @values = (); - my $next = $self->nextToken(); - if ($next->type() == StringToken) { - my $enumValueToken = $self->getToken(); - $self->assertTokenType($enumValueToken, StringToken); - my $enumValue = $self->unquoteString($enumValueToken->value()); - push(@values, $enumValue); - push(@values, @{$self->parseEnumValues()}); - return \@values; - } - # value list must be non-empty - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseEnumValues -{ - my $self = shift; - my @values = (); - my $next = $self->nextToken(); - if ($next->value() eq ",") { - $self->assertTokenValue($self->getToken(), ",", __LINE__); - my $enumValueToken = $self->getToken(); - $self->assertTokenType($enumValueToken, StringToken); - my $enumValue = $self->unquoteString($enumValueToken->value()); - push(@values, $enumValue); - push(@values, @{$self->parseEnumValues()}); - return \@values; - } - return \@values; # empty list (end of enumeration-values) -} - -sub parseCallbackRest -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->type() == IdentifierToken) { - my $callback = callbackFunction->new(); - my $name = $self->getToken(); - $self->assertTokenType($name, IdentifierToken); - $callback->name($name->value()); - $self->assertTokenValue($self->getToken(), "=", __LINE__); - $callback->type($self->parseReturnType()); - $self->assertTokenValue($self->getToken(), "(", __LINE__); - $callback->parameters($self->parseArgumentList()); - $self->assertTokenValue($self->getToken(), ")", __LINE__); - $self->assertTokenValue($self->getToken(), ";", __LINE__); - return $callback; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseTypedef -{ - my $self = shift; - my $extendedAttributeList = shift; - die "Extended attributes are not applicable to typedefs themselves: " . $self->{Line} if %{$extendedAttributeList}; - - my $next = $self->nextToken(); - if ($next->value() eq "typedef") { - $self->assertTokenValue($self->getToken(), "typedef", __LINE__); - my $typedef = $self->parseType(); - my $nameToken = $self->getToken(); - $self->assertTokenType($nameToken, IdentifierToken); - $self->assertTokenValue($self->getToken(), ";", __LINE__); - my $name = $nameToken->value(); - die "typedef redefinition for " . $name . " at " . $self->{Line} if (exists $typedefs{$name} && $typedef ne $typedefs{$name}); - $typedefs{$name} = $typedef; - return; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseImplementsStatement -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->type() == IdentifierToken) { - $self->parseScopedName(); - $self->assertTokenValue($self->getToken(), "implements", __LINE__); - $self->parseScopedName(); - $self->assertTokenValue($self->getToken(), ";", __LINE__); - return; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseConst -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() eq "const") { - my $newDataNode = domConstant->new(); - $self->assertTokenValue($self->getToken(), "const", __LINE__); - $newDataNode->type($self->parseConstType()); - my $constNameToken = $self->getToken(); - $self->assertTokenType($constNameToken, IdentifierToken); - $newDataNode->name($constNameToken->value()); - $self->assertTokenValue($self->getToken(), "=", __LINE__); - $newDataNode->value($self->parseConstValue()); - $self->assertTokenValue($self->getToken(), ";", __LINE__); - $newDataNode->extendedAttributes($extendedAttributeList); - return $newDataNode; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseConstValue -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() =~ /$nextConstValue_1/) { - return $self->parseBooleanLiteral(); - } - if ($next->value() eq "null") { - $self->assertTokenValue($self->getToken(), "null", __LINE__); - return "null"; - } - if ($next->type() == FloatToken || $next->value() =~ /$nextConstValue_2/) { - return $self->parseFloatLiteral(); - } - # backward compatibility - if ($next->type() == StringToken) { - return $self->getToken()->value(); - } - if ($next->type() == IntegerToken) { - return $self->getToken()->value(); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseBooleanLiteral -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "true") { - $self->assertTokenValue($self->getToken(), "true", __LINE__); - return "true"; - } - if ($next->value() eq "false") { - $self->assertTokenValue($self->getToken(), "false", __LINE__); - return "false"; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseFloatLiteral -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "-") { - $self->assertTokenValue($self->getToken(), "-", __LINE__); - $self->assertTokenValue($self->getToken(), "Infinity", __LINE__); - return "-Infinity"; - } - if ($next->value() eq "Infinity") { - $self->assertTokenValue($self->getToken(), "Infinity", __LINE__); - return "Infinity"; - } - if ($next->value() eq "NaN") { - $self->assertTokenValue($self->getToken(), "NaN", __LINE__); - return "NaN"; - } - if ($next->type() == FloatToken) { - return $self->getToken()->value(); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseAttributeOrOperationOrIterator -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() eq "serializer") { - return $self->parseSerializer($extendedAttributeList); - } - if ($next->value() =~ /$nextAttributeOrOperationOrIterator_1/) { - my $qualifier = $self->parseQualifier(); - my $newDataNode = $self->parseAttributeOrOperationRest($extendedAttributeList); - if (defined($newDataNode) && $qualifier eq "static") { - $newDataNode->isStatic(1); - } - return $newDataNode; - } - if ($next->value() =~ /$nextAttribute_1/) { - return $self->parseAttribute($extendedAttributeList); - } - if ($next->type() == IdentifierToken || $next->value() =~ /$nextAttributeOrOperationOrIterator_2/) { - return $self->parseOperationOrIterator($extendedAttributeList); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseSerializer -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() eq "serializer") { - $self->assertTokenValue($self->getToken(), "serializer", __LINE__); - return $self->parseSerializerRest($extendedAttributeList); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseSerializerRest -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() eq "=") { - $self->assertTokenValue($self->getToken(), "=", __LINE__); - return $self->parseSerializationPattern($extendedAttributeList); - } - if ($next->type() == IdentifierToken || $next->value() eq "(") { - return $self->parseOperationRest($extendedAttributeList); - } -} - -sub parseSerializationPattern -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() eq "{") { - $self->assertTokenValue($self->getToken(), "{", __LINE__); - $self->parseSerializationPatternMap(); - $self->assertTokenValue($self->getToken(), "}", __LINE__); - return; - } - if ($next->value() eq "[") { - $self->assertTokenValue($self->getToken(), "[", __LINE__); - $self->parseSerializationPatternList(); - $self->assertTokenValue($self->getToken(), "]", __LINE__); - return; - } - if ($next->type() == IdentifierToken) { - $self->assertTokenType($self->getToken(), IdentifierToken); - return; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseSerializationPatternMap -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "getter") { - $self->assertTokenValue($self->getToken(), "getter", __LINE__); - return; - } - if ($next->value() eq "inherit") { - $self->assertTokenValue($self->getToken(), "inherit", __LINE__); - $self->parseIdentifiers(); - return; - } - if ($next->type() == IdentifierToken) { - $self->assertTokenType($self->getToken(), IdentifierToken); - $self->parseIdentifiers(); - } -} - -sub parseSerializationPatternList -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "getter") { - $self->assertTokenValue($self->getToken(), "getter", __LINE__); - return; - } - if ($next->type() == IdentifierToken) { - $self->assertTokenType($self->getToken(), IdentifierToken); - $self->parseIdentifiers(); - } -} - -sub parseIdentifiers -{ - my $self = shift; - my @idents = (); - - while (1) { - my $next = $self->nextToken(); - if ($next->value() eq ",") { - $self->assertTokenValue($self->getToken(), ",", __LINE__); - my $token = $self->getToken(); - $self->assertTokenType($token, IdentifierToken); - push(@idents, $token->value()); - } else { - last; - } - } - return \@idents; -} - -sub parseQualifier -{ - my $self = shift; - - my $next = $self->nextToken(); - if ($next->value() eq "static") { - $self->assertTokenValue($self->getToken(), "static", __LINE__); - return "static"; - } - if ($next->value() eq "stringifier") { - $self->assertTokenValue($self->getToken(), "stringifier", __LINE__); - return "stringifier"; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseAttributeOrOperationRest -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() =~ /$nextAttributeRest_1/) { - return $self->parseAttributeRest($extendedAttributeList); - } - if ($next->value() eq ";") { - $self->assertTokenValue($self->getToken(), ";", __LINE__); - return; - } - if ($next->type() == IdentifierToken || $next->value() =~ /$nextAttributeOrOperationRest_1/) { - my $returnType = $self->parseReturnType(); - my $function = $self->parseOperationRest($extendedAttributeList); - if (defined ($function)) { - $function->type($returnType); - } - return $function; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseAttribute -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() =~ /$nextAttribute_1/) { - $self->parseInherit(); - return $self->parseAttributeRest($extendedAttributeList); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseAttributeRest -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() =~ /$nextAttributeRest_1/) { - my $newDataNode = domAttribute->new(); - if ($self->parseReadOnly()) { - $newDataNode->isReadOnly(1); - } - $self->assertTokenValue($self->getToken(), "attribute", __LINE__); - my $type = $self->parseType(); - $newDataNode->isNullable(typeHasNullableSuffix($type)); - # Remove all "?" in the type declaration, e.g. "double?" -> "double". - $newDataNode->type(typeRemoveNullableSuffix($type)); - my $token = $self->getToken(); - $self->assertTokenType($token, IdentifierToken); - $newDataNode->name($token->value()); - $self->assertTokenValue($self->getToken(), ";", __LINE__); - # CustomConstructor may also be used on attributes. - if (defined $extendedAttributeList->{"CustomConstructors"}) { - delete $extendedAttributeList->{"CustomConstructors"}; - $extendedAttributeList->{"CustomConstructor"} = "VALUE_IS_MISSING"; - } - $newDataNode->extendedAttributes($extendedAttributeList); - return $newDataNode; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseInherit -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "inherit") { - $self->assertTokenValue($self->getToken(), "inherit", __LINE__); - return 1; - } - return 0; -} - -sub parseReadOnly -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "readonly") { - $self->assertTokenValue($self->getToken(), "readonly", __LINE__); - return 1; - } - return 0; -} - -sub parseOperationOrIterator -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() =~ /$nextSpecials_1/) { - return $self->parseSpecialOperation($extendedAttributeList); - } - if ($next->type() == IdentifierToken || $next->value() =~ /$nextAttributeOrOperationRest_1/) { - my $returnType = $self->parseReturnType(); - my $interface = $self->parseOperationOrIteratorRest($extendedAttributeList); - if (defined ($interface)) { - $interface->type($returnType); - } - return $interface; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseSpecialOperation -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() =~ /$nextSpecials_1/) { - my @specials = (); - push(@specials, @{$self->parseSpecials()}); - my $returnType = $self->parseReturnType(); - my $function = $self->parseOperationRest($extendedAttributeList); - if (defined ($function)) { - $function->type($returnType); - $function->specials(\@specials); - } - return $function; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseSpecials -{ - my $self = shift; - my @specials = (); - - while (1) { - my $next = $self->nextToken(); - if ($next->value() =~ /$nextSpecials_1/) { - push(@specials, $self->parseSpecial()); - } else { - last; - } - } - return \@specials; -} - -sub parseSpecial -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "getter") { - $self->assertTokenValue($self->getToken(), "getter", __LINE__); - return "getter"; - } - if ($next->value() eq "setter") { - $self->assertTokenValue($self->getToken(), "setter", __LINE__); - return "setter"; - } - if ($next->value() eq "creator") { - $self->assertTokenValue($self->getToken(), "creator", __LINE__); - return "creator"; - } - if ($next->value() eq "deleter") { - $self->assertTokenValue($self->getToken(), "deleter", __LINE__); - return "deleter"; - } - if ($next->value() eq "legacycaller") { - $self->assertTokenValue($self->getToken(), "legacycaller", __LINE__); - return "legacycaller"; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseOperationOrIteratorRest -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() eq "iterator") { - return $self->parseIteratorRest($extendedAttributeList); - } - if ($next->type() == IdentifierToken || $next->value() eq "(") { - return $self->parseOperationRest($extendedAttributeList); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseIteratorRest -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() eq "iterator") { - $self->assertTokenValue($self->getToken(), "iterator", __LINE__); - $self->parseOptionalIteratorInterfaceOrObject($extendedAttributeList); - $self->assertTokenValue($self->getToken(), ";", __LINE__); - return; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseOptionalIteratorInterfaceOrObject -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() =~ /$nextOptionalIteratorInterfaceOrObject_1/) { - return $self->parseOptionalIteratorInterface($extendedAttributeList); - } - if ($next->value() eq "object") { - $self->assertTokenValue($self->getToken(), "object", __LINE__); - return; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseOptionalIteratorInterface -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() eq "=") { - $self->assertTokenValue($self->getToken(), "=", __LINE__); - $self->assertTokenType($self->getToken(), IdentifierToken); - } -} - -sub parseOperationRest -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->type() == IdentifierToken || $next->value() eq "(") { - my $newDataNode = domFunction->new(); - my $name = $self->parseOptionalIdentifier(); - $newDataNode->name($name); - $self->assertTokenValue($self->getToken(), "(", __LINE__); - push(@{$newDataNode->parameters}, @{$self->parseArgumentList()}); - $self->assertTokenValue($self->getToken(), ")", __LINE__); - $self->assertTokenValue($self->getToken(), ";", __LINE__); - $newDataNode->extendedAttributes($extendedAttributeList); - return $newDataNode; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseOptionalIdentifier -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->type() == IdentifierToken) { - my $token = $self->getToken(); - return $token->value(); - } - return ""; -} - -sub parseArgumentList -{ - my $self = shift; - my @arguments = (); - - my $next = $self->nextToken(); - if ($next->type() == IdentifierToken || $next->value() =~ /$nextArgumentList_1/) { - push(@arguments, $self->parseArgument()); - push(@arguments, @{$self->parseArguments()}); - } - return \@arguments; -} - -sub parseArguments -{ - my $self = shift; - my @arguments = (); - - while (1) { - my $next = $self->nextToken(); - if ($next->value() eq ",") { - $self->assertTokenValue($self->getToken(), ",", __LINE__); - push(@arguments, $self->parseArgument()); - } else { - last; - } - } - return \@arguments; -} - -sub parseArgument -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->type() == IdentifierToken || $next->value() =~ /$nextArgumentList_1/) { - my $extendedAttributeList = $self->parseExtendedAttributeListAllowEmpty(); - my $argument = $self->parseOptionalOrRequiredArgument($extendedAttributeList); - return $argument; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseOptionalOrRequiredArgument -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $paramDataNode = domParameter->new(); - $paramDataNode->extendedAttributes($extendedAttributeList); - - my $next = $self->nextToken(); - if ($next->value() eq "optional") { - $self->assertTokenValue($self->getToken(), "optional", __LINE__); - my $type = $self->parseType(); - # domDataNode can only consider last "?". - $paramDataNode->isNullable(typeHasNullableSuffix($type)); - # Remove all "?" if exists, e.g. "object?[]?" -> "object[]". - $paramDataNode->type(typeRemoveNullableSuffix($type)); - $paramDataNode->isOptional(1); - $paramDataNode->name($self->parseArgumentName()); - $self->parseDefault(); - return $paramDataNode; - } - if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) { - my $type = $self->parseType(); - # domDataNode can only consider last "?". - $paramDataNode->isNullable(typeHasNullableSuffix($type)); - # Remove all "?" if exists, e.g. "object?[]?" -> "object[]". - $paramDataNode->type(typeRemoveNullableSuffix($type)); - $paramDataNode->isOptional(0); - $paramDataNode->isVariadic($self->parseEllipsis()); - $paramDataNode->name($self->parseArgumentName()); - return $paramDataNode; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseArgumentName -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() =~ /$nextArgumentName_1/) { - return $self->parseArgumentNameKeyword(); - } - if ($next->type() == IdentifierToken) { - return $self->getToken()->value(); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseEllipsis -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "...") { - $self->assertTokenValue($self->getToken(), "...", __LINE__); - return 1; - } - return 0; -} - -sub parseExceptionMember -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->value() eq "const") { - return $self->parseConst($extendedAttributeList); - } - if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) { - return $self->parseExceptionField($extendedAttributeList); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseExceptionField -{ - my $self = shift; - my $extendedAttributeList = shift; - - my $next = $self->nextToken(); - if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) { - my $newDataNode = domAttribute->new(); - $newDataNode->type("attribute"); - $newDataNode->isReadOnly(1); - $newDataNode->type($self->parseType()); - my $token = $self->getToken(); - $self->assertTokenType($token, IdentifierToken); - $newDataNode->name($token->value()); - $self->assertTokenValue($self->getToken(), ";", __LINE__); - $newDataNode->extendedAttributes($extendedAttributeList); - return $newDataNode; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseExtendedAttributeListAllowEmpty -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "[") { - return $self->parseExtendedAttributeList(); - } - return {}; -} - -sub copyExtendedAttributes -{ - my $extendedAttributeList = shift; - my $attr = shift; - - for my $key (keys %{$attr}) { - if ($key eq "Constructor") { - push(@{$extendedAttributeList->{"Constructors"}}, $attr->{$key}); - } elsif ($key eq "Constructors") { - my @constructors = @{$attr->{$key}}; - foreach my $constructor (@constructors) { - push(@{$extendedAttributeList->{"Constructors"}}, $constructor); - } - } elsif ($key eq "CustomConstructor") { - push(@{$extendedAttributeList->{"CustomConstructors"}}, $attr->{$key}); - } elsif ($key eq "CustomConstructors") { - my @customConstructors = @{$attr->{$key}}; - foreach my $customConstructor (@customConstructors) { - push(@{$extendedAttributeList->{"CustomConstructors"}}, $customConstructor); - } - } else { - $extendedAttributeList->{$key} = $attr->{$key}; - } - } -} - -sub parseExtendedAttributeList -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "[") { - $self->assertTokenValue($self->getToken(), "[", __LINE__); - my $extendedAttributeList = {}; - my $attr = $self->parseExtendedAttribute(); - copyExtendedAttributes($extendedAttributeList, $attr); - $attr = $self->parseExtendedAttributes(); - copyExtendedAttributes($extendedAttributeList, $attr); - $self->assertTokenValue($self->getToken(), "]", __LINE__); - return $extendedAttributeList; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseExtendedAttributes -{ - my $self = shift; - my $extendedAttributeList = {}; - - while (1) { - my $next = $self->nextToken(); - if ($next->value() eq ",") { - $self->assertTokenValue($self->getToken(), ",", __LINE__); - my $attr = $self->parseExtendedAttribute2(); - copyExtendedAttributes($extendedAttributeList, $attr); - } else { - last; - } - } - return $extendedAttributeList; -} - -sub parseExtendedAttribute -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->type() == IdentifierToken || $next->value() eq "::") { - my $scopedName = $self->parseScopedName(); - return $self->parseExtendedAttributeRest($scopedName); - } - # backward compatibility. Spec doesn' allow "[]". But WebKit requires. - if ($next->value() eq ']') { - return {}; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseExtendedAttribute2 -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->type() == IdentifierToken || $next->value() eq "::") { - my $scopedName = $self->parseScopedName(); - return $self->parseExtendedAttributeRest($scopedName); - } - return {}; -} - -sub parseExtendedAttributeRest -{ - my $self = shift; - my $name = shift; - my $attrs = {}; - - my $next = $self->nextToken(); - if ($next->value() eq "(") { - $self->assertTokenValue($self->getToken(), "(", __LINE__); - $attrs->{$name} = $self->parseArgumentList(); - $self->assertTokenValue($self->getToken(), ")", __LINE__); - return $attrs; - } - if ($next->value() eq "=") { - $self->assertTokenValue($self->getToken(), "=", __LINE__); - $attrs->{$name} = $self->parseExtendedAttributeRest2(); - return $attrs; - } - - if ($name eq "Constructor" || $name eq "CustomConstructor") { - $attrs->{$name} = []; - } else { - $attrs->{$name} = "VALUE_IS_MISSING"; - } - return $attrs; -} - -sub parseExtendedAttributeRest2 -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->type() == IdentifierToken || $next->value() eq "::") { - my $scopedName = $self->parseScopedName(); - return $self->parseExtendedAttributeRest3($scopedName); - } - if ($next->type() == IntegerToken) { - my $token = $self->getToken(); - return $token->value(); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseExtendedAttributeRest3 -{ - my $self = shift; - my $name = shift; - - my $next = $self->nextToken(); - if ($next->value() eq "&") { - $self->assertTokenValue($self->getToken(), "&", __LINE__); - my $rightValue = $self->parseScopedName(); - return $name . "&" . $rightValue; - } - if ($next->value() eq "|") { - $self->assertTokenValue($self->getToken(), "|", __LINE__); - my $rightValue = $self->parseScopedName(); - return $name . "|" . $rightValue; - } - if ($next->value() eq "(") { - my $attr = {}; - $self->assertTokenValue($self->getToken(), "(", __LINE__); - $attr->{$name} = $self->parseArgumentList(); - $self->assertTokenValue($self->getToken(), ")", __LINE__); - return $attr; - } - if ($next->type() == IdentifierToken || $next->value() =~ /$nextExtendedAttributeRest3_1/) { - my @names = (); - push(@names, $name); - push(@names, @{$self->parseScopedNameListNoComma()}); - return join(' ', @names); - } - $self->assertUnexpectedToken($next->value()); -} - -sub parseScopedNameListNoComma -{ - my $self = shift; - my @names = (); - - while (1) { - my $next = $self->nextToken(); - if ($next->type() == IdentifierToken || $next->value() eq "::") { - push(@names, $self->parseScopedName()); - } else { - last; - } - } - return \@names; -} - -sub parseArgumentNameKeyword -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "attribute") { - return $self->getToken()->value(); - } - if ($next->value() eq "callback") { - return $self->getToken()->value(); - } - if ($next->value() eq "const") { - return $self->getToken()->value(); - } - if ($next->value() eq "creator") { - return $self->getToken()->value(); - } - if ($next->value() eq "deleter") { - return $self->getToken()->value(); - } - if ($next->value() eq "dictionary") { - return $self->getToken()->value(); - } - if ($next->value() eq "enum") { - return $self->getToken()->value(); - } - if ($next->value() eq "exception") { - return $self->getToken()->value(); - } - if ($next->value() eq "getter") { - return $self->getToken()->value(); - } - if ($next->value() eq "implements") { - return $self->getToken()->value(); - } - if ($next->value() eq "inherit") { - return $self->getToken()->value(); - } - if ($next->value() eq "interface") { - return $self->getToken()->value(); - } - if ($next->value() eq "legacycaller") { - return $self->getToken()->value(); - } - if ($next->value() eq "partial") { - return $self->getToken()->value(); - } - if ($next->value() eq "serializer") { - return $self->getToken()->value(); - } - if ($next->value() eq "setter") { - return $self->getToken()->value(); - } - if ($next->value() eq "static") { - return $self->getToken()->value(); - } - if ($next->value() eq "stringifier") { - return $self->getToken()->value(); - } - if ($next->value() eq "typedef") { - return $self->getToken()->value(); - } - if ($next->value() eq "unrestricted") { - return $self->getToken()->value(); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseType -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "(") { - my $unionType = $self->parseUnionType(); - my $suffix = $self->parseTypeSuffix(); - die "Suffix after UnionType is not supported." if $suffix ne ""; - return $unionType; - } - if ($next->type() == IdentifierToken || $next->value() =~ /$nextType_1/) { - return $self->parseSingleType(); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseSingleType -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "any") { - $self->assertTokenValue($self->getToken(), "any", __LINE__); - return "any" . $self->parseTypeSuffixStartingWithArray(); - } - if ($next->type() == IdentifierToken || $next->value() =~ /$nextSingleType_1/) { - return $self->parseNonAnyType(); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseUnionType -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "(") { - my $unionType = UnionType->new(); - $self->assertTokenValue($self->getToken(), "(", __LINE__); - push @{$unionType->unionMemberTypes}, $self->parseUnionMemberType(); - $self->assertTokenValue($self->getToken(), "or", __LINE__); - push @{$unionType->unionMemberTypes}, $self->parseUnionMemberType(); - push @{$unionType->unionMemberTypes}, $self->parseUnionMemberTypes(); - $self->assertTokenValue($self->getToken(), ")", __LINE__); - return $unionType; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -# Returns UnionType or string -sub parseUnionMemberType -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "(") { - my $unionType = $self->parseUnionType(); - my $suffix = $self->parseTypeSuffix(); - die "Suffix after UnionType is not supported." if $suffix ne ""; - return $unionType; - } - if ($next->value() eq "any") { - my $type = $self->assertTokenValue($self->getToken(), "any", __LINE__); - $type .= $self->assertTokenValue($self->getToken(), "[", __LINE__); - $type .= $self->assertTokenValue($self->getToken(), "]", __LINE__); - $type .= $self->parseTypeSuffix(); - return $type; - } - if ($next->type() == IdentifierToken || $next->value() =~ /$nextSingleType_1/) { - return $self->parseNonAnyType(); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseUnionMemberTypes -{ - my $self = shift; - my @types = (); - my $next = $self->nextToken(); - if ($next->value() eq "or") { - $self->assertTokenValue($self->getToken(), "or", __LINE__); - push @types, $self->parseUnionMemberType(); - push @types, $self->parseUnionMemberTypes(); - } - return @types; -} - -sub parseNonAnyType -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() =~ /$nextNonAnyType_1/) { - return $self->parsePrimitiveType() . $self->parseTypeSuffix(); - } - if ($next->value() eq "ByteString") { - $self->assertTokenValue($self->getToken(), "ByteString", __LINE__); - return "ByteString" . $self->parseTypeSuffix(); - } - if ($next->value() eq "DOMString") { - $self->assertTokenValue($self->getToken(), "DOMString", __LINE__); - return "DOMString" . $self->parseTypeSuffix(); - } - if ($next->value() eq "Promise") { - $self->assertTokenValue($self->getToken(), "Promise", __LINE__); - return "Promise" . $self->parseTypeSuffix(); - } - if ($next->value() eq "sequence") { - $self->assertTokenValue($self->getToken(), "sequence", __LINE__); - $self->assertTokenValue($self->getToken(), "<", __LINE__); - my $type = $self->parseType(); - $self->assertTokenValue($self->getToken(), ">", __LINE__); - return "sequence<" . $type . ">" . $self->parseNull(); - } - if ($next->value() eq "object") { - $self->assertTokenValue($self->getToken(), "object", __LINE__); - return "object" . $self->parseTypeSuffix(); - } - if ($next->value() eq "Date") { - $self->assertTokenValue($self->getToken(), "Date", __LINE__); - return "Date" . $self->parseTypeSuffix(); - } - if ($next->type() == IdentifierToken || $next->value() eq "::") { - my $name = $self->parseScopedName(); - return $name . $self->parseTypeSuffix(); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseConstType -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() =~ /$nextNonAnyType_1/) { - return $self->parsePrimitiveType() . $self->parseNull(); - } - if ($next->type() == IdentifierToken) { - my $token = $self->getToken(); - return $token->value() . $self->parseNull(); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parsePrimitiveType -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() =~ /$nextPrimitiveType_1/) { - return $self->parseUnsignedIntegerType(); - } - if ($next->value() =~ /$nextPrimitiveType_2/) { - return $self->parseUnrestrictedFloatType(); - } - if ($next->value() eq "boolean") { - $self->assertTokenValue($self->getToken(), "boolean", __LINE__); - return "boolean"; - } - if ($next->value() eq "byte") { - $self->assertTokenValue($self->getToken(), "byte", __LINE__); - return "byte"; - } - if ($next->value() eq "octet") { - $self->assertTokenValue($self->getToken(), "octet", __LINE__); - return "octet"; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseUnrestrictedFloatType -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "unrestricted") { - $self->assertTokenValue($self->getToken(), "unrestricted", __LINE__); - return "unrestricted " . $self->parseFloatType(); - } - if ($next->value() =~ /$nextUnrestrictedFloatType_1/) { - return $self->parseFloatType(); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseFloatType -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "float") { - $self->assertTokenValue($self->getToken(), "float", __LINE__); - return "float"; - } - if ($next->value() eq "double") { - $self->assertTokenValue($self->getToken(), "double", __LINE__); - return "double"; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseUnsignedIntegerType -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "unsigned") { - $self->assertTokenValue($self->getToken(), "unsigned", __LINE__); - return "unsigned " . $self->parseIntegerType(); - } - if ($next->value() =~ /$nextUnsignedIntegerType_1/) { - return $self->parseIntegerType(); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseIntegerType -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "short") { - $self->assertTokenValue($self->getToken(), "short", __LINE__); - return "short"; - } - if ($next->value() eq "int") { - $self->assertTokenValue($self->getToken(), "int", __LINE__); - return "int"; - } - if ($next->value() eq "long") { - $self->assertTokenValue($self->getToken(), "long", __LINE__); - if ($self->parseOptionalLong()) { - return "long long"; - } - return "long"; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseOptionalLong -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "long") { - $self->assertTokenValue($self->getToken(), "long", __LINE__); - return 1; - } - return 0; -} - -sub parseTypeSuffix -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "[") { - $self->assertTokenValue($self->getToken(), "[", __LINE__); - $self->assertTokenValue($self->getToken(), "]", __LINE__); - return "[]" . $self->parseTypeSuffix(); - } - if ($next->value() eq "?") { - $self->assertTokenValue($self->getToken(), "?", __LINE__); - return "?" . $self->parseTypeSuffixStartingWithArray(); - } - return ""; -} - -sub parseTypeSuffixStartingWithArray -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "[") { - $self->assertTokenValue($self->getToken(), "[", __LINE__); - $self->assertTokenValue($self->getToken(), "]", __LINE__); - return "[]" . $self->parseTypeSuffix(); - } - return ""; -} - -sub parseNull -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "?") { - $self->assertTokenValue($self->getToken(), "?", __LINE__); - return "?"; - } - return ""; -} - -sub parseReturnType -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "void") { - $self->assertTokenValue($self->getToken(), "void", __LINE__); - return "void"; - } - if ($next->type() == IdentifierToken || $next->value() =~ /$nextExceptionField_1/) { - return $self->parseType(); - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseExceptionList -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "(") { - my @exceptions = (); - $self->assertTokenValue($self->getToken(), "(", __LINE__); - push(@exceptions, @{$self->parseScopedNameList()}); - $self->assertTokenValue($self->getToken(), ")", __LINE__); - return \@exceptions; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseRaises -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "raises") { - $self->assertTokenValue($self->getToken(), "raises", __LINE__); - return $self->parseExceptionList(); - } - return []; -} - -sub parseOptionalSemicolon -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq ";") { - $self->assertTokenValue($self->getToken(), ";", __LINE__); - } -} - -sub parseScopedName -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "::") { - return $self->parseAbsoluteScopedName(); - } - if ($next->type() == IdentifierToken) { - return $self->parseRelativeScopedName(); - } - $self->assertUnexpectedToken($next->value()); -} - -sub parseAbsoluteScopedName -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->value() eq "::") { - $self->assertTokenValue($self->getToken(), "::"); - my $token = $self->getToken(); - $self->assertTokenType($token, IdentifierToken); - return "::" . $token->value() . $self->parseScopedNameParts(); - } - $self->assertUnexpectedToken($next->value()); -} - -sub parseRelativeScopedName -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->type() == IdentifierToken) { - my $token = $self->getToken(); - return $token->value() . $self->parseScopedNameParts(); - } - $self->assertUnexpectedToken($next->value()); -} - -sub parseScopedNameParts -{ - my $self = shift; - my @names = (); - - while (1) { - my $next = $self->nextToken(); - if ($next->value() eq "::") { - $self->assertTokenValue($self->getToken(), "::"); - push(@names, "::"); - my $token = $self->getToken(); - $self->assertTokenType($token, IdentifierToken); - push(@names, $token->value()); - } else { - last; - } - } - return join("", @names); -} - -sub parseScopedNameList -{ - my $self = shift; - my $next = $self->nextToken(); - if ($next->type() == IdentifierToken || $next->value() eq "::") { - my @names = (); - push(@names, $self->parseScopedName()); - push(@names, @{$self->parseScopedNames()}); - return \@names; - } - $self->assertUnexpectedToken($next->value(), __LINE__); -} - -sub parseScopedNames -{ - my $self = shift; - my @names = (); - - while (1) { - my $next = $self->nextToken(); - if ($next->value() eq ",") { - $self->assertTokenValue($self->getToken(), ","); - push(@names, $self->parseScopedName()); - } else { - last; - } - } - return \@names; -} - -sub applyMemberList -{ - my $interface = shift; - my $members = shift; - - for my $item (@{$members}) { - if (ref($item) eq "domAttribute") { - push(@{$interface->attributes}, $item); - next; - } - if (ref($item) eq "domConstant") { - push(@{$interface->constants}, $item); - next; - } - if (ref($item) eq "domFunction") { - push(@{$interface->functions}, $item); - next; - } - } -} - -sub applyExtendedAttributeList -{ - my $interface = shift; - my $extendedAttributeList = shift; - - if (defined $extendedAttributeList->{"Constructors"}) { - my @constructorParams = @{$extendedAttributeList->{"Constructors"}}; - my $index = (@constructorParams == 1) ? 0 : 1; - foreach my $param (@constructorParams) { - my $constructor = domFunction->new(); - $constructor->name("Constructor"); - $constructor->extendedAttributes($extendedAttributeList); - $constructor->parameters($param); - $constructor->overloadedIndex($index++); - push(@{$interface->constructors}, $constructor); - } - delete $extendedAttributeList->{"Constructors"}; - $extendedAttributeList->{"Constructor"} = "VALUE_IS_MISSING"; - } elsif (defined $extendedAttributeList->{"NamedConstructor"}) { - my $newDataNode = domFunction->new(); - $newDataNode->name("NamedConstructor"); - $newDataNode->extendedAttributes($extendedAttributeList); - my %attributes = %{$extendedAttributeList->{"NamedConstructor"}}; - my @attributeKeys = keys (%attributes); - my $constructorName = $attributeKeys[0]; - push(@{$newDataNode->parameters}, @{$attributes{$constructorName}}); - $extendedAttributeList->{"NamedConstructor"} = $constructorName; - push(@{$interface->constructors}, $newDataNode); - } - if (defined $extendedAttributeList->{"CustomConstructors"}) { - my @customConstructorParams = @{$extendedAttributeList->{"CustomConstructors"}}; - my $index = (@customConstructorParams == 1) ? 0 : 1; - foreach my $param (@customConstructorParams) { - my $customConstructor = domFunction->new(); - $customConstructor->name("CustomConstructor"); - $customConstructor->extendedAttributes($extendedAttributeList); - $customConstructor->parameters($param); - $customConstructor->overloadedIndex($index++); - push(@{$interface->customConstructors}, $customConstructor); - } - delete $extendedAttributeList->{"CustomConstructors"}; - $extendedAttributeList->{"CustomConstructor"} = "VALUE_IS_MISSING"; - } - $interface->extendedAttributes($extendedAttributeList); -} - -1; diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/idl_reader.py b/chromium/third_party/WebKit/Source/bindings/scripts/idl_reader.py new file mode 100644 index 00000000000..450c73d9f29 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/idl_reader.py @@ -0,0 +1,109 @@ +# Copyright (C) 2013 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. + +"""Read an IDL file or complete IDL interface, producing an IdlDefinitions object. + +Design doc: +http://www.chromium.org/developers/design-documents/idl-compiler#TOC-Front-end +""" + +import os + +import blink_idl_parser +from blink_idl_parser import BlinkIDLParser +from idl_definitions import IdlDefinitions +from idl_validator import EXTENDED_ATTRIBUTES_RELATIVE_PATH, IDLInvalidExtendedAttributeError, IDLExtendedAttributeValidator +from interface_dependency_resolver import InterfaceDependencyResolver + + +class IdlReader(object): + def __init__(self, interfaces_info=None, outputdir=''): + self.extended_attribute_validator = IDLExtendedAttributeValidator() + + if interfaces_info: + self.interface_dependency_resolver = InterfaceDependencyResolver(interfaces_info, self) + else: + self.interface_dependency_resolver = None + + self.parser = BlinkIDLParser(outputdir=outputdir) + + def read_idl_definitions(self, idl_filename): + """Returns an IdlDefinitions object for an IDL file, including all dependencies.""" + definitions = self.read_idl_file(idl_filename) + if not self.interface_dependency_resolver: + return definitions + self.interface_dependency_resolver.resolve_dependencies(definitions) + return definitions + + def read_idl_file(self, idl_filename): + """Returns an IdlDefinitions object for an IDL file, without any dependencies. + + The IdlDefinitions object is guaranteed to contain a single + IdlInterface; it may also contain other definitions, such as + callback functions and enumerations.""" + ast = blink_idl_parser.parse_file(self.parser, idl_filename) + if not ast: + raise Exception('Failed to parse %s' % idl_filename) + definitions = IdlDefinitions(ast) + + # Validate file contents with filename convention + # The Blink IDL filenaming convention is that the file + # <interface_name>.idl MUST contain exactly 1 interface (or exception), + # and the interface name must agree with the file's basename, + # unless it is a partial interface. + # (e.g., 'partial interface Foo' can be in FooBar.idl). + number_of_interfaces = len(definitions.interfaces) + if number_of_interfaces != 1: + raise Exception( + 'Expected exactly 1 interface in file {0}, but found {1}' + .format(idl_filename, number_of_interfaces)) + interface = next(definitions.interfaces.itervalues()) + idl_file_basename, _ = os.path.splitext(os.path.basename(idl_filename)) + if not interface.is_partial and interface.name != idl_file_basename: + raise Exception( + 'Interface name "{0}" disagrees with IDL file basename "{1}".' + .format(interface.name, idl_file_basename)) + + # Validate extended attributes + if not self.extended_attribute_validator: + return definitions + + try: + self.extended_attribute_validator.validate_extended_attributes(definitions) + except IDLInvalidExtendedAttributeError as error: + raise IDLInvalidExtendedAttributeError(""" +IDL ATTRIBUTE ERROR in file: +%s: + %s +If you want to add a new IDL extended attribute, please add it to: + %s +and add an explanation to the Blink IDL documentation at: + http://www.chromium.org/blink/webidl/blink-idl-extended-attributes + """ % (idl_filename, str(error), EXTENDED_ATTRIBUTES_RELATIVE_PATH)) + + return definitions diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/idl_serializer.pm b/chromium/third_party/WebKit/Source/bindings/scripts/idl_serializer.pm deleted file mode 100644 index 0a6fdae3124..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/scripts/idl_serializer.pm +++ /dev/null @@ -1,126 +0,0 @@ -# Copyright (C) 2013 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. - - -# Converts the intermediate representation of IDLs between Perl and JSON, for: -# 1. Modularity between parser and code generator; and -# 2. Piecemeal porting to Python, by letting us connect Perl and Python scripts. - -use strict; -use warnings; - -use Class::Struct; -use JSON -convert_blessed_universally; # IR contains objects (blessed references) - -sub serializeJSON -{ - my $document = shift; - my $json = JSON->new->utf8; - # JSON.pm defaults to dying on objects (blessed references) and returning - # keys in indeterminate order. We set options to change this: - # allow_blessed: don't die when encounter a blessed reference - # (but default to return null) - # convert_blessed: convert blessed reference as if unblessed - # (rather than returning null) - # canonical: sort keys when writing JSON, so JSON always in same order, - # so can compare output between runs or between Perl and Python - $json = $json->allow_blessed->convert_blessed->canonical(); - return $json->encode($document); -} - -sub deserializeJSON -{ - my $jsonText = shift; - my $json = JSON->new->utf8; - my $jsonHash = $json->decode($jsonText); - return jsonToPerl($jsonHash); -} - -sub jsonToPerl -{ - # JSON.pm serializes Perl objects as hashes (with keys CLASS::KEY), - # so we need to rebuild objects when deserializing - my $jsonData = shift; - - if (ref $jsonData eq "ARRAY") { - return [map(jsonToPerl($_), @$jsonData)]; - } - - if (ref $jsonData eq "HASH") { - my @keys = keys %$jsonData; - return {} unless @keys; - - my $class = determineClassFromKeys(@keys); - return jsonHashToPerlObject($jsonData, $class) if $class; - - # just a hash - my $hashRef = {}; - foreach my $key (@keys) { - $hashRef->{$key} = jsonToPerl($jsonData->{$key}); - } - return $hashRef; - } - - die "Unexpected reference type: " . ref $jsonData . "\n" if ref $jsonData; - - return $jsonData; -} - -sub determineClassFromKeys -{ - my @keys = shift; - - # Detect objects as hashes where all keys are of the form CLASS::KEY. - my $firstKey = $keys[0]; - my $isObject = $firstKey =~ /::/; - - return unless $isObject; - - my $class = (split('::', $firstKey))[0]; - return $class; -} - -sub jsonHashToPerlObject -{ - # JSON.pm serializes hash objects of class CLASS as a hash with keys - # CLASS::KEY1, CLASS::KEY2, etc. - # When deserializing, need to rebuild objects by stripping prefix - # and calling the constructor. - my $jsonHash = shift; - my $class = shift; - - my %keysValues = (); - foreach my $classAndKey (keys %{$jsonHash}) { - my $key = (split('::', $classAndKey))[1]; - $keysValues{$key} = jsonToPerl($jsonHash->{$classAndKey}); - } - my $object = $class->new(%keysValues); # Build object - return $object; -} - -1; diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/idl_types.py b/chromium/third_party/WebKit/Source/bindings/scripts/idl_types.py new file mode 100644 index 00000000000..e488e332648 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/idl_types.py @@ -0,0 +1,321 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +"""IDL type handling. + +Classes: +IdlType +IdlUnionType +""" + +from collections import defaultdict + + +################################################################################ +# IDL types +################################################################################ + +INTEGER_TYPES = frozenset([ + # http://www.w3.org/TR/WebIDL/#dfn-integer-type + 'byte', + 'octet', + 'short', + 'unsigned short', + # int and unsigned are not IDL types + 'long', + 'unsigned long', + 'long long', + 'unsigned long long', +]) +NUMERIC_TYPES = (INTEGER_TYPES | frozenset([ + # http://www.w3.org/TR/WebIDL/#dfn-numeric-type + 'float', + 'unrestricted float', + 'double', + 'unrestricted double', +])) +# http://www.w3.org/TR/WebIDL/#dfn-primitive-type +PRIMITIVE_TYPES = (frozenset(['boolean']) | NUMERIC_TYPES) +BASIC_TYPES = (PRIMITIVE_TYPES | frozenset([ + # Built-in, non-composite, non-object data types + # http://heycam.github.io/webidl/#idl-types + 'DOMString', + 'ByteString', + 'Date', + # http://heycam.github.io/webidl/#es-type-mapping + 'void', + # http://encoding.spec.whatwg.org/#type-scalarvaluestring + 'ScalarValueString', +])) +TYPE_NAMES = { + # http://heycam.github.io/webidl/#dfn-type-name + 'any': 'Any', + 'boolean': 'Boolean', + 'byte': 'Byte', + 'octet': 'Octet', + 'short': 'Short', + 'unsigned short': 'UnsignedShort', + 'long': 'Long', + 'unsigned long': 'UnsignedLong', + 'long long': 'LongLong', + 'unsigned long long': 'UnsignedLongLong', + 'float': 'Float', + 'unrestricted float': 'UnrestrictedFloat', + 'double': 'Double', + 'unrestricted double': 'UnrestrictedDouble', + 'DOMString': 'String', + 'ByteString': 'ByteString', + 'ScalarValueString': 'ScalarValueString', + 'object': 'Object', + 'Date': 'Date', +} + + +################################################################################ +# Inheritance +################################################################################ + +ancestors = defaultdict(list) # interface_name -> ancestors + +def inherits_interface(interface_name, ancestor_name): + return (interface_name == ancestor_name or + ancestor_name in ancestors[interface_name]) + + +def set_ancestors(new_ancestors): + ancestors.update(new_ancestors) + + +################################################################################ +# IdlType +################################################################################ + +class IdlType(object): + # FIXME: incorporate Nullable, etc. + # FIXME: use nested types: IdlArrayType, IdlNullableType, IdlSequenceType + # to support types like short?[] vs. short[]?, instead of treating these + # as orthogonal properties (via flags). + callback_functions = set() + callback_interfaces = set() + enums = {} # name -> values + + def __init__(self, base_type, is_array=False, is_sequence=False, is_nullable=False, is_unrestricted=False): + if is_array and is_sequence: + raise ValueError('Array of Sequences are not allowed.') + if is_unrestricted: + self.base_type = 'unrestricted %s' % base_type + else: + self.base_type = base_type + self.is_array = is_array + self.is_sequence = is_sequence + self.is_nullable = is_nullable + + def __str__(self): + type_string = self.base_type + if self.is_array: + return type_string + '[]' + if self.is_sequence: + return 'sequence<%s>' % type_string + if self.is_nullable: + # FIXME: Dictionary::ConversionContext::setConversionType can't + # handle the '?' in nullable types (passes nullability separately). + # Update that function to handle nullability from the type name, + # simplifying its signature. + # return type_string + '?' + return type_string + return type_string + + # FIXME: rename to native_array_element_type and move to v8_types.py + @property + def array_or_sequence_type(self): + return self.array_type or self.sequence_type + + # FIXME: rename to array_element_type + @property + def array_type(self): + return self.is_array and IdlType(self.base_type) + + # FIXME: rename to sequence_element_type + @property + def sequence_type(self): + return self.is_sequence and IdlType(self.base_type) + + @property + def is_basic_type(self): + return self.base_type in BASIC_TYPES and not self.array_or_sequence_type + + @property + def is_callback_function(self): + return self.base_type in IdlType.callback_functions + + @property + def is_callback_interface(self): + return self.base_type in IdlType.callback_interfaces + + @property + def is_composite_type(self): + return (self.name == 'Any' or + self.array_type or + self.sequence_type or + self.is_union_type) + + @property + def is_enum(self): + # FIXME: add an IdlEnumType class and a resolve_enums step at end of + # IdlDefinitions constructor + return self.name in IdlType.enums + + @property + def enum_values(self): + return IdlType.enums[self.name] + + @property + def is_integer_type(self): + return self.base_type in INTEGER_TYPES and not self.array_or_sequence_type + + @property + def is_numeric_type(self): + return self.base_type in NUMERIC_TYPES and not self.array_or_sequence_type + + @property + def is_primitive_type(self): + return self.base_type in PRIMITIVE_TYPES and not self.array_or_sequence_type + + @property + def is_interface_type(self): + # Anything that is not another type is an interface type. + # http://www.w3.org/TR/WebIDL/#idl-types + # http://www.w3.org/TR/WebIDL/#idl-interface + # In C++ these are RefPtr or PassRefPtr types. + return not(self.is_basic_type or + self.is_composite_type or + self.is_callback_function or + self.is_enum or + self.name == 'Object' or + self.name == 'Promise') # Promise will be basic in future + + @property + def is_union_type(self): + return isinstance(self, IdlUnionType) + + @property + def name(self): + """Return type name. + + http://heycam.github.io/webidl/#dfn-type-name + """ + base_type = self.base_type + base_type_name = TYPE_NAMES.get(base_type, base_type) + if self.is_array: + return base_type_name + 'Array' + if self.is_sequence: + return base_type_name + 'Sequence' + if self.is_nullable: + return base_type_name + 'OrNull' + return base_type_name + + @classmethod + def set_callback_functions(cls, new_callback_functions): + cls.callback_functions.update(new_callback_functions) + + @classmethod + def set_callback_interfaces(cls, new_callback_interfaces): + cls.callback_interfaces.update(new_callback_interfaces) + + @classmethod + def set_enums(cls, new_enums): + cls.enums.update(new_enums) + + def resolve_typedefs(self, typedefs): + if self.base_type not in typedefs: + return self + new_type = typedefs[self.base_type] + if type(new_type) != type(self): + # If type changes, need to return a different object, + # since can't change type(self) + return new_type + # If type doesn't change, just mutate self to avoid a new object + # FIXME: a bit ugly; use __init__ instead of setting flags + self.base_type = new_type.base_type + # handle array both in use and in typedef itself: + # typedef Type TypeDef; + # TypeDef[] ... + # and: + # typedef Type[] TypeArray + # TypeArray ... + self.is_array |= new_type.is_array + self.is_sequence |= new_type.is_sequence + return self + + +################################################################################ +# IdlUnionType +################################################################################ + +class IdlUnionType(object): + # http://heycam.github.io/webidl/#idl-union + # FIXME: derive from IdlType, instead of stand-alone class, to reduce + # duplication. + def __init__(self, member_types, is_nullable=False): + self.member_types = member_types + self.is_nullable = is_nullable + + @property + def array_or_sequence_type(self): + return False + + @property + def array_type(self): + return False + + @property + def is_array(self): + # We do not support arrays of union types + return False + + @property + def base_type(self): + return None + + @property + def is_basic_type(self): + return False + + @property + def is_callback_function(self): + return False + + @property + def is_enum(self): + return False + + @property + def is_integer_type(self): + return False + + @property + def is_numeric_type(self): + return False + + @property + def is_primitivee_type(self): + return False + + @property + def is_sequence(self): + # We do not support sequences of union types + return False + + @property + def is_union_type(self): + return True + + @property + def name(self): + return 'Or'.join(member_type.name for member_type in self.member_types) + + def resolve_typedefs(self, typedefs): + self.member_types = [ + typedefs.get(member_type, member_type) + for member_type in self.member_types] + return self diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/idl_validator.py b/chromium/third_party/WebKit/Source/bindings/scripts/idl_validator.py index aa93242d46f..e527442cab7 100644 --- a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/idl_validator.py +++ b/chromium/third_party/WebKit/Source/bindings/scripts/idl_validator.py @@ -26,19 +26,29 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -"""Validate extended attributes.""" +"""Validate extended attributes. +Design doc: http://www.chromium.org/developers/design-documents/idl-compiler#TOC-Extended-attribute-validation +""" + +import os.path import re +module_path = os.path.dirname(__file__) +source_path = os.path.join(module_path, os.pardir, os.pardir) +EXTENDED_ATTRIBUTES_RELATIVE_PATH = os.path.join('bindings', + 'IDLExtendedAttributes.txt') +EXTENDED_ATTRIBUTES_FILENAME = os.path.join(source_path, + EXTENDED_ATTRIBUTES_RELATIVE_PATH) class IDLInvalidExtendedAttributeError(Exception): pass class IDLExtendedAttributeValidator(object): - def __init__(self, extended_attributes_filename): - self.valid_extended_attributes = read_extended_attributes_file(extended_attributes_filename) + def __init__(self): + self.valid_extended_attributes = read_extended_attributes_file() def validate_extended_attributes(self, definitions): # FIXME: this should be done when parsing the file, rather than after. @@ -56,13 +66,13 @@ class IDLExtendedAttributeValidator(object): self.validate_name_values_string(name, values_string) def validate_name_values_string(self, name, values_string): - if name == 'ImplementedBy': # attribute added when merging interfaces - return if name not in self.valid_extended_attributes: - raise IDLInvalidExtendedAttributeError('Unknown extended attribute [%s]' % name) + raise IDLInvalidExtendedAttributeError( + 'Unknown extended attribute [%s]' % name) valid_values = self.valid_extended_attributes[name] if values_string is None and None not in valid_values: - raise IDLInvalidExtendedAttributeError('Missing required argument for extended attribute [%s]' % name) + raise IDLInvalidExtendedAttributeError( + 'Missing required argument for extended attribute [%s]' % name) if '*' in valid_values: # wildcard, any (non-empty) value ok return if values_string is None: @@ -72,12 +82,14 @@ class IDLExtendedAttributeValidator(object): invalid_values = values - valid_values if invalid_values: invalid_value = invalid_values.pop() - raise IDLInvalidExtendedAttributeError('Invalid value "%s" found in extended attribute [%s=%s]' % (invalid_value, name, values_string)) + raise IDLInvalidExtendedAttributeError( + 'Invalid value "%s" found in extended attribute [%s=%s]' % + (invalid_value, name, values_string)) -def read_extended_attributes_file(extended_attributes_filename): +def read_extended_attributes_file(): def extended_attribute_name_values(): - with open(extended_attributes_filename) as extended_attributes_file: + with open(EXTENDED_ATTRIBUTES_FILENAME) as extended_attributes_file: for line in extended_attributes_file: line = line.strip() if not line or line.startswith('#'): diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/interface_dependency_resolver.py b/chromium/third_party/WebKit/Source/bindings/scripts/interface_dependency_resolver.py new file mode 100644 index 00000000000..c65d3f68734 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/interface_dependency_resolver.py @@ -0,0 +1,179 @@ +# Copyright (C) 2013 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. + +"""Resolve interface dependencies, producing a merged IdlDefinitions object. + +This library computes interface dependencies (partial interfaces and +implements), reads the dependency files, and merges them to the IdlDefinitions +for the main IDL file, producing an IdlDefinitions object representing the +entire interface. + +Design doc: http://www.chromium.org/developers/design-documents/idl-compiler#TOC-Dependency-resolution +""" + +import os.path + +# The following extended attributes can be applied to a dependency interface, +# and are then applied to the individual members when merging. +# Note that this moves the extended attribute from the interface to the member, +# which changes the semantics and yields different code than the same extended +# attribute on the main interface. +DEPENDENCY_EXTENDED_ATTRIBUTES = set([ + 'Conditional', + 'PerContextEnabled', + 'RuntimeEnabled', +]) + + +class InterfaceDependencyResolver(object): + def __init__(self, interfaces_info, reader): + """Initialize dependency resolver. + + Args: + interfaces_info: + dict of interfaces information, from compute_dependencies.py + reader: + IdlReader, used for reading dependency files + """ + self.interfaces_info = interfaces_info + self.reader = reader + + def resolve_dependencies(self, definitions): + """Resolve dependencies, merging them into IDL definitions of main file. + + Dependencies consist of 'partial interface' for the same interface as + in the main file, and other interfaces that this interface 'implements'. + These are merged into the main IdlInterface, as the main IdlInterface + implements all these members. + + Referenced interfaces are added to IdlDefinitions, but not merged into + the main IdlInterface, as these are only referenced (their members are + introspected, but not implemented in this interface). + + Inherited extended attributes are also added to the main IdlInterface. + + Modifies definitions in place by adding parsed dependencies. + + Args: + definitions: IdlDefinitions object, modified in place + """ + target_interface = next(definitions.interfaces.itervalues()) + interface_name = target_interface.name + interface_info = self.interfaces_info[interface_name] + + if 'inherited_extended_attributes' in interface_info: + target_interface.extended_attributes.update( + interface_info['inherited_extended_attributes']) + + merge_interface_dependencies(definitions, + target_interface, + interface_info['dependencies_full_paths'], + self.reader) + + for referenced_interface_name in interface_info['referenced_interfaces']: + referenced_definitions = self.reader.read_idl_definitions( + self.interfaces_info[referenced_interface_name]['full_path']) + definitions.update(referenced_definitions) + + +def merge_interface_dependencies(definitions, target_interface, dependency_idl_filenames, reader): + """Merge dependencies ('partial interface' and 'implements') in dependency_idl_filenames into target_interface. + + No return: modifies target_interface in place. + """ + # Sort so order consistent, so can compare output from run to run. + for dependency_idl_filename in sorted(dependency_idl_filenames): + dependency_definitions = reader.read_idl_file(dependency_idl_filename) + dependency_interface = next(dependency_definitions.interfaces.itervalues()) + dependency_interface_basename, _ = os.path.splitext(os.path.basename(dependency_idl_filename)) + + transfer_extended_attributes(dependency_interface, + dependency_interface_basename) + definitions.update(dependency_definitions) # merges partial interfaces + if not dependency_interface.is_partial: + # Implemented interfaces (non-partial dependencies) are also merged + # into the target interface, so Code Generator can just iterate + # over one list (and not need to handle 'implements' itself). + target_interface.merge(dependency_interface) + + +def transfer_extended_attributes(dependency_interface, dependency_interface_basename): + """Transfer extended attributes from dependency interface onto members. + + Merging consists of storing certain interface-level data in extended + attributes of the *members* (because there is no separate dependency + interface post-merging). + + The data storing consists of: + * applying certain extended attributes from the dependency interface + to its members + * storing the C++ class of the implementation in an internal + extended attribute of each member, [PartialInterfaceImplementedAs] + + No return: modifies dependency_interface in place. + """ + merged_extended_attributes = dict( + (key, value) + for key, value in dependency_interface.extended_attributes.iteritems() + if key in DEPENDENCY_EXTENDED_ATTRIBUTES) + + # A partial interface's members are implemented as static member functions + # in a separate C++ class. This class name is stored in + # [PartialInterfaceImplementedAs] which defaults to the basename of + # dependency IDL file. + # This class name can be overridden by [ImplementedAs] on the partial + # interface definition. + # + # Note that implemented interfaces do *not* need [ImplementedAs], since + # they are implemented on the C++ object |impl| itself, just like members of + # the main interface definition, so the bindings do not need to know in + # which class implemented interfaces are implemented. + # + # Currently [LegacyTreatAsPartialInterface] can be used to have partial + # interface behavior on implemented interfaces, but this is being removed + # as legacy cruft: + # FIXME: Remove [LegacyTreatAsPartialInterface] + # http://crbug.com/360435 + # + # Note that [ImplementedAs] is used with different meanings on interfaces + # and members: + # for Blink class name and function name (or constant name), respectively. + # Thus we do not want to copy this from the interface to the member, but + # instead extract it and handle it separately. + if (dependency_interface.is_partial or + 'LegacyTreatAsPartialInterface' in dependency_interface.extended_attributes): + merged_extended_attributes['PartialInterfaceImplementedAs'] = ( + dependency_interface.extended_attributes.get( + 'ImplementedAs', dependency_interface_basename)) + + for attribute in dependency_interface.attributes: + attribute.extended_attributes.update(merged_extended_attributes) + for constant in dependency_interface.constants: + constant.extended_attributes.update(merged_extended_attributes) + for operation in dependency_interface.operations: + operation.extended_attributes.update(merged_extended_attributes) diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/interfaces_info_individual.gypi b/chromium/third_party/WebKit/Source/bindings/scripts/interfaces_info_individual.gypi new file mode 100644 index 00000000000..32f72b5011e --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/interfaces_info_individual.gypi @@ -0,0 +1,70 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# This file is meant to be included into a target to provide an action +# to compute information about individual interfaces defined in a component. +# +# To use this, create a gyp target with the following form: +# { +# 'target_name': 'interfaces_info_individual_component', +# 'dependencies': [ +# 'generated_idls_target', +# ], +# 'variables': { +# 'static_idl_files': '<(component_static_idl_files)', +# 'generated_idl_files': '<(component_generated_idl_files)', +# 'component_dir': 'component', +# 'output_file': +# '<(bindings_core_output_dir)/InterfacesInfoComponentIndividual.pickle', +# }, +# 'includes': ['path/to/this/gypi/file'], +# }, +# +# Required variables: +# static_idl_files - All static .idl files for the component, including +# dependencies and testing. +# generated_idl_files - All generated .idl files for the component. +# (Must be separate from static because build dir not know at gyp time.) +# component_dir - Relative directory for component, e.g., 'core'. +# output_file - Pickle file containing output. +# +# Design document: http://www.chromium.org/developers/design-documents/idl-build + +{ + 'type': 'none', + 'actions': [{ + 'action_name': 'compute_<(_target_name)', + 'message': 'Computing global information about individual IDL files for <(_target_name)', + 'variables': { + 'static_idl_files_list': + '<|(<(_target_name)_static_idl_files_list.tmp <@(static_idl_files))', + }, + 'inputs': [ + '<(bindings_scripts_dir)/compute_interfaces_info_individual.py', + '<(bindings_scripts_dir)/utilities.py', + '<(static_idl_files_list)', + '<@(static_idl_files)', + '<@(generated_idl_files)', + ], + 'outputs': [ + '<(output_file)', + ], + + 'action': [ + 'python', + '<(bindings_scripts_dir)/compute_interfaces_info_individual.py', + '--component-dir', + '<(component_dir)', + '--idl-files-list', + '<(static_idl_files_list)', + '--interfaces-info-file', + '<(output_file)', + '--write-file-only-if-changed', + '<(write_file_only_if_changed)', + '--', + # Generated files must be passed at command line + '<@(generated_idl_files)', + ], + }], +} diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/interfaces_info_overall.gypi b/chromium/third_party/WebKit/Source/bindings/scripts/interfaces_info_overall.gypi new file mode 100644 index 00000000000..024fb2a6511 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/interfaces_info_overall.gypi @@ -0,0 +1,56 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. +# +# This file is meant to be included into a target to provide an action +# to compute overall information about interfaces defined in a component. +# +# To use this, create a gyp target with the following form: +# { +# 'target_name': 'interfaces_info_component', +# 'dependencies': [ +# 'interfaces_info_individual_base_component', +# 'interfaces_info_individual_component', +# ], +# 'variables': { +# 'input_files': [ +# '<(bindings_base_component_output_dir)/InterfacesInfoBaseComponentIndividual.pickle', +# '<(bindings_component_output_dir)/InterfacesInfoComponentIndividual.pickle', +# ], +# 'output_file': +# '<(bindings_component_output_dir)/InterfacesInfoComponent.pickle', +# }, +# 'includes': ['path/to/this/gypi/file'], +# }, +# +# Required variables: +# input_files - Pickle files containing info about individual interfaces, both +# current component and any base components. +# output_file - Pickle file containing output (overall info). +# +# Design document: http://www.chromium.org/developers/design-documents/idl-build + +{ + 'type': 'none', + 'actions': [{ + 'action_name': 'compute_<(_target_name)', + 'message': 'Computing overall global information about IDL files for <(_target_name)', + + 'inputs': [ + '<(bindings_scripts_dir)/compute_interfaces_info_overall.py', + '<@(input_files)', + ], + 'outputs': [ + '<(output_file)', + ], + 'action': [ + 'python', + '<(bindings_scripts_dir)/compute_interfaces_info_overall.py', + '--write-file-only-if-changed', + '<(write_file_only_if_changed)', + '--', + '<@(input_files)', + '<(output_file)', + ], + }], +} diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/scripts.gni b/chromium/third_party/WebKit/Source/bindings/scripts/scripts.gni new file mode 100644 index 00000000000..f606a56439a --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/scripts.gni @@ -0,0 +1,202 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/WebKit/Source/bindings/core/v8/generated.gni") +import("//third_party/WebKit/Source/bindings/modules/idl.gni") +import("//third_party/WebKit/Source/bindings/modules/modules.gni") + +bindings_scripts_dir = get_path_info(".", "abspath") +bindings_scripts_output_dir = "$root_gen_dir/blink/bindings/scripts" + +# Replacing <(DEPTH) with "/" makes paths like "<(DEPTH)/foo" absolute. +_gypi = exec_script( + "//build/gypi_to_gn.py", + [ rebase_path("scripts.gypi"), + "--replace=<(DEPTH)=/" ], + "scope", + [ "scripts.gypi" ]) + +jinja_module_files = get_path_info(_gypi.jinja_module_files, "abspath") +idl_lexer_parser_files = get_path_info(_gypi.idl_lexer_parser_files, "abspath") +idl_compiler_files = get_path_info(_gypi.idl_compiler_files, "abspath") + +# Calls the compute_interfaces_info_individual script. +# +# Parameters: +# sources_static = list of IDL files to pass as inputs +# sources_generated = list of generated IDL files to pass as inputs +# component_dir = name if subdirectory (one word, no slashes) of component. +# output_file = pickle file to write +# +# FIXME: Note the static/generated split is for consistency with GYP. This +# split is not necessary in the GN build and could be combined into a single +# "sources". +template("compute_interfaces_info_individual") { + action(target_name) { + script = "$bindings_scripts_dir/compute_interfaces_info_individual.py" + if (defined(invoker.visibility)) { + visibility = invoker.visibility + } + + # Save static list to temp file to avoid blowing out command-line length + # limit. + file_list = "$target_gen_dir/${target_name}_file_list.txt" + write_file(file_list, rebase_path(invoker.sources_static, root_build_dir)) + + source_prereqs = [ + "$bindings_scripts_dir/utilities.py", + file_list, + ] + invoker.sources_static + invoker.sources_generated + + outputs = [ + invoker.output_file + ] + + args = [ + "--component-dir", invoker.component_dir, + "--idl-files-list", rebase_path(file_list, root_build_dir), + "--interfaces-info-file", + rebase_path(invoker.output_file, root_build_dir), + "--write-file-only-if-changed=1", + "--", + ] + rebase_path(invoker.sources_generated, root_build_dir) + + deps = [ + # FIXME: should be {modules|core}_generated_idls + # http://crbug.com/358074 + "//third_party/WebKit/Source/bindings:generated_idls", + ] + } +} + +# Calls generate_event_interfaces +# +# Parameters: +# sources = A list of IDL files to process. +# output_file = The .in file to write, relative to the blink_gen_dir. +# suffix = (Optional) String to be passed to script via --suffix +template("generate_event_interfaces") { + action(target_name) { + # Write the file list to a unique temp file to avoid blowing out the + # command line length limit. + idl_files_list = "$target_gen_dir/${target_name}_file_list.tmp" + write_file(idl_files_list, + rebase_path(invoker.sources, root_build_dir)) + + source_prereqs = [ + "//third_party/WebKit/Source/bindings/scripts/utilities.py", + idl_files_list, + ] + invoker.sources + + output_file = "$root_gen_dir/blink/" + invoker.output_file + outputs = [ output_file ] + + script = "//third_party/WebKit/Source/bindings/scripts/generate_event_interfaces.py" + args = [ + "--event-idl-files-list", + rebase_path(idl_files_list, root_build_dir), + "--event-interfaces-file", + rebase_path(output_file, root_build_dir), + "--write-file-only-if-changed=1", # Always true for Ninja. + ] + + if (defined(invoker.suffix)) { + args += [ "--suffix", invoker.suffix ] + } + } +} + +# Runs the idl_compiler script over a list of sources. +# +# Parameters: +# sources = list of IDL files to compile +# output_dir = string containing the directory to put the output files. +template("idl_compiler") { + output_dir = invoker.output_dir + + action_foreach(target_name) { + # TODO(brettw) GYP adds a "-S before the script name to skip "import site" to + # speed up startup. Figure out if we need this and do something similar (not + # really expressible in GN now). + script = "//third_party/WebKit/Source/bindings/scripts/idl_compiler.py" + + source_prereqs = + idl_lexer_parser_files + # to be explicit (covered by parsetab) + idl_compiler_files + source_prereqs += [ + "$bindings_scripts_output_dir/lextab.py", + "$bindings_scripts_output_dir/parsetab.pickle", + "$bindings_scripts_output_dir/cached_jinja_templates.stamp", + "$bindings_dir/IDLExtendedAttributes.txt", + # If the dependency structure or public interface info (e.g., + # [ImplementedAs]) changes, we rebuild all files, since we're not + # computing dependencies file-by-file in the build. + # This data is generally stable. + "$bindings_modules_output_dir/InterfacesInfoModules.pickle", + ] + # Further, if any dependency (partial interface or implemented + # interface) changes, rebuild everything, since every IDL potentially + # depends on them, because we're not computing dependencies + # file-by-file. + # FIXME: This is too conservative, and causes excess rebuilds: + # compute this file-by-file. http://crbug.com/341748 + # This should theoretically just be the IDL files passed in. + source_prereqs += all_dependency_idl_files + + sources = invoker.sources + outputs = [ + "$output_dir/V8{{source_name_part}}.cpp", + "$output_dir/V8{{source_name_part}}.h", + ] + + args = [ + "--cache-dir", + rebase_path(bindings_scripts_output_dir, root_build_dir), + "--output-dir", + rebase_path(output_dir, root_build_dir), + "--interfaces-info", + rebase_path("$bindings_modules_output_dir/InterfacesInfoModules.pickle", + root_build_dir), + "--write-file-only-if-changed=1", # Always true for Ninja. + "{{source}}", + ] + + deps = [ + # FIXME: should be interfaces_info_core (w/o modules) + # http://crbug.com/358074 + "//third_party/WebKit/Source/bindings/modules:interfaces_info", + + "//third_party/WebKit/Source/bindings/scripts:cached_lex_yacc_tables", + "//third_party/WebKit/Source/bindings/scripts:cached_jinja_templates", + "//third_party/WebKit/Source/core:generated_testing_idls", + ] + } +} + +# Calls the aggregate_generated_bindings script. +# +# Parameters: +# sources = a list of source IDL files. +# component_dir = Name of directory for these files (one word, no slashes). +# outputs = a list of files to write to. +template("aggregate_generated_bindings") { + action(target_name) { + script = "//third_party/WebKit/Source/bindings/scripts/aggregate_generated_bindings.py" + + # Write lists of main IDL files to a file, so that the command lines don't + # exceed OS length limits. + idl_files_list = "$target_gen_dir/${target_name}_file_list.tmp" + write_file(idl_files_list, rebase_path(invoker.sources, root_build_dir)) + + source_prereqs = [ idl_files_list ] + invoker.sources + outputs = invoker.outputs + + args = [ + invoker.component_dir, + rebase_path(idl_files_list, root_build_dir), + "--", + ] + args += rebase_path(invoker.outputs, root_build_dir) + } +} diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/scripts.gyp b/chromium/third_party/WebKit/Source/bindings/scripts/scripts.gyp new file mode 100644 index 00000000000..d8d86871713 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/scripts.gyp @@ -0,0 +1,75 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Pre-caching steps used internally by the IDL compiler +# +# Design doc: http://www.chromium.org/developers/design-documents/idl-build + +{ + 'includes': [ + 'scripts.gypi', + '../bindings.gypi', + '../templates/templates.gypi', + ], + + 'targets': [ +################################################################################ + { + # A separate pre-caching step is *not required* to use lex/parse table + # caching in PLY, as the caches are concurrency-safe. + # However, pre-caching ensures that all compiler processes use the cached + # files (hence maximizing speed), instead of early processes building the + # tables themselves (as they've not yet been written when they start). + # + # GN version: //third_party/WebKit/Source/bindings/scripts:cached_lex_yacc_tables + 'target_name': 'cached_lex_yacc_tables', + 'type': 'none', + 'actions': [{ + 'action_name': 'cache_lex_yacc_tables', + 'inputs': [ + '<@(idl_lexer_parser_files)', + ], + 'outputs': [ + '<(bindings_scripts_output_dir)/lextab.py', + '<(bindings_scripts_output_dir)/parsetab.pickle', + ], + 'action': [ + 'python', + 'blink_idl_parser.py', + '<(bindings_scripts_output_dir)', + ], + 'message': 'Caching PLY lex & yacc lex/parse tables', + }], + }, +################################################################################ + { + # A separate pre-caching step is *required* to use bytecode caching in + # Jinja (which improves speed significantly), as the bytecode cache is + # not concurrency-safe on write; details in code_generator_v8.py. + # + # GN version: //third_party/WebKit/Source/bindings/scripts:cached_jinja_templates + 'target_name': 'cached_jinja_templates', + 'type': 'none', + 'actions': [{ + 'action_name': 'cache_jinja_templates', + 'inputs': [ + '<@(jinja_module_files)', + 'code_generator_v8.py', + '<@(code_generator_template_files)', + ], + 'outputs': [ + '<(bindings_scripts_output_dir)/cached_jinja_templates.stamp', # Dummy to track dependency + ], + 'action': [ + 'python', + 'code_generator_v8.py', + '<(bindings_scripts_output_dir)', + '<(bindings_scripts_output_dir)/cached_jinja_templates.stamp', + ], + 'message': 'Caching bytecode of Jinja templates', + }], + }, +################################################################################ + ], # targets +} diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/scripts.gypi b/chromium/third_party/WebKit/Source/bindings/scripts/scripts.gypi new file mode 100644 index 00000000000..9bf033d7eee --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/scripts.gypi @@ -0,0 +1,59 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + 'bindings_scripts_dir': '.', + 'bindings_scripts_output_dir': '<(SHARED_INTERMEDIATE_DIR)/blink/bindings/scripts', + 'jinja_module_files': [ + # jinja2/__init__.py contains version string, so sufficient for package + '<(DEPTH)/third_party/jinja2/__init__.py', + '<(DEPTH)/third_party/markupsafe/__init__.py', # jinja2 dep + ], + 'idl_lexer_parser_files': [ + # PLY (Python Lex-Yacc) + '<(DEPTH)/third_party/ply/lex.py', + '<(DEPTH)/third_party/ply/yacc.py', + # Web IDL lexer/parser (base parser) + '<(DEPTH)/tools/idl_parser/idl_lexer.py', + '<(DEPTH)/tools/idl_parser/idl_node.py', + '<(DEPTH)/tools/idl_parser/idl_parser.py', + # Blink IDL lexer/parser/constructor + 'blink_idl_lexer.py', + 'blink_idl_parser.py', + ], + 'idl_compiler_files': [ + 'idl_compiler.py', + # Blink IDL front end (ex-lexer/parser) + 'idl_definitions.py', + 'idl_reader.py', + 'idl_types.py', + 'idl_validator.py', + 'interface_dependency_resolver.py', + # V8 code generator + 'code_generator_v8.py', + 'v8_attributes.py', + 'v8_callback_interface.py', + 'v8_globals.py', + 'v8_interface.py', + 'v8_methods.py', + 'v8_types.py', + 'v8_utilities.py', + ], + + 'conditions': [ + # These scripts can skip writing generated files if they are identical + # to the already existing files, which avoids further build steps, like + # recompilation. However, a dependency (earlier build step) having a + # newer timestamp than an output (later build step) confuses some build + # systems, so only use this on ninja, which explicitly supports this use + # case (gyp turns all actions into ninja restat rules). + ['"<(GENERATOR)"=="ninja"', { + 'write_file_only_if_changed': '1', + }, { + 'write_file_only_if_changed': '0', + }], + ], + }, +} diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/code_generator_v8.py b/chromium/third_party/WebKit/Source/bindings/scripts/unstable/code_generator_v8.py deleted file mode 100644 index 21e5ce2cce9..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/code_generator_v8.py +++ /dev/null @@ -1,156 +0,0 @@ -# Copyright (C) 2013 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. - -"""Generate Blink V8 bindings (.h and .cpp files). - -FIXME: Not currently used in build. -This is a rewrite of the Perl IDL compiler in Python, but is not complete. -Once it is complete, we will switch all IDL files over to Python at once. -Until then, please work on the Perl IDL compiler. -For details, see bug http://crbug.com/239771 - -Input: An object of class IdlDefinitions, containing an IDL interface X -Output: V8X.h and V8X.cpp -""" - -import os -import posixpath -import re -import sys - -# jinja2 is in chromium's third_party directory. -module_path, module_name = os.path.split(__file__) -third_party = os.path.join(module_path, os.pardir, os.pardir, os.pardir, os.pardir, os.pardir) -# Insert at front to override system libraries, and after path[0] == script dir -sys.path.insert(1, third_party) -import jinja2 - -templates_dir = os.path.join(module_path, os.pardir, os.pardir, 'templates') - -import v8_callback_interface -from v8_globals import includes -import v8_interface -import v8_types -from v8_utilities import capitalize, cpp_name, conditional_string, v8_class_name - - -class CodeGeneratorV8: - def __init__(self, definitions, interface_name, output_directory, relative_dir_posix, idl_directories, verbose=False): - self.idl_definitions = definitions - self.interface_name = interface_name - self.idl_directories = idl_directories - self.output_directory = output_directory - self.verbose = verbose - # FIXME: remove definitions check when remove write_dummy_header_and_cpp - if not definitions: - return - try: - self.interface = definitions.interfaces[interface_name] - except KeyError: - raise Exception('%s not in IDL definitions' % interface_name) - if self.interface.is_callback: - header_template_filename = 'callback_interface.h' - cpp_template_filename = 'callback_interface.cpp' - self.generate_contents = v8_callback_interface.generate_callback_interface - else: - header_template_filename = 'interface.h' - cpp_template_filename = 'interface.cpp' - self.generate_contents = v8_interface.generate_interface - jinja_env = jinja2.Environment( - loader=jinja2.FileSystemLoader(templates_dir), - keep_trailing_newline=True, # newline-terminate generated files - lstrip_blocks=True, # so can indent control flow tags - trim_blocks=True) - jinja_env.filters.update({ - 'blink_capitalize': capitalize, - 'conditional': conditional_if_endif, - 'runtime_enabled': runtime_enabled_if, - }) - self.header_template = jinja_env.get_template(header_template_filename) - self.cpp_template = jinja_env.get_template(cpp_template_filename) - - class_name = cpp_name(self.interface) - self.include_for_cpp_class = posixpath.join(relative_dir_posix, class_name + '.h') - enumerations = definitions.enumerations - if enumerations: - v8_types.set_enum_types(enumerations) - - def write_dummy_header_and_cpp(self): - # FIXME: fix GYP so these files aren't needed and remove this method - target_interface_name = self.interface_name - header_basename = 'V8%s.h' % target_interface_name - cpp_basename = 'V8%s.cpp' % target_interface_name - contents = """/* - This file is generated just to tell build scripts that {header_basename} and - {cpp_basename} are created for {target_interface_name}.idl, and thus - prevent the build scripts from trying to generate {header_basename} and - {cpp_basename} at every build. This file must not be tried to compile. -*/ -""".format(**locals()) - self.write_file(header_basename, contents) - self.write_file(cpp_basename, contents) - - def write_header_and_cpp(self): - interface = self.interface - template_contents = self.generate_contents(interface) - template_contents['header_includes'].add(self.include_for_cpp_class) - template_contents['header_includes'] = sorted(template_contents['header_includes']) - template_contents['cpp_includes'] = sorted(includes) - - header_basename = v8_class_name(interface) + '.h' - header_file_text = self.header_template.render(template_contents) - self.write_file(header_basename, header_file_text) - - cpp_basename = v8_class_name(interface) + '.cpp' - cpp_file_text = self.cpp_template.render(template_contents) - self.write_file(cpp_basename, cpp_file_text) - - def write_file(self, basename, file_text): - filename = os.path.join(self.output_directory, basename) - with open(filename, 'w') as output_file: - output_file.write(file_text) - - -# [Conditional] -def conditional_if_endif(code, conditional_string): - # Jinja2 filter to generate if/endif directive blocks - if not conditional_string: - return code - return ('#if %s\n' % conditional_string + - code + - '#endif // %s\n' % conditional_string) - - -# [RuntimeEnabled] -def runtime_enabled_if(code, runtime_enabled_function_name): - if not runtime_enabled_function_name: - return code - # Indent if statement to level of original code - indent = re.match(' *', code).group(0) - return ('%sif (%s())\n' % (indent, runtime_enabled_function_name) + - ' %s' % code) diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/idl_compiler.py b/chromium/third_party/WebKit/Source/bindings/scripts/unstable/idl_compiler.py deleted file mode 100755 index b95a759f44b..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/idl_compiler.py +++ /dev/null @@ -1,129 +0,0 @@ -#!/usr/bin/python -# Copyright (C) 2013 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. - -"""Compile an .idl file to Blink V8 bindings (.h and .cpp files). - -FIXME: Not currently used in build. -This is a rewrite of the Perl IDL compiler in Python, but is not complete. -Once it is complete, we will switch all IDL files over to Python at once. -Until then, please work on the Perl IDL compiler. -For details, see bug http://crbug.com/239771 -""" - -import optparse -import os -import pickle -import posixpath -import shlex -import sys - -import code_generator_v8 -import idl_reader - -module_path, _ = os.path.split(__file__) -source_path = os.path.normpath(os.path.join(module_path, os.pardir, os.pardir, os.pardir)) - - -def parse_options(): - parser = optparse.OptionParser() - parser.add_option('--additional-idl-files') - # FIXME: The --dump-json-and-pickle option is only for debugging and will - # be removed once we complete migrating all IDL files from the Perl flow to - # the Python flow. - parser.add_option('--dump-json-and-pickle', action='store_true', default=False) - parser.add_option('--idl-attributes-file') - parser.add_option('--include', dest='idl_directories', action='append') - parser.add_option('--output-directory') - parser.add_option('--interface-dependencies-file') - parser.add_option('--verbose', action='store_true', default=False) - parser.add_option('--write-file-only-if-changed', type='int') - # ensure output comes last, so command line easy to parse via regexes - parser.disable_interspersed_args() - - options, args = parser.parse_args() - if options.output_directory is None: - parser.error('Must specify output directory using --output-directory.') - if options.additional_idl_files is None: - options.additional_idl_files = [] - else: - # additional_idl_files is passed as a string with varied (shell-style) - # quoting, hence needs parsing. - options.additional_idl_files = shlex.split(options.additional_idl_files) - if len(args) != 1: - parser.error('Must specify exactly 1 input file as argument, but %d given.' % len(args)) - options.idl_filename = os.path.realpath(args[0]) - return options - - -def get_relative_dir_posix(filename): - """Returns directory of a local file relative to Source, in POSIX format.""" - relative_path_local = os.path.relpath(filename, source_path) - relative_dir_local = os.path.dirname(relative_path_local) - return relative_dir_local.replace(os.path.sep, posixpath.sep) - - -def write_json_and_pickle(definitions, interface_name, output_directory): - json_string = definitions.to_json() - json_basename = interface_name + '.json' - json_filename = os.path.join(output_directory, json_basename) - with open(json_filename, 'w') as json_file: - json_file.write(json_string) - pickle_basename = interface_name + '.pkl' - pickle_filename = os.path.join(output_directory, pickle_basename) - with open(pickle_filename, 'wb') as pickle_file: - pickle.dump(definitions, pickle_file) - - -def main(): - options = parse_options() - idl_filename = options.idl_filename - basename = os.path.basename(idl_filename) - interface_name, _ = os.path.splitext(basename) - output_directory = options.output_directory - verbose = options.verbose - if verbose: - print idl_filename - relative_dir_posix = get_relative_dir_posix(idl_filename) - - reader = idl_reader.IdlReader(options.interface_dependencies_file, options.additional_idl_files, options.idl_attributes_file, output_directory, verbose) - definitions = reader.read_idl_definitions(idl_filename) - code_generator = code_generator_v8.CodeGeneratorV8(definitions, interface_name, options.output_directory, relative_dir_posix, options.idl_directories, verbose) - if not definitions: - # We generate dummy .h and .cpp files just to tell build scripts - # that outputs have been created. - code_generator.write_dummy_header_and_cpp() - return - if options.dump_json_and_pickle: - write_json_and_pickle(definitions, interface_name, output_directory) - return - code_generator.write_header_and_cpp() - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/idl_definitions.py b/chromium/third_party/WebKit/Source/bindings/scripts/unstable/idl_definitions.py deleted file mode 100644 index ef6ff79466c..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/idl_definitions.py +++ /dev/null @@ -1,446 +0,0 @@ -# Copyright (C) 2013 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. - -"""Blink IDL Intermediate Representation (IR) classes. - -Also JSON export, using legacy Perl terms and format, to ensure that both -parsers produce the same output. -FIXME: remove BaseIdl, JSON export (json_serializable and to_json), and Perl -compatibility functions and hacks once Perl compiler gone. -""" - -# Disable attribute hiding check (else JSONEncoder default raises an error) -# pylint: disable=E0202 -# pylint doesn't understand ABCs. -# pylint: disable=W0232, E0203, W0201 - -import abc -import json -import re - - -# Base classes - - -class BaseIdl: - """Abstract base class, used for JSON serialization.""" - __metaclass__ = abc.ABCMeta - - @abc.abstractmethod - def json_serializable(self): - """Returns a JSON serializable form of the object. - - This should be a dictionary, with keys scoped names of the form - Class::key, where the scope is the class name. - This is so we produce identical output to the Perl code, which uses - the Perl module JSON.pm, which uses this format. - """ - pass - - -class TypedObject: - """Object with a type, such as an Attribute or Operation (return value). - - The type can be an actual type, or can be a typedef, which must be resolved - before passing data to the code generator. - """ - __metaclass__ = abc.ABCMeta - idl_type = None - extended_attributes = None - - def resolve_typedefs(self, typedefs): - """Resolve typedefs to actual types in the object.""" - # Constructors don't have their own return type, because it's the - # interface itself. - if not self.idl_type: - return - # Convert string representation to and from an IdlType object - # to handle parsing of composite types (arrays and sequences) - idl_type_object = IdlType.from_string(self.idl_type) - base_type = idl_type_object.base_type - if base_type in typedefs: - idl_type_object.base_type = typedefs[base_type] - self.idl_type = str(idl_type_object) - - -# IDL classes - - -class IdlDefinitions(BaseIdl): - def __init__(self, callback_functions=None, enumerations=None, exceptions=None, file_name=None, interfaces=None, typedefs=None): - self.callback_functions = callback_functions or {} - self.enumerations = enumerations or {} - self.exceptions = exceptions or {} - self.file_name = file_name or None - self.interfaces = interfaces or {} - # Typedefs are not exposed by bindings; resolve typedefs with the - # actual types and then discard the Typedefs. - # http://www.w3.org/TR/WebIDL/#idl-typedefs - if typedefs: - self.resolve_typedefs(typedefs) - - def resolve_typedefs(self, typedefs): - for callback_function in self.callback_functions.itervalues(): - callback_function.resolve_typedefs(typedefs) - for exception in self.exceptions.itervalues(): - exception.resolve_typedefs(typedefs) - for interface in self.interfaces.itervalues(): - interface.resolve_typedefs(typedefs) - - def json_serializable(self): - return { - 'idlDocument::callbackFunctions': self.callback_functions.values(), - 'idlDocument::enumerations': self.enumerations.values(), - 'idlDocument::fileName': self.file_name, - # Perl treats exceptions as a kind of interface - 'idlDocument::interfaces': sorted(self.exceptions.values() + self.interfaces.values()), - } - - def to_json(self, debug=False): - """Returns a JSON string representing the Definitions. - - The JSON output should be identical with the output of the Perl parser, - specifically the function serializeJSON in idl_serializer.pm, - which takes a Perl object created by idl_parser.pm. - """ - # Sort so order consistent, allowing comparison of output - if debug: - # indent turns on pretty-printing for legibility - return json.dumps(self, cls=IdlEncoder, sort_keys=True, indent=4) - # Use compact separators so output identical to Perl - return json.dumps(self, cls=IdlEncoder, sort_keys=True, separators=(',', ':')) - - -class IdlCallbackFunction(BaseIdl, TypedObject): - def __init__(self, name=None, idl_type=None, arguments=None): - self.idl_type = idl_type - self.name = name - self.arguments = arguments or [] - - def resolve_typedefs(self, typedefs): - TypedObject.resolve_typedefs(self, typedefs) - for argument in self.arguments: - argument.resolve_typedefs(typedefs) - raise ValueError('Typedefs in callback functions are untested!') - - def json_serializable(self): - return { - 'callbackFunction::name': self.name, - 'callbackFunction::type': self.idl_type, - 'callbackFunction::parameters': self.arguments, - } - - -class IdlEnum(BaseIdl): - def __init__(self, name=None, values=None): - self.name = name - self.values = values or [] - - def json_serializable(self): - return { - 'domEnum::name': self.name, - 'domEnum::values': self.values, - } - - -class IdlInterface(BaseIdl): - def __init__(self, attributes=None, constants=None, constructors=None, custom_constructors=None, extended_attributes=None, operations=None, is_callback=False, is_partial=False, name=None, parent=None): - self.attributes = attributes or [] - self.constants = constants or [] - self.constructors = constructors or [] - self.custom_constructors = custom_constructors or [] - self.extended_attributes = extended_attributes or {} - self.operations = operations or [] - self.is_callback = is_callback - self.is_partial = is_partial - self.name = name - self.parent = parent - - def resolve_typedefs(self, typedefs): - for attribute in self.attributes: - attribute.resolve_typedefs(typedefs) - for constant in self.constants: - constant.resolve_typedefs(typedefs) - for constructor in self.constructors: - constructor.resolve_typedefs(typedefs) - for custom_constructor in self.custom_constructors: - custom_constructor.resolve_typedefs(typedefs) - for operation in self.operations: - operation.resolve_typedefs(typedefs) - - def json_serializable(self): - return { - 'domInterface::attributes': self.attributes, - 'domInterface::constants': self.constants, - 'domInterface::constructors': self.constructors, - 'domInterface::customConstructors': self.custom_constructors, - 'domInterface::extendedAttributes': none_to_value_is_missing(self.extended_attributes), - 'domInterface::functions': self.operations, - 'domInterface::isException': None, - 'domInterface::isCallback': boolean_to_perl(false_to_none(self.is_callback)), - 'domInterface::isPartial': false_to_none(self.is_partial), - 'domInterface::name': self.name, - 'domInterface::parent': self.parent, - } - - -class IdlException(BaseIdl): - def __init__(self, name=None, constants=None, operations=None, attributes=None, extended_attributes=None): - self.attributes = attributes or [] - self.constants = constants or [] - self.extended_attributes = extended_attributes or {} - self.operations = operations or [] - self.name = name - - def resolve_typedefs(self, typedefs): - for constant in self.constants: - constant.resolve_typedefs(typedefs) - for attribute in self.attributes: - attribute.resolve_typedefs(typedefs) - for operations in self.operations: - operations.resolve_typedefs(typedefs) - - def json_serializable(self): - return { - # Perl code treats Exceptions as a kind of Interface - 'domInterface::name': self.name, - 'domInterface::attributes': self.attributes, - 'domInterface::constants': self.constants, - 'domInterface::extendedAttributes': none_to_value_is_missing(self.extended_attributes), - 'domInterface::functions': self.operations, - # These values don't vary for exceptions - 'domInterface::constructors': [], - 'domInterface::customConstructors': [], - 'domInterface::isException': 1, - 'domInterface::isCallback': None, - 'domInterface::isPartial': None, - 'domInterface::parent': None, - } - - -class IdlAttribute(BaseIdl, TypedObject): - def __init__(self, idl_type=None, extended_attributes=None, getter_exceptions=None, is_nullable=False, is_static=False, is_read_only=False, name=None, setter_exceptions=None): - self.idl_type = idl_type - self.extended_attributes = extended_attributes or {} - self.getter_exceptions = getter_exceptions or [] - self.is_nullable = is_nullable - self.is_static = is_static - self.is_read_only = is_read_only - self.name = name - self.setter_exceptions = setter_exceptions or [] - - def json_serializable(self): - return { - 'domAttribute::extendedAttributes': none_to_value_is_missing(self.extended_attributes), - 'domAttribute::getterExceptions': self.getter_exceptions, - 'domAttribute::isNullable': boolean_to_perl_quoted(false_to_none(self.is_nullable)), - 'domAttribute::isReadOnly': boolean_to_perl(false_to_none(self.is_read_only)), - 'domAttribute::isStatic': boolean_to_perl(false_to_none(self.is_static)), - 'domAttribute::name': self.name, - 'domAttribute::setterExceptions': self.setter_exceptions, - 'domAttribute::type': self.idl_type, - } - - -class IdlConstant(BaseIdl, TypedObject): - def __init__(self, name=None, idl_type=None, value=None, extended_attributes=None): - self.idl_type = idl_type - self.extended_attributes = extended_attributes or {} - self.name = name - self.value = value - - def json_serializable(self): - return { - 'domConstant::extendedAttributes': none_to_value_is_missing(self.extended_attributes), - 'domConstant::name': self.name, - 'domConstant::type': self.idl_type, - 'domConstant::value': self.value, - } - - -class IdlOperation(BaseIdl, TypedObject): - def __init__(self, is_static=False, name=None, idl_type=None, extended_attributes=None, specials=None, arguments=None, overloaded_index=None): - self.is_static = is_static - self.name = name or '' - self.idl_type = idl_type - self.extended_attributes = extended_attributes or {} - self.specials = specials or [] - self.arguments = arguments or [] - # FIXME: remove overloaded_index (only here for Perl compatibility), - # as overloading is handled in code generator (v8_interface.py). - self.overloaded_index = overloaded_index - - def resolve_typedefs(self, typedefs): - TypedObject.resolve_typedefs(self, typedefs) - for argument in self.arguments: - argument.resolve_typedefs(typedefs) - - def json_serializable(self): - return { - 'domFunction::extendedAttributes': none_to_value_is_missing(self.extended_attributes), - 'domFunction::isStatic': boolean_to_perl(false_to_none(self.is_static)), - 'domFunction::name': self.name, - 'domFunction::overloadedIndex': self.overloaded_index, - 'domFunction::parameters': self.arguments, - 'domFunction::specials': self.specials, - 'domFunction::type': self.idl_type, - } - - -class IdlArgument(BaseIdl, TypedObject): - def __init__(self, name=None, idl_type=None, extended_attributes=None, is_optional=False, is_nullable=None, is_variadic=False): - self.idl_type = idl_type - self.extended_attributes = extended_attributes or {} - # FIXME: boolean values are inconsistent. - # The below hack is so that generated JSON is identical to - # Perl-generated JSON, where the exact values depend on the code path. - # False and None (Perl: 0 and undef) are semantically interchangeable, - # but yield different JSON. - # Once Perl removed, have all default to False. - if is_optional is None: - is_optional = False - if is_variadic is None: - is_variadic = False - self.is_nullable = is_nullable # (T?) - self.is_optional = is_optional # (optional T) - self.is_variadic = is_variadic # (T...) - self.name = name - - def json_serializable(self): - return { - 'domParameter::extendedAttributes': none_to_value_is_missing(self.extended_attributes), - 'domParameter::isNullable': boolean_to_perl_quoted(self.is_nullable), - 'domParameter::isOptional': boolean_to_perl(self.is_optional), - 'domParameter::isVariadic': boolean_to_perl(self.is_variadic), - 'domParameter::name': self.name, - 'domParameter::type': self.idl_type, - } - -# Type classes - - -class IdlType: - # FIXME: replace type strings with these objects, - # so don't need to parse everywhere types are used. - # Types are stored internally as strings, not objects, - # e.g., as 'sequence<Foo>' or 'Foo[]', - # hence need to parse the string whenever a type is used. - # FIXME: incorporate Nullable, Variadic, etc. - # FIXME: properly should nest types - # Formally types are nested, e.g., short?[] vs. short[]?, - # but in practice these complex types aren't used and can treat - # as orthogonal properties. - def __init__(self, base_type, is_array=False, is_sequence=False): - if is_array and is_sequence: - raise ValueError('Array of Sequences are not allowed.') - self.base_type = base_type - self.is_array = is_array - self.is_sequence = is_sequence - - def __str__(self): - type_string = self.base_type - if self.is_array: - return type_string + '[]' - if self.is_sequence: - return 'sequence<%s>' % type_string - return type_string - - @classmethod - def from_string(cls, type_string): - sequence_re = r'^sequence<([^>]*)>$' - if type_string.endswith('[]'): - type_string = type_string[:-2] - sequence_match = re.match(sequence_re, type_string) - if sequence_match: - raise ValueError('Array of Sequences are not allowed.') - return cls(type_string, is_array=True) - sequence_match = re.match(sequence_re, type_string) - if sequence_match: - base_type = sequence_match.group(1) - return cls(base_type, is_sequence=True) - return cls(type_string) - - -class IdlUnionType(BaseIdl): - def __init__(self, union_member_types=None): - self.union_member_types = union_member_types or [] - - def json_serializable(self): - return { - 'UnionType::unionMemberTypes': self.union_member_types, - } - - -# Perl JSON compatibility functions - -def none_to_value_is_missing(extended_attributes): - # Perl IDL Parser uses 'VALUE_IS_MISSING' for null values in - # extended attributes, so add this as a filter when exporting to JSON. - new_extended_attributes = {} - for key, value in extended_attributes.iteritems(): - if value is None: - new_extended_attributes[key] = 'VALUE_IS_MISSING' - else: - new_extended_attributes[key] = value - return new_extended_attributes - - -def boolean_to_perl(value): - # Perl stores booleans as 1, 0, or undefined (JSON null); - # convert to this format. - if value is None: - return None - return int(value) - - -def boolean_to_perl_quoted(value): - # Bug-for-bug compatibility with Perl. - # The value of isNullable is quoted ('1', '0', or undefined), rather than - # an integer, so add quotes. - if value is None: - return None - return str(int(value)) - - -def false_to_none(value): - # The Perl parser generally uses undefined (Python None) rather than False - # for boolean flags, because the value is simply left undefined, rather than - # explicitly set to False. - if value is False: - return None - return value - - -# JSON export - - -class IdlEncoder(json.JSONEncoder): - def default(self, obj): - if isinstance(obj, BaseIdl): - return obj.json_serializable() - return json.JSONEncoder.default(self, obj) diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/idl_definitions_builder.py b/chromium/third_party/WebKit/Source/bindings/scripts/unstable/idl_definitions_builder.py deleted file mode 100644 index 720c014de24..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/idl_definitions_builder.py +++ /dev/null @@ -1,511 +0,0 @@ -# Copyright (C) 2013 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. - -"""Builds an IdlDefinitions object from an AST (produced by blink_idl_parser).""" - -import os - -from idl_definitions import IdlDefinitions, IdlInterface, IdlException, IdlOperation, IdlCallbackFunction, IdlArgument, IdlAttribute, IdlConstant, IdlEnum, IdlUnionType - -SPECIAL_KEYWORD_LIST = ['GETTER', 'SETTER', 'DELETER'] -STANDARD_TYPEDEFS = { - # http://www.w3.org/TR/WebIDL/#common-DOMTimeStamp - 'DOMTimeStamp': 'unsigned long long', -} - -def build_idl_definitions_from_ast(node): - if node is None: - return None - node_class = node.GetClass() - if node_class != 'File': - raise ValueError('Unrecognized node class: %s' % node_class) - return file_node_to_idl_definitions(node) - - -def file_node_to_idl_definitions(node): - callback_functions = {} - enumerations = {} - exceptions = {} - interfaces = {} - typedefs = STANDARD_TYPEDEFS - - # FIXME: only needed for Perl, remove later - file_name = os.path.abspath(node.GetName()) - - children = node.GetChildren() - for child in children: - child_class = child.GetClass() - if child_class == 'Interface': - interface = interface_node_to_idl_interface(child) - interfaces[interface.name] = interface - elif child_class == 'Exception': - exception = exception_node_to_idl_exception(child) - exceptions[exception.name] = exception - elif child_class == 'Typedef': - type_name = child.GetName() - typedefs[type_name] = typedef_node_to_type(child) - elif child_class == 'Enum': - enumeration = enum_node_to_idl_enum(child) - enumerations[enumeration.name] = enumeration - elif child_class == 'Callback': - callback_function = callback_node_to_idl_callback_function(child) - callback_functions[callback_function.name] = callback_function - elif child_class == 'Implements': - # Implements is handled at the interface merging step - pass - else: - raise ValueError('Unrecognized node class: %s' % child_class) - - return IdlDefinitions(callback_functions=callback_functions, enumerations=enumerations, exceptions=exceptions, file_name=file_name, interfaces=interfaces, typedefs=typedefs) - -# Constructors for Interface definitions and interface members - - -def interface_node_to_idl_interface(node): - attributes = [] - constants = [] - constructors = None - custom_constructors = None - extended_attributes = None - operations = [] - is_callback = node.GetProperty('CALLBACK') or False - # FIXME: uppercase 'Partial' => 'PARTIAL' in base IDL parser - is_partial = node.GetProperty('Partial') or False - name = node.GetName() - parent = None - - children = node.GetChildren() - for child in children: - child_class = child.GetClass() - if child_class == 'Attribute': - attributes.append(attribute_node_to_idl_attribute(child)) - elif child_class == 'Const': - constants.append(constant_node_to_idl_constant(child)) - elif child_class == 'ExtAttributes': - extended_attributes = ext_attributes_node_to_extended_attributes(child) - constructors, custom_constructors = extended_attributes_to_constructors(extended_attributes) - clear_constructor_attributes(extended_attributes) - elif child_class == 'Operation': - operations.append(operation_node_to_idl_operation(child)) - elif child_class == 'Inherit': - parent = child.GetName() - else: - raise ValueError('Unrecognized node class: %s' % child_class) - - return IdlInterface(name=name, attributes=attributes, constants=constants, constructors=constructors, custom_constructors=custom_constructors, extended_attributes=extended_attributes, operations=operations, is_callback=is_callback, is_partial=is_partial, parent=parent) - - -def attribute_node_to_idl_attribute(node): - idl_type = None - extended_attributes = {} - is_nullable = False - is_read_only = node.GetProperty('READONLY') or False - is_static = node.GetProperty('STATIC') or False - name = node.GetName() - - children = node.GetChildren() - for child in children: - child_class = child.GetClass() - if child_class == 'Type': - idl_type = type_node_to_type(child) - is_nullable = child.GetProperty('NULLABLE') or False - elif child_class == 'ExtAttributes': - extended_attributes = ext_attributes_node_to_extended_attributes(child) - else: - raise ValueError('Unrecognized node class: %s' % child_class) - - return IdlAttribute(idl_type=idl_type, extended_attributes=extended_attributes, is_nullable=is_nullable, is_read_only=is_read_only, is_static=is_static, name=name) - - -def constant_node_to_idl_constant(node): - name = node.GetName() - - children = node.GetChildren() - num_children = len(children) - if num_children < 2 or num_children > 3: - raise ValueError('Expected 2 or 3 children, got %s' % num_children) - - type_node = children[0] - # ConstType is more limited than Type, so subtree is smaller and we don't - # use the full type_node_to_type function. - idl_type = type_node_inner_to_type(type_node) - - value_node = children[1] - value_node_class = value_node.GetClass() - if value_node_class != 'Value': - raise ValueError('Expected Value node, got %s' % value_node_class) - value = value_node.GetName() - - extended_attributes = None - if num_children == 3: - ext_attributes_node = children[2] - extended_attributes = ext_attributes_node_to_extended_attributes(ext_attributes_node) - - return IdlConstant(idl_type=idl_type, extended_attributes=extended_attributes, name=name, value=value) - - -def operation_node_to_idl_operation(node): - name = node.GetName() - # FIXME: AST should use None internally - if name == '_unnamed_': - name = None - - is_static = node.GetProperty('STATIC') or False - specials = [] - property_dictionary = node.GetProperties() - for special_keyword in SPECIAL_KEYWORD_LIST: - if special_keyword in property_dictionary: - specials.append(special_keyword.lower()) - - extended_attributes = None - arguments = [] - return_type = None - children = node.GetChildren() - for child in children: - child_class = child.GetClass() - if child_class == 'Arguments': - arguments = arguments_node_to_arguments(child) - elif child_class == 'Type': - return_type = type_node_to_type(child) - elif child_class == 'ExtAttributes': - extended_attributes = ext_attributes_node_to_extended_attributes(child) - else: - raise ValueError('Unrecognized node class: %s' % child_class) - - return IdlOperation(name=name, idl_type=return_type, extended_attributes=extended_attributes, is_static=is_static, arguments=arguments, specials=specials) - - -def arguments_node_to_arguments(node): - # [Constructor] and [CustomConstructor] without arguments (the bare form) - # have None instead of an arguments node, but have the same meaning as using - # an empty argument list, [Constructor()], so special-case this. - # http://www.w3.org/TR/WebIDL/#Constructor - if node is None: - return [] - arguments = [] - argument_node_list = node.GetChildren() - for argument_node in argument_node_list: - arguments.append(argument_node_to_idl_argument(argument_node)) - return arguments - - -def argument_node_to_idl_argument(node): - name = node.GetName() - - idl_type = None - extended_attributes = {} - # FIXME: Boolean values are inconsistent due to Perl compatibility. - # Make all default to False once Perl removed. - is_nullable = False - is_optional = node.GetProperty('OPTIONAL') - is_variadic = None - children = node.GetChildren() - for child in children: - child_class = child.GetClass() - if child_class == 'Type': - idl_type = type_node_to_type(child) - # FIXME: Doesn't handle nullable arrays (Foo[]?), and arrays of - # nullable (Foo?[]) are treated as nullable arrays. No actual use. - is_nullable = child.GetProperty('NULLABLE') - elif child_class == 'ExtAttributes': - extended_attributes = ext_attributes_node_to_extended_attributes(child) - elif child_class == 'Argument': - child_name = child.GetName() - if child_name != '...': - raise ValueError('Unrecognized Argument node; expected "...", got "%s"' % child_name) - is_variadic = child.GetProperty('ELLIPSIS') or False - else: - raise ValueError('Unrecognized node class: %s' % child_class) - - return IdlArgument(name=name, idl_type=idl_type, extended_attributes=extended_attributes, is_nullable=is_nullable, is_optional=is_optional, is_variadic=is_variadic) - -# Constructors for for non-interface definitions - - -def callback_node_to_idl_callback_function(node): - name = node.GetName() - children = node.GetChildren() - num_children = len(children) - if num_children != 2: - raise ValueError('Expected 2 children, got %s' % num_children) - - type_node = children[0] - idl_type = type_node_to_type(type_node) - - arguments_node = children[1] - arguments_node_class = arguments_node.GetClass() - if arguments_node_class != 'Arguments': - raise ValueError('Expected Value node, got %s' % arguments_node_class) - arguments = arguments_node_to_arguments(arguments_node) - - return IdlCallbackFunction(name=name, idl_type=idl_type, arguments=arguments) - - -def enum_node_to_idl_enum(node): - name = node.GetName() - values = [] - for child in node.GetChildren(): - values.append(child.GetName()) - return IdlEnum(name=name, values=values) - - -def exception_operation_node_to_idl_operation(node): - # Needed to handle one case in DOMException.idl: - # // Override in a Mozilla compatible format - # [NotEnumerable] DOMString toString(); - # FIXME: can we remove this? replace with a stringifier? - extended_attributes = {} - name = node.GetName() - children = node.GetChildren() - if len(children) < 1 or len(children) > 2: - raise ValueError('ExceptionOperation node with %s children, expected 1 or 2' % len(children)) - - type_node = children[0] - return_type = type_node_to_type(type_node) - - if len(children) > 1: - ext_attributes_node = children[1] - extended_attributes = ext_attributes_node_to_extended_attributes(ext_attributes_node) - - return IdlOperation(name=name, idl_type=return_type, extended_attributes=extended_attributes) - - -def exception_node_to_idl_exception(node): - # Exceptions are similar to Interfaces, but simpler - attributes = [] - constants = [] - extended_attributes = None - operations = [] - name = node.GetName() - - children = node.GetChildren() - for child in children: - child_class = child.GetClass() - if child_class == 'Attribute': - attribute = attribute_node_to_idl_attribute(child) - attributes.append(attribute) - elif child_class == 'Const': - constants.append(constant_node_to_idl_constant(child)) - elif child_class == 'ExtAttributes': - extended_attributes = ext_attributes_node_to_extended_attributes(child) - elif child_class == 'ExceptionOperation': - operations.append(exception_operation_node_to_idl_operation(child)) - else: - raise ValueError('Unrecognized node class: %s' % child_class) - - return IdlException(name=name, attributes=attributes, constants=constants, extended_attributes=extended_attributes, operations=operations) - - -def typedef_node_to_type(node): - children = node.GetChildren() - if len(children) != 1: - raise ValueError('Typedef node with %s children, expected 1' % len(children)) - child = children[0] - child_class = child.GetClass() - if child_class != 'Type': - raise ValueError('Unrecognized node class: %s' % child_class) - return type_node_to_type(child) - -# Extended attributes - - -def ext_attributes_node_to_extended_attributes(node): - """ - Returns: - Dictionary of {ExtAttributeName: ExtAttributeValue}. - Value is usually a string, with three exceptions: - Constructors: value is a list of Arguments nodes, corresponding to - possibly signatures of the constructor. - CustomConstructors: value is a list of Arguments nodes, corresponding to - possibly signatures of the custom constructor. - NamedConstructor: value is a Call node, corresponding to the single - signature of the named constructor. - """ - # Primarily just make a dictionary from the children. - # The only complexity is handling various types of constructors: - # Constructors and Custom Constructors can have duplicate entries due to - # overloading, and thus are stored in temporary lists. - # However, Named Constructors cannot be overloaded, and thus do not have - # a list. - # FIXME: move Constructor logic into separate function, instead of modifying - # extended attributes in-place. - constructors = [] - custom_constructors = [] - extended_attributes = {} - - attribute_list = node.GetChildren() - for attribute in attribute_list: - name = attribute.GetName() - children = attribute.GetChildren() - if name in ['Constructor', 'CustomConstructor', 'NamedConstructor']: - child = None - child_class = None - if children: - if len(children) > 1: - raise ValueError('ExtAttributes node with %s children, expected at most 1' % len(children)) - child = children[0] - child_class = child.GetClass() - if name == 'Constructor': - if child_class and child_class != 'Arguments': - raise ValueError('Constructor only supports Arguments as child, but has child of class: %s' % child_class) - constructors.append(child) - elif name == 'CustomConstructor': - if child_class and child_class != 'Arguments': - raise ValueError('Custom Constructor only supports Arguments as child, but has child of class: %s' % child_class) - custom_constructors.append(child) - else: # name == 'NamedConstructor' - if child_class and child_class != 'Call': - raise ValueError('Named Constructor only supports Call as child, but has child of class: %s' % child_class) - extended_attributes[name] = child - elif children: - raise ValueError('Non-constructor ExtAttributes node with children: %s' % name) - else: - value = attribute.GetProperty('VALUE') - extended_attributes[name] = value - - # Store constructors and custom constructors in special list attributes, - # which are deleted later. Note plural in key. - if constructors: - extended_attributes['Constructors'] = constructors - if custom_constructors: - extended_attributes['CustomConstructors'] = custom_constructors - - return extended_attributes - - -def extended_attributes_to_constructors(extended_attributes): - """Returns constructors and custom_constructors (lists of IdlOperations). - - Auxiliary function for interface_node_to_idl_interface. - """ - constructors = [] - custom_constructors = [] - if 'Constructors' in extended_attributes: - constructor_list = extended_attributes['Constructors'] - # If not overloaded, have index 0, otherwise index from 1 - overloaded_index = 0 if len(constructor_list) == 1 else 1 - for arguments_node in constructor_list: - name = 'Constructor' - arguments = arguments_node_to_arguments(arguments_node) - constructor = IdlOperation(name=name, extended_attributes=extended_attributes, overloaded_index=overloaded_index, arguments=arguments) - constructors.append(constructor) - overloaded_index += 1 - - if 'CustomConstructors' in extended_attributes: - custom_constructor_list = extended_attributes['CustomConstructors'] - # If not overloaded, have index 0, otherwise index from 1 - overloaded_index = 0 if len(custom_constructor_list) == 1 else 1 - for arguments_node in custom_constructor_list: - name = 'CustomConstructor' - arguments = arguments_node_to_arguments(arguments_node) - custom_constructor = IdlOperation(name=name, extended_attributes=extended_attributes, overloaded_index=overloaded_index, arguments=arguments) - custom_constructors.append(custom_constructor) - overloaded_index += 1 - - if 'NamedConstructor' in extended_attributes: - name = 'NamedConstructor' - call_node = extended_attributes['NamedConstructor'] - extended_attributes['NamedConstructor'] = call_node.GetName() - overloaded_index = None # named constructors are not overloaded - children = call_node.GetChildren() - if len(children) != 1: - raise ValueError('NamedConstructor node expects 1 child, got %s.' % len(children)) - arguments_node = children[0] - arguments = arguments_node_to_arguments(arguments_node) - named_constructor = IdlOperation(name=name, extended_attributes=extended_attributes, overloaded_index=overloaded_index, arguments=arguments) - # FIXME: should return named_constructor separately; appended for Perl - constructors.append(named_constructor) - - return constructors, custom_constructors - - -def clear_constructor_attributes(extended_attributes): - # Deletes Constructor*s* (plural), sets Constructor (singular) - if 'Constructors' in extended_attributes: - del extended_attributes['Constructors'] - extended_attributes['Constructor'] = None - if 'CustomConstructors' in extended_attributes: - del extended_attributes['CustomConstructors'] - extended_attributes['CustomConstructor'] = None - - -# Types - - -def type_node_to_type(node): - children = node.GetChildren() - if len(children) < 1 or len(children) > 2: - raise ValueError('Type node expects 1 or 2 children (type + optional array []), got %s (multi-dimensional arrays are not supported).' % len(children)) - - type_node_child = children[0] - idl_type = type_node_inner_to_type(type_node_child) - - if len(children) == 2: - array_node = children[1] - array_node_class = array_node.GetClass() - if array_node_class != 'Array': - raise ValueError('Expected Array node as TypeSuffix, got %s node.' % array_node_class) - idl_type += '[]' - - return idl_type - - -def type_node_inner_to_type(node): - node_class = node.GetClass() - # Note Type*r*ef, not Typedef, meaning the type is an identifier, thus - # either a typedef shorthand (but not a Typedef declaration itself) or an - # interface type. We do not distinguish these, and just use the type name. - if node_class in ['PrimitiveType', 'Typeref']: - return node.GetName() - elif node_class == 'Any': - return 'any' - elif node_class == 'Sequence': - return sequence_node_to_type(node) - elif node_class == 'UnionType': - return union_type_node_to_idl_union_type(node) - raise ValueError('Unrecognized node class: %s' % node_class) - - -def sequence_node_to_type(node): - children = node.GetChildren() - if len(children) != 1: - raise ValueError('Sequence node expects exactly 1 child, got %s' % len(children)) - sequence_child = children[0] - sequence_child_class = sequence_child.GetClass() - if sequence_child_class != 'Type': - raise ValueError('Unrecognized node class: %s' % sequence_child_class) - sequence_type = type_node_to_type(sequence_child) - return 'sequence<%s>' % sequence_type - - -def union_type_node_to_idl_union_type(node): - union_member_types = [] - for member_type_node in node.GetChildren(): - member_type = type_node_to_type(member_type_node) - union_member_types.append(member_type) - return IdlUnionType(union_member_types=union_member_types) diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/idl_reader.py b/chromium/third_party/WebKit/Source/bindings/scripts/unstable/idl_reader.py deleted file mode 100644 index eece7425ae6..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/idl_reader.py +++ /dev/null @@ -1,80 +0,0 @@ -# Copyright (C) 2013 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. - -"""Read an IDL file or complete IDL interface, producing an IdlDefinitions object.""" - -import os.path - -import blink_idl_parser -import idl_definitions_builder -import idl_validator -import interface_dependency_resolver - - -class IdlReader: - def __init__(self, interface_dependencies_filename=None, additional_idl_filenames=None, idl_attributes_filename=None, outputdir='', verbose=False): - if idl_attributes_filename: - self.extended_attribute_validator = idl_validator.IDLExtendedAttributeValidator(idl_attributes_filename) - else: - self.extended_attribute_validator = None - - if interface_dependencies_filename: - self.interface_dependency_resolver = interface_dependency_resolver.InterfaceDependencyResolver(interface_dependencies_filename, additional_idl_filenames, self) - else: - self.interface_dependency_resolver = None - - self.parser = blink_idl_parser.BlinkIDLParser(outputdir=outputdir, verbose=verbose) - - def read_idl_definitions(self, idl_filename): - """Returns an IdlDefinitions object for an IDL file, including all dependencies.""" - basename = os.path.basename(idl_filename) - interface_name, _ = os.path.splitext(basename) - definitions = self.read_idl_file(idl_filename) - if self.interface_dependency_resolver: - should_generate_bindings = self.interface_dependency_resolver.resolve_dependencies(definitions, interface_name) - if not should_generate_bindings: - return None - return definitions - - def read_idl_file(self, idl_filename): - """Returns an IdlDefinitions object for an IDL file, without any dependencies.""" - ast = blink_idl_parser.parse_file(self.parser, idl_filename) - definitions = idl_definitions_builder.build_idl_definitions_from_ast(ast) - if self.extended_attribute_validator: - try: - self.extended_attribute_validator.validate_extended_attributes(definitions) - except idl_validator.IDLInvalidExtendedAttributeError as error: - raise idl_validator.IDLInvalidExtendedAttributeError("""IDL ATTRIBUTE ERROR in file %s: - %s -If you want to add a new IDL extended attribute, please add it to - bindings/IDLExtendedAttributes.txt -and add an explanation to the Blink IDL documentation at: - http://www.chromium.org/blink/webidl/blink-idl-extended-attributes - """ % (idl_filename, str(error))) - - return definitions diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/interface_dependency_resolver.py b/chromium/third_party/WebKit/Source/bindings/scripts/unstable/interface_dependency_resolver.py deleted file mode 100644 index 592be907051..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/interface_dependency_resolver.py +++ /dev/null @@ -1,211 +0,0 @@ -# Copyright (C) 2013 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. - -"""Resolve interface dependencies, producing a merged IdlDefinitions object. - -This library computes interface dependencies (partial interfaces and -implements), reads the dependency files, and merges them to the IdlDefinitions -for the main IDL file, producing an IdlDefinitions object representing the -entire interface. - -It also checks whether a file should have bindings generated, or whether -instead it is just a dependency. -""" - -import os.path - - -class InterfaceNotFoundError(Exception): - """Raised if (partial) interface not found in target IDL file.""" - pass - - -class InvalidPartialInterfaceError(Exception): - """Raised if a file listed as a partial interface is not in fact so.""" - pass - - -class InterfaceDependencyResolver: - def __init__(self, interface_dependencies_filename, additional_idl_filenames, reader): - """Inits dependency resolver. - - Args: - interface_dependencies_filename: - filename of dependencies file (produced by - compute_dependencies.py) - additional_idl_filenames: - list of additional files, not listed in - interface_dependencies_file, for which bindings should - nonetheless be generated - reader: - IdlReader, used for reading dependency files - """ - self.interface_dependencies = read_interface_dependencies_file(interface_dependencies_filename) - self.additional_interfaces = set() - for filename in additional_idl_filenames: - basename = os.path.basename(filename) - interface_name, _ = os.path.splitext(basename) - self.additional_interfaces.add(interface_name) - self.reader = reader - - def resolve_dependencies(self, definitions, interface_name): - """Resolves dependencies, merging them into IDL definitions of main file. - - Dependencies consist of 'partial interface' for the same interface as - in the main file, and other interfaces that this interface 'implements'. - - Modifies definitions in place by adding parsed dependencies, and checks - whether bindings should be generated, returning bool. - - Args: - definitions: IdlDefinitions object, modified in place - idl_filename: filename of main IDL file for the interface - Returns: - bool, whether bindings should be generated or not. - """ - dependency_idl_filenames = self.compute_dependency_idl_files(interface_name) - if dependency_idl_filenames is None: - return False - # The Blink IDL filenaming convention is that the file - # <interface_name>.idl MUST contain the interface "interface_name" or - # exception "interface_name", unless it is a dependency (e.g., - # 'partial interface Foo' can be in FooBar.idl). - if interface_name in definitions.exceptions: - # Exceptions do not have dependencies, so no merging necessary - return definitions - try: - target_interface = definitions.interfaces[interface_name] - except KeyError: - raise InterfaceNotFoundError('Could not find interface or exception "{0}" in {0}.idl'.format(interface_name)) - merge_interface_dependencies(target_interface, dependency_idl_filenames, self.reader) - - return definitions - - def compute_dependency_idl_files(self, target_interface_name): - """Returns list of IDL file dependencies for a given main IDL file. - - - Returns a list of IDL files on which a given IDL file depends, - possibly empty. - Dependencies consist of partial interface files and files for other - interfaces that the given interface implements. - - Returns an empty list also if the given IDL file is an additional IDL - file. - - Otherwise, return None. This happens when the given IDL file is a - dependency, for which we don't want to generate bindings. - """ - if target_interface_name in self.interface_dependencies: - return self.interface_dependencies[target_interface_name] - - # additional_interfaces is a list of interfaces that should not be - # included in DerivedSources*.cpp, and hence are not listed in the - # interface dependencies file, but for which we should generate .cpp - # and .h files. - if target_interface_name in self.additional_interfaces: - return [] - - return None - - -def read_interface_dependencies_file(interface_dependencies_filename): - """Reads the interface dependencies file, returns a dict for resolving dependencies. - - The format of the interface dependencies file is: - - Document.idl P.idl - Event.idl - Window.idl Q.idl R.idl S.idl - ... - - The above indicates that: - Document.idl depends on P.idl, - Event.idl depends on no other IDL files, and - Window.idl depends on Q.idl, R.idl, and S.idl. - - The head entries (first IDL file on a line) are the files that should - have bindings generated. - - An IDL file that is a dependency of another IDL file (e.g., P.idl in the - above example) does not have its own line in the dependency file: - dependencies do not have bindings generated, and do not have their - own dependencies. - - Args: - interface_dependencies_filename: filename of file in above format - Returns: - dict of interface_name -> dependency_filenames - """ - interface_dependencies = {} - with open(interface_dependencies_filename) as interface_dependencies_file: - for line in interface_dependencies_file: - idl_filename, _, dependency_filenames_string = line.partition(' ') - idl_basename = os.path.basename(idl_filename) - interface_name, _ = os.path.splitext(idl_basename) - dependency_filenames = dependency_filenames_string.split() - interface_dependencies[interface_name] = dependency_filenames - return interface_dependencies - - -def merge_interface_dependencies(target_interface, dependency_idl_filenames, reader): - """Merge dependencies ('partial interface' and 'implements') in dependency_idl_filenames into target_interface. - - No return: modifies target_document in place. - """ - # Sort so order consistent, so can compare output from run to run. - for dependency_idl_filename in sorted(dependency_idl_filenames): - dependency_interface_name, _ = os.path.splitext(os.path.basename(dependency_idl_filename)) - definitions = reader.read_idl_file(dependency_idl_filename) - - for dependency_interface in definitions.interfaces.itervalues(): - # Dependency files contain either partial interfaces for - # the (single) target interface, in which case the interface names - # must agree, or interfaces that are implemented by the target - # interface, in which case the interface names differ. - if dependency_interface.is_partial and dependency_interface.name != target_interface.name: - raise InvalidPartialInterfaceError('%s is not a partial interface of %s. There maybe a bug in the the dependency generator (compute_depedencies.py).' % (dependency_idl_filename, target_interface.name)) - if 'ImplementedAs' in dependency_interface.extended_attributes: - del dependency_interface.extended_attributes['ImplementedAs'] - merge_dependency_interface(target_interface, dependency_interface, dependency_interface_name) - - -def merge_dependency_interface(target_interface, dependency_interface, dependency_interface_name): - """Merge dependency_interface into target_interface. - - No return: modifies target_interface in place. - """ - def merge_lists(source_list, target_list): - for element in source_list: - # FIXME: remove check for LegacyImplementedInBaseClass when this - # attribute is removed - if 'LegacyImplementedInBaseClass' not in dependency_interface.extended_attributes: - element.extended_attributes['ImplementedBy'] = dependency_interface_name - element.extended_attributes.update(dependency_interface.extended_attributes) - target_list.append(element) - - merge_lists(dependency_interface.attributes, target_interface.attributes) - merge_lists(dependency_interface.constants, target_interface.constants) - merge_lists(dependency_interface.operations, target_interface.operations) diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/v8_attributes.py b/chromium/third_party/WebKit/Source/bindings/scripts/unstable/v8_attributes.py deleted file mode 100644 index 56b14963983..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/v8_attributes.py +++ /dev/null @@ -1,331 +0,0 @@ -# Copyright (C) 2013 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. - -"""Generate template values for attributes. - -FIXME: Not currently used in build. -This is a rewrite of the Perl IDL compiler in Python, but is not complete. -Once it is complete, we will switch all IDL files over to Python at once. -Until then, please work on the Perl IDL compiler. -For details, see bug http://crbug.com/239771 -""" - -from v8_globals import includes -import v8_types -import v8_utilities -from v8_utilities import capitalize, cpp_name, has_extended_attribute, uncapitalize - - -def generate_attribute(interface, attribute): - idl_type = attribute.idl_type - extended_attributes = attribute.extended_attributes - - v8_types.add_includes_for_type(idl_type) - - # [CheckSecurity] - is_check_security_for_node = 'CheckSecurity' in extended_attributes - if is_check_security_for_node: - includes.add('bindings/v8/BindingSecurity.h') - # [Custom] - has_custom_getter = ('Custom' in extended_attributes and - extended_attributes['Custom'] in [None, 'Getter']) - has_custom_setter = (not attribute.is_read_only and - 'Custom' in extended_attributes and - extended_attributes['Custom'] in [None, 'Setter']) - # [Reflect] - is_reflect = 'Reflect' in extended_attributes - if is_reflect: - includes.add('core/dom/custom/CustomElementCallbackDispatcher.h') - - if (idl_type == 'EventHandler' and - interface.name in ['Window', 'WorkerGlobalScope'] and - attribute.name == 'onerror'): - includes.add('bindings/v8/V8ErrorHandler.h') - - contents = { - 'access_control_list': access_control_list(attribute), - 'activity_logging_world_list_for_getter': v8_utilities.activity_logging_world_list(attribute, 'Getter'), # [ActivityLogging] - 'activity_logging_world_list_for_setter': v8_utilities.activity_logging_world_list(attribute, 'Setter'), # [ActivityLogging] - 'cached_attribute_validation_method': extended_attributes.get('CachedAttribute'), - 'conditional_string': v8_utilities.conditional_string(attribute), - 'constructor_type': v8_types.constructor_type(idl_type) - if is_constructor_attribute(attribute) else None, - 'cpp_name': cpp_name(attribute), - 'cpp_type': v8_types.cpp_type(idl_type), - 'deprecate_as': v8_utilities.deprecate_as(attribute), # [DeprecateAs] - 'enum_validation_expression': - v8_utilities.enum_validation_expression(idl_type), - 'has_custom_getter': has_custom_getter, - 'has_custom_setter': has_custom_setter, - 'has_strict_type_checking': ( - 'StrictTypeChecking' in extended_attributes and - v8_types.is_interface_type(idl_type)), - 'idl_type': idl_type, - 'is_call_with_execution_context': v8_utilities.has_extended_attribute_value(attribute, 'CallWith', 'ExecutionContext'), - 'is_check_security_for_node': is_check_security_for_node, - 'is_expose_js_accessors': 'ExposeJSAccessors' in extended_attributes, - 'is_getter_raises_exception': ( # [RaisesException] - 'RaisesException' in extended_attributes and - extended_attributes['RaisesException'] in [None, 'Getter']), - 'is_initialized_by_event_constructor': - 'InitializedByEventConstructor' in extended_attributes, - 'is_keep_alive_for_gc': is_keep_alive_for_gc(attribute), - 'is_nullable': attribute.is_nullable, - 'is_per_world_bindings': 'PerWorldBindings' in extended_attributes, - 'is_read_only': attribute.is_read_only, - 'is_reflect': is_reflect, - 'is_replaceable': 'Replaceable' in attribute.extended_attributes, - 'is_setter_raises_exception': ( - 'RaisesException' in extended_attributes and - extended_attributes['RaisesException'] in [None, 'Setter']), - 'is_static': attribute.is_static, - 'is_unforgeable': 'Unforgeable' in extended_attributes, - 'measure_as': v8_utilities.measure_as(attribute), # [MeasureAs] - 'name': attribute.name, - 'per_context_enabled_function': v8_utilities.per_context_enabled_function_name(attribute), # [PerContextEnabled] - 'property_attributes': property_attributes(attribute), - 'setter_callback': setter_callback_name(interface, attribute), - 'v8_type': v8_types.v8_type(idl_type), - 'runtime_enabled_function': v8_utilities.runtime_enabled_function_name(attribute), # [RuntimeEnabled] - 'world_suffixes': ['', 'ForMainWorld'] - if 'PerWorldBindings' in extended_attributes - else [''], # [PerWorldBindings] - } - - if is_constructor_attribute(attribute): - return contents - if not has_custom_getter: - generate_getter(interface, attribute, contents) - if not(attribute.is_read_only or has_custom_setter): - contents.update({ - 'cpp_setter': setter_expression(interface, attribute, contents), - 'v8_value_to_local_cpp_value': v8_types.v8_value_to_local_cpp_value( - idl_type, extended_attributes, 'jsValue', 'cppValue'), - }) - - return contents - - -# Getter - -def generate_getter(interface, attribute, contents): - idl_type = attribute.idl_type - extended_attributes = attribute.extended_attributes - - cpp_value = getter_expression(interface, attribute, contents) - # Normally we can inline the function call into the return statement to - # avoid the overhead of using a Ref<> temporary, but for some cases - # (nullable types, EventHandler, [CachedAttribute], or if there are - # exceptions), we need to use a local variable. - # FIXME: check if compilers are smart enough to inline this, and if so, - # always use a local variable (for readability and CG simplicity). - if (attribute.is_nullable or - idl_type == 'EventHandler' or - 'CachedAttribute' in extended_attributes or - contents['is_getter_raises_exception']): - contents['cpp_value_original'] = cpp_value - cpp_value = 'jsValue' - - if contents['is_keep_alive_for_gc']: - v8_set_return_value_statement = 'v8SetReturnValue(info, wrapper)' - includes.add('bindings/v8/V8HiddenPropertyName.h') - else: - v8_set_return_value_statement = v8_types.v8_set_return_value(idl_type, cpp_value, extended_attributes=extended_attributes, script_wrappable='imp') - - contents.update({ - 'cpp_value': cpp_value, - 'v8_set_return_value': v8_set_return_value_statement, - }) - - -def getter_expression(interface, attribute, contents): - arguments = [] - this_getter_base_name = getter_base_name(attribute, arguments) - getter_name = v8_utilities.scoped_name(interface, attribute, this_getter_base_name) - - arguments.extend(v8_utilities.call_with_arguments(attribute)) - if attribute.is_nullable: - arguments.append('isNull') - if contents['is_getter_raises_exception']: - arguments.append('exceptionState') - if attribute.idl_type == 'EventHandler': - arguments.append('isolatedWorldForIsolate(info.GetIsolate())') - return '%s(%s)' % (getter_name, ', '.join(arguments)) - - -CONTENT_ATTRIBUTE_GETTER_NAMES = { - 'boolean': 'fastHasAttribute', - 'long': 'getIntegralAttribute', - 'unsigned long': 'getUnsignedIntegralAttribute', -} - - -def getter_base_name(attribute, arguments): - extended_attributes = attribute.extended_attributes - if 'Reflect' not in extended_attributes: - return uncapitalize(cpp_name(attribute)) - - content_attribute_name = extended_attributes['Reflect'] or attribute.name.lower() - if content_attribute_name in ['class', 'id', 'name']: - # Special-case for performance optimization. - return 'get%sAttribute' % content_attribute_name.capitalize() - - arguments.append(scoped_content_attribute_name(attribute)) - - idl_type = attribute.idl_type - if idl_type in CONTENT_ATTRIBUTE_GETTER_NAMES: - return CONTENT_ATTRIBUTE_GETTER_NAMES[idl_type] - if 'URL' in attribute.extended_attributes: - return 'getURLAttribute' - return 'fastGetAttribute' - - -def is_keep_alive_for_gc(attribute): - idl_type = attribute.idl_type - extended_attributes = attribute.extended_attributes - return ( - # For readonly attributes, for performance reasons we keep the attribute - # wrapper alive while the owner wrapper is alive, because the attribute - # never changes. - (attribute.is_read_only and - v8_types.is_wrapper_type(idl_type) and - # There are some exceptions, however: - not( - # Node lifetime is managed by object grouping. - v8_types.is_dom_node_type(idl_type) or - # A self-reference is unnecessary. - attribute.name == 'self' or - # FIXME: Remove these hard-coded hacks. - idl_type in ['EventHandler', 'Promise', 'Window'] or - idl_type.startswith('HTML')))) - - -# Setter - -def setter_expression(interface, attribute, contents): - arguments = v8_utilities.call_with_arguments(attribute, attribute.extended_attributes.get('SetterCallWith')) - - this_setter_base_name = setter_base_name(attribute, arguments) - setter_name = v8_utilities.scoped_name(interface, attribute, this_setter_base_name) - - idl_type = attribute.idl_type - if idl_type == 'EventHandler': - # FIXME: pass the isolate instead of the isolated world - isolated_world = 'isolatedWorldForIsolate(info.GetIsolate())' - arguments.extend(['V8EventListenerList::getEventListener(jsValue, true, ListenerFindOrCreate)', isolated_world]) - contents['event_handler_getter_expression'] = 'imp->%s(%s)' % (cpp_name(attribute), isolated_world) - elif v8_types.is_interface_type(idl_type) and not v8_types.array_type(idl_type): - # FIXME: should be able to eliminate WTF::getPtr in most or all cases - arguments.append('WTF::getPtr(cppValue)') - else: - arguments.append('cppValue') - if contents['is_setter_raises_exception']: - arguments.append('exceptionState') - - return '%s(%s)' % (setter_name, ', '.join(arguments)) - - -CONTENT_ATTRIBUTE_SETTER_NAMES = { - 'boolean': 'setBooleanAttribute', - 'long': 'setIntegralAttribute', - 'unsigned long': 'setUnsignedIntegralAttribute', -} - - -def setter_base_name(attribute, arguments): - if 'Reflect' not in attribute.extended_attributes: - return 'set%s' % capitalize(cpp_name(attribute)) - arguments.append(scoped_content_attribute_name(attribute)) - - idl_type = attribute.idl_type - if idl_type in CONTENT_ATTRIBUTE_SETTER_NAMES: - return CONTENT_ATTRIBUTE_SETTER_NAMES[idl_type] - return 'setAttribute' - - -def scoped_content_attribute_name(attribute): - content_attribute_name = attribute.extended_attributes['Reflect'] or attribute.name.lower() - namespace = 'HTMLNames' # FIXME: can be SVG too - includes.add('%s.h' % namespace) - return '%s::%sAttr' % (namespace, content_attribute_name) - - -def scoped_name(interface, attribute, base_name): - if attribute.is_static: - return '%s::%s' % (interface.name, base_name) - return 'imp->%s' % base_name - - -# Attribute configuration - -# [Replaceable] -def setter_callback_name(interface, attribute): - cpp_class_name = cpp_name(interface) - if ('Replaceable' in attribute.extended_attributes or - is_constructor_attribute(attribute)): - # FIXME: rename to ForceSetAttributeOnThisCallback, since also used for Constructors - return '{0}V8Internal::{0}ReplaceableAttributeSetterCallback'.format(cpp_class_name) - # FIXME: support [PutForwards] - if attribute.is_read_only: - return '0' - return '%sV8Internal::%sAttributeSetterCallback' % (cpp_class_name, attribute.name) - - -# [DoNotCheckSecurity], [Unforgeable] -def access_control_list(attribute): - extended_attributes = attribute.extended_attributes - access_control = [] - if 'DoNotCheckSecurity' in extended_attributes: - do_not_check_security = extended_attributes['DoNotCheckSecurity'] - if do_not_check_security == 'Setter': - access_control.append('v8::ALL_CAN_WRITE') - else: - access_control.append('v8::ALL_CAN_READ') - if not attribute.is_read_only: - access_control.append('v8::ALL_CAN_WRITE') - if 'Unforgeable' in extended_attributes: - access_control.append('v8::PROHIBITS_OVERWRITING') - return access_control or ['v8::DEFAULT'] - - -# [NotEnumerable], [Unforgeable] -def property_attributes(attribute): - extended_attributes = attribute.extended_attributes - property_attributes_list = [] - if ('NotEnumerable' in extended_attributes or - is_constructor_attribute(attribute)): - property_attributes_list.append('v8::DontEnum') - if 'Unforgeable' in extended_attributes: - property_attributes_list.append('v8::DontDelete') - return property_attributes_list or ['v8::None'] - - -# Constructors - -def is_constructor_attribute(attribute): - return attribute.idl_type.endswith('Constructor') diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/v8_interface.py b/chromium/third_party/WebKit/Source/bindings/scripts/unstable/v8_interface.py deleted file mode 100644 index 5d8b312fa5b..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/v8_interface.py +++ /dev/null @@ -1,406 +0,0 @@ -# Copyright (C) 2013 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. - -"""Generate template values for an interface. - -FIXME: Not currently used in build. -This is a rewrite of the Perl IDL compiler in Python, but is not complete. -Once it is complete, we will switch all IDL files over to Python at once. -Until then, please work on the Perl IDL compiler. -For details, see bug http://crbug.com/239771 -""" - -import v8_attributes -from v8_globals import includes -import v8_methods -import v8_types -import v8_utilities -from v8_utilities import capitalize, conditional_string, cpp_name, has_extended_attribute, has_extended_attribute_value, runtime_enabled_function_name - - -INTERFACE_H_INCLUDES = set([ - 'bindings/v8/V8Binding.h', - 'bindings/v8/V8DOMWrapper.h', - 'bindings/v8/WrapperTypeInfo.h', -]) -INTERFACE_CPP_INCLUDES = set([ - 'RuntimeEnabledFeatures.h', - 'bindings/v8/ExceptionState.h', - 'bindings/v8/V8DOMConfiguration.h', - 'core/dom/ContextFeatures.h', - 'core/dom/Document.h', - 'platform/TraceEvent.h', -]) - - -def generate_interface(interface): - includes.clear() - includes.update(INTERFACE_CPP_INCLUDES) - header_includes = INTERFACE_H_INCLUDES - - parent_interface = interface.parent - if parent_interface: - header_includes.update(v8_types.includes_for_type(parent_interface)) - extended_attributes = interface.extended_attributes - - # [CheckSecurity] - is_check_security = 'CheckSecurity' in extended_attributes - if is_check_security: - includes.add('bindings/v8/BindingSecurity.h') - - # [GenerateVisitDOMWrapper] - generate_visit_dom_wrapper_function = extended_attributes.get('GenerateVisitDOMWrapper') - if generate_visit_dom_wrapper_function: - includes.update(['bindings/v8/V8GCController.h', - 'core/dom/Element.h']) - - # [MeasureAs] - is_measure_as = 'MeasureAs' in extended_attributes - if is_measure_as: - includes.add('core/frame/UseCounter.h') - - # [SpecialWrapFor] - if 'SpecialWrapFor' in extended_attributes: - special_wrap_for = extended_attributes['SpecialWrapFor'].split('|') - else: - special_wrap_for = [] - for special_wrap_interface in special_wrap_for: - v8_types.add_includes_for_type(special_wrap_interface) - - # Constructors - constructors = [generate_constructor(interface, constructor) - for constructor in interface.constructors - # FIXME: shouldn't put named constructors with constructors - # (currently needed for Perl compatibility) - # Handle named constructors separately - if constructor.name == 'Constructor'] - generate_constructor_overloads(constructors) - - # [CustomConstructor] - has_custom_constructor = 'CustomConstructor' in extended_attributes - - # [EventConstructor] - has_event_constructor = 'EventConstructor' in extended_attributes - any_type_attributes = [attribute for attribute in interface.attributes - if attribute.idl_type == 'any'] - if has_event_constructor: - includes.add('bindings/v8/Dictionary.h') - if any_type_attributes: - includes.add('bindings/v8/SerializedScriptValue.h') - - # [NamedConstructor] - if 'NamedConstructor' in extended_attributes: - # FIXME: parser should return named constructor separately; - # included in constructors (and only name stored in extended attribute) - # for Perl compatibility - named_constructor = {'name': extended_attributes['NamedConstructor']} - else: - named_constructor = None - - if (constructors or has_custom_constructor or has_event_constructor or - named_constructor): - includes.add('bindings/v8/V8ObjectConstructor.h') - - template_contents = { - 'any_type_attributes': any_type_attributes, - 'conditional_string': conditional_string(interface), # [Conditional] - 'constructors': constructors, - 'cpp_class': cpp_name(interface), - 'generate_visit_dom_wrapper_function': generate_visit_dom_wrapper_function, - 'has_custom_constructor': has_custom_constructor, - 'has_custom_legacy_call_as_function': has_extended_attribute_value(interface, 'Custom', 'LegacyCallAsFunction'), # [Custom=LegacyCallAsFunction] - 'has_custom_to_v8': has_extended_attribute_value(interface, 'Custom', 'ToV8'), # [Custom=ToV8] - 'has_custom_wrap': has_extended_attribute_value(interface, 'Custom', 'Wrap'), # [Custom=Wrap] - 'has_event_constructor': has_event_constructor, - 'has_visit_dom_wrapper': ( - # [Custom=Wrap], [GenerateVisitDOMWrapper] - has_extended_attribute_value(interface, 'Custom', 'VisitDOMWrapper') or - 'GenerateVisitDOMWrapper' in extended_attributes), - 'header_includes': header_includes, - 'interface_length': interface_length(interface, constructors), - 'interface_name': interface.name, - 'is_active_dom_object': 'ActiveDOMObject' in extended_attributes, # [ActiveDOMObject] - 'is_check_security': is_check_security, - 'is_constructor_call_with_document': has_extended_attribute_value( - interface, 'ConstructorCallWith', 'Document'), # [ConstructorCallWith=Document] - 'is_constructor_call_with_execution_context': has_extended_attribute_value( - interface, 'ConstructorCallWith', 'ExecutionContext'), # [ConstructorCallWith=ExeuctionContext] - 'is_constructor_raises_exception': extended_attributes.get('RaisesException') == 'Constructor', # [RaisesException=Constructor] - 'is_dependent_lifetime': 'DependentLifetime' in extended_attributes, # [DependentLifetime] - 'is_event_target': inherits_interface(interface, 'EventTarget'), - 'is_node': inherits_interface(interface, 'Node'), - 'measure_as': v8_utilities.measure_as(interface), # [MeasureAs] - 'named_constructor': named_constructor, - 'parent_interface': parent_interface, - 'runtime_enabled_function': runtime_enabled_function_name(interface), # [RuntimeEnabled] - 'special_wrap_for': special_wrap_for, - 'v8_class': v8_utilities.v8_class_name(interface), - } - - template_contents.update({ - 'constants': [generate_constant(constant) for constant in interface.constants], - 'do_not_check_constants': 'DoNotCheckConstants' in extended_attributes, - }) - - attributes = [v8_attributes.generate_attribute(interface, attribute) - for attribute in interface.attributes] - template_contents.update({ - 'attributes': attributes, - 'has_accessors': any(attribute['is_expose_js_accessors'] for attribute in attributes), - 'has_constructor_attributes': any(attribute['constructor_type'] for attribute in attributes), - 'has_per_context_enabled_attributes': any(attribute['per_context_enabled_function'] for attribute in attributes), - 'has_replaceable_attributes': any(attribute['is_replaceable'] for attribute in attributes), - }) - - methods = [v8_methods.generate_method(interface, method) - for method in interface.operations] - generate_overloads(methods) - for method in methods: - method['do_generate_method_configuration'] = ( - method['do_not_check_signature'] and - not method['per_context_enabled_function'] and - # For overloaded methods, only generate one accessor - ('overload_index' not in method or method['overload_index'] == 1)) - - template_contents.update({ - 'has_origin_safe_method_setter': any( - method['is_check_security_for_frame'] and not method['is_read_only'] - for method in methods), - 'has_method_configuration': any(method['do_generate_method_configuration'] for method in methods), - 'has_per_context_enabled_methods': any(method['per_context_enabled_function'] for method in methods), - 'methods': methods, - }) - - return template_contents - - -# [DeprecateAs], [Reflect], [RuntimeEnabled] -def generate_constant(constant): - # (Blink-only) string literals are unquoted in tokenizer, must be re-quoted - # in C++. - if constant.idl_type == 'DOMString': - value = '"%s"' % constant.value - else: - value = constant.value - - constant_parameter = { - 'name': constant.name, - # FIXME: use 'reflected_name' as correct 'name' - 'reflected_name': constant.extended_attributes.get('Reflect', constant.name), - 'runtime_enabled_function': runtime_enabled_function_name(constant), - 'value': value, - } - return constant_parameter - - -# Overloads - -def generate_overloads(methods): - generate_overloads_by_type(methods, is_static=False) # Regular methods - generate_overloads_by_type(methods, is_static=True) - - -def generate_overloads_by_type(methods, is_static): - # Generates |overloads| template values and modifies |methods| in place; - # |is_static| flag used (instead of partitioning list in 2) because need to - # iterate over original list of methods to modify in place - method_counts = {} - for method in methods: - if method['is_static'] != is_static: - continue - name = method['name'] - method_counts.setdefault(name, 0) - method_counts[name] += 1 - - # Filter to only methods that are actually overloaded - overloaded_method_counts = dict((name, count) - for name, count in method_counts.iteritems() - if count > 1) - - # Add overload information only to overloaded methods, so template code can - # easily verify if a function is overloaded - method_overloads = {} - for method in methods: - name = method['name'] - if (method['is_static'] != is_static or - name not in overloaded_method_counts): - continue - # Overload index includes self, so first append, then compute index - method_overloads.setdefault(name, []).append(method) - method.update({ - 'overload_index': len(method_overloads[name]), - 'overload_resolution_expression': overload_resolution_expression(method), - }) - - # Resolution function is generated after last overloaded function; - # package necessary information into |method.overloads| for that method. - for method in methods: - if (method['is_static'] != is_static or - 'overload_index' not in method): - continue - name = method['name'] - if method['overload_index'] != overloaded_method_counts[name]: - continue - overloads = method_overloads[name] - method['overloads'] = { - 'name': name, - 'methods': overloads, - 'minimum_number_of_required_arguments': min( - overload['number_of_required_arguments'] - for overload in overloads), - } - - -def overload_resolution_expression(method): - # Expression is an OR of ANDs: each term in the OR corresponds to a - # possible argument count for a given method, with type checks. - # FIXME: Blink's overload resolution algorithm is incorrect, per: - # https://code.google.com/p/chromium/issues/detail?id=293561 - # Properly: - # 1. Compute effective overload set. - # 2. First check type list length. - # 3. If multiple entries for given length, compute distinguishing argument - # index and have check for that type. - arguments = method['arguments'] - overload_checks = [overload_check_expression(method, index) - # check *omitting* optional arguments at |index| and up: - # index 0 => argument_count 0 (no arguments) - # index 1 => argument_count 1 (index 0 argument only) - for index, argument in enumerate(arguments) - if argument['is_optional']] - # FIXME: this is wrong if a method has optional arguments and a variadic - # one, though there are not yet any examples of this - if not method['is_variadic']: - # Includes all optional arguments (len = last index + 1) - overload_checks.append(overload_check_expression(method, len(arguments))) - return ' || '.join('(%s)' % check for check in overload_checks) - - -def overload_check_expression(method, argument_count): - overload_checks = ['info.Length() == %s' % argument_count] - arguments = method['arguments'][:argument_count] - overload_checks.extend(overload_check_argument(index, argument) - for index, argument in - enumerate(arguments)) - return ' && '.join('(%s)' % check for check in overload_checks if check) - - -def overload_check_argument(index, argument): - cpp_value = 'info[%s]' % index - idl_type = argument['idl_type'] - # FIXME: proper type checking, sharing code with attributes and methods - if idl_type == 'DOMString' and argument['is_strict_type_checking']: - return ' || '.join(['%s->IsNull()' % cpp_value, - '%s->IsUndefined()' % cpp_value, - '%s->IsString()' % cpp_value, - '%s->IsObject()' % cpp_value]) - if v8_types.array_or_sequence_type(idl_type): - return '%s->IsArray()' % cpp_value - if v8_types.is_wrapper_type(idl_type): - type_check = 'V8{idl_type}::hasInstance({cpp_value}, info.GetIsolate(), worldType(info.GetIsolate()))'.format(idl_type=idl_type, cpp_value=cpp_value) - if argument['is_nullable']: - type_check = ' || '.join(['%s->IsNull()' % cpp_value, type_check]) - return type_check - return None - - -# Constructors - -# [Constructor] -def generate_constructor(interface, constructor): - return { - 'argument_list': constructor_argument_list(interface, constructor), - 'arguments': [constructor_argument(argument, index) - for index, argument in enumerate(constructor.arguments)], - 'is_constructor': True, - 'is_variadic': False, # Required for overload resolution - 'number_of_required_arguments': - len([argument for argument in constructor.arguments - if not argument.is_optional]), - } - - -def constructor_argument_list(interface, constructor): - arguments = [] - # [ConstructorCallWith=ExecutionContext] - if has_extended_attribute_value(interface, 'ConstructorCallWith', 'ExecutionContext'): - arguments.append('context') - # [ConstructorCallWith=Document] - if has_extended_attribute_value(interface, 'ConstructorCallWith', 'Document'): - arguments.append('document') - - arguments.extend([argument.name for argument in constructor.arguments]) - - # [RaisesException=Constructor] - if interface.extended_attributes.get('RaisesException') == 'Constructor': - arguments.append('exceptionState') - - return arguments - - -def constructor_argument(argument, index): - return { - 'has_default': 'Default' in argument.extended_attributes, - 'idl_type': argument.idl_type, - 'index': index, - 'is_nullable': False, # Required for overload resolution - 'is_optional': argument.is_optional, - 'is_strict_type_checking': False, # Required for overload resolution - 'name': argument.name, - 'v8_value_to_local_cpp_value': - v8_methods.v8_value_to_local_cpp_value(argument, index), - } - - -def generate_constructor_overloads(constructors): - if len(constructors) <= 1: - return - for overload_index, constructor in enumerate(constructors): - constructor.update({ - 'overload_index': overload_index + 1, - 'overload_resolution_expression': - overload_resolution_expression(constructor), - }) - - -def interface_length(interface, constructors): - # Docs: http://heycam.github.io/webidl/#es-interface-call - if 'EventConstructor' in interface.extended_attributes: - return 1 - if not constructors: - return 0 - return min(constructor['number_of_required_arguments'] - for constructor in constructors) - - -# Interface dependencies - -def inherits_interface(interface, ancestor): - # FIXME: support distant ancestors (but don't parse all ancestors!) - # Do by computing ancestor chain in compute_dependencies.py - return ancestor in [interface.name, interface.parent] diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/v8_methods.py b/chromium/third_party/WebKit/Source/bindings/scripts/unstable/v8_methods.py deleted file mode 100644 index 13a5c66e2e3..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/v8_methods.py +++ /dev/null @@ -1,232 +0,0 @@ -# Copyright (C) 2013 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. - -"""Generate template values for methods. - -FIXME: Not currently used in build. -This is a rewrite of the Perl IDL compiler in Python, but is not complete. -Once it is complete, we will switch all IDL files over to Python at once. -Until then, please work on the Perl IDL compiler. -For details, see bug http://crbug.com/239771 -""" - -from v8_globals import includes -import v8_types -import v8_utilities -from v8_utilities import has_extended_attribute_value - - -def generate_method(interface, method): - arguments = method.arguments - extended_attributes = method.extended_attributes - idl_type = method.idl_type - is_static = method.is_static - name = method.name - - this_cpp_value = cpp_value(interface, method, len(arguments)) - this_custom_signature = custom_signature(method, arguments) - - def function_template(): - if is_static: - return 'functionTemplate' - if 'Unforgeable' in extended_attributes: - return 'instanceTemplate' - return 'prototypeTemplate' - - def signature(): - if this_custom_signature: - return name + 'Signature' - if is_static or 'DoNotCheckSignature' in extended_attributes: - return 'v8::Local<v8::Signature>()' - return 'defaultSignature' - - is_call_with_script_arguments = has_extended_attribute_value(method, 'CallWith', 'ScriptArguments') - if is_call_with_script_arguments: - includes.update(['bindings/v8/ScriptCallStackFactory.h', - 'core/inspector/ScriptArguments.h']) - is_call_with_script_state = has_extended_attribute_value(method, 'CallWith', 'ScriptState') - if is_call_with_script_state: - includes.add('bindings/v8/ScriptState.h') - is_check_security_for_node = 'CheckSecurity' in extended_attributes - if is_check_security_for_node: - includes.add('bindings/v8/BindingSecurity.h') - is_custom_element_callbacks = 'CustomElementCallbacks' in extended_attributes - if is_custom_element_callbacks: - includes.add('core/dom/custom/CustomElementCallbackDispatcher.h') - - contents = { - 'activity_logging_world_list': v8_utilities.activity_logging_world_list(method), # [ActivityLogging] - 'arguments': [generate_argument(interface, method, argument, index) - for index, argument in enumerate(arguments)], - 'conditional_string': v8_utilities.conditional_string(method), - 'cpp_type': v8_types.cpp_type(idl_type), - 'cpp_value': this_cpp_value, - 'custom_signature': this_custom_signature, - 'deprecate_as': v8_utilities.deprecate_as(method), # [DeprecateAs] - 'do_not_check_signature': not(this_custom_signature or is_static or - v8_utilities.has_extended_attribute(method, - ['DoNotCheckSecurity', 'DoNotCheckSignature', 'NotEnumerable', - 'ReadOnly', 'RuntimeEnabled', 'Unforgeable'])), - 'function_template': function_template(), - 'idl_type': idl_type, - 'is_call_with_execution_context': has_extended_attribute_value(method, 'CallWith', 'ExecutionContext'), - 'is_call_with_script_arguments': is_call_with_script_arguments, - 'is_call_with_script_state': is_call_with_script_state, - 'is_check_security_for_frame': ( - 'CheckSecurity' in interface.extended_attributes and - 'DoNotCheckSecurity' not in extended_attributes), - 'is_check_security_for_node': is_check_security_for_node, - 'is_custom': 'Custom' in extended_attributes, - 'is_custom_element_callbacks': is_custom_element_callbacks, - 'is_do_not_check_security': 'DoNotCheckSecurity' in extended_attributes, - 'is_per_world_bindings': 'PerWorldBindings' in extended_attributes, - 'is_raises_exception': 'RaisesException' in extended_attributes, - 'is_read_only': 'ReadOnly' in extended_attributes, - 'is_static': is_static, - 'is_strict_type_checking': 'StrictTypeChecking' in extended_attributes, - 'is_variadic': arguments and arguments[-1].is_variadic, - 'measure_as': v8_utilities.measure_as(method), # [MeasureAs] - 'name': name, - 'number_of_arguments': len(arguments), - 'number_of_required_arguments': len([ - argument for argument in arguments - if not (argument.is_optional or argument.is_variadic)]), - 'number_of_required_or_variadic_arguments': len([ - argument for argument in arguments - if not argument.is_optional]), - 'per_context_enabled_function': v8_utilities.per_context_enabled_function_name(method), # [PerContextEnabled] - 'property_attributes': property_attributes(method), - 'runtime_enabled_function': v8_utilities.runtime_enabled_function_name(method), # [RuntimeEnabled] - 'signature': signature(), - 'v8_set_return_value': v8_set_return_value(method, this_cpp_value), - 'world_suffixes': ['', 'ForMainWorld'] if 'PerWorldBindings' in extended_attributes else [''], # [PerWorldBindings] - } - return contents - - -def generate_argument(interface, method, argument, index): - extended_attributes = argument.extended_attributes - idl_type = argument.idl_type - this_cpp_value = cpp_value(interface, method, index) - return { - 'cpp_type': v8_types.cpp_type(idl_type), - 'cpp_value': this_cpp_value, - 'enum_validation_expression': v8_utilities.enum_validation_expression(idl_type), - 'has_default': 'Default' in extended_attributes, - 'idl_type': idl_type, - 'index': index, - 'is_clamp': 'Clamp' in extended_attributes, - 'is_nullable': argument.is_nullable, - 'is_optional': argument.is_optional, - 'is_strict_type_checking': 'StrictTypeChecking' in extended_attributes, - 'is_variadic_wrapper_type': argument.is_variadic and v8_types.is_wrapper_type(idl_type), - 'is_wrapper_type': v8_types.is_wrapper_type(idl_type), - 'name': argument.name, - 'v8_set_return_value': v8_set_return_value(method, this_cpp_value), - 'v8_value_to_local_cpp_value': v8_value_to_local_cpp_value(argument, index), - } - - -def cpp_value(interface, method, number_of_arguments): - def cpp_argument(argument): - if argument.idl_type in ['NodeFilter', 'XPathNSResolver']: - # FIXME: remove this special case - return '%s.release()' % argument.name - return argument.name - - # Truncate omitted optional arguments - arguments = method.arguments[:number_of_arguments] - cpp_arguments = v8_utilities.call_with_arguments(method) - cpp_arguments.extend(cpp_argument(argument) for argument in arguments) - if 'RaisesException' in method.extended_attributes: - cpp_arguments.append('exceptionState') - - cpp_method_name = v8_utilities.scoped_name(interface, method, v8_utilities.cpp_name(method)) - return '%s(%s)' % (cpp_method_name, ', '.join(cpp_arguments)) - - -def v8_set_return_value(method, cpp_value): - idl_type = method.idl_type - if idl_type == 'void': - return None - # [CallWith=ScriptState] - if has_extended_attribute_value(method, 'CallWith', 'ScriptState'): - cpp_value = 'result' # use local variable for value - return v8_types.v8_set_return_value(idl_type, cpp_value, method.extended_attributes) - - -def custom_signature(method, arguments): - def argument_template(argument): - idl_type = argument.idl_type - if (v8_types.is_wrapper_type(idl_type) and - not v8_types.is_typed_array_type(idl_type) and - # Compatibility: all other browsers accepts a callable for - # XPathNSResolver, despite it being against spec. - not idl_type == 'XPathNSResolver'): - return 'V8PerIsolateData::from(isolate)->rawDOMTemplate(&V8{idl_type}::wrapperTypeInfo, currentWorldType)'.format(idl_type=idl_type) - return 'v8::Handle<v8::FunctionTemplate>()' - - if (any(argument.is_optional and - 'Default' not in argument.extended_attributes - for argument in arguments) or - all(not v8_types.is_wrapper_type(argument.idl_type) - for argument in arguments) or - # For [StrictTypeChecking], type checking is done in the generated code - 'StrictTypeChecking' in method.extended_attributes): - return None - return ', '.join([argument_template(argument) for argument in arguments]) - - -# [NotEnumerable] -def property_attributes(method): - extended_attributes = method.extended_attributes - property_attributes_list = [] - if 'NotEnumerable' in extended_attributes: - property_attributes_list.append('v8::DontEnum') - if 'ReadOnly' in extended_attributes: - property_attributes_list.append('v8::ReadOnly') - if property_attributes_list: - property_attributes_list.insert(0, 'v8::DontDelete') - return property_attributes_list - - -def v8_value_to_local_cpp_value(argument, index): - extended_attributes = argument.extended_attributes - idl_type = argument.idl_type - name = argument.name - if argument.is_variadic: - return 'V8TRYCATCH_VOID(Vector<{cpp_type}>, {name}, toNativeArguments<{cpp_type}>(info, {index}))'.format( - cpp_type=v8_types.cpp_type(idl_type), name=name, index=index) - # [Default=NullString] - if (argument.is_optional and idl_type == 'DOMString' and - extended_attributes.get('Default') == 'NullString'): - v8_value = 'argumentOrNull(info, %s)' % index - else: - v8_value = 'info[%s]' % index - return v8_types.v8_value_to_local_cpp_value( - idl_type, argument.extended_attributes, v8_value, name, index=index) diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/v8_types.py b/chromium/third_party/WebKit/Source/bindings/scripts/unstable/v8_types.py deleted file mode 100644 index e7ca508865d..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/v8_types.py +++ /dev/null @@ -1,583 +0,0 @@ -# Copyright (C) 2013 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. - -"""Functions for type handling and type conversion (Blink/C++ <-> V8/JS). - -Spec: -http://www.w3.org/TR/WebIDL/#es-type-mapping - -FIXME: Not currently used in build. -This is a rewrite of the Perl IDL compiler in Python, but is not complete. -Once it is complete, we will switch all IDL files over to Python at once. -Until then, please work on the Perl IDL compiler. -For details, see bug http://crbug.com/239771 -""" - -import posixpath -import re - -from v8_globals import includes -import idl_definitions # for UnionType -from v8_utilities import strip_suffix - -################################################################################ -# IDL types -################################################################################ - -BASIC_TYPES = set([ - # Built-in, non-composite, non-object data types - # http://www.w3.org/TR/WebIDL/#dfn-primitive-type - 'boolean', - 'float', - # unrestricted float is not supported - 'double', - # unrestricted double is not supported - # integer types - # http://www.w3.org/TR/WebIDL/#dfn-integer-type - 'byte', - 'octet', - 'short', - 'unsigned short', - # int and unsigned are not IDL types - 'long', - 'unsigned long', - 'long long', - 'unsigned long long', - # http://www.w3.org/TR/WebIDL/#idl-types - 'DOMString', - 'Date', - # http://www.w3.org/TR/WebIDL/#es-type-mapping - 'void', -]) - -enum_types = {} # name -> values -callback_function_types = set() - - -def array_or_sequence_type(idl_type): - return array_type(idl_type) or sequence_type(idl_type) - - -def array_type(idl_type): - matched = re.match(r'([\w\s]+)\[\]', idl_type) - return matched and matched.group(1) - - -def is_basic_type(idl_type): - return idl_type in BASIC_TYPES - - -def is_callback_function_type(idl_type): - return idl_type in callback_function_types - - -def set_callback_function_types(callback_functions): - callback_function_types.update(callback_functions.keys()) - - -def is_composite_type(idl_type): - return (idl_type == 'any' or - array_type(idl_type) or - sequence_type(idl_type) or - is_union_type(idl_type)) - - -def is_enum_type(idl_type): - return idl_type in enum_types - - -def enum_values(idl_type): - return enum_types.get(idl_type) - - -def set_enum_types(enumerations): - enum_types.update([[enum.name, enum.values] - for enum in enumerations.values()]) - - -def is_interface_type(idl_type): - # Anything that is not another type is an interface type. - # http://www.w3.org/TR/WebIDL/#idl-types - # http://www.w3.org/TR/WebIDL/#idl-interface - # In C++ these are RefPtr or PassRefPtr types. - return not(is_basic_type(idl_type) or - is_composite_type(idl_type) or - is_callback_function_type(idl_type) or - is_enum_type(idl_type) or - idl_type == 'object' or - idl_type == 'Promise') # Promise will be basic in future - - -def sequence_type(idl_type): - matched = re.match(r'sequence<([\w\s]+)>', idl_type) - return matched and matched.group(1) - - -def is_union_type(idl_type): - return isinstance(idl_type, idl_definitions.IdlUnionType) - - -################################################################################ -# V8-specific type handling -################################################################################ - -DOM_NODE_TYPES = set([ - 'Attr', - 'CDATASection', - 'CharacterData', - 'Comment', - 'Document', - 'DocumentFragment', - 'DocumentType', - 'Element', - 'Entity', - 'HTMLDocument', - 'Node', - 'Notation', - 'ProcessingInstruction', - 'ShadowRoot', - 'SVGDocument', - 'Text', - 'TestNode', -]) -NON_WRAPPER_TYPES = set([ - 'CompareHow', - 'Dictionary', - 'MediaQueryListListener', - 'NodeFilter', - 'SerializedScriptValue', -]) -TYPED_ARRAYS = { - # (cpp_type, v8_type), used by constructor templates - 'ArrayBuffer': None, - 'ArrayBufferView': None, - 'Float32Array': ('float', 'v8::kExternalFloatArray'), - 'Float64Array': ('double', 'v8::kExternalDoubleArray'), - 'Int8Array': ('signed char', 'v8::kExternalByteArray'), - 'Int16Array': ('short', 'v8::kExternalShortArray'), - 'Int32Array': ('int', 'v8::kExternalIntArray'), - 'Uint8Array': ('unsigned char', 'v8::kExternalUnsignedByteArray'), - 'Uint8ClampedArray': ('unsigned char', 'v8::kExternalPixelArray'), - 'Uint16Array': ('unsigned short', 'v8::kExternalUnsignedShortArray'), - 'Uint32Array': ('unsigned int', 'v8::kExternalUnsignedIntArray'), -} - - -def constructor_type(idl_type): - return strip_suffix(idl_type, 'Constructor') - - -def is_dom_node_type(idl_type): - return (idl_type in DOM_NODE_TYPES or - (idl_type.startswith(('HTML', 'SVG')) and - idl_type.endswith('Element'))) - - -def is_typed_array_type(idl_type): - return idl_type in TYPED_ARRAYS - - -def is_wrapper_type(idl_type): - return (is_interface_type(idl_type) and - idl_type not in NON_WRAPPER_TYPES) - - -################################################################################ -# C++ types -################################################################################ - -CPP_TYPE_SAME_AS_IDL_TYPE = set([ - 'double', - 'float', - 'long long', - 'unsigned long long', -]) -CPP_INT_TYPES = set([ - 'byte', - 'long', - 'short', -]) -CPP_UNSIGNED_TYPES = set([ - 'octet', - 'unsigned int', - 'unsigned long', - 'unsigned short', -]) -CPP_SPECIAL_CONVERSION_RULES = { - 'CompareHow': 'Range::CompareHow', - 'Date': 'double', - 'Dictionary': 'Dictionary', - 'EventHandler': 'EventListener*', - 'Promise': 'ScriptPromise', - 'any': 'ScriptValue', - 'boolean': 'bool', -} - -def cpp_type(idl_type, extended_attributes=None, used_as_argument=False): - """Returns C++ type corresponding to IDL type.""" - def string_mode(): - # FIXME: the Web IDL spec requires 'EmptyString', not 'NullString', - # but we use NullString for performance. - if extended_attributes.get('TreatNullAs') != 'NullString': - return '' - if extended_attributes.get('TreatUndefinedAs') != 'NullString': - return 'WithNullCheck' - return 'WithUndefinedOrNullCheck' - - extended_attributes = extended_attributes or {} - idl_type = preprocess_idl_type(idl_type) - - if idl_type in CPP_TYPE_SAME_AS_IDL_TYPE: - return idl_type - if idl_type in CPP_INT_TYPES: - return 'int' - if idl_type in CPP_UNSIGNED_TYPES: - return 'unsigned' - if idl_type in CPP_SPECIAL_CONVERSION_RULES: - return CPP_SPECIAL_CONVERSION_RULES[idl_type] - if (idl_type in NON_WRAPPER_TYPES or - idl_type == 'XPathNSResolver'): # FIXME: eliminate this special case - return 'RefPtr<%s>' % idl_type - if idl_type == 'DOMString': - if not used_as_argument: - return 'String' - return 'V8StringResource<%s>' % string_mode() - if is_union_type(idl_type): - raise Exception('UnionType is not supported') - this_array_or_sequence_type = array_or_sequence_type(idl_type) - if this_array_or_sequence_type: - return cpp_template_type('Vector', cpp_type(this_array_or_sequence_type)) - - if is_typed_array_type and used_as_argument: - return idl_type + '*' - if is_interface_type(idl_type) and not used_as_argument: - return cpp_template_type('RefPtr', idl_type) - # Default, assume native type is a pointer with same type name as idl type - return idl_type + '*' - - -def cpp_template_type(template, inner_type): - """Returns C++ template specialized to type, with space added if needed.""" - if inner_type.endswith('>'): - format_string = '{template}<{inner_type} >' - else: - format_string = '{template}<{inner_type}>' - return format_string.format(template=template, inner_type=inner_type) - - -def v8_type(interface_type): - return 'V8' + interface_type - - -################################################################################ -# Includes -################################################################################ - - -def includes_for_cpp_class(class_name, relative_dir_posix): - return set([posixpath.join('bindings', relative_dir_posix, class_name + '.h')]) - - -INCLUDES_FOR_TYPE = { - 'any': set(['bindings/v8/ScriptValue.h']), - 'object': set(), - 'Dictionary': set(['bindings/v8/Dictionary.h']), - 'EventHandler': set(['bindings/v8/V8AbstractEventListener.h', - 'bindings/v8/V8EventListenerList.h']), - 'EventListener': set(['bindings/v8/BindingSecurity.h', - 'bindings/v8/V8EventListenerList.h', - 'core/frame/DOMWindow.h']), - 'MediaQueryListListener': set(['core/css/MediaQueryListListener.h']), - 'Promise': set(['bindings/v8/ScriptPromise.h']), - 'SerializedScriptValue': set(['bindings/v8/SerializedScriptValue.h']), -} - -def includes_for_type(idl_type): - if idl_type in INCLUDES_FOR_TYPE: - return INCLUDES_FOR_TYPE[idl_type] - if is_basic_type(idl_type) or is_enum_type(idl_type): - return set() - if is_typed_array_type(idl_type): - return set(['bindings/v8/custom/V8%sCustom.h' % idl_type]) - this_array_or_sequence_type = array_or_sequence_type(idl_type) - if this_array_or_sequence_type: - return includes_for_type(this_array_or_sequence_type) - if idl_type.endswith('Constructor'): - idl_type = constructor_type(idl_type) - return set(['V8%s.h' % idl_type]) - - -def add_includes_for_type(idl_type): - includes.update(includes_for_type(idl_type)) - - -################################################################################ -# V8 -> C++ -################################################################################ - -V8_VALUE_TO_CPP_VALUE = { - # Basic - 'Date': 'toWebCoreDate({v8_value})', - 'DOMString': '{v8_value}', - 'boolean': '{v8_value}->BooleanValue()', - 'float': 'static_cast<float>({v8_value}->NumberValue())', - 'double': 'static_cast<double>({v8_value}->NumberValue())', - 'byte': 'toInt8({arguments})', - 'octet': 'toUInt8({arguments})', - 'short': 'toInt16({arguments})', - 'unsigned short': 'toUInt16({arguments})', - 'long': 'toInt32({arguments})', - 'unsigned long': 'toUInt32({arguments})', - 'long long': 'toInt64({arguments})', - 'unsigned long long': 'toUInt64({arguments})', - # Interface types - 'any': 'ScriptValue({v8_value}, info.GetIsolate())', - 'CompareHow': 'static_cast<Range::CompareHow>({v8_value}->Int32Value())', - 'Dictionary': 'Dictionary({v8_value}, info.GetIsolate())', - 'MediaQueryListListener': 'MediaQueryListListener::create(ScriptValue({v8_value}, info.GetIsolate()))', - 'NodeFilter': 'toNodeFilter({v8_value}, info.GetIsolate())', - 'Promise': 'ScriptPromise({v8_value})', - 'SerializedScriptValue': 'SerializedScriptValue::create({v8_value}, info.GetIsolate())', - 'XPathNSResolver': 'toXPathNSResolver({v8_value}, info.GetIsolate())', -} - - -def v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, index): - this_array_or_sequence_type = array_or_sequence_type(idl_type) - if this_array_or_sequence_type: - return v8_value_to_cpp_value_array_or_sequence(this_array_or_sequence_type, v8_value, index) - - idl_type = preprocess_idl_type(idl_type) - add_includes_for_type(idl_type) - - if 'EnforceRange' in extended_attributes: - arguments = ', '.join([v8_value, 'EnforceRange', 'ok']) - else: # NormalConversion - arguments = v8_value - - if idl_type in V8_VALUE_TO_CPP_VALUE: - cpp_expression_format = V8_VALUE_TO_CPP_VALUE[idl_type] - elif is_typed_array_type(idl_type): - cpp_expression_format = ( - '{v8_value}->Is{idl_type}() ? ' - 'V8{idl_type}::toNative(v8::Handle<v8::{idl_type}>::Cast({v8_value})) : 0') - else: - cpp_expression_format = ( - 'V8{idl_type}::hasInstance({v8_value}, info.GetIsolate(), worldType(info.GetIsolate())) ? ' - 'V8{idl_type}::toNative(v8::Handle<v8::Object>::Cast({v8_value})) : 0') - - return cpp_expression_format.format(arguments=arguments, idl_type=idl_type, v8_value=v8_value) - - -def v8_value_to_cpp_value_array_or_sequence(this_array_or_sequence_type, v8_value, index): - # Index is None for setters, index (starting at 0) for method arguments, - # and is used to provide a human-readable exception message - if index is None: - index = 0 # special case, meaning "setter" - else: - index += 1 # human-readable index - if (is_interface_type(this_array_or_sequence_type) and - this_array_or_sequence_type != 'Dictionary'): - this_cpp_type = None - expression_format = '(toRefPtrNativeArray<{array_or_sequence_type}, V8{array_or_sequence_type}>({v8_value}, {index}, info.GetIsolate()))' - add_includes_for_type(this_array_or_sequence_type) - else: - this_cpp_type = cpp_type(this_array_or_sequence_type) - expression_format = 'toNativeArray<{cpp_type}>({v8_value}, {index}, info.GetIsolate())' - expression = expression_format.format(array_or_sequence_type=this_array_or_sequence_type, cpp_type=this_cpp_type, index=index, v8_value=v8_value) - return expression - - -def v8_value_to_local_cpp_value(idl_type, extended_attributes, v8_value, variable_name, index=None): - """Returns an expression that converts a V8 value to a C++ value and stores it as a local value.""" - this_cpp_type = cpp_type(idl_type, extended_attributes=extended_attributes, used_as_argument=True) - - idl_type = preprocess_idl_type(idl_type) - if idl_type == 'DOMString': - format_string = 'V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID({cpp_type}, {variable_name}, {cpp_value})' - elif 'EnforceRange' in extended_attributes: - format_string = 'V8TRYCATCH_WITH_TYPECHECK_VOID({cpp_type}, {variable_name}, {cpp_value}, info.GetIsolate())' - else: - format_string = 'V8TRYCATCH_VOID({cpp_type}, {variable_name}, {cpp_value})' - - cpp_value = v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, index) - return format_string.format(cpp_type=this_cpp_type, cpp_value=cpp_value, variable_name=variable_name) - - -################################################################################ -# C++ -> V8 -################################################################################ - - -def preprocess_idl_type(idl_type): - if is_enum_type(idl_type): - # Enumerations are internally DOMStrings - return 'DOMString' - if is_callback_function_type(idl_type): - return 'ScriptValue' - return idl_type - - -def preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes): - """Returns IDL type and value, with preliminary type conversions applied.""" - idl_type = preprocess_idl_type(idl_type) - if idl_type in ['Promise', 'any']: - idl_type = 'ScriptValue' - if idl_type in ['long long', 'unsigned long long']: - # long long and unsigned long long are not representable in ECMAScript; - # we represent them as doubles. - idl_type = 'double' - cpp_value = 'static_cast<double>(%s)' % cpp_value - # HTML5 says that unsigned reflected attributes should be in the range - # [0, 2^31). When a value isn't in this range, a default value (or 0) - # should be returned instead. - extended_attributes = extended_attributes or {} - if ('Reflect' in extended_attributes and - idl_type in ['unsigned long', 'unsigned short']): - cpp_value = cpp_value.replace('getUnsignedIntegralAttribute', - 'getIntegralAttribute') - cpp_value = 'std::max(0, %s)' % cpp_value - return idl_type, cpp_value - - -def v8_conversion_type(idl_type, extended_attributes): - """Returns V8 conversion type, adding any additional includes. - - The V8 conversion type is used to select the C++ -> V8 conversion function - or v8SetReturnValue* function; it can be an idl_type, a cpp_type, or a - separate name for the type of conversion (e.g., 'DOMWrapper'). - """ - extended_attributes = extended_attributes or {} - # Basic types, without additional includes - if idl_type in CPP_INT_TYPES: - return 'int' - if idl_type in CPP_UNSIGNED_TYPES: - return 'unsigned' - if idl_type == 'DOMString': - if 'TreatReturnedNullStringAs' not in extended_attributes: - return 'DOMString' - treat_returned_null_string_as = extended_attributes['TreatReturnedNullStringAs'] - if treat_returned_null_string_as == 'Null': - return 'StringOrNull' - if treat_returned_null_string_as == 'Undefined': - return 'StringOrUndefined' - raise 'Unrecognized TreatReturnNullStringAs value: "%s"' % treat_returned_null_string_as - if is_basic_type(idl_type) or idl_type == 'ScriptValue': - return idl_type - - # Data type with potential additional includes - this_array_or_sequence_type = array_or_sequence_type(idl_type) - if this_array_or_sequence_type: - if is_interface_type(this_array_or_sequence_type): - add_includes_for_type(this_array_or_sequence_type) - return 'array' - - add_includes_for_type(idl_type) - if idl_type in V8_SET_RETURN_VALUE: # Special v8SetReturnValue treatment - return idl_type - - # Pointer type - includes.add('wtf/GetPtr.h') # FIXME: remove if can eliminate WTF::getPtr - includes.add('wtf/RefPtr.h') - return 'DOMWrapper' - - -V8_SET_RETURN_VALUE = { - 'boolean': 'v8SetReturnValueBool(info, {cpp_value})', - 'int': 'v8SetReturnValueInt(info, {cpp_value})', - 'unsigned': 'v8SetReturnValueUnsigned(info, {cpp_value})', - 'DOMString': 'v8SetReturnValueString(info, {cpp_value}, info.GetIsolate())', - # [TreatNullReturnValueAs] - 'StringOrNull': 'v8SetReturnValueStringOrNull(info, {cpp_value}, info.GetIsolate())', - 'StringOrUndefined': 'v8SetReturnValueStringOrUndefined(info, {cpp_value}, info.GetIsolate())', - 'void': '', - # No special v8SetReturnValue* function (set value directly) - 'float': 'v8SetReturnValue(info, {cpp_value})', - 'double': 'v8SetReturnValue(info, {cpp_value})', - # No special v8SetReturnValue* function, but instead convert value to V8 - # and then use general v8SetReturnValue. - 'array': 'v8SetReturnValue(info, {cpp_value})', - 'Date': 'v8SetReturnValue(info, {cpp_value})', - 'EventHandler': 'v8SetReturnValue(info, {cpp_value})', - 'ScriptValue': 'v8SetReturnValue(info, {cpp_value})', - 'SerializedScriptValue': 'v8SetReturnValue(info, {cpp_value})', - # DOMWrapper - 'DOMWrapperFast': 'v8SetReturnValueFast(info, {cpp_value}, {script_wrappable})', - 'DOMWrapperDefault': 'v8SetReturnValue(info, {cpp_value})', -} - - -def v8_set_return_value(idl_type, cpp_value, extended_attributes=None, script_wrappable=''): - """Returns a statement that converts a C++ value to a V8 value and sets it as a return value.""" - def dom_wrapper_conversion_type(): - if not script_wrappable: - return 'DOMWrapperDefault' - return 'DOMWrapperFast' - - idl_type, cpp_value = preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes) - this_v8_conversion_type = v8_conversion_type(idl_type, extended_attributes) - # SetReturn-specific overrides - if this_v8_conversion_type in ['Date', 'EventHandler', 'ScriptValue', 'SerializedScriptValue', 'array']: - # Convert value to V8 and then use general v8SetReturnValue - cpp_value = cpp_value_to_v8_value(idl_type, cpp_value, extended_attributes=extended_attributes) - if this_v8_conversion_type == 'DOMWrapper': - this_v8_conversion_type = dom_wrapper_conversion_type() - - format_string = V8_SET_RETURN_VALUE[this_v8_conversion_type] - statement = format_string.format(cpp_value=cpp_value, script_wrappable=script_wrappable) - return statement - - -CPP_VALUE_TO_V8_VALUE = { - # Built-in types - 'Date': 'v8DateOrNull({cpp_value}, {isolate})', - 'DOMString': 'v8String({isolate}, {cpp_value})', - 'boolean': 'v8Boolean({cpp_value}, {isolate})', - 'int': 'v8::Integer::New({isolate}, {cpp_value})', - 'unsigned': 'v8::Integer::NewFromUnsigned({isolate}, {cpp_value})', - 'float': 'v8::Number::New({isolate}, {cpp_value})', - 'double': 'v8::Number::New({isolate}, {cpp_value})', - 'void': 'v8Undefined()', - # Special cases - 'EventHandler': '{cpp_value} ? v8::Handle<v8::Value>(V8AbstractEventListener::cast({cpp_value})->getListenerObject(imp->executionContext())) : v8::Handle<v8::Value>(v8::Null({isolate}))', - 'ScriptValue': '{cpp_value}.v8Value()', - 'SerializedScriptValue': '{cpp_value} ? {cpp_value}->deserialize() : v8::Handle<v8::Value>(v8::Null({isolate}))', - # General - 'array': 'v8Array({cpp_value}, {isolate})', - 'DOMWrapper': 'toV8({cpp_value}, {creation_context}, {isolate})', -} - - -def cpp_value_to_v8_value(idl_type, cpp_value, isolate='info.GetIsolate()', creation_context='', extended_attributes=None): - """Returns an expression that converts a C++ value to a V8 value.""" - # the isolate parameter is needed for callback interfaces - idl_type, cpp_value = preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes) - this_v8_conversion_type = v8_conversion_type(idl_type, extended_attributes) - format_string = CPP_VALUE_TO_V8_VALUE[this_v8_conversion_type] - statement = format_string.format(cpp_value=cpp_value, isolate=isolate, creation_context=creation_context) - return statement diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/utilities.py b/chromium/third_party/WebKit/Source/bindings/scripts/utilities.py new file mode 100644 index 00000000000..0aeabc20b36 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/utilities.py @@ -0,0 +1,171 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Utility functions (file reading, simple IDL parsing by regexes) for IDL build. + +Design doc: http://www.chromium.org/developers/design-documents/idl-build +""" + +import os +import cPickle as pickle +import re +import string + + +class IdlBadFilenameError(Exception): + """Raised if an IDL filename disagrees with the interface name in the file.""" + pass + + +def idl_filename_to_interface_name(idl_filename): + # interface name is the root of the basename: InterfaceName.idl + return os.path.splitext(os.path.basename(idl_filename))[0] + + +################################################################################ +# Basic file reading/writing +################################################################################ + +def get_file_contents(filename): + with open(filename) as f: + return f.read() + + +def read_file_to_list(filename): + """Returns a list of (stripped) lines for a given filename.""" + with open(filename) as f: + return [line.rstrip('\n') for line in f] + + +def read_pickle_files(pickle_filenames): + for pickle_filename in pickle_filenames: + with open(pickle_filename) as pickle_file: + yield pickle.load(pickle_file) + + +def write_file(new_text, destination_filename, only_if_changed): + if only_if_changed and os.path.isfile(destination_filename): + with open(destination_filename) as destination_file: + if destination_file.read() == new_text: + return + with open(destination_filename, 'w') as destination_file: + destination_file.write(new_text) + + +def write_pickle_file(pickle_filename, data, only_if_changed): + if only_if_changed and os.path.isfile(pickle_filename): + with open(pickle_filename) as pickle_file: + try: + if pickle.load(pickle_file) == data: + return + except (EOFError, pickle.UnpicklingError): + # If trouble unpickling, overwrite + pass + with open(pickle_filename, 'w') as pickle_file: + pickle.dump(data, pickle_file) + + +################################################################################ +# IDL parsing +# +# We use regular expressions for parsing; this is incorrect (Web IDL is not a +# regular language), but simple and sufficient in practice. +# Leading and trailing context (e.g. following '{') used to avoid false matches. +################################################################################ + +def get_partial_interface_name_from_idl(file_contents): + match = re.search(r'partial\s+interface\s+(\w+)\s*{', file_contents) + return match and match.group(1) + + +def get_implements_from_idl(file_contents, interface_name): + """Returns lists of implementing and implemented interfaces. + + Rule is: identifier-A implements identifier-B; + i.e., implement*ing* implements implement*ed*; + http://www.w3.org/TR/WebIDL/#idl-implements-statements + + Returns two lists of interfaces: identifier-As and identifier-Bs. + An 'implements' statements can be present in the IDL file for either the + implementing or the implemented interface, but not other files. + """ + implements_re = (r'^\s*' + r'(\w+)\s+' + r'implements\s+' + r'(\w+)\s*' + r';') + implements_matches = re.finditer(implements_re, file_contents, re.MULTILINE) + implements_pairs = [match.groups() for match in implements_matches] + + foreign_implements = [pair for pair in implements_pairs + if interface_name not in pair] + if foreign_implements: + left, right = foreign_implements.pop() + raise IdlBadFilenameError( + 'implements statement found in unrelated IDL file.\n' + 'Statement is:\n' + ' %s implements %s;\n' + 'but filename is unrelated "%s.idl"' % + (left, right, interface_name)) + + return ( + [left for left, right in implements_pairs if right == interface_name], + [right for left, right in implements_pairs if left == interface_name]) + + +def is_callback_interface_from_idl(file_contents): + match = re.search(r'callback\s+interface\s+\w+\s*{', file_contents) + return bool(match) + + +def get_parent_interface(file_contents): + match = re.search(r'interface\s+' + r'\w+\s*' + r':\s*(\w+)\s*' + r'{', + file_contents) + return match and match.group(1) + + +def get_interface_extended_attributes_from_idl(file_contents): + # Strip comments + # re.compile needed b/c Python 2.6 doesn't support flags in re.sub + single_line_comment_re = re.compile(r'//.*$', flags=re.MULTILINE) + block_comment_re = re.compile(r'/\*.*?\*/', flags=re.MULTILINE | re.DOTALL) + file_contents = re.sub(single_line_comment_re, '', file_contents) + file_contents = re.sub(block_comment_re, '', file_contents) + + match = re.search(r'\[(.*)\]\s*' + r'((callback|partial)\s+)?' + r'(interface|exception)\s+' + r'\w+\s*' + r'(:\s*\w+\s*)?' + r'{', + file_contents, flags=re.DOTALL) + if not match: + return {} + + extended_attributes_string = match.group(1) + extended_attributes = {} + # FIXME: this splitting is WRONG: it fails on ExtendedAttributeArgList like + # 'NamedConstructor=Foo(a, b)' + parts = [extended_attribute.strip() + for extended_attribute in extended_attributes_string.split(',') + # Discard empty parts, which may exist due to trailing comma + if extended_attribute.strip()] + for part in parts: + name, _, value = map(string.strip, part.partition('=')) + extended_attributes[name] = value + return extended_attributes + + +def get_put_forward_interfaces_from_idl(file_contents): + put_forwards_pattern = (r'\[[^\]]*PutForwards=[^\]]*\]\s+' + r'readonly\s+' + r'attribute\s+' + r'(\w+)') + return sorted(set(match.group(1) + for match in re.finditer(put_forwards_pattern, + file_contents, + flags=re.DOTALL))) diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/v8_attributes.py b/chromium/third_party/WebKit/Source/bindings/scripts/v8_attributes.py new file mode 100644 index 00000000000..d774313bb9b --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/v8_attributes.py @@ -0,0 +1,436 @@ +# Copyright (C) 2013 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. + +"""Generate template values for attributes. + +Extends IdlType with property |constructor_type_name|. + +Design doc: http://www.chromium.org/developers/design-documents/idl-compiler +""" + +import idl_types +from idl_types import inherits_interface +from v8_globals import includes, interfaces +import v8_types +import v8_utilities +from v8_utilities import capitalize, cpp_name, has_extended_attribute, has_extended_attribute_value, scoped_name, strip_suffix, uncapitalize + + +def generate_attribute(interface, attribute): + idl_type = attribute.idl_type + base_idl_type = idl_type.base_type + extended_attributes = attribute.extended_attributes + + idl_type.add_includes_for_type() + + # [CheckSecurity] + is_check_security_for_node = 'CheckSecurity' in extended_attributes + if is_check_security_for_node: + includes.add('bindings/v8/BindingSecurity.h') + # [Custom] + has_custom_getter = ('Custom' in extended_attributes and + extended_attributes['Custom'] in [None, 'Getter']) + has_custom_setter = (not attribute.is_read_only and + 'Custom' in extended_attributes and + extended_attributes['Custom'] in [None, 'Setter']) + # [CustomElementCallbacks], [Reflect] + is_custom_element_callbacks = 'CustomElementCallbacks' in extended_attributes + is_reflect = 'Reflect' in extended_attributes + if is_custom_element_callbacks or is_reflect: + includes.add('core/dom/custom/CustomElementCallbackDispatcher.h') + # [PerWorldBindings] + if 'PerWorldBindings' in extended_attributes: + assert idl_type.is_wrapper_type or 'LogActivity' in extended_attributes, '[PerWorldBindings] should only be used with wrapper types: %s.%s' % (interface.name, attribute.name) + # [RaisesException], [RaisesException=Setter] + is_setter_raises_exception = ( + 'RaisesException' in extended_attributes and + extended_attributes['RaisesException'] in [None, 'Setter']) + # [TypeChecking] + has_type_checking_interface = ( + (has_extended_attribute_value(interface, 'TypeChecking', 'Interface') or + has_extended_attribute_value(attribute, 'TypeChecking', 'Interface')) and + idl_type.is_wrapper_type) + has_type_checking_nullable = ( + (has_extended_attribute_value(interface, 'TypeChecking', 'Nullable') or + has_extended_attribute_value(attribute, 'TypeChecking', 'Nullable')) and + idl_type.is_wrapper_type) + has_type_checking_unrestricted = ( + (has_extended_attribute_value(interface, 'TypeChecking', 'Unrestricted') or + has_extended_attribute_value(attribute, 'TypeChecking', 'Unrestricted')) and + idl_type.name in ('Float', 'Double')) + + if (base_idl_type == 'EventHandler' and + interface.name in ['Window', 'WorkerGlobalScope'] and + attribute.name == 'onerror'): + includes.add('bindings/v8/V8ErrorHandler.h') + + contents = { + 'access_control_list': access_control_list(attribute), + 'activity_logging_world_list_for_getter': v8_utilities.activity_logging_world_list(attribute, 'Getter'), # [ActivityLogging] + 'activity_logging_world_list_for_setter': v8_utilities.activity_logging_world_list(attribute, 'Setter'), # [ActivityLogging] + 'activity_logging_include_old_value_for_setter': 'LogPreviousValue' in extended_attributes, # [ActivityLogging] + 'activity_logging_world_check': v8_utilities.activity_logging_world_check(attribute), # [ActivityLogging] + 'cached_attribute_validation_method': extended_attributes.get('CachedAttribute'), + 'conditional_string': v8_utilities.conditional_string(attribute), + 'constructor_type': idl_type.constructor_type_name + if is_constructor_attribute(attribute) else None, + 'cpp_name': cpp_name(attribute), + 'cpp_type': idl_type.cpp_type, + 'cpp_value_to_v8_value': idl_type.cpp_value_to_v8_value(cpp_value='original', creation_context='info.Holder()'), + 'deprecate_as': v8_utilities.deprecate_as(attribute), # [DeprecateAs] + 'enum_validation_expression': idl_type.enum_validation_expression, + 'has_custom_getter': has_custom_getter, + 'has_custom_setter': has_custom_setter, + 'has_setter_exception_state': + is_setter_raises_exception or has_type_checking_interface or + has_type_checking_nullable or has_type_checking_unrestricted or + idl_type.is_integer_type or + idl_type.name in ('ByteString', 'ScalarValueString'), + 'has_type_checking_interface': has_type_checking_interface, + 'has_type_checking_nullable': has_type_checking_nullable, + 'has_type_checking_unrestricted': has_type_checking_unrestricted, + 'idl_type': str(idl_type), # need trailing [] on array for Dictionary::ConversionContext::setConversionType + 'is_call_with_execution_context': v8_utilities.has_extended_attribute_value(attribute, 'CallWith', 'ExecutionContext'), + 'is_call_with_script_state': v8_utilities.has_extended_attribute_value(attribute, 'CallWith', 'ScriptState'), + 'is_check_security_for_node': is_check_security_for_node, + 'is_custom_element_callbacks': is_custom_element_callbacks, + 'is_expose_js_accessors': 'ExposeJSAccessors' in extended_attributes, + 'is_getter_raises_exception': # [RaisesException] + 'RaisesException' in extended_attributes and + extended_attributes['RaisesException'] in (None, 'Getter'), + 'is_initialized_by_event_constructor': + 'InitializedByEventConstructor' in extended_attributes, + 'is_keep_alive_for_gc': is_keep_alive_for_gc(interface, attribute), + 'is_nullable': attribute.idl_type.is_nullable, + 'is_partial_interface_member': + 'PartialInterfaceImplementedAs' in extended_attributes, + 'is_per_world_bindings': 'PerWorldBindings' in extended_attributes, + 'is_read_only': attribute.is_read_only, + 'is_reflect': is_reflect, + 'is_replaceable': 'Replaceable' in attribute.extended_attributes, + 'is_setter_call_with_execution_context': v8_utilities.has_extended_attribute_value(attribute, 'SetterCallWith', 'ExecutionContext'), + 'is_setter_raises_exception': is_setter_raises_exception, + 'is_static': attribute.is_static, + 'is_url': 'URL' in extended_attributes, + 'is_unforgeable': 'Unforgeable' in extended_attributes, + 'measure_as': v8_utilities.measure_as(attribute), # [MeasureAs] + 'name': attribute.name, + 'per_context_enabled_function': v8_utilities.per_context_enabled_function_name(attribute), # [PerContextEnabled] + 'property_attributes': property_attributes(attribute), + 'put_forwards': 'PutForwards' in extended_attributes, + 'reflect_empty': extended_attributes.get('ReflectEmpty'), + 'reflect_invalid': extended_attributes.get('ReflectInvalid', ''), + 'reflect_missing': extended_attributes.get('ReflectMissing'), + 'reflect_only': extended_attributes['ReflectOnly'].split('|') + if 'ReflectOnly' in extended_attributes else None, + 'setter_callback': setter_callback_name(interface, attribute), + 'v8_type': v8_types.v8_type(base_idl_type), + 'runtime_enabled_function': v8_utilities.runtime_enabled_function_name(attribute), # [RuntimeEnabled] + 'world_suffixes': ['', 'ForMainWorld'] + if 'PerWorldBindings' in extended_attributes + else [''], # [PerWorldBindings] + } + + if is_constructor_attribute(attribute): + generate_constructor_getter(interface, attribute, contents) + return contents + if not has_custom_getter: + generate_getter(interface, attribute, contents) + if (not has_custom_setter and + (not attribute.is_read_only or 'PutForwards' in extended_attributes)): + generate_setter(interface, attribute, contents) + + return contents + + +################################################################################ +# Getter +################################################################################ + +def generate_getter(interface, attribute, contents): + idl_type = attribute.idl_type + base_idl_type = idl_type.base_type + extended_attributes = attribute.extended_attributes + + cpp_value = getter_expression(interface, attribute, contents) + # Normally we can inline the function call into the return statement to + # avoid the overhead of using a Ref<> temporary, but for some cases + # (nullable types, EventHandler, [CachedAttribute], or if there are + # exceptions), we need to use a local variable. + # FIXME: check if compilers are smart enough to inline this, and if so, + # always use a local variable (for readability and CG simplicity). + release = False + if (idl_type.is_nullable or + base_idl_type == 'EventHandler' or + 'CachedAttribute' in extended_attributes or + 'ReflectOnly' in extended_attributes or + contents['is_getter_raises_exception']): + contents['cpp_value_original'] = cpp_value + cpp_value = 'v8Value' + # EventHandler has special handling + if base_idl_type != 'EventHandler' and idl_type.is_interface_type: + release = True + + def v8_set_return_value_statement(for_main_world=False): + if contents['is_keep_alive_for_gc']: + return 'v8SetReturnValue(info, wrapper)' + return idl_type.v8_set_return_value(cpp_value, extended_attributes=extended_attributes, script_wrappable='impl', release=release, for_main_world=for_main_world) + + contents.update({ + 'cpp_value': cpp_value, + 'cpp_value_to_v8_value': idl_type.cpp_value_to_v8_value(cpp_value=cpp_value, creation_context='info.Holder()'), + 'v8_set_return_value_for_main_world': v8_set_return_value_statement(for_main_world=True), + 'v8_set_return_value': v8_set_return_value_statement(), + }) + + +def getter_expression(interface, attribute, contents): + arguments = [] + this_getter_base_name = getter_base_name(interface, attribute, arguments) + getter_name = scoped_name(interface, attribute, this_getter_base_name) + + arguments.extend(v8_utilities.call_with_arguments( + attribute.extended_attributes.get('CallWith'))) + # Members of IDL partial interface definitions are implemented in C++ as + # static member functions, which for instance members (non-static members) + # take *impl as their first argument + if ('PartialInterfaceImplementedAs' in attribute.extended_attributes and + not attribute.is_static): + arguments.append('*impl') + if attribute.idl_type.is_nullable and not contents['has_type_checking_nullable']: + arguments.append('isNull') + if contents['is_getter_raises_exception']: + arguments.append('exceptionState') + return '%s(%s)' % (getter_name, ', '.join(arguments)) + + +CONTENT_ATTRIBUTE_GETTER_NAMES = { + 'boolean': 'fastHasAttribute', + 'long': 'getIntegralAttribute', + 'unsigned long': 'getUnsignedIntegralAttribute', +} + + +def getter_base_name(interface, attribute, arguments): + extended_attributes = attribute.extended_attributes + if 'Reflect' not in extended_attributes: + return uncapitalize(cpp_name(attribute)) + + content_attribute_name = extended_attributes['Reflect'] or attribute.name.lower() + if content_attribute_name in ['class', 'id', 'name']: + # Special-case for performance optimization. + return 'get%sAttribute' % content_attribute_name.capitalize() + + arguments.append(scoped_content_attribute_name(interface, attribute)) + + base_idl_type = attribute.idl_type.base_type + if base_idl_type in CONTENT_ATTRIBUTE_GETTER_NAMES: + return CONTENT_ATTRIBUTE_GETTER_NAMES[base_idl_type] + if 'URL' in attribute.extended_attributes: + return 'getURLAttribute' + return 'fastGetAttribute' + + +def is_keep_alive_for_gc(interface, attribute): + idl_type = attribute.idl_type + base_idl_type = idl_type.base_type + extended_attributes = attribute.extended_attributes + return ( + # For readonly attributes, for performance reasons we keep the attribute + # wrapper alive while the owner wrapper is alive, because the attribute + # never changes. + (attribute.is_read_only and + idl_type.is_wrapper_type and + # There are some exceptions, however: + not( + # Node lifetime is managed by object grouping. + inherits_interface(interface.name, 'Node') or + inherits_interface(base_idl_type, 'Node') or + # A self-reference is unnecessary. + attribute.name == 'self' or + # FIXME: Remove these hard-coded hacks. + base_idl_type in ['EventTarget', 'Window'] or + base_idl_type.startswith(('HTML', 'SVG'))))) + + +################################################################################ +# Setter +################################################################################ + +def generate_setter(interface, attribute, contents): + def target_attribute(): + target_interface_name = attribute.idl_type.base_type + target_attribute_name = extended_attributes['PutForwards'] + target_interface = interfaces[target_interface_name] + try: + return next(attribute + for attribute in target_interface.attributes + if attribute.name == target_attribute_name) + except StopIteration: + raise Exception('[PutForward] target not found:\n' + 'Attribute "%s" is not present in interface "%s"' % + (target_attribute_name, target_interface_name)) + + extended_attributes = attribute.extended_attributes + + if 'PutForwards' in extended_attributes: + # Use target attribute in place of original attribute + attribute = target_attribute() + + contents.update({ + 'cpp_setter': setter_expression(interface, attribute, contents), + 'v8_value_to_local_cpp_value': attribute.idl_type.v8_value_to_local_cpp_value(extended_attributes, 'v8Value', 'cppValue'), + }) + + +def setter_expression(interface, attribute, contents): + extended_attributes = attribute.extended_attributes + arguments = v8_utilities.call_with_arguments( + extended_attributes.get('SetterCallWith') or + extended_attributes.get('CallWith')) + + this_setter_base_name = setter_base_name(interface, attribute, arguments) + setter_name = scoped_name(interface, attribute, this_setter_base_name) + + # Members of IDL partial interface definitions are implemented in C++ as + # static member functions, which for instance members (non-static members) + # take *impl as their first argument + if ('PartialInterfaceImplementedAs' in extended_attributes and + not attribute.is_static): + arguments.append('*impl') + idl_type = attribute.idl_type + if idl_type.base_type == 'EventHandler': + getter_name = scoped_name(interface, attribute, cpp_name(attribute)) + contents['event_handler_getter_expression'] = '%s(%s)' % ( + getter_name, ', '.join(arguments)) + if (interface.name in ['Window', 'WorkerGlobalScope'] and + attribute.name == 'onerror'): + includes.add('bindings/v8/V8ErrorHandler.h') + arguments.append('V8EventListenerList::findOrCreateWrapper<V8ErrorHandler>(v8Value, true, ScriptState::current(info.GetIsolate()))') + else: + arguments.append('V8EventListenerList::getEventListener(ScriptState::current(info.GetIsolate()), v8Value, true, ListenerFindOrCreate)') + elif idl_type.is_interface_type and not idl_type.array_type: + # FIXME: should be able to eliminate WTF::getPtr in most or all cases + arguments.append('WTF::getPtr(cppValue)') + else: + arguments.append('cppValue') + if contents['is_setter_raises_exception']: + arguments.append('exceptionState') + + return '%s(%s)' % (setter_name, ', '.join(arguments)) + + +CONTENT_ATTRIBUTE_SETTER_NAMES = { + 'boolean': 'setBooleanAttribute', + 'long': 'setIntegralAttribute', + 'unsigned long': 'setUnsignedIntegralAttribute', +} + + +def setter_base_name(interface, attribute, arguments): + if 'Reflect' not in attribute.extended_attributes: + return 'set%s' % capitalize(cpp_name(attribute)) + arguments.append(scoped_content_attribute_name(interface, attribute)) + + base_idl_type = attribute.idl_type.base_type + if base_idl_type in CONTENT_ATTRIBUTE_SETTER_NAMES: + return CONTENT_ATTRIBUTE_SETTER_NAMES[base_idl_type] + return 'setAttribute' + + +def scoped_content_attribute_name(interface, attribute): + content_attribute_name = attribute.extended_attributes['Reflect'] or attribute.name.lower() + namespace = 'SVGNames' if interface.name.startswith('SVG') else 'HTMLNames' + includes.add('%s.h' % namespace) + return '%s::%sAttr' % (namespace, content_attribute_name) + + +################################################################################ +# Attribute configuration +################################################################################ + +# [Replaceable] +def setter_callback_name(interface, attribute): + cpp_class_name = cpp_name(interface) + extended_attributes = attribute.extended_attributes + if (('Replaceable' in extended_attributes and + 'PutForwards' not in extended_attributes) or + is_constructor_attribute(attribute)): + # FIXME: rename to ForceSetAttributeOnThisCallback, since also used for Constructors + return '{0}V8Internal::{0}ReplaceableAttributeSetterCallback'.format(cpp_class_name) + if attribute.is_read_only and 'PutForwards' not in extended_attributes: + return '0' + return '%sV8Internal::%sAttributeSetterCallback' % (cpp_class_name, attribute.name) + + +# [DoNotCheckSecurity], [Unforgeable] +def access_control_list(attribute): + extended_attributes = attribute.extended_attributes + access_control = [] + if 'DoNotCheckSecurity' in extended_attributes: + do_not_check_security = extended_attributes['DoNotCheckSecurity'] + if do_not_check_security == 'Setter': + access_control.append('v8::ALL_CAN_WRITE') + else: + access_control.append('v8::ALL_CAN_READ') + if (not attribute.is_read_only or + 'Replaceable' in extended_attributes): + access_control.append('v8::ALL_CAN_WRITE') + if 'Unforgeable' in extended_attributes: + access_control.append('v8::PROHIBITS_OVERWRITING') + return access_control or ['v8::DEFAULT'] + + +# [NotEnumerable], [Unforgeable] +def property_attributes(attribute): + extended_attributes = attribute.extended_attributes + property_attributes_list = [] + if ('NotEnumerable' in extended_attributes or + is_constructor_attribute(attribute)): + property_attributes_list.append('v8::DontEnum') + if 'Unforgeable' in extended_attributes: + property_attributes_list.append('v8::DontDelete') + return property_attributes_list or ['v8::None'] + + +################################################################################ +# Constructors +################################################################################ + +idl_types.IdlType.constructor_type_name = property( + # FIXME: replace this with a [ConstructorAttribute] extended attribute + lambda self: strip_suffix(self.base_type, 'Constructor')) + + +def is_constructor_attribute(attribute): + # FIXME: replace this with [ConstructorAttribute] extended attribute + return attribute.idl_type.base_type.endswith('Constructor') + + +def generate_constructor_getter(interface, attribute, contents): + contents['needs_constructor_getter_callback'] = contents['measure_as'] or contents['deprecate_as'] diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/v8_callback_interface.py b/chromium/third_party/WebKit/Source/bindings/scripts/v8_callback_interface.py index 2e310d19a10..06c18f2b809 100644 --- a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/v8_callback_interface.py +++ b/chromium/third_party/WebKit/Source/bindings/scripts/v8_callback_interface.py @@ -28,81 +28,72 @@ """Generate template values for a callback interface. -FIXME: Not currently used in build. -This is a rewrite of the Perl IDL compiler in Python, but is not complete. -Once it is complete, we will switch all IDL files over to Python at once. -Until then, please work on the Perl IDL compiler. -For details, see bug http://crbug.com/239771 +Extends IdlType with property |callback_cpp_type|. + +Design doc: http://www.chromium.org/developers/design-documents/idl-compiler """ +from idl_types import IdlType from v8_globals import includes import v8_types import v8_utilities -CALLBACK_INTERFACE_H_INCLUDES = set([ +CALLBACK_INTERFACE_H_INCLUDES = frozenset([ 'bindings/v8/ActiveDOMCallback.h', 'bindings/v8/DOMWrapperWorld.h', 'bindings/v8/ScopedPersistent.h', ]) -CALLBACK_INTERFACE_CPP_INCLUDES = set([ +CALLBACK_INTERFACE_CPP_INCLUDES = frozenset([ 'bindings/v8/V8Binding.h', 'bindings/v8/V8Callback.h', 'core/dom/ExecutionContext.h', 'wtf/Assertions.h', + 'wtf/GetPtr.h', + 'wtf/RefPtr.h', ]) -def cpp_to_v8_conversion(idl_type, name): - # FIXME: setting creation_context=v8::Handle<v8::Object>() is wrong, - # as toV8 then implicitly uses the current context, which causes leaks - # between isolate worlds if a different context should be used. - cpp_value_to_v8_value = v8_types.cpp_value_to_v8_value(idl_type, name, - isolate='isolate', creation_context='v8::Handle<v8::Object>()') - return 'v8::Handle<v8::Value> {name}Handle = {cpp_to_v8};'.format( - name=name, cpp_to_v8=cpp_value_to_v8_value) - - def cpp_type(idl_type): # FIXME: remove this function by making callback types consistent # (always use usual v8_types.cpp_type) - if idl_type == 'DOMString': + idl_type_name = idl_type.name + if idl_type_name == 'String': return 'const String&' - if idl_type == 'void': + if idl_type_name == 'void': return 'void' # Callbacks use raw pointers, so used_as_argument=True - usual_cpp_type = v8_types.cpp_type(idl_type, used_as_argument=True) - if usual_cpp_type.startswith('Vector'): + usual_cpp_type = idl_type.cpp_type_args(used_as_argument=True) + if usual_cpp_type.startswith(('Vector', 'HeapVector', 'WillBeHeapVector')): return 'const %s&' % usual_cpp_type return usual_cpp_type +IdlType.callback_cpp_type = property(cpp_type) + def generate_callback_interface(callback_interface): includes.clear() includes.update(CALLBACK_INTERFACE_CPP_INCLUDES) - name = callback_interface.name - - methods = [generate_method(operation) - for operation in callback_interface.operations] - template_contents = { + return { 'conditional_string': v8_utilities.conditional_string(callback_interface), - 'cpp_class': name, + 'cpp_class': callback_interface.name, 'v8_class': v8_utilities.v8_class_name(callback_interface), - 'header_includes': CALLBACK_INTERFACE_H_INCLUDES, - 'methods': methods, + 'header_includes': set(CALLBACK_INTERFACE_H_INCLUDES), + 'methods': [generate_method(operation) + for operation in callback_interface.operations], } - return template_contents def add_includes_for_operation(operation): - v8_types.add_includes_for_type(operation.idl_type) + operation.idl_type.add_includes_for_type() for argument in operation.arguments: - v8_types.add_includes_for_type(argument.idl_type) + argument.idl_type.add_includes_for_type() def generate_method(operation): extended_attributes = operation.extended_attributes idl_type = operation.idl_type - if idl_type not in ['boolean', 'void']: + idl_type_str = str(idl_type) + if idl_type_str not in ['boolean', 'void']: raise Exception('We only support callbacks that return boolean or void values.') is_custom = 'Custom' in extended_attributes if not is_custom: @@ -111,10 +102,10 @@ def generate_method(operation): call_with_this_handle = v8_utilities.extended_attribute_value_contains(call_with, 'ThisValue') contents = { 'call_with_this_handle': call_with_this_handle, + 'cpp_type': idl_type.callback_cpp_type, 'custom': is_custom, + 'idl_type': idl_type_str, 'name': operation.name, - 'return_cpp_type': cpp_type(idl_type), - 'return_idl_type': idl_type, } contents.update(generate_arguments_contents(operation.arguments, call_with_this_handle)) return contents @@ -123,17 +114,21 @@ def generate_method(operation): def generate_arguments_contents(arguments, call_with_this_handle): def generate_argument(argument): return { - 'name': argument.name, - 'cpp_to_v8_conversion': cpp_to_v8_conversion(argument.idl_type, argument.name), + 'handle': '%sHandle' % argument.name, + # FIXME: setting creation_context=v8::Handle<v8::Object>() is + # wrong, as toV8 then implicitly uses the current context, which + # causes leaks between isolated worlds if a different context is + # used. + 'cpp_value_to_v8_value': argument.idl_type.cpp_value_to_v8_value( + argument.name, isolate='isolate', + creation_context='m_scriptState->context()->Global()'), } - argument_declarations = [ - '%s %s' % (cpp_type(argument.idl_type), argument.name) - for argument in arguments] - if call_with_this_handle: - argument_declarations.insert(0, 'ScriptValue thisValue') + argument_declarations = ['ScriptValue thisValue'] if call_with_this_handle else [] + argument_declarations.extend( + '%s %s' % (argument.idl_type.callback_cpp_type, argument.name) + for argument in arguments) return { 'argument_declarations': argument_declarations, 'arguments': [generate_argument(argument) for argument in arguments], - 'handles': ['%sHandle' % argument.name for argument in arguments], } diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/v8_globals.py b/chromium/third_party/WebKit/Source/bindings/scripts/v8_globals.py index b640703647a..9ca2a3574a9 100644 --- a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/v8_globals.py +++ b/chromium/third_party/WebKit/Source/bindings/scripts/v8_globals.py @@ -26,6 +26,7 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -"""Module to share global variables (namely includes) across modules.""" +"""Module to share global variables (includes and interfaces) across modules.""" includes = set() +interfaces = {} diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/v8_interface.py b/chromium/third_party/WebKit/Source/bindings/scripts/v8_interface.py new file mode 100644 index 00000000000..abc23b40b07 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/v8_interface.py @@ -0,0 +1,1087 @@ +# Copyright (C) 2013 Google Inc. All rights reserved. +# coding=utf-8 +# +# 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. + +"""Generate template values for an interface. + +Design doc: http://www.chromium.org/developers/design-documents/idl-compiler +""" + +from collections import defaultdict +import itertools +from operator import itemgetter + +import idl_types +from idl_types import IdlType, inherits_interface +import v8_attributes +from v8_globals import includes +import v8_methods +import v8_types +from v8_types import cpp_ptr_type, cpp_template_type +import v8_utilities +from v8_utilities import capitalize, conditional_string, cpp_name, gc_type, has_extended_attribute_value, runtime_enabled_function_name + + +INTERFACE_H_INCLUDES = frozenset([ + 'bindings/v8/V8Binding.h', + 'bindings/v8/V8DOMWrapper.h', + 'bindings/v8/WrapperTypeInfo.h', + 'platform/heap/Handle.h', +]) +INTERFACE_CPP_INCLUDES = frozenset([ + 'bindings/v8/ExceptionState.h', + 'bindings/v8/V8DOMConfiguration.h', + 'bindings/v8/V8HiddenValue.h', + 'bindings/v8/V8ObjectConstructor.h', + 'core/dom/ContextFeatures.h', + 'core/dom/Document.h', + 'platform/RuntimeEnabledFeatures.h', + 'platform/TraceEvent.h', + 'wtf/GetPtr.h', + 'wtf/RefPtr.h', +]) + + +def generate_interface(interface): + includes.clear() + includes.update(INTERFACE_CPP_INCLUDES) + header_includes = set(INTERFACE_H_INCLUDES) + + parent_interface = interface.parent + if parent_interface: + header_includes.update(v8_types.includes_for_interface(parent_interface)) + extended_attributes = interface.extended_attributes + + is_audio_buffer = inherits_interface(interface.name, 'AudioBuffer') + if is_audio_buffer: + includes.add('modules/webaudio/AudioBuffer.h') + + is_document = inherits_interface(interface.name, 'Document') + if is_document: + includes.update(['bindings/v8/ScriptController.h', + 'bindings/v8/V8WindowShell.h', + 'core/frame/LocalFrame.h']) + + # [ActiveDOMObject] + is_active_dom_object = 'ActiveDOMObject' in extended_attributes + + # [CheckSecurity] + is_check_security = 'CheckSecurity' in extended_attributes + if is_check_security: + includes.add('bindings/v8/BindingSecurity.h') + + # [DependentLifetime] + is_dependent_lifetime = 'DependentLifetime' in extended_attributes + + # [MeasureAs] + is_measure_as = 'MeasureAs' in extended_attributes + if is_measure_as: + includes.add('core/frame/UseCounter.h') + + # [SetWrapperReferenceFrom] + reachable_node_function = extended_attributes.get('SetWrapperReferenceFrom') + if reachable_node_function: + includes.update(['bindings/v8/V8GCController.h', + 'core/dom/Element.h']) + + # [SetWrapperReferenceTo] + set_wrapper_reference_to_list = [{ + 'name': argument.name, + # FIXME: properly should be: + # 'cpp_type': argument.idl_type.cpp_type_args(used_as_argument=True), + # (if type is non-wrapper type like NodeFilter, normally RefPtr) + # Raw pointers faster though, and NodeFilter hacky anyway. + 'cpp_type': argument.idl_type.implemented_as + '*', + 'idl_type': argument.idl_type, + 'v8_type': v8_types.v8_type(argument.idl_type.name), + } for argument in extended_attributes.get('SetWrapperReferenceTo', [])] + for set_wrapper_reference_to in set_wrapper_reference_to_list: + set_wrapper_reference_to['idl_type'].add_includes_for_type() + + # [SpecialWrapFor] + if 'SpecialWrapFor' in extended_attributes: + special_wrap_for = extended_attributes['SpecialWrapFor'].split('|') + else: + special_wrap_for = [] + for special_wrap_interface in special_wrap_for: + v8_types.add_includes_for_interface(special_wrap_interface) + + # [Custom=Wrap], [SetWrapperReferenceFrom] + has_visit_dom_wrapper = ( + has_extended_attribute_value(interface, 'Custom', 'VisitDOMWrapper') or + reachable_node_function or + set_wrapper_reference_to_list) + + this_gc_type = gc_type(interface) + + template_contents = { + 'conditional_string': conditional_string(interface), # [Conditional] + 'cpp_class': cpp_name(interface), + 'gc_type': this_gc_type, + 'has_custom_legacy_call_as_function': has_extended_attribute_value(interface, 'Custom', 'LegacyCallAsFunction'), # [Custom=LegacyCallAsFunction] + 'has_custom_to_v8': has_extended_attribute_value(interface, 'Custom', 'ToV8'), # [Custom=ToV8] + 'has_custom_wrap': has_extended_attribute_value(interface, 'Custom', 'Wrap'), # [Custom=Wrap] + 'has_visit_dom_wrapper': has_visit_dom_wrapper, + 'header_includes': header_includes, + 'interface_name': interface.name, + 'is_active_dom_object': is_active_dom_object, + 'is_audio_buffer': is_audio_buffer, + 'is_check_security': is_check_security, + 'is_dependent_lifetime': is_dependent_lifetime, + 'is_document': is_document, + 'is_event_target': inherits_interface(interface.name, 'EventTarget'), + 'is_exception': interface.is_exception, + 'is_node': inherits_interface(interface.name, 'Node'), + 'measure_as': v8_utilities.measure_as(interface), # [MeasureAs] + 'parent_interface': parent_interface, + 'pass_cpp_type': cpp_template_type( + cpp_ptr_type('PassRefPtr', 'RawPtr', this_gc_type), + cpp_name(interface)), + 'reachable_node_function': reachable_node_function, + 'runtime_enabled_function': runtime_enabled_function_name(interface), # [RuntimeEnabled] + 'set_wrapper_reference_to_list': set_wrapper_reference_to_list, + 'special_wrap_for': special_wrap_for, + 'v8_class': v8_utilities.v8_class_name(interface), + 'wrapper_configuration': 'WrapperConfiguration::Dependent' + if (has_visit_dom_wrapper or + is_active_dom_object or + is_dependent_lifetime) + else 'WrapperConfiguration::Independent', + } + + # Constructors + constructors = [generate_constructor(interface, constructor) + for constructor in interface.constructors + # FIXME: shouldn't put named constructors with constructors + # (currently needed for Perl compatibility) + # Handle named constructors separately + if constructor.name == 'Constructor'] + if len(constructors) > 1: + template_contents['constructor_overloads'] = generate_overloads(constructors) + + # [CustomConstructor] + custom_constructors = [{ # Only needed for computing interface length + 'number_of_required_arguments': + number_of_required_arguments(constructor), + } for constructor in interface.custom_constructors] + + # [EventConstructor] + has_event_constructor = 'EventConstructor' in extended_attributes + any_type_attributes = [attribute for attribute in interface.attributes + if attribute.idl_type.name == 'Any'] + if has_event_constructor: + includes.add('bindings/v8/Dictionary.h') + if any_type_attributes: + includes.add('bindings/v8/SerializedScriptValue.h') + + # [NamedConstructor] + named_constructor = generate_named_constructor(interface) + + if (constructors or custom_constructors or has_event_constructor or + named_constructor): + includes.add('bindings/v8/V8ObjectConstructor.h') + includes.add('core/frame/LocalDOMWindow.h') + + template_contents.update({ + 'any_type_attributes': any_type_attributes, + 'constructors': constructors, + 'has_custom_constructor': bool(custom_constructors), + 'has_event_constructor': has_event_constructor, + 'interface_length': + interface_length(interface, constructors + custom_constructors), + 'is_constructor_call_with_document': has_extended_attribute_value( + interface, 'ConstructorCallWith', 'Document'), # [ConstructorCallWith=Document] + 'is_constructor_call_with_execution_context': has_extended_attribute_value( + interface, 'ConstructorCallWith', 'ExecutionContext'), # [ConstructorCallWith=ExeuctionContext] + 'is_constructor_raises_exception': extended_attributes.get('RaisesException') == 'Constructor', # [RaisesException=Constructor] + 'named_constructor': named_constructor, + }) + + # Constants + template_contents.update({ + 'constants': [generate_constant(constant) for constant in interface.constants], + 'do_not_check_constants': 'DoNotCheckConstants' in extended_attributes, + }) + + # Attributes + attributes = [v8_attributes.generate_attribute(interface, attribute) + for attribute in interface.attributes] + template_contents.update({ + 'attributes': attributes, + 'has_accessors': any(attribute['is_expose_js_accessors'] for attribute in attributes), + 'has_attribute_configuration': any( + not (attribute['is_expose_js_accessors'] or + attribute['is_static'] or + attribute['runtime_enabled_function'] or + attribute['per_context_enabled_function']) + for attribute in attributes), + 'has_constructor_attributes': any(attribute['constructor_type'] for attribute in attributes), + 'has_per_context_enabled_attributes': any(attribute['per_context_enabled_function'] for attribute in attributes), + 'has_replaceable_attributes': any(attribute['is_replaceable'] for attribute in attributes), + }) + + # Methods + methods = [v8_methods.generate_method(interface, method) + for method in interface.operations + if method.name] # Skip anonymous special operations (methods) + generate_method_overloads(methods) + + per_context_enabled_methods = [] + custom_registration_methods = [] + method_configuration_methods = [] + + for method in methods: + # Skip all but one method in each set of overloaded methods. + if 'overload_index' in method and 'overloads' not in method: + continue + + if 'overloads' in method: + overloads = method['overloads'] + per_context_enabled_function = overloads['per_context_enabled_function_all'] + runtime_enabled_function = overloads['runtime_enabled_function_all'] + has_custom_registration = overloads['has_custom_registration_all'] + else: + per_context_enabled_function = method['per_context_enabled_function'] + runtime_enabled_function = method['runtime_enabled_function'] + has_custom_registration = method['has_custom_registration'] + + if per_context_enabled_function: + per_context_enabled_methods.append(method) + continue + if runtime_enabled_function or has_custom_registration: + custom_registration_methods.append(method) + continue + method_configuration_methods.append(method) + + for method in methods: + # The value of the Function object’s “length” property is a Number + # determined as follows: + # 1. Let S be the effective overload set for regular operations (if the + # operation is a regular operation) or for static operations (if the + # operation is a static operation) with identifier id on interface I and + # with argument count 0. + # 2. Return the length of the shortest argument list of the entries in S. + # FIXME: This calculation doesn't take into account whether runtime + # enabled overloads are actually enabled, so length may be incorrect. + # E.g., [RuntimeEnabled=Foo] void f(); void f(long x); + # should have length 1 if Foo is not enabled, but length 0 if it is. + method['length'] = (method['overloads']['minarg'] if 'overloads' in method else + method['number_of_required_arguments']) + + template_contents.update({ + 'custom_registration_methods': custom_registration_methods, + 'has_origin_safe_method_setter': any( + method['is_check_security_for_frame'] and not method['is_read_only'] + for method in methods), + 'method_configuration_methods': method_configuration_methods, + 'per_context_enabled_methods': per_context_enabled_methods, + 'methods': methods, + }) + + template_contents.update({ + 'indexed_property_getter': indexed_property_getter(interface), + 'indexed_property_setter': indexed_property_setter(interface), + 'indexed_property_deleter': indexed_property_deleter(interface), + 'is_override_builtins': 'OverrideBuiltins' in extended_attributes, + 'named_property_getter': named_property_getter(interface), + 'named_property_setter': named_property_setter(interface), + 'named_property_deleter': named_property_deleter(interface), + }) + + return template_contents + + +# [DeprecateAs], [Reflect], [RuntimeEnabled] +def generate_constant(constant): + # (Blink-only) string literals are unquoted in tokenizer, must be re-quoted + # in C++. + if constant.idl_type.name == 'String': + value = '"%s"' % constant.value + else: + value = constant.value + + extended_attributes = constant.extended_attributes + return { + 'cpp_class': extended_attributes.get('PartialInterfaceImplementedAs'), + 'name': constant.name, + # FIXME: use 'reflected_name' as correct 'name' + 'reflected_name': extended_attributes.get('Reflect', constant.name), + 'runtime_enabled_function': runtime_enabled_function_name(constant), + 'value': value, + } + + +################################################################################ +# Overloads +################################################################################ + +def generate_method_overloads(methods): + # Regular methods + generate_overloads_by_type([method for method in methods + if not method['is_static']]) + # Static methods + generate_overloads_by_type([method for method in methods + if method['is_static']]) + + +def generate_overloads_by_type(methods): + """Generates |method.overload*| template values. + + Called separately for static and non-static (regular) methods, + as these are overloaded separately. + Modifies |method| in place for |method| in |methods|. + Doesn't change the |methods| list itself (only the values, i.e. individual + methods), so ok to treat these separately. + """ + # Add overload information only to overloaded methods, so template code can + # easily verify if a function is overloaded + for name, overloads in method_overloads_by_name(methods): + # Resolution function is generated after last overloaded function; + # package necessary information into |method.overloads| for that method. + overloads[-1]['overloads'] = generate_overloads(overloads) + overloads[-1]['overloads']['name'] = name + + +def method_overloads_by_name(methods): + """Returns generator of overloaded methods by name: [name, [method]]""" + # Filter to only methods that are actually overloaded + method_counts = Counter(method['name'] for method in methods) + overloaded_method_names = set(name + for name, count in method_counts.iteritems() + if count > 1) + overloaded_methods = [method for method in methods + if method['name'] in overloaded_method_names] + + # Group by name (generally will be defined together, but not necessarily) + return sort_and_groupby(overloaded_methods, itemgetter('name')) + + +def generate_overloads(overloads): + """Returns |overloads| template values for a single name. + + Sets |method.overload_index| in place for |method| in |overloads| + and returns dict of overall overload template values. + """ + assert len(overloads) > 1 # only apply to overloaded names + for index, method in enumerate(overloads, 1): + method['overload_index'] = index + + effective_overloads_by_length = effective_overload_set_by_length(overloads) + lengths = [length for length, _ in effective_overloads_by_length] + name = overloads[0].get('name', '<constructor>') + + # Check and fail if all overloads with the shortest acceptable arguments + # list are runtime enabled, since we would otherwise set 'length' on the + # function object to an incorrect value when none of those overloads were + # actually enabled at runtime. The exception is if all overloads are + # controlled by the same runtime enabled feature, in which case there would + # be no function object at all if it is not enabled. + shortest_overloads = effective_overloads_by_length[0][1] + if (all(method.get('runtime_enabled_function') + for method, _, _ in shortest_overloads) and + not common_value(overloads, 'runtime_enabled_function')): + raise ValueError('Function.length of %s depends on runtime enabled features' % name) + + # Check and fail if overloads disagree on any of the extended attributes + # that affect how the method should be registered. + # Skip the check for overloaded constructors, since they don't support any + # of the extended attributes in question. + if not overloads[0].get('is_constructor'): + overload_extended_attributes = [ + method['custom_registration_extended_attributes'] + for method in overloads] + for extended_attribute in v8_methods.CUSTOM_REGISTRATION_EXTENDED_ATTRIBUTES: + if common_key(overload_extended_attributes, extended_attribute) is None: + raise ValueError('Overloads of %s have conflicting extended attribute %s' + % (name, extended_attribute)) + + return { + 'deprecate_all_as': common_value(overloads, 'deprecate_as'), # [DeprecateAs] + 'length_tests_methods': length_tests_methods(effective_overloads_by_length), + 'minarg': lengths[0], + # 1. Let maxarg be the length of the longest type list of the + # entries in S. + 'maxarg': lengths[-1], + 'measure_all_as': common_value(overloads, 'measure_as'), # [MeasureAs] + 'has_custom_registration_all': common_value(overloads, 'has_custom_registration'), + 'per_context_enabled_function_all': common_value(overloads, 'per_context_enabled_function'), # [PerContextEnabled] + 'runtime_enabled_function_all': common_value(overloads, 'runtime_enabled_function'), # [RuntimeEnabled] + 'valid_arities': lengths + # Only need to report valid arities if there is a gap in the + # sequence of possible lengths, otherwise invalid length means + # "not enough arguments". + if lengths[-1] - lengths[0] != len(lengths) - 1 else None, + } + + +def effective_overload_set(F): + """Returns the effective overload set of an overloaded function. + + An effective overload set is the set of overloaded functions + signatures + (type list of arguments, with optional and variadic arguments included or + not), and is used in the overload resolution algorithm. + + For example, given input [f1(optional long x), f2(DOMString s)], the output + is informally [f1(), f1(long), f2(DOMString)], and formally + [(f1, [], []), (f1, [long], [optional]), (f2, [DOMString], [required])]. + + Currently the optionality list is a list of |is_optional| booleans (True + means optional, False means required); to support variadics this needs to + be tri-valued as required, optional, or variadic. + + Formally: + An effective overload set represents the allowable invocations for a + particular operation, constructor (specified with [Constructor] or + [NamedConstructor]), legacy caller or callback function. + + An additional argument N (argument count) is needed when overloading + variadics, but we don't use that currently. + + Spec: http://heycam.github.io/webidl/#dfn-effective-overload-set + + Formally the input and output lists are sets, but methods are stored + internally as dicts, which can't be stored in a set because they are not + hashable, so we use lists instead. + + Arguments: + F: list of overloads for a given callable name. + + Returns: + S: list of tuples of the form (callable, type list, optionality list). + """ + # Code closely follows the algorithm in the spec, for clarity and + # correctness, and hence is not very Pythonic. + + # 1. Initialize S to ∅. + # (We use a list because we can't use a set, as noted above.) + S = [] + + # 2. Let F be a set with elements as follows, according to the kind of + # effective overload set: + # (Passed as argument, nothing to do.) + + # 3. & 4. (maxarg, m) are only needed for variadics, not used. + + # 5. For each operation, extended attribute or callback function X in F: + for X in F: # X is the "callable", F is the overloads. + arguments = X['arguments'] + # 1. Let n be the number of arguments X is declared to take. + n = len(arguments) + # 2. Let t0..n−1 be a list of types, where ti is the type of X’s + # argument at index i. + # (“type list”) + t = tuple(argument['idl_type_object'] for argument in arguments) + # 3. Let o0..n−1 be a list of optionality values, where oi is “variadic” + # if X’s argument at index i is a final, variadic argument, “optional” + # if the argument is optional, and “required” otherwise. + # (“optionality list”) + # (We’re just using a boolean for optional vs. required.) + o = tuple(argument['is_optional'] for argument in arguments) + # 4. Add to S the tuple <X, t0..n−1, o0..n−1>. + S.append((X, t, o)) + # 5. If X is declared to be variadic, then: + # (Not used, so not implemented.) + # 6. Initialize i to n−1. + i = n - 1 + # 7. While i ≥ 0: + # Spec bug (fencepost error); should be “While i > 0:” + # https://www.w3.org/Bugs/Public/show_bug.cgi?id=25590 + while i > 0: + # 1. If argument i of X is not optional, then break this loop. + if not o[i]: + break + # 2. Otherwise, add to S the tuple <X, t0..i−1, o0..i−1>. + S.append((X, t[:i], o[:i])) + # 3. Set i to i−1. + i = i - 1 + # 8. If n > 0 and all arguments of X are optional, then add to S the + # tuple <X, (), ()> (where “()” represents the empty list). + if n > 0 and all(oi for oi in o): + S.append((X, [], [])) + # 6. The effective overload set is S. + return S + + +def effective_overload_set_by_length(overloads): + def type_list_length(entry): + # Entries in the effective overload set are 3-tuples: + # (callable, type list, optionality list) + return len(entry[1]) + + effective_overloads = effective_overload_set(overloads) + return list(sort_and_groupby(effective_overloads, type_list_length)) + + +def distinguishing_argument_index(entries): + """Returns the distinguishing argument index for a sequence of entries. + + Entries are elements of the effective overload set with the same number + of arguments (formally, same type list length), each a 3-tuple of the form + (callable, type list, optionality list). + + Spec: http://heycam.github.io/webidl/#dfn-distinguishing-argument-index + + If there is more than one entry in an effective overload set that has a + given type list length, then for those entries there must be an index i + such that for each pair of entries the types at index i are + distinguishable. + The lowest such index is termed the distinguishing argument index for the + entries of the effective overload set with the given type list length. + """ + # Only applicable “If there is more than one entry” + assert len(entries) > 1 + type_lists = [tuple(idl_type.name for idl_type in entry[1]) + for entry in entries] + type_list_length = len(type_lists[0]) + # Only applicable for entries that “[have] a given type list length” + assert all(len(type_list) == type_list_length for type_list in type_lists) + name = entries[0][0].get('name', 'Constructor') # for error reporting + + # The spec defines the distinguishing argument index by conditions it must + # satisfy, but does not give an algorithm. + # + # We compute the distinguishing argument index by first computing the + # minimum index where not all types are the same, and then checking that + # all types in this position are distinguishable (and the optionality lists + # up to this point are identical), since "minimum index where not all types + # are the same" is a *necessary* condition, and more direct to check than + # distinguishability. + types_by_index = (set(types) for types in zip(*type_lists)) + try: + # “In addition, for each index j, where j is less than the + # distinguishing argument index for a given type list length, the types + # at index j in all of the entries’ type lists must be the same” + index = next(i for i, types in enumerate(types_by_index) + if len(types) > 1) + except StopIteration: + raise ValueError('No distinguishing index found for %s, length %s:\n' + 'All entries have the same type list:\n' + '%s' % (name, type_list_length, type_lists[0])) + # Check optionality + # “and the booleans in the corresponding list indicating argument + # optionality must be the same.” + # FIXME: spec typo: optionality value is no longer a boolean + # https://www.w3.org/Bugs/Public/show_bug.cgi?id=25628 + initial_optionality_lists = set(entry[2][:index] for entry in entries) + if len(initial_optionality_lists) > 1: + raise ValueError( + 'Invalid optionality lists for %s, length %s:\n' + 'Optionality lists differ below distinguishing argument index %s:\n' + '%s' + % (name, type_list_length, index, set(initial_optionality_lists))) + + # Check distinguishability + # http://heycam.github.io/webidl/#dfn-distinguishable + # Use names to check for distinct types, since objects are distinct + # FIXME: check distinguishability more precisely, for validation + distinguishing_argument_type_names = [type_list[index] + for type_list in type_lists] + if (len(set(distinguishing_argument_type_names)) != + len(distinguishing_argument_type_names)): + raise ValueError('Types in distinguishing argument are not distinct:\n' + '%s' % distinguishing_argument_type_names) + + return index + + +def length_tests_methods(effective_overloads_by_length): + """Returns sorted list of resolution tests and associated methods, by length. + + This builds the main data structure for the overload resolution loop. + For a given argument length, bindings test argument at distinguishing + argument index, in order given by spec: if it is compatible with + (optionality or) type required by an overloaded method, resolve to that + method. + + Returns: + [(length, [(test, method)])] + """ + return [(length, list(resolution_tests_methods(effective_overloads))) + for length, effective_overloads in effective_overloads_by_length] + + +def resolution_tests_methods(effective_overloads): + """Yields resolution test and associated method, in resolution order, for effective overloads of a given length. + + This is the heart of the resolution algorithm. + http://heycam.github.io/webidl/#dfn-overload-resolution-algorithm + + Note that a given method can be listed multiple times, with different tests! + This is to handle implicit type conversion. + + Returns: + [(test, method)] + """ + methods = [effective_overload[0] + for effective_overload in effective_overloads] + if len(methods) == 1: + # If only one method with a given length, no test needed + yield 'true', methods[0] + return + + # 6. If there is more than one entry in S, then set d to be the + # distinguishing argument index for the entries of S. + index = distinguishing_argument_index(effective_overloads) + # (7-9 are for handling |undefined| values for optional arguments before + # the distinguishing argument (as “missing”), so you can specify only some + # optional arguments. We don’t support this, so we skip these steps.) + # 10. If i = d, then: + # (d is the distinguishing argument index) + # 1. Let V be argi. + # Note: This is the argument that will be used to resolve which + # overload is selected. + cpp_value = 'info[%s]' % index + + # Extract argument and IDL type to simplify accessing these in each loop. + arguments = [method['arguments'][index] for method in methods] + arguments_methods = zip(arguments, methods) + idl_types = [argument['idl_type_object'] for argument in arguments] + idl_types_methods = zip(idl_types, methods) + + # We can’t do a single loop through all methods or simply sort them, because + # a method may be listed in multiple steps of the resolution algorithm, and + # which test to apply differs depending on the step. + # + # Instead, we need to go through all methods at each step, either finding + # first match (if only one test is allowed) or filtering to matches (if + # multiple tests are allowed), and generating an appropriate tests. + + # 2. If V is undefined, and there is an entry in S whose list of + # optionality values has “optional” at index i, then remove from S all + # other entries. + try: + method = next(method for argument, method in arguments_methods + if argument['is_optional']) + test = '%s->IsUndefined()' % cpp_value + yield test, method + except StopIteration: + pass + + # 3. Otherwise: if V is null or undefined, and there is an entry in S that + # has one of the following types at position i of its type list, + # • a nullable type + try: + method = next(method for idl_type, method in idl_types_methods + if idl_type.is_nullable) + test = 'isUndefinedOrNull(%s)' % cpp_value + yield test, method + except StopIteration: + pass + + # 4. Otherwise: if V is a platform object – but not a platform array + # object – and there is an entry in S that has one of the following + # types at position i of its type list, + # • an interface type that V implements + # (Unlike most of these tests, this can return multiple methods, since we + # test if it implements an interface. Thus we need a for loop, not a next.) + # (We distinguish wrapper types from built-in interface types.) + for idl_type, method in ((idl_type, method) + for idl_type, method in idl_types_methods + if idl_type.is_wrapper_type): + test = 'V8{idl_type}::hasInstance({cpp_value}, isolate)'.format(idl_type=idl_type.base_type, cpp_value=cpp_value) + yield test, method + + # 8. Otherwise: if V is any kind of object except for a native Date object, + # a native RegExp object, and there is an entry in S that has one of the + # following types at position i of its type list, + # • an array type + # • a sequence type + # ... + # • a dictionary + try: + # FIXME: IDL dictionary not implemented, so use Blink Dictionary + # http://crbug.com/321462 + idl_type, method = next((idl_type, method) + for idl_type, method in idl_types_methods + if (idl_type.array_or_sequence_type or + idl_type.name == 'Dictionary')) + if idl_type.array_or_sequence_type: + # (We test for Array instead of generic Object to type-check.) + # FIXME: test for Object during resolution, then have type check for + # Array in overloaded method: http://crbug.com/262383 + test = '%s->IsArray()' % cpp_value + else: + # FIXME: should be '{1}->IsObject() && !{1}->IsDate() && !{1}->IsRegExp()'.format(cpp_value) + # FIXME: the IsDate and IsRegExp checks can be skipped if we've + # already generated tests for them. + test = '%s->IsObject()' % cpp_value + yield test, method + except StopIteration: + pass + + # (Check for exact type matches before performing automatic type conversion; + # only needed if distinguishing between primitive types.) + if len([idl_type.is_primitive_type for idl_type in idl_types]) > 1: + # (Only needed if match in step 11, otherwise redundant.) + if any(idl_type.name == 'String' or idl_type.is_enum + for idl_type in idl_types): + # 10. Otherwise: if V is a Number value, and there is an entry in S + # that has one of the following types at position i of its type + # list, + # • a numeric type + try: + method = next(method for idl_type, method in idl_types_methods + if idl_type.is_numeric_type) + test = '%s->IsNumber()' % cpp_value + yield test, method + except StopIteration: + pass + + # (Perform automatic type conversion, in order. If any of these match, + # that’s the end, and no other tests are needed.) To keep this code simple, + # we rely on the C++ compiler's dead code elimination to deal with the + # redundancy if both cases below trigger. + + # 11. Otherwise: if there is an entry in S that has one of the following + # types at position i of its type list, + # • DOMString + # • an enumeration type + # * ByteString + # Blink: ScalarValueString is a pending Web IDL addition + try: + method = next(method for idl_type, method in idl_types_methods + if idl_type.name in ('String', + 'ByteString', + 'ScalarValueString') or + idl_type.is_enum) + yield 'true', method + except StopIteration: + pass + + # 12. Otherwise: if there is an entry in S that has one of the following + # types at position i of its type list, + # • a numeric type + try: + method = next(method for idl_type, method in idl_types_methods + if idl_type.is_numeric_type) + yield 'true', method + except StopIteration: + pass + + +################################################################################ +# Utility functions +################################################################################ + +def Counter(iterable): + # Once using Python 2.7, using collections.Counter + counter = defaultdict(lambda: 0) + for item in iterable: + counter[item] += 1 + return counter + + +def common(dicts, f): + """Returns common result of f across an iterable of dicts, or None. + + Call f for each dict and return its result if the same across all dicts. + """ + values = (f(d) for d in dicts) + first_value = next(values) + if all(value == first_value for value in values): + return first_value + return None + + +def common_key(dicts, key): + """Returns common presence of a key across an iterable of dicts, or None. + + True if all dicts have the key, False if none of the dicts have the key, + and None if some but not all dicts have the key. + """ + return common(dicts, lambda d: key in d) + + +def common_value(dicts, key): + """Returns common value of a key across an iterable of dicts, or None. + + Auxiliary function for overloads, so can consolidate an extended attribute + that appears with the same value on all items in an overload set. + """ + return common(dicts, lambda d: d.get(key)) + + +def sort_and_groupby(l, key=None): + """Returns a generator of (key, list), sorting and grouping list by key.""" + l.sort(key=key) + return ((k, list(g)) for k, g in itertools.groupby(l, key)) + + +################################################################################ +# Constructors +################################################################################ + +# [Constructor] +def generate_constructor(interface, constructor): + arguments_need_try_catch = any(v8_methods.argument_needs_try_catch(argument) + for argument in constructor.arguments) + + return { + 'arguments': [v8_methods.generate_argument(interface, constructor, argument, index) + for index, argument in enumerate(constructor.arguments)], + 'arguments_need_try_catch': arguments_need_try_catch, + 'cpp_type': cpp_template_type( + cpp_ptr_type('RefPtr', 'RawPtr', gc_type(interface)), + cpp_name(interface)), + 'cpp_value': v8_methods.cpp_value( + interface, constructor, len(constructor.arguments)), + 'has_exception_state': + # [RaisesException=Constructor] + interface.extended_attributes.get('RaisesException') == 'Constructor' or + any(argument for argument in constructor.arguments + if argument.idl_type.name == 'SerializedScriptValue' or + argument.idl_type.is_integer_type), + 'is_constructor': True, + 'is_named_constructor': False, + 'number_of_required_arguments': + number_of_required_arguments(constructor), + } + + +# [NamedConstructor] +def generate_named_constructor(interface): + extended_attributes = interface.extended_attributes + if 'NamedConstructor' not in extended_attributes: + return None + # FIXME: parser should return named constructor separately; + # included in constructors (and only name stored in extended attribute) + # for Perl compatibility + idl_constructor = interface.constructors[-1] + assert idl_constructor.name == 'NamedConstructor' + constructor = generate_constructor(interface, idl_constructor) + constructor.update({ + 'name': extended_attributes['NamedConstructor'], + 'is_named_constructor': True, + }) + return constructor + + +def number_of_required_arguments(constructor): + return len([argument for argument in constructor.arguments + if not argument.is_optional]) + + +def interface_length(interface, constructors): + # Docs: http://heycam.github.io/webidl/#es-interface-call + if 'EventConstructor' in interface.extended_attributes: + return 1 + if not constructors: + return 0 + return min(constructor['number_of_required_arguments'] + for constructor in constructors) + + +################################################################################ +# Special operations (methods) +# http://heycam.github.io/webidl/#idl-special-operations +################################################################################ + +def property_getter(getter, cpp_arguments): + def is_null_expression(idl_type): + if idl_type.is_union_type: + return ' && '.join('!result%sEnabled' % i + for i, _ in enumerate(idl_type.member_types)) + if idl_type.name == 'String': + return 'result.isNull()' + if idl_type.is_interface_type: + return '!result' + return '' + + idl_type = getter.idl_type + extended_attributes = getter.extended_attributes + is_raises_exception = 'RaisesException' in extended_attributes + + # FIXME: make more generic, so can use v8_methods.cpp_value + cpp_method_name = 'impl->%s' % cpp_name(getter) + + if is_raises_exception: + cpp_arguments.append('exceptionState') + union_arguments = idl_type.union_arguments + if union_arguments: + cpp_arguments.extend(union_arguments) + + cpp_value = '%s(%s)' % (cpp_method_name, ', '.join(cpp_arguments)) + + return { + 'cpp_type': idl_type.cpp_type, + 'cpp_value': cpp_value, + 'is_custom': + 'Custom' in extended_attributes and + (not extended_attributes['Custom'] or + has_extended_attribute_value(getter, 'Custom', 'PropertyGetter')), + 'is_custom_property_enumerator': has_extended_attribute_value( + getter, 'Custom', 'PropertyEnumerator'), + 'is_custom_property_query': has_extended_attribute_value( + getter, 'Custom', 'PropertyQuery'), + 'is_enumerable': 'NotEnumerable' not in extended_attributes, + 'is_null_expression': is_null_expression(idl_type), + 'is_raises_exception': is_raises_exception, + 'name': cpp_name(getter), + 'union_arguments': union_arguments, + 'v8_set_return_value': idl_type.v8_set_return_value('result', extended_attributes=extended_attributes, script_wrappable='impl', release=idl_type.release), + } + + +def property_setter(setter): + idl_type = setter.arguments[1].idl_type + extended_attributes = setter.extended_attributes + is_raises_exception = 'RaisesException' in extended_attributes + return { + 'has_type_checking_interface': + has_extended_attribute_value(setter, 'TypeChecking', 'Interface') and + idl_type.is_wrapper_type, + 'idl_type': idl_type.base_type, + 'is_custom': 'Custom' in extended_attributes, + 'has_exception_state': is_raises_exception or + idl_type.is_integer_type, + 'is_raises_exception': is_raises_exception, + 'name': cpp_name(setter), + 'v8_value_to_local_cpp_value': idl_type.v8_value_to_local_cpp_value( + extended_attributes, 'v8Value', 'propertyValue'), + } + + +def property_deleter(deleter): + idl_type = deleter.idl_type + if str(idl_type) != 'boolean': + raise Exception( + 'Only deleters with boolean type are allowed, but type is "%s"' % + idl_type) + extended_attributes = deleter.extended_attributes + return { + 'is_custom': 'Custom' in extended_attributes, + 'is_raises_exception': 'RaisesException' in extended_attributes, + 'name': cpp_name(deleter), + } + + +################################################################################ +# Indexed properties +# http://heycam.github.io/webidl/#idl-indexed-properties +################################################################################ + +def indexed_property_getter(interface): + try: + # Find indexed property getter, if present; has form: + # getter TYPE [OPTIONAL_IDENTIFIER](unsigned long ARG1) + getter = next( + method + for method in interface.operations + if ('getter' in method.specials and + len(method.arguments) == 1 and + str(method.arguments[0].idl_type) == 'unsigned long')) + except StopIteration: + return None + + return property_getter(getter, ['index']) + + +def indexed_property_setter(interface): + try: + # Find indexed property setter, if present; has form: + # setter RETURN_TYPE [OPTIONAL_IDENTIFIER](unsigned long ARG1, ARG_TYPE ARG2) + setter = next( + method + for method in interface.operations + if ('setter' in method.specials and + len(method.arguments) == 2 and + str(method.arguments[0].idl_type) == 'unsigned long')) + except StopIteration: + return None + + return property_setter(setter) + + +def indexed_property_deleter(interface): + try: + # Find indexed property deleter, if present; has form: + # deleter TYPE [OPTIONAL_IDENTIFIER](unsigned long ARG) + deleter = next( + method + for method in interface.operations + if ('deleter' in method.specials and + len(method.arguments) == 1 and + str(method.arguments[0].idl_type) == 'unsigned long')) + except StopIteration: + return None + + return property_deleter(deleter) + + +################################################################################ +# Named properties +# http://heycam.github.io/webidl/#idl-named-properties +################################################################################ + +def named_property_getter(interface): + try: + # Find named property getter, if present; has form: + # getter TYPE [OPTIONAL_IDENTIFIER](DOMString ARG1) + getter = next( + method + for method in interface.operations + if ('getter' in method.specials and + len(method.arguments) == 1 and + str(method.arguments[0].idl_type) == 'DOMString')) + except StopIteration: + return None + + getter.name = getter.name or 'anonymousNamedGetter' + return property_getter(getter, ['propertyName']) + + +def named_property_setter(interface): + try: + # Find named property setter, if present; has form: + # setter RETURN_TYPE [OPTIONAL_IDENTIFIER](DOMString ARG1, ARG_TYPE ARG2) + setter = next( + method + for method in interface.operations + if ('setter' in method.specials and + len(method.arguments) == 2 and + str(method.arguments[0].idl_type) == 'DOMString')) + except StopIteration: + return None + + return property_setter(setter) + + +def named_property_deleter(interface): + try: + # Find named property deleter, if present; has form: + # deleter TYPE [OPTIONAL_IDENTIFIER](DOMString ARG) + deleter = next( + method + for method in interface.operations + if ('deleter' in method.specials and + len(method.arguments) == 1 and + str(method.arguments[0].idl_type) == 'DOMString')) + except StopIteration: + return None + + return property_deleter(deleter) diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/v8_methods.py b/chromium/third_party/WebKit/Source/bindings/scripts/v8_methods.py new file mode 100644 index 00000000000..11486410b0f --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/v8_methods.py @@ -0,0 +1,349 @@ +# Copyright (C) 2013 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. + +"""Generate template values for methods. + +Extends IdlType and IdlUnionType with property |union_arguments|. + +Design doc: http://www.chromium.org/developers/design-documents/idl-compiler +""" + +from idl_types import IdlType, IdlUnionType, inherits_interface +from v8_globals import includes +import v8_types +import v8_utilities +from v8_utilities import has_extended_attribute_value + + +# Methods with any of these require custom method registration code in the +# interface's configure*Template() function. +CUSTOM_REGISTRATION_EXTENDED_ATTRIBUTES = frozenset([ + 'DoNotCheckSecurity', + 'DoNotCheckSignature', + 'NotEnumerable', + 'ReadOnly', + 'Unforgeable', +]) + + +def argument_needs_try_catch(argument): + idl_type = argument.idl_type + base_type = not idl_type.array_or_sequence_type and idl_type.base_type + + return not ( + # These cases are handled by separate code paths in the + # generate_argument() macro in Source/bindings/templates/methods.cpp. + idl_type.is_callback_interface or + base_type == 'SerializedScriptValue' or + (argument.is_variadic and idl_type.is_wrapper_type) or + # String and enumeration arguments converted using one of the + # TOSTRING_* macros in Source/bindings/v8/V8BindingMacros.h don't + # use a v8::TryCatch. + (base_type == 'DOMString' and not argument.is_variadic)) + + +def generate_method(interface, method): + arguments = method.arguments + extended_attributes = method.extended_attributes + idl_type = method.idl_type + is_static = method.is_static + name = method.name + + idl_type.add_includes_for_type() + this_cpp_value = cpp_value(interface, method, len(arguments)) + + def function_template(): + if is_static: + return 'functionTemplate' + if 'Unforgeable' in extended_attributes: + return 'instanceTemplate' + return 'prototypeTemplate' + + is_call_with_script_arguments = has_extended_attribute_value(method, 'CallWith', 'ScriptArguments') + if is_call_with_script_arguments: + includes.update(['bindings/v8/ScriptCallStackFactory.h', + 'core/inspector/ScriptArguments.h']) + is_call_with_script_state = has_extended_attribute_value(method, 'CallWith', 'ScriptState') + if is_call_with_script_state: + includes.add('bindings/v8/ScriptState.h') + is_check_security_for_node = 'CheckSecurity' in extended_attributes + if is_check_security_for_node: + includes.add('bindings/v8/BindingSecurity.h') + is_custom_element_callbacks = 'CustomElementCallbacks' in extended_attributes + if is_custom_element_callbacks: + includes.add('core/dom/custom/CustomElementCallbackDispatcher.h') + + has_event_listener_argument = any( + argument for argument in arguments + if argument.idl_type.name == 'EventListener') + is_check_security_for_frame = ( + 'CheckSecurity' in interface.extended_attributes and + 'DoNotCheckSecurity' not in extended_attributes) + is_raises_exception = 'RaisesException' in extended_attributes + + arguments_need_try_catch = any(argument_needs_try_catch(argument) + for argument in arguments) + + return { + 'activity_logging_world_list': v8_utilities.activity_logging_world_list(method), # [ActivityLogging] + 'arguments': [generate_argument(interface, method, argument, index) + for index, argument in enumerate(arguments)], + 'arguments_need_try_catch': arguments_need_try_catch, + 'conditional_string': v8_utilities.conditional_string(method), + 'cpp_type': idl_type.cpp_type, + 'cpp_value': this_cpp_value, + 'custom_registration_extended_attributes': + CUSTOM_REGISTRATION_EXTENDED_ATTRIBUTES.intersection( + extended_attributes.iterkeys()), + 'deprecate_as': v8_utilities.deprecate_as(method), # [DeprecateAs] + 'function_template': function_template(), + 'has_custom_registration': is_static or + v8_utilities.has_extended_attribute( + method, CUSTOM_REGISTRATION_EXTENDED_ATTRIBUTES), + 'has_event_listener_argument': has_event_listener_argument, + 'has_exception_state': + has_event_listener_argument or + is_raises_exception or + is_check_security_for_frame or + any(argument for argument in arguments + if argument.idl_type.name in ('ByteString', + 'ScalarValueString', + 'SerializedScriptValue') or + argument.idl_type.is_integer_type), + 'idl_type': idl_type.base_type, + 'is_call_with_execution_context': has_extended_attribute_value(method, 'CallWith', 'ExecutionContext'), + 'is_call_with_script_arguments': is_call_with_script_arguments, + 'is_call_with_script_state': is_call_with_script_state, + 'is_check_security_for_frame': is_check_security_for_frame, + 'is_check_security_for_node': is_check_security_for_node, + 'is_custom': 'Custom' in extended_attributes, + 'is_custom_element_callbacks': is_custom_element_callbacks, + 'is_do_not_check_security': 'DoNotCheckSecurity' in extended_attributes, + 'is_do_not_check_signature': 'DoNotCheckSignature' in extended_attributes, + 'is_partial_interface_member': + 'PartialInterfaceImplementedAs' in extended_attributes, + 'is_per_world_bindings': 'PerWorldBindings' in extended_attributes, + 'is_raises_exception': is_raises_exception, + 'is_read_only': 'ReadOnly' in extended_attributes, + 'is_static': is_static, + 'is_variadic': arguments and arguments[-1].is_variadic, + 'measure_as': v8_utilities.measure_as(method), # [MeasureAs] + 'name': name, + 'number_of_arguments': len(arguments), + 'number_of_required_arguments': len([ + argument for argument in arguments + if not (argument.is_optional or argument.is_variadic)]), + 'number_of_required_or_variadic_arguments': len([ + argument for argument in arguments + if not argument.is_optional]), + 'per_context_enabled_function': v8_utilities.per_context_enabled_function_name(method), # [PerContextEnabled] + 'property_attributes': property_attributes(method), + 'runtime_enabled_function': v8_utilities.runtime_enabled_function_name(method), # [RuntimeEnabled] + 'signature': 'v8::Local<v8::Signature>()' if is_static or 'DoNotCheckSignature' in extended_attributes else 'defaultSignature', + 'union_arguments': idl_type.union_arguments, + 'v8_set_return_value_for_main_world': v8_set_return_value(interface.name, method, this_cpp_value, for_main_world=True), + 'v8_set_return_value': v8_set_return_value(interface.name, method, this_cpp_value), + 'world_suffixes': ['', 'ForMainWorld'] if 'PerWorldBindings' in extended_attributes else [''], # [PerWorldBindings] + } + + +def generate_argument(interface, method, argument, index): + extended_attributes = argument.extended_attributes + idl_type = argument.idl_type + this_cpp_value = cpp_value(interface, method, index) + is_variadic_wrapper_type = argument.is_variadic and idl_type.is_wrapper_type + + return { + 'cpp_type': idl_type.cpp_type_args(extended_attributes=extended_attributes, + used_as_argument=True, + used_as_variadic_argument=argument.is_variadic), + 'cpp_value': this_cpp_value, + # FIXME: check that the default value's type is compatible with the argument's + 'default_value': str(argument.default_value) if argument.default_value else None, + 'enum_validation_expression': idl_type.enum_validation_expression, + # FIXME: remove once [Default] removed and just use argument.default_value + 'has_default': 'Default' in extended_attributes or argument.default_value, + 'has_event_listener_argument': any( + argument_so_far for argument_so_far in method.arguments[:index] + if argument_so_far.idl_type.name == 'EventListener'), + 'has_type_checking_interface': + (has_extended_attribute_value(interface, 'TypeChecking', 'Interface') or + has_extended_attribute_value(method, 'TypeChecking', 'Interface')) and + idl_type.is_wrapper_type, + 'has_type_checking_unrestricted': + (has_extended_attribute_value(interface, 'TypeChecking', 'Unrestricted') or + has_extended_attribute_value(method, 'TypeChecking', 'Unrestricted')) and + idl_type.name in ('Float', 'Double'), + # Dictionary is special-cased, but arrays and sequences shouldn't be + 'idl_type': not idl_type.array_or_sequence_type and idl_type.base_type, + 'idl_type_object': idl_type, + 'index': index, + 'is_clamp': 'Clamp' in extended_attributes, + 'is_callback_interface': idl_type.is_callback_interface, + 'is_nullable': idl_type.is_nullable, + 'is_optional': argument.is_optional, + 'is_variadic_wrapper_type': is_variadic_wrapper_type, + 'vector_type': v8_types.cpp_ptr_type('Vector', 'HeapVector', idl_type.gc_type), + 'is_wrapper_type': idl_type.is_wrapper_type, + 'name': argument.name, + 'v8_set_return_value_for_main_world': v8_set_return_value(interface.name, method, this_cpp_value, for_main_world=True), + 'v8_set_return_value': v8_set_return_value(interface.name, method, this_cpp_value), + 'v8_value_to_local_cpp_value': v8_value_to_local_cpp_value(argument, index), + } + + +################################################################################ +# Value handling +################################################################################ + +def cpp_value(interface, method, number_of_arguments): + def cpp_argument(argument): + idl_type = argument.idl_type + if idl_type.name == 'EventListener': + if (interface.name == 'EventTarget' and + method.name == 'removeEventListener'): + # FIXME: remove this special case by moving get() into + # EventTarget::removeEventListener + return '%s.get()' % argument.name + return argument.name + if (idl_type.is_callback_interface or + idl_type.name in ['NodeFilter', 'XPathNSResolver']): + # FIXME: remove this special case + return '%s.release()' % argument.name + return argument.name + + # Truncate omitted optional arguments + arguments = method.arguments[:number_of_arguments] + cpp_arguments = [] + if method.is_constructor: + call_with_values = interface.extended_attributes.get('ConstructorCallWith') + else: + call_with_values = method.extended_attributes.get('CallWith') + cpp_arguments.extend(v8_utilities.call_with_arguments(call_with_values)) + # Members of IDL partial interface definitions are implemented in C++ as + # static member functions, which for instance members (non-static members) + # take *impl as their first argument + if ('PartialInterfaceImplementedAs' in method.extended_attributes and + not method.is_static): + cpp_arguments.append('*impl') + cpp_arguments.extend(cpp_argument(argument) for argument in arguments) + this_union_arguments = method.idl_type and method.idl_type.union_arguments + if this_union_arguments: + cpp_arguments.extend(this_union_arguments) + + if ('RaisesException' in method.extended_attributes or + (method.is_constructor and + has_extended_attribute_value(interface, 'RaisesException', 'Constructor'))): + cpp_arguments.append('exceptionState') + + if method.name == 'Constructor': + base_name = 'create' + elif method.name == 'NamedConstructor': + base_name = 'createForJSConstructor' + else: + base_name = v8_utilities.cpp_name(method) + + cpp_method_name = v8_utilities.scoped_name(interface, method, base_name) + return '%s(%s)' % (cpp_method_name, ', '.join(cpp_arguments)) + + +def v8_set_return_value(interface_name, method, cpp_value, for_main_world=False): + idl_type = method.idl_type + extended_attributes = method.extended_attributes + if not idl_type or idl_type.name == 'void': + # Constructors and void methods don't have a return type + return None + + release = False + # [CallWith=ScriptState], [RaisesException] + if (has_extended_attribute_value(method, 'CallWith', 'ScriptState') or + 'RaisesException' in extended_attributes or + idl_type.is_union_type): + cpp_value = 'result' # use local variable for value + release = idl_type.release + + script_wrappable = 'impl' if inherits_interface(interface_name, 'Node') else '' + return idl_type.v8_set_return_value(cpp_value, extended_attributes, script_wrappable=script_wrappable, release=release, for_main_world=for_main_world) + + +def v8_value_to_local_cpp_variadic_value(argument, index): + assert argument.is_variadic + idl_type = argument.idl_type + + macro = 'TONATIVE_VOID_INTERNAL' + macro_args = [ + argument.name, + 'toNativeArguments<%s>(info, %s)' % (idl_type.cpp_type, index), + ] + + return '%s(%s)' % (macro, ', '.join(macro_args)) + + +def v8_value_to_local_cpp_value(argument, index): + extended_attributes = argument.extended_attributes + idl_type = argument.idl_type + name = argument.name + if argument.is_variadic: + return v8_value_to_local_cpp_variadic_value(argument, index) + # FIXME: This special way of handling string arguments with null defaults + # can go away once we fully support default values. + if (argument.is_optional and + idl_type.name in ('String', 'ByteString', 'ScalarValueString') and + argument.default_value and argument.default_value.is_null): + v8_value = 'argumentOrNull(info, %s)' % index + else: + v8_value = 'info[%s]' % index + return idl_type.v8_value_to_local_cpp_value(extended_attributes, v8_value, + name, index=index, declare_variable=False) + + +################################################################################ +# Auxiliary functions +################################################################################ + +# [NotEnumerable] +def property_attributes(method): + extended_attributes = method.extended_attributes + property_attributes_list = [] + if 'NotEnumerable' in extended_attributes: + property_attributes_list.append('v8::DontEnum') + if 'ReadOnly' in extended_attributes: + property_attributes_list.append('v8::ReadOnly') + if property_attributes_list: + property_attributes_list.insert(0, 'v8::DontDelete') + return property_attributes_list + + +def union_arguments(idl_type): + """Return list of ['result0Enabled', 'result0', 'result1Enabled', ...] for union types, for use in setting return value""" + return [arg + for i in range(len(idl_type.member_types)) + for arg in ['result%sEnabled' % i, 'result%s' % i]] + +IdlType.union_arguments = property(lambda self: None) +IdlUnionType.union_arguments = property(union_arguments) diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/v8_types.py b/chromium/third_party/WebKit/Source/bindings/scripts/v8_types.py new file mode 100644 index 00000000000..5f735af235c --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/scripts/v8_types.py @@ -0,0 +1,691 @@ +# Copyright (C) 2013 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. + +"""Functions for type handling and type conversion (Blink/C++ <-> V8/JS). + +Extends IdlType and IdlUnionType with V8-specific properties, methods, and +class methods. + +Spec: +http://www.w3.org/TR/WebIDL/#es-type-mapping + +Design doc: http://www.chromium.org/developers/design-documents/idl-compiler +""" + +import posixpath + +from idl_types import IdlType, IdlUnionType +import v8_attributes # for IdlType.constructor_type_name +from v8_globals import includes + + +################################################################################ +# V8-specific handling of IDL types +################################################################################ + +NON_WRAPPER_TYPES = frozenset([ + 'CompareHow', + 'Dictionary', + 'EventHandler', + 'EventListener', + 'MediaQueryListListener', + 'NodeFilter', + 'SerializedScriptValue', +]) +TYPED_ARRAYS = { + # (cpp_type, v8_type), used by constructor templates + 'ArrayBuffer': None, + 'ArrayBufferView': None, + 'Float32Array': ('float', 'v8::kExternalFloatArray'), + 'Float64Array': ('double', 'v8::kExternalDoubleArray'), + 'Int8Array': ('signed char', 'v8::kExternalByteArray'), + 'Int16Array': ('short', 'v8::kExternalShortArray'), + 'Int32Array': ('int', 'v8::kExternalIntArray'), + 'Uint8Array': ('unsigned char', 'v8::kExternalUnsignedByteArray'), + 'Uint8ClampedArray': ('unsigned char', 'v8::kExternalPixelArray'), + 'Uint16Array': ('unsigned short', 'v8::kExternalUnsignedShortArray'), + 'Uint32Array': ('unsigned int', 'v8::kExternalUnsignedIntArray'), +} + +IdlType.is_typed_array_type = property( + lambda self: self.base_type in TYPED_ARRAYS) + + +IdlType.is_wrapper_type = property( + lambda self: (self.is_interface_type and + self.base_type not in NON_WRAPPER_TYPES)) + + +################################################################################ +# C++ types +################################################################################ + +CPP_TYPE_SAME_AS_IDL_TYPE = set([ + 'double', + 'float', + 'long long', + 'unsigned long long', +]) +CPP_INT_TYPES = set([ + 'byte', + 'long', + 'short', +]) +CPP_UNSIGNED_TYPES = set([ + 'octet', + 'unsigned int', + 'unsigned long', + 'unsigned short', +]) +CPP_SPECIAL_CONVERSION_RULES = { + 'CompareHow': 'Range::CompareHow', + 'Date': 'double', + 'Dictionary': 'Dictionary', + 'EventHandler': 'EventListener*', + 'MediaQueryListListener': 'RefPtrWillBeRawPtr<MediaQueryListListener>', + 'NodeFilter': 'RefPtrWillBeRawPtr<NodeFilter>', + 'Promise': 'ScriptPromise', + 'ScriptValue': 'ScriptValue', + # FIXME: Eliminate custom bindings for XPathNSResolver http://crbug.com/345529 + 'XPathNSResolver': 'RefPtrWillBeRawPtr<XPathNSResolver>', + 'boolean': 'bool', + 'unrestricted double': 'double', + 'unrestricted float': 'float', +} + + +def cpp_type(idl_type, extended_attributes=None, used_as_argument=False, used_as_variadic_argument=False, used_in_cpp_sequence=False): + """Returns C++ type corresponding to IDL type. + + |idl_type| argument is of type IdlType, while return value is a string + + Args: + idl_type: + IdlType + used_as_argument: + bool, True if idl_type's raw/primitive C++ type should be returned. + used_in_cpp_sequence: + bool, True if the C++ type is used as an element of an array or sequence. + """ + def string_mode(): + # FIXME: the Web IDL spec requires 'EmptyString', not 'NullString', + # but we use NullString for performance. + if extended_attributes.get('TreatNullAs') != 'NullString': + return '' + if extended_attributes.get('TreatUndefinedAs') != 'NullString': + return 'WithNullCheck' + return 'WithUndefinedOrNullCheck' + + extended_attributes = extended_attributes or {} + idl_type = idl_type.preprocessed_type + + # Composite types + if used_as_variadic_argument: + array_or_sequence_type = idl_type + else: + array_or_sequence_type = idl_type.array_or_sequence_type + if array_or_sequence_type: + vector_type = cpp_ptr_type('Vector', 'HeapVector', array_or_sequence_type.gc_type) + return cpp_template_type(vector_type, array_or_sequence_type.cpp_type_args(used_in_cpp_sequence=True)) + + # Simple types + base_idl_type = idl_type.base_type + + if base_idl_type in CPP_TYPE_SAME_AS_IDL_TYPE: + return base_idl_type + if base_idl_type in CPP_INT_TYPES: + return 'int' + if base_idl_type in CPP_UNSIGNED_TYPES: + return 'unsigned' + if base_idl_type in CPP_SPECIAL_CONVERSION_RULES: + return CPP_SPECIAL_CONVERSION_RULES[base_idl_type] + + if base_idl_type in NON_WRAPPER_TYPES: + return 'RefPtr<%s>' % base_idl_type + if base_idl_type in ('DOMString', 'ByteString', 'ScalarValueString'): + if not used_as_argument: + return 'String' + return 'V8StringResource<%s>' % string_mode() + + if idl_type.is_typed_array_type and used_as_argument: + return base_idl_type + '*' + if idl_type.is_interface_type: + implemented_as_class = idl_type.implemented_as + if used_as_argument: + return implemented_as_class + '*' + new_type = 'Member' if used_in_cpp_sequence else 'RawPtr' + ptr_type = cpp_ptr_type('RefPtr', new_type, idl_type.gc_type) + return cpp_template_type(ptr_type, implemented_as_class) + # Default, assume native type is a pointer with same type name as idl type + return base_idl_type + '*' + + +def cpp_type_union(idl_type, extended_attributes=None, used_as_argument=False): + return (member_type.cpp_type for member_type in idl_type.member_types) + + +# Allow access as idl_type.cpp_type if no arguments +IdlType.cpp_type = property(cpp_type) +IdlUnionType.cpp_type = property(cpp_type_union) +IdlType.cpp_type_args = cpp_type +IdlUnionType.cpp_type_args = cpp_type_union + + +def cpp_template_type(template, inner_type): + """Returns C++ template specialized to type, with space added if needed.""" + if inner_type.endswith('>'): + format_string = '{template}<{inner_type} >' + else: + format_string = '{template}<{inner_type}>' + return format_string.format(template=template, inner_type=inner_type) + + +def cpp_ptr_type(old_type, new_type, gc_type): + if gc_type == 'GarbageCollectedObject': + return new_type + if gc_type == 'WillBeGarbageCollectedObject': + if old_type == 'Vector': + return 'WillBe' + new_type + return old_type + 'WillBe' + new_type + return old_type + + +def v8_type(interface_name): + return 'V8' + interface_name + + +# [ImplementedAs] +# This handles [ImplementedAs] on interface types, not [ImplementedAs] in the +# interface being generated. e.g., given: +# Foo.idl: interface Foo {attribute Bar bar}; +# Bar.idl: [ImplementedAs=Zork] interface Bar {}; +# when generating bindings for Foo, the [ImplementedAs] on Bar is needed. +# This data is external to Foo.idl, and hence computed as global information in +# compute_interfaces_info.py to avoid having to parse IDLs of all used interfaces. +IdlType.implemented_as_interfaces = {} + + +def implemented_as(idl_type): + base_idl_type = idl_type.base_type + if base_idl_type in IdlType.implemented_as_interfaces: + return IdlType.implemented_as_interfaces[base_idl_type] + return base_idl_type + + +IdlType.implemented_as = property(implemented_as) + +IdlType.set_implemented_as_interfaces = classmethod( + lambda cls, new_implemented_as_interfaces: + cls.implemented_as_interfaces.update(new_implemented_as_interfaces)) + + +# [GarbageCollected] +IdlType.garbage_collected_types = set() + +IdlType.is_garbage_collected = property( + lambda self: self.base_type in IdlType.garbage_collected_types) + +IdlType.set_garbage_collected_types = classmethod( + lambda cls, new_garbage_collected_types: + cls.garbage_collected_types.update(new_garbage_collected_types)) + + +# [WillBeGarbageCollected] +IdlType.will_be_garbage_collected_types = set() + +IdlType.is_will_be_garbage_collected = property( + lambda self: self.base_type in IdlType.will_be_garbage_collected_types) + +IdlType.set_will_be_garbage_collected_types = classmethod( + lambda cls, new_will_be_garbage_collected_types: + cls.will_be_garbage_collected_types.update(new_will_be_garbage_collected_types)) + + +def gc_type(idl_type): + if idl_type.is_garbage_collected: + return 'GarbageCollectedObject' + if idl_type.is_will_be_garbage_collected: + return 'WillBeGarbageCollectedObject' + return 'RefCountedObject' + +IdlType.gc_type = property(gc_type) + + +################################################################################ +# Includes +################################################################################ + +def includes_for_cpp_class(class_name, relative_dir_posix): + return set([posixpath.join('bindings', relative_dir_posix, class_name + '.h')]) + + +INCLUDES_FOR_TYPE = { + 'object': set(), + 'CompareHow': set(), + 'Dictionary': set(['bindings/v8/Dictionary.h']), + 'EventHandler': set(['bindings/v8/V8AbstractEventListener.h', + 'bindings/v8/V8EventListenerList.h']), + 'EventListener': set(['bindings/v8/BindingSecurity.h', + 'bindings/v8/V8EventListenerList.h', + 'core/frame/LocalDOMWindow.h']), + 'HTMLCollection': set(['bindings/core/v8/V8HTMLCollection.h', + 'core/dom/ClassCollection.h', + 'core/dom/TagCollection.h', + 'core/html/HTMLCollection.h', + 'core/html/HTMLFormControlsCollection.h', + 'core/html/HTMLTableRowsCollection.h']), + 'MediaQueryListListener': set(['core/css/MediaQueryListListener.h']), + 'NodeList': set(['bindings/core/v8/V8NodeList.h', + 'core/dom/NameNodeList.h', + 'core/dom/NodeList.h', + 'core/dom/StaticNodeList.h', + 'core/html/LabelsNodeList.h']), + 'Promise': set(['bindings/v8/ScriptPromise.h']), + 'SerializedScriptValue': set(['bindings/v8/SerializedScriptValue.h']), + 'ScriptValue': set(['bindings/v8/ScriptValue.h']), +} + + +def includes_for_type(idl_type): + idl_type = idl_type.preprocessed_type + + # Composite types + array_or_sequence_type = idl_type.array_or_sequence_type + if array_or_sequence_type: + return includes_for_type(array_or_sequence_type) + + # Simple types + base_idl_type = idl_type.base_type + if base_idl_type in INCLUDES_FOR_TYPE: + return INCLUDES_FOR_TYPE[base_idl_type] + if idl_type.is_basic_type: + return set() + if idl_type.is_typed_array_type: + return set(['bindings/v8/custom/V8%sCustom.h' % base_idl_type]) + if base_idl_type.endswith('ConstructorConstructor'): + # FIXME: rename to NamedConstructor + # FIXME: replace with a [NamedConstructorAttribute] extended attribute + # Ending with 'ConstructorConstructor' indicates a named constructor, + # and these do not have header files, as they are part of the generated + # bindings for the interface + return set() + if base_idl_type.endswith('Constructor'): + # FIXME: replace with a [ConstructorAttribute] extended attribute + base_idl_type = idl_type.constructor_type_name + return set(['bindings/%s/v8/V8%s.h' % (component_dir[base_idl_type], + base_idl_type)]) + +IdlType.includes_for_type = property(includes_for_type) +IdlUnionType.includes_for_type = property( + lambda self: set.union(*[includes_for_type(member_type) + for member_type in self.member_types])) + + +def add_includes_for_type(idl_type): + includes.update(idl_type.includes_for_type) + +IdlType.add_includes_for_type = add_includes_for_type +IdlUnionType.add_includes_for_type = add_includes_for_type + + +def includes_for_interface(interface_name): + return IdlType(interface_name).includes_for_type + + +def add_includes_for_interface(interface_name): + includes.update(includes_for_interface(interface_name)) + +component_dir = {} + + +def set_component_dirs(new_component_dirs): + component_dir.update(new_component_dirs) + + +################################################################################ +# V8 -> C++ +################################################################################ + +V8_VALUE_TO_CPP_VALUE = { + # Basic + 'Date': 'toCoreDate({v8_value})', + 'DOMString': '{v8_value}', + 'ByteString': 'toByteString({arguments})', + 'ScalarValueString': 'toScalarValueString({arguments})', + 'boolean': '{v8_value}->BooleanValue()', + 'float': 'static_cast<float>({v8_value}->NumberValue())', + 'unrestricted float': 'static_cast<float>({v8_value}->NumberValue())', + 'double': 'static_cast<double>({v8_value}->NumberValue())', + 'unrestricted double': 'static_cast<double>({v8_value}->NumberValue())', + 'byte': 'toInt8({arguments})', + 'octet': 'toUInt8({arguments})', + 'short': 'toInt16({arguments})', + 'unsigned short': 'toUInt16({arguments})', + 'long': 'toInt32({arguments})', + 'unsigned long': 'toUInt32({arguments})', + 'long long': 'toInt64({arguments})', + 'unsigned long long': 'toUInt64({arguments})', + # Interface types + 'CompareHow': 'static_cast<Range::CompareHow>({v8_value}->Int32Value())', + 'Dictionary': 'Dictionary({v8_value}, info.GetIsolate())', + 'EventTarget': 'V8DOMWrapper::isDOMWrapper({v8_value}) ? toWrapperTypeInfo(v8::Handle<v8::Object>::Cast({v8_value}))->toEventTarget(v8::Handle<v8::Object>::Cast({v8_value})) : 0', + 'MediaQueryListListener': 'MediaQueryListListener::create(ScriptState::current(info.GetIsolate()), ScriptValue(ScriptState::current(info.GetIsolate()), {v8_value}))', + 'NodeFilter': 'toNodeFilter({v8_value}, info.Holder(), ScriptState::current(info.GetIsolate()))', + 'Promise': 'ScriptPromise::cast(ScriptState::current(info.GetIsolate()), {v8_value})', + 'SerializedScriptValue': 'SerializedScriptValue::create({v8_value}, info.GetIsolate())', + 'ScriptValue': 'ScriptValue(ScriptState::current(info.GetIsolate()), {v8_value})', + 'Window': 'toDOMWindow({v8_value}, info.GetIsolate())', + 'XPathNSResolver': 'toXPathNSResolver({v8_value}, info.GetIsolate())', +} + + +def v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, index): + # Composite types + array_or_sequence_type = idl_type.array_or_sequence_type + if array_or_sequence_type: + return v8_value_to_cpp_value_array_or_sequence(array_or_sequence_type, v8_value, index) + + # Simple types + idl_type = idl_type.preprocessed_type + add_includes_for_type(idl_type) + base_idl_type = idl_type.base_type + + if 'EnforceRange' in extended_attributes: + arguments = ', '.join([v8_value, 'EnforceRange', 'exceptionState']) + elif (idl_type.is_integer_type or # NormalConversion + idl_type.name in ('ByteString', 'ScalarValueString')): + arguments = ', '.join([v8_value, 'exceptionState']) + else: + arguments = v8_value + + if base_idl_type in V8_VALUE_TO_CPP_VALUE: + cpp_expression_format = V8_VALUE_TO_CPP_VALUE[base_idl_type] + elif idl_type.is_typed_array_type: + cpp_expression_format = ( + '{v8_value}->Is{idl_type}() ? ' + 'V8{idl_type}::toNative(v8::Handle<v8::{idl_type}>::Cast({v8_value})) : 0') + else: + cpp_expression_format = ( + 'V8{idl_type}::toNativeWithTypeCheck(info.GetIsolate(), {v8_value})') + + return cpp_expression_format.format(arguments=arguments, idl_type=base_idl_type, v8_value=v8_value) + + +def v8_value_to_cpp_value_array_or_sequence(array_or_sequence_type, v8_value, index): + # Index is None for setters, index (starting at 0) for method arguments, + # and is used to provide a human-readable exception message + if index is None: + index = 0 # special case, meaning "setter" + else: + index += 1 # human-readable index + if (array_or_sequence_type.is_interface_type and + array_or_sequence_type.name != 'Dictionary'): + this_cpp_type = None + ref_ptr_type = cpp_ptr_type('RefPtr', 'Member', array_or_sequence_type.gc_type) + expression_format = '(to{ref_ptr_type}NativeArray<{array_or_sequence_type}, V8{array_or_sequence_type}>({v8_value}, {index}, info.GetIsolate()))' + add_includes_for_type(array_or_sequence_type) + else: + ref_ptr_type = None + this_cpp_type = array_or_sequence_type.cpp_type + expression_format = 'toNativeArray<{cpp_type}>({v8_value}, {index}, info.GetIsolate())' + expression = expression_format.format(array_or_sequence_type=array_or_sequence_type.name, cpp_type=this_cpp_type, index=index, ref_ptr_type=ref_ptr_type, v8_value=v8_value) + return expression + + +def v8_value_to_local_cpp_value(idl_type, extended_attributes, v8_value, variable_name, index=None, declare_variable=True): + """Returns an expression that converts a V8 value to a C++ value and stores it as a local value.""" + this_cpp_type = idl_type.cpp_type_args(extended_attributes=extended_attributes, used_as_argument=True) + + idl_type = idl_type.preprocessed_type + cpp_value = v8_value_to_cpp_value(idl_type, extended_attributes, v8_value, index) + args = [variable_name, cpp_value] + if idl_type.base_type == 'DOMString' and not idl_type.array_or_sequence_type: + macro = 'TOSTRING_VOID' + elif (idl_type.is_integer_type or + idl_type.name in ('ByteString', 'ScalarValueString')): + macro = 'TONATIVE_VOID_EXCEPTIONSTATE' + args.append('exceptionState') + else: + macro = 'TONATIVE_VOID' + + # Macros come in several variants, to minimize expensive creation of + # v8::TryCatch. + suffix = '' + + if declare_variable: + args.insert(0, this_cpp_type) + else: + suffix += '_INTERNAL' + + return '%s(%s)' % (macro + suffix, ', '.join(args)) + + +IdlType.v8_value_to_local_cpp_value = v8_value_to_local_cpp_value +IdlUnionType.v8_value_to_local_cpp_value = v8_value_to_local_cpp_value + + +################################################################################ +# C++ -> V8 +################################################################################ + +def preprocess_idl_type(idl_type): + if idl_type.is_enum: + # Enumerations are internally DOMStrings + return IdlType('DOMString') + if (idl_type.name == 'Any' or idl_type.is_callback_function): + return IdlType('ScriptValue') + return idl_type + +IdlType.preprocessed_type = property(preprocess_idl_type) +IdlUnionType.preprocessed_type = property(preprocess_idl_type) + + +def preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes): + """Returns IDL type and value, with preliminary type conversions applied.""" + idl_type = idl_type.preprocessed_type + if idl_type.name == 'Promise': + idl_type = IdlType('ScriptValue') + if idl_type.base_type in ['long long', 'unsigned long long']: + # long long and unsigned long long are not representable in ECMAScript; + # we represent them as doubles. + idl_type = IdlType('double', is_nullable=idl_type.is_nullable) + cpp_value = 'static_cast<double>(%s)' % cpp_value + # HTML5 says that unsigned reflected attributes should be in the range + # [0, 2^31). When a value isn't in this range, a default value (or 0) + # should be returned instead. + extended_attributes = extended_attributes or {} + if ('Reflect' in extended_attributes and + idl_type.base_type in ['unsigned long', 'unsigned short']): + cpp_value = cpp_value.replace('getUnsignedIntegralAttribute', + 'getIntegralAttribute') + cpp_value = 'std::max(0, %s)' % cpp_value + return idl_type, cpp_value + + +def v8_conversion_type(idl_type, extended_attributes): + """Returns V8 conversion type, adding any additional includes. + + The V8 conversion type is used to select the C++ -> V8 conversion function + or v8SetReturnValue* function; it can be an idl_type, a cpp_type, or a + separate name for the type of conversion (e.g., 'DOMWrapper'). + """ + extended_attributes = extended_attributes or {} + + # Composite types + array_or_sequence_type = idl_type.array_or_sequence_type + if array_or_sequence_type: + if array_or_sequence_type.is_interface_type: + add_includes_for_type(array_or_sequence_type) + return 'array' + + # Simple types + base_idl_type = idl_type.base_type + # Basic types, without additional includes + if base_idl_type in CPP_INT_TYPES: + return 'int' + if base_idl_type in CPP_UNSIGNED_TYPES: + return 'unsigned' + if base_idl_type in ('DOMString', 'ByteString', 'ScalarValueString'): + if 'TreatReturnedNullStringAs' not in extended_attributes: + return base_idl_type + treat_returned_null_string_as = extended_attributes['TreatReturnedNullStringAs'] + if treat_returned_null_string_as == 'Null': + return 'StringOrNull' + if treat_returned_null_string_as == 'Undefined': + return 'StringOrUndefined' + raise 'Unrecognized TreatReturnNullStringAs value: "%s"' % treat_returned_null_string_as + if idl_type.is_basic_type or base_idl_type == 'ScriptValue': + return base_idl_type + + # Data type with potential additional includes + add_includes_for_type(idl_type) + if base_idl_type in V8_SET_RETURN_VALUE: # Special v8SetReturnValue treatment + return base_idl_type + + # Pointer type + return 'DOMWrapper' + +IdlType.v8_conversion_type = v8_conversion_type + + +V8_SET_RETURN_VALUE = { + 'boolean': 'v8SetReturnValueBool(info, {cpp_value})', + 'int': 'v8SetReturnValueInt(info, {cpp_value})', + 'unsigned': 'v8SetReturnValueUnsigned(info, {cpp_value})', + 'DOMString': 'v8SetReturnValueString(info, {cpp_value}, info.GetIsolate())', + 'ByteString': 'v8SetReturnValueString(info, {cpp_value}, info.GetIsolate())', + 'ScalarValueString': 'v8SetReturnValueString(info, {cpp_value}, info.GetIsolate())', + # [TreatNullReturnValueAs] + 'StringOrNull': 'v8SetReturnValueStringOrNull(info, {cpp_value}, info.GetIsolate())', + 'StringOrUndefined': 'v8SetReturnValueStringOrUndefined(info, {cpp_value}, info.GetIsolate())', + 'void': '', + # No special v8SetReturnValue* function (set value directly) + 'float': 'v8SetReturnValue(info, {cpp_value})', + 'unrestricted float': 'v8SetReturnValue(info, {cpp_value})', + 'double': 'v8SetReturnValue(info, {cpp_value})', + 'unrestricted double': 'v8SetReturnValue(info, {cpp_value})', + # No special v8SetReturnValue* function, but instead convert value to V8 + # and then use general v8SetReturnValue. + 'array': 'v8SetReturnValue(info, {cpp_value})', + 'Date': 'v8SetReturnValue(info, {cpp_value})', + 'EventHandler': 'v8SetReturnValue(info, {cpp_value})', + 'ScriptValue': 'v8SetReturnValue(info, {cpp_value})', + 'SerializedScriptValue': 'v8SetReturnValue(info, {cpp_value})', + # DOMWrapper + 'DOMWrapperForMainWorld': 'v8SetReturnValueForMainWorld(info, WTF::getPtr({cpp_value}))', + 'DOMWrapperFast': 'v8SetReturnValueFast(info, WTF::getPtr({cpp_value}), {script_wrappable})', + 'DOMWrapperDefault': 'v8SetReturnValue(info, {cpp_value})', +} + + +def v8_set_return_value(idl_type, cpp_value, extended_attributes=None, script_wrappable='', release=False, for_main_world=False): + """Returns a statement that converts a C++ value to a V8 value and sets it as a return value. + + """ + def dom_wrapper_conversion_type(): + if not script_wrappable: + return 'DOMWrapperDefault' + if for_main_world: + return 'DOMWrapperForMainWorld' + return 'DOMWrapperFast' + + idl_type, cpp_value = preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes) + this_v8_conversion_type = idl_type.v8_conversion_type(extended_attributes) + # SetReturn-specific overrides + if this_v8_conversion_type in ['Date', 'EventHandler', 'ScriptValue', 'SerializedScriptValue', 'array']: + # Convert value to V8 and then use general v8SetReturnValue + cpp_value = idl_type.cpp_value_to_v8_value(cpp_value, extended_attributes=extended_attributes) + if this_v8_conversion_type == 'DOMWrapper': + this_v8_conversion_type = dom_wrapper_conversion_type() + + format_string = V8_SET_RETURN_VALUE[this_v8_conversion_type] + # FIXME: oilpan: Remove .release() once we remove all RefPtrs from generated code. + if release: + cpp_value = '%s.release()' % cpp_value + statement = format_string.format(cpp_value=cpp_value, script_wrappable=script_wrappable) + return statement + + +def v8_set_return_value_union(idl_type, cpp_value, extended_attributes=None, script_wrappable='', release=False, for_main_world=False): + """ + release: can be either False (False for all member types) or + a sequence (list or tuple) of booleans (if specified individually). + """ + + return [ + member_type.v8_set_return_value(cpp_value + str(i), + extended_attributes, + script_wrappable, + release and release[i], + for_main_world) + for i, member_type in + enumerate(idl_type.member_types)] + +IdlType.v8_set_return_value = v8_set_return_value +IdlUnionType.v8_set_return_value = v8_set_return_value_union + +IdlType.release = property(lambda self: self.is_interface_type) +IdlUnionType.release = property( + lambda self: [member_type.is_interface_type + for member_type in self.member_types]) + + +CPP_VALUE_TO_V8_VALUE = { + # Built-in types + 'Date': 'v8DateOrNaN({cpp_value}, {isolate})', + 'DOMString': 'v8String({isolate}, {cpp_value})', + 'ByteString': 'v8String({isolate}, {cpp_value})', + 'ScalarValueString': 'v8String({isolate}, {cpp_value})', + 'boolean': 'v8Boolean({cpp_value}, {isolate})', + 'int': 'v8::Integer::New({isolate}, {cpp_value})', + 'unsigned': 'v8::Integer::NewFromUnsigned({isolate}, {cpp_value})', + 'float': 'v8::Number::New({isolate}, {cpp_value})', + 'unrestricted float': 'v8::Number::New({isolate}, {cpp_value})', + 'double': 'v8::Number::New({isolate}, {cpp_value})', + 'unrestricted double': 'v8::Number::New({isolate}, {cpp_value})', + 'void': 'v8Undefined()', + # Special cases + 'EventHandler': '{cpp_value} ? v8::Handle<v8::Value>(V8AbstractEventListener::cast({cpp_value})->getListenerObject(impl->executionContext())) : v8::Handle<v8::Value>(v8::Null({isolate}))', + 'ScriptValue': '{cpp_value}.v8Value()', + 'SerializedScriptValue': '{cpp_value} ? {cpp_value}->deserialize() : v8::Handle<v8::Value>(v8::Null({isolate}))', + # General + 'array': 'v8Array({cpp_value}, {creation_context}, {isolate})', + 'DOMWrapper': 'toV8({cpp_value}, {creation_context}, {isolate})', +} + + +def cpp_value_to_v8_value(idl_type, cpp_value, isolate='info.GetIsolate()', creation_context='info.Holder()', extended_attributes=None): + """Returns an expression that converts a C++ value to a V8 value.""" + # the isolate parameter is needed for callback interfaces + idl_type, cpp_value = preprocess_idl_type_and_value(idl_type, cpp_value, extended_attributes) + this_v8_conversion_type = idl_type.v8_conversion_type(extended_attributes) + format_string = CPP_VALUE_TO_V8_VALUE[this_v8_conversion_type] + statement = format_string.format(cpp_value=cpp_value, isolate=isolate, creation_context=creation_context) + return statement + +IdlType.cpp_value_to_v8_value = cpp_value_to_v8_value diff --git a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/v8_utilities.py b/chromium/third_party/WebKit/Source/bindings/scripts/v8_utilities.py index 4752c45ab8c..112ff114a7e 100644 --- a/chromium/third_party/WebKit/Source/bindings/scripts/unstable/v8_utilities.py +++ b/chromium/third_party/WebKit/Source/bindings/scripts/v8_utilities.py @@ -28,24 +28,36 @@ """Functions shared by various parts of the code generator. -FIXME: Not currently used in build. -This is a rewrite of the Perl IDL compiler in Python, but is not complete. -Once it is complete, we will switch all IDL files over to Python at once. -Until then, please work on the Perl IDL compiler. -For details, see bug http://crbug.com/239771 -""" +Extends IdlType and IdlUnion type with |enum_validation_expression| property. -# FIXME: eliminate this file if possible +Design doc: http://www.chromium.org/developers/design-documents/idl-compiler +""" import re +from idl_types import IdlType, IdlUnionType +import idl_types from v8_globals import includes import v8_types -ACRONYMS = ['CSS', 'HTML', 'IME', 'JS', 'SVG', 'URL', 'WOFF', 'XML', 'XSLT'] +ACRONYMS = [ + 'CSSOM', # must come *before* CSS to match full acronym + 'CSS', + 'HTML', + 'IME', + 'JS', + 'SVG', + 'URL', + 'WOFF', + 'XML', + 'XSLT', +] -# Extended attributes +################################################################################ +# Extended attribute parsing +################################################################################ + def extended_attribute_value_contains(extended_attribute_value, value): return (extended_attribute_value and value in re.split('[|&]', extended_attribute_value)) @@ -62,7 +74,10 @@ def has_extended_attribute_value(definition_or_member, name, value): extended_attribute_value_contains(extended_attributes[name], value)) +################################################################################ # String handling +################################################################################ + def capitalize(name): """Capitalize first letter or initial acronym (used in setter names).""" for acronym in ACRONYMS: @@ -84,58 +99,87 @@ def uncapitalize(name): """ for acronym in ACRONYMS: if name.startswith(acronym): - name.replace(acronym, acronym.lower()) - return name + return name.replace(acronym, acronym.lower()) return name[0].lower() + name[1:] +################################################################################ # C++ +################################################################################ + def enum_validation_expression(idl_type): - if not v8_types.is_enum_type(idl_type): + # FIXME: Add IdlEnumType, move property to derived type, and remove this check + if not idl_type.is_enum: return None return ' || '.join(['string == "%s"' % enum_value - for enum_value in v8_types.enum_values(idl_type)]) + for enum_value in idl_type.enum_values]) +IdlType.enum_validation_expression = property(enum_validation_expression) def scoped_name(interface, definition, base_name): - if definition.is_static: - return '%s::%s' % (interface.name, base_name) - return 'imp->%s' % base_name + # partial interfaces are implemented as separate classes, with their members + # implemented as static member functions + partial_interface_implemented_as = definition.extended_attributes.get('PartialInterfaceImplementedAs') + if partial_interface_implemented_as: + return '%s::%s' % (partial_interface_implemented_as, base_name) + if (definition.is_static or + definition.name in ('Constructor', 'NamedConstructor')): + return '%s::%s' % (cpp_name(interface), base_name) + return 'impl->%s' % base_name def v8_class_name(interface): return v8_types.v8_type(interface.name) +################################################################################ +# Specific extended attributes +################################################################################ + # [ActivityLogging] -def activity_logging_world_list(member, access_type=None): +def activity_logging_world_list(member, access_type=''): """Returns a set of world suffixes for which a definition member has activity logging, for specified access type. access_type can be 'Getter' or 'Setter' if only checking getting or setting. """ - if 'ActivityLogging' not in member.extended_attributes: + extended_attributes = member.extended_attributes + if 'LogActivity' not in extended_attributes: return set() - activity_logging = member.extended_attributes['ActivityLogging'] - # [ActivityLogging=For*] (no prefix, starts with the worlds suffix) means - # "log for all use (method)/access (attribute)", otherwise check that value - # agrees with specified access_type (Getter/Setter). - has_logging = (activity_logging.startswith('For') or - (access_type and activity_logging.startswith(access_type))) - if not has_logging: + log_activity = extended_attributes['LogActivity'] + if log_activity and not log_activity.startswith(access_type): return set() + includes.add('bindings/v8/V8DOMActivityLogger.h') - if activity_logging.endswith('ForIsolatedWorlds'): - return set(['']) - return set(['', 'ForMainWorld']) # endswith('ForAllWorlds') + if 'LogAllWorlds' in extended_attributes: + return set(['', 'ForMainWorld']) + return set(['']) # At minimum, include isolated worlds. + + +# [ActivityLogging] +def activity_logging_world_check(member): + """Returns if an isolated world check is required when generating activity + logging code. + + The check is required when there is no per-world binding code and logging is + required only for isolated world. + """ + extended_attributes = member.extended_attributes + if 'LogActivity' not in extended_attributes: + return False + if ('PerWorldBindings' not in extended_attributes and + 'LogAllWorlds' not in extended_attributes): + return True + return False # [CallWith] CALL_WITH_ARGUMENTS = { - 'ScriptState': '&state', - 'ExecutionContext': 'scriptContext', + 'ScriptState': 'scriptState', + 'ExecutionContext': 'executionContext', 'ScriptArguments': 'scriptArguments.release()', - 'ActiveWindow': 'activeDOMWindow()', - 'FirstWindow': 'firstDOMWindow()', + 'ActiveWindow': 'callingDOMWindow(info.GetIsolate())', + 'FirstWindow': 'enteredDOMWindow(info.GetIsolate())', + 'Document': 'document', } # List because key order matters, as we want arguments in deterministic order CALL_WITH_VALUES = [ @@ -144,12 +188,11 @@ CALL_WITH_VALUES = [ 'ScriptArguments', 'ActiveWindow', 'FirstWindow', + 'Document', ] -def call_with_arguments(member, call_with_values=None): - # Optional parameter so setter can override with [SetterCallWith] - call_with_values = call_with_values or member.extended_attributes.get('CallWith') +def call_with_arguments(call_with_values): if not call_with_values: return [] return [CALL_WITH_ARGUMENTS[value] @@ -180,6 +223,16 @@ def deprecate_as(member): return extended_attributes['DeprecateAs'] +# [GarbageCollected], [WillBeGarbageCollected] +def gc_type(definition): + extended_attributes = definition.extended_attributes + if 'GarbageCollected' in extended_attributes: + return 'GarbageCollectedObject' + elif 'WillBeGarbageCollected' in extended_attributes: + return 'WillBeGarbageCollectedObject' + return 'RefCountedObject' + + # [ImplementedAs] def cpp_name(definition_or_member): extended_attributes = definition_or_member.extended_attributes diff --git a/chromium/third_party/WebKit/Source/bindings/templates/attributes.cpp b/chromium/third_party/WebKit/Source/bindings/templates/attributes.cpp index cbbe4192db6..c25e298e314 100644 --- a/chromium/third_party/WebKit/Source/bindings/templates/attributes.cpp +++ b/chromium/third_party/WebKit/Source/bindings/templates/attributes.cpp @@ -8,71 +8,104 @@ const v8::FunctionCallbackInfo<v8::Value>& info const v8::PropertyCallbackInfo<v8::Value>& info {%- endif %}) { - {% if attribute.is_unforgeable %} - v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain({{v8_class}}::domTemplate(info.GetIsolate(), worldType(info.GetIsolate()))); + {% if attribute.is_reflect and not attribute.is_url and + attribute.idl_type == 'DOMString' and is_node %} + {% set cpp_class, v8_class = 'Element', 'V8Element' %} + {% endif %} + {# holder #} + {% if attribute.is_unforgeable and interface_name != 'Window' %} + {# perform lookup first #} + {# FIXME: can we remove this lookup? #} + v8::Handle<v8::Object> holder = {{v8_class}}::findInstanceInPrototypeChain(info.This(), info.GetIsolate()); if (holder.IsEmpty()) return; - {{cpp_class}}* imp = {{v8_class}}::toNative(holder); + {% elif not attribute.is_static %} + v8::Handle<v8::Object> holder = info.Holder(); {% endif %} + {# impl #} {% if attribute.cached_attribute_validation_method %} - v8::Handle<v8::String> propertyName = v8::String::NewFromUtf8(info.GetIsolate(), "{{attribute.name}}", v8::String::kInternalizedString); - {{cpp_class}}* imp = {{v8_class}}::toNative(info.Holder()); - if (!imp->{{attribute.cached_attribute_validation_method}}()) { - v8::Handle<v8::Value> jsValue = info.Holder()->GetHiddenValue(propertyName); - if (!jsValue.IsEmpty()) { - v8SetReturnValue(info, jsValue); + v8::Handle<v8::String> propertyName = v8AtomicString(info.GetIsolate(), "{{attribute.name}}"); + {{cpp_class}}* impl = {{v8_class}}::toNative(holder); + if (!impl->{{attribute.cached_attribute_validation_method}}()) { + v8::Handle<v8::Value> v8Value = V8HiddenValue::getHiddenValue(info.GetIsolate(), holder, propertyName); + if (!v8Value.IsEmpty()) { + v8SetReturnValue(info, v8Value); return; } } - {% elif not (attribute.is_static or attribute.is_unforgeable) %} - {{cpp_class}}* imp = {{v8_class}}::toNative(info.Holder()); + {% elif not attribute.is_static %} + {{cpp_class}}* impl = {{v8_class}}::toNative(holder); + {% endif %} + {% if interface_name == 'Window' and attribute.idl_type == 'EventHandler' %} + if (!impl->document()) + return; {% endif %} + {# Local variables #} {% if attribute.is_call_with_execution_context %} - ExecutionContext* scriptContext = getExecutionContext(); + ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate()); + {% endif %} + {% if attribute.is_call_with_script_state %} + ScriptState* scriptState = ScriptState::current(info.GetIsolate()); {% endif %} - {# Special cases #} {% if attribute.is_check_security_for_node or attribute.is_getter_raises_exception %} - ExceptionState exceptionState(ExceptionState::GetterContext, "{{attribute.name}}", "{{interface_name}}", info.Holder(), info.GetIsolate()); + ExceptionState exceptionState(ExceptionState::GetterContext, "{{attribute.name}}", "{{interface_name}}", holder, info.GetIsolate()); + {% endif %} + {% if attribute.is_nullable and not attribute.has_type_checking_nullable %} + bool isNull = false; + {% endif %} + {# FIXME: consider always using a local variable for value #} + {% if attribute.cached_attribute_validation_method or + attribute.is_getter_raises_exception or + attribute.is_nullable or + attribute.reflect_only or + attribute.idl_type == 'EventHandler' %} + {{attribute.cpp_type}} {{attribute.cpp_value}} = {{attribute.cpp_value_original}}; + {% endif %} + {# Checks #} + {% if attribute.is_getter_raises_exception %} + if (UNLIKELY(exceptionState.throwIfNeeded())) + return; {% endif %} {% if attribute.is_check_security_for_node %} - {# FIXME: consider using a local variable to not call getter twice #} - if (!BindingSecurity::shouldAllowAccessToNode({{attribute.cpp_value}}, exceptionState)) { + {# FIXME: use a local variable to not call getter twice #} + if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), {{attribute.cpp_value}}, exceptionState)) { v8SetReturnValueNull(info); exceptionState.throwIfNeeded(); return; } {% endif %} - {% if attribute.is_getter_raises_exception %} - {{attribute.cpp_type}} {{attribute.cpp_value}} = {{attribute.cpp_value_original}}; - if (UNLIKELY(exceptionState.throwIfNeeded())) - return; + {% if attribute.reflect_only %} + {{release_only_check(attribute.reflect_only, attribute.reflect_missing, + attribute.reflect_invalid, attribute.reflect_empty) + | indent}} {% endif %} {% if attribute.is_nullable %} - bool isNull = false; - {{attribute.cpp_type}} {{attribute.cpp_value}} = {{attribute.cpp_value_original}}; + {% if attribute.has_type_checking_nullable %} + if (!{{attribute.cpp_value}}) { + {% else %} if (isNull) { + {% endif %} v8SetReturnValueNull(info); return; } - {% elif attribute.idl_type == 'EventHandler' or - attribute.cached_attribute_validation_method %} - {# FIXME: consider merging all these assign to local variable statements #} - {{attribute.cpp_type}} {{attribute.cpp_value}} = {{attribute.cpp_value_original}}; {% endif %} {% if attribute.cached_attribute_validation_method %} - info.Holder()->SetHiddenValue(propertyName, {{attribute.cpp_value}}.v8Value()); + V8HiddenValue::setHiddenValue(info.GetIsolate(), holder, propertyName, {{attribute.cpp_value_to_v8_value}}); {% endif %} - {# End special cases #} + {# v8SetReturnValue #} {% if attribute.is_keep_alive_for_gc %} - {{attribute.cpp_type}} result = {{attribute.cpp_value}}; - if (result && DOMDataStore::setReturnValueFromWrapper<{{attribute.v8_type}}>(info.GetReturnValue(), result.get())) + {# FIXME: merge local variable assignment with above #} + {{attribute.cpp_type}} result({{attribute.cpp_value}}); + if (result && DOMDataStore::setReturnValueFromWrapper{{world_suffix}}<{{attribute.v8_type}}>(info.GetReturnValue(), result.get())) return; - v8::Handle<v8::Value> wrapper = toV8(result.get(), info.Holder(), info.GetIsolate()); + v8::Handle<v8::Value> wrapper = toV8(result.get(), holder, info.GetIsolate()); if (!wrapper.IsEmpty()) { - V8HiddenPropertyName::setNamedHiddenReference(info.Holder(), "{{attribute.name}}", wrapper); + V8HiddenValue::setHiddenValue(info.GetIsolate(), holder, v8AtomicString(info.GetIsolate(), "{{attribute.name}}"), wrapper); {{attribute.v8_set_return_value}}; } + {% elif world_suffix %} + {{attribute.v8_set_return_value_for_main_world}}; {% else %} {{attribute.v8_set_return_value}}; {% endif %} @@ -80,6 +113,39 @@ const v8::PropertyCallbackInfo<v8::Value>& info {% endfilter %} {% endmacro %} +{######################################} +{% macro release_only_check(reflect_only_values, reflect_missing, + reflect_invalid, reflect_empty) %} +{# Attribute is limited to only known values: check that the attribute value is + one of those. If not, set it to the empty string. + http://www.whatwg.org/specs/web-apps/current-work/#limited-to-only-known-values #} +{% if reflect_empty %} +if (v8Value.isNull()) { +{% if reflect_missing %} + v8Value = "{{reflect_missing}}"; +{% else %} + ; +{% endif %} +} else if (v8Value.isEmpty()) { + v8Value = "{{reflect_empty}}"; +{% else %} +if (v8Value.isEmpty()) { +{# FIXME: should use [ReflectEmpty] instead; need to change IDL files #} +{% if reflect_missing %} + v8Value = "{{reflect_missing}}"; +{% else %} + ; +{% endif %} +{% endif %} +{% for value in reflect_only_values %} +} else if (equalIgnoringCase(v8Value, "{{value}}")) { + v8Value = "{{value}}"; +{% endfor %} +} else { + v8Value = "{{reflect_invalid}}"; +} +{% endmacro %} + {##############################################################################} {% macro attribute_getter_callback(attribute, world_suffix) %} @@ -93,22 +159,46 @@ v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info { TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMGetter"); {% if attribute.deprecate_as %} - UseCounter::countDeprecation(activeExecutionContext(), UseCounter::{{attribute.deprecate_as}}); + UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}}); {% endif %} {% if attribute.measure_as %} - UseCounter::count(activeDOMWindow(), UseCounter::{{attribute.measure_as}}); + UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}}); {% endif %} {% if world_suffix in attribute.activity_logging_world_list_for_getter %} - V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->GetCurrentContext()); + ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext()); + V8PerContextData* contextData = scriptState->perContextData(); + {% if attribute.activity_logging_world_check %} + if (scriptState->world().isIsolatedWorld() && contextData && contextData->activityLogger()) + {% else %} if (contextData && contextData->activityLogger()) - contextData->activityLogger()->log("{{interface_name}}.{{attribute.name}}", 0, 0, "Getter"); + {% endif %} + contextData->activityLogger()->logGetter("{{interface_name}}.{{attribute.name}}"); {% endif %} {% if attribute.has_custom_getter %} {{v8_class}}::{{attribute.name}}AttributeGetterCustom(info); {% else %} {{cpp_class}}V8Internal::{{attribute.name}}AttributeGetter{{world_suffix}}(info); {% endif %} - TRACE_EVENT_SET_SAMPLING_STATE("V8", "Execution"); + TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution"); +} +{% endfilter %} +{% endmacro %} + + +{##############################################################################} +{% macro constructor_getter_callback(attribute, world_suffix) %} +{% filter conditional(attribute.conditional_string) %} +static void {{attribute.name}}ConstructorGetterCallback{{world_suffix}}(v8::Local<v8::String> property, const v8::PropertyCallbackInfo<v8::Value>& info) +{ + TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMGetter"); + {% if attribute.deprecate_as %} + UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}}); + {% endif %} + {% if attribute.measure_as %} + UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}}); + {% endif %} + {{cpp_class}}V8Internal::{{cpp_class}}ConstructorGetter{{world_suffix}}(property, info); + TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution"); } {% endfilter %} {% endmacro %} @@ -119,54 +209,88 @@ v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info {% filter conditional(attribute.conditional_string) %} static void {{attribute.name}}AttributeSetter{{world_suffix}}( {%- if attribute.is_expose_js_accessors %} -v8::Local<v8::Value> jsValue, const v8::FunctionCallbackInfo<v8::Value>& info +v8::Local<v8::Value> v8Value, const v8::FunctionCallbackInfo<v8::Value>& info {%- else %} -v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info +v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info {%- endif %}) { - {% if attribute.is_setter_raises_exception or - attribute.has_strict_type_checking %} - ExceptionState exceptionState(ExceptionState::SetterContext, "{{attribute.name}}", "{{interface_name}}", info.Holder(), info.GetIsolate()); + {% if attribute.is_reflect and attribute.idl_type == 'DOMString' and + is_node %} + {% set cpp_class, v8_class = 'Element', 'V8Element' %} + {% endif %} + {# Local variables #} + {% if not attribute.is_static %} + v8::Handle<v8::Object> holder = info.Holder(); {% endif %} - {% if attribute.has_strict_type_checking %} + {% if attribute.has_setter_exception_state %} + ExceptionState exceptionState(ExceptionState::SetterContext, "{{attribute.name}}", "{{interface_name}}", holder, info.GetIsolate()); + {% endif %} + {# Type checking #} + {% if attribute.has_type_checking_interface %} {# Type checking for interface types (if interface not implemented, throw TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #} - if (!isUndefinedOrNull(jsValue) && !V8{{attribute.idl_type}}::hasInstance(jsValue, info.GetIsolate(), worldType(info.GetIsolate()))) { + if ({% if attribute.is_nullable %}!isUndefinedOrNull(v8Value) && {% endif %}!V8{{attribute.idl_type}}::hasInstance(v8Value, info.GetIsolate())) { exceptionState.throwTypeError("The provided value is not of type '{{attribute.idl_type}}'."); exceptionState.throwIfNeeded(); return; } {% endif %} - {% if not attribute.is_static %} - {{cpp_class}}* imp = {{v8_class}}::toNative(info.Holder()); + {# impl #} + {% if attribute.put_forwards %} + {{cpp_class}}* proxyImpl = {{v8_class}}::toNative(holder); + {{attribute.cpp_type}} impl = WTF::getPtr(proxyImpl->{{attribute.name}}()); + if (!impl) + return; + {% elif not attribute.is_static %} + {{cpp_class}}* impl = {{v8_class}}::toNative(holder); {% endif %} {% if attribute.idl_type == 'EventHandler' and interface_name == 'Window' %} - if (!imp->document()) + if (!impl->document()) return; {% endif %} + {# Convert JS value to C++ value #} {% if attribute.idl_type != 'EventHandler' %} {{attribute.v8_value_to_local_cpp_value}}; - {% else %}{# EventHandler hack #} - transferHiddenDependency(info.Holder(), {{attribute.event_handler_getter_expression}}, jsValue, {{v8_class}}::eventListenerCacheIndex, info.GetIsolate()); + {% elif not is_node %}{# EventHandler hack #} + moveEventListenerToNewWrapper(holder, {{attribute.event_handler_getter_expression}}, v8Value, {{v8_class}}::eventListenerCacheIndex, info.GetIsolate()); {% endif %} - {% if attribute.enum_validation_expression %} - {# Setter ignores invalid enum values: http://www.w3.org/TR/WebIDL/#idl-enums #} + {# Type checking, possibly throw a TypeError, per: + http://www.w3.org/TR/WebIDL/#es-type-mapping #} + {% if attribute.has_type_checking_unrestricted %} + {# Non-finite floating point values (NaN, +Infinity or −Infinity), per: + http://heycam.github.io/webidl/#es-float + http://heycam.github.io/webidl/#es-double #} + if (!std::isfinite(cppValue)) { + exceptionState.throwTypeError("The provided {{attribute.idl_type}} value is non-finite."); + exceptionState.throwIfNeeded(); + return; + } + {% elif attribute.enum_validation_expression %} + {# Setter ignores invalid enum values: + http://www.w3.org/TR/WebIDL/#idl-enums #} String string = cppValue; if (!({{attribute.enum_validation_expression}})) return; {% endif %} - {% if attribute.is_reflect %} + {# Pre-set context #} + {% if attribute.is_custom_element_callbacks or + (attribute.is_reflect and + not(attribute.idl_type == 'DOMString' and is_node)) %} + {# Skip on compact node DOMString getters #} CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope; {% endif %} - {% if attribute.is_call_with_execution_context %} - ExecutionContext* scriptContext = getExecutionContext(); + {% if attribute.is_call_with_execution_context or + attribute.is_setter_call_with_execution_context %} + ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate()); {% endif %} + {# Set #} {{attribute.cpp_setter}}; + {# Post-set #} {% if attribute.is_setter_raises_exception %} exceptionState.throwIfNeeded(); {% endif %} {% if attribute.cached_attribute_validation_method %} - info.Holder()->DeleteHiddenValue(v8::String::NewFromUtf8(info.GetIsolate(), "{{attribute.name}}", v8::String::kInternalizedString)); // Invalidate the cached value. + V8HiddenValue::deleteHiddenValue(info.GetIsolate(), holder, v8AtomicString(info.GetIsolate(), "{{attribute.name}}")); // Invalidate the cached value. {% endif %} } {% endfilter %} @@ -180,35 +304,50 @@ static void {{attribute.name}}AttributeSetterCallback{{world_suffix}}( {%- if attribute.is_expose_js_accessors %} const v8::FunctionCallbackInfo<v8::Value>& info {%- else %} -v8::Local<v8::String>, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info +v8::Local<v8::String>, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info {%- endif %}) { {% if attribute.is_expose_js_accessors %} - v8::Local<v8::Value> jsValue = info[0]; + v8::Local<v8::Value> v8Value = info[0]; {% endif %} TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMSetter"); {% if attribute.deprecate_as %} - UseCounter::countDeprecation(activeExecutionContext(), UseCounter::{{attribute.deprecate_as}}); + UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}}); {% endif %} {% if attribute.measure_as %} - UseCounter::count(activeDOMWindow(), UseCounter::{{attribute.measure_as}}); + UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.measure_as}}); {% endif %} {% if world_suffix in attribute.activity_logging_world_list_for_setter %} - V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->GetCurrentContext()); + ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext()); + V8PerContextData* contextData = scriptState->perContextData(); + {% if attribute.activity_logging_world_check %} + if (scriptState->world().isIsolatedWorld() && contextData && contextData->activityLogger()) { + {% else %} if (contextData && contextData->activityLogger()) { - v8::Handle<v8::Value> loggerArg[] = { jsValue }; - contextData->activityLogger()->log("{{interface_name}}.{{attribute.name}}", 1, &loggerArg[0], "Setter"); + {% endif %} + {% if attribute.activity_logging_include_old_value_for_setter %} + {{cpp_class}}* impl = {{v8_class}}::toNative(info.Holder()); + {% if attribute.cpp_value_original %} + {{attribute.cpp_type}} original = {{attribute.cpp_value_original}}; + {% else %} + {{attribute.cpp_type}} original = {{attribute.cpp_value}}; + {% endif %} + v8::Handle<v8::Value> originalValue = {{attribute.cpp_value_to_v8_value}}; + contextData->activityLogger()->logSetter("{{interface_name}}.{{attribute.name}}", v8Value, originalValue); + {% else %} + contextData->activityLogger()->logSetter("{{interface_name}}.{{attribute.name}}", v8Value); + {% endif %} } {% endif %} - {% if attribute.is_reflect %} + {% if attribute.is_custom_element_callbacks or attribute.is_reflect %} CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope; {% endif %} {% if attribute.has_custom_setter %} - {{v8_class}}::{{attribute.name}}AttributeSetterCustom(jsValue, info); + {{v8_class}}::{{attribute.name}}AttributeSetterCustom(v8Value, info); {% else %} - {{cpp_class}}V8Internal::{{attribute.name}}AttributeSetter{{world_suffix}}(jsValue, info); + {{cpp_class}}V8Internal::{{attribute.name}}AttributeSetter{{world_suffix}}(v8Value, info); {% endif %} - TRACE_EVENT_SET_SAMPLING_STATE("V8", "Execution"); + TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution"); } {% endfilter %} {% endmacro %} diff --git a/chromium/third_party/WebKit/Source/bindings/templates/callback_interface.cpp b/chromium/third_party/WebKit/Source/bindings/templates/callback_interface.cpp index ea297b71be5..5f33caa55ab 100644 --- a/chromium/third_party/WebKit/Source/bindings/templates/callback_interface.cpp +++ b/chromium/third_party/WebKit/Source/bindings/templates/callback_interface.cpp @@ -1,36 +1,8 @@ -{# http://www.chromium.org/blink/coding-style#TOC-License #} -/* - * Copyright (C) 2013 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. - */ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -{# FIXME: Rename to Python when switch #} -// This file has been auto-generated by code_generator_v8.pm. DO NOT MODIFY! +// This file has been auto-generated by {{code_generator}}. DO NOT MODIFY! #include "config.h" {% filter conditional(conditional_string) %} @@ -39,13 +11,14 @@ {% for filename in cpp_includes %} #include "{{filename}}" {% endfor %} + namespace WebCore { -{{v8_class}}::{{v8_class}}(v8::Handle<v8::Function> callback, ExecutionContext* context) - : ActiveDOMCallback(context) - , m_callback(toIsolate(context), callback) - , m_world(DOMWrapperWorld::current()) +{{v8_class}}::{{v8_class}}(v8::Handle<v8::Function> callback, ScriptState* scriptState) + : ActiveDOMCallback(scriptState->executionContext()) + , m_scriptState(scriptState) { + m_callback.set(scriptState->isolate(), callback); } {{v8_class}}::~{{v8_class}}() @@ -53,21 +26,18 @@ namespace WebCore { } {% for method in methods if not method.custom %} -{{method.return_cpp_type}} {{v8_class}}::{{method.name}}({{method.argument_declarations | join(', ')}}) +{{method.cpp_type}} {{v8_class}}::{{method.name}}({{method.argument_declarations | join(', ')}}) { {% set return_default = 'return true' - if method.return_idl_type == 'boolean' else 'return' %}{# void #} + if method.idl_type == 'boolean' else 'return' %}{# void #} if (!canInvokeCallback()) {{return_default}}; - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::HandleScope handleScope(isolate); - - v8::Handle<v8::Context> v8Context = toV8Context(executionContext(), m_world.get()); - if (v8Context.IsEmpty()) + v8::Isolate* isolate = m_scriptState->isolate(); + if (m_scriptState->contextIsEmpty()) {{return_default}}; - v8::Context::Scope scope(v8Context); + ScriptState::Scope scope(m_scriptState.get()); {% if method.call_with_this_handle %} v8::Handle<v8::Value> thisHandle = thisValue.v8Value(); if (thisHandle.IsEmpty()) { @@ -75,27 +45,26 @@ namespace WebCore { CRASH(); {{return_default}}; } - ASSERT(thisHandle->IsObject()); {% endif %} {% for argument in method.arguments %} - {{argument.cpp_to_v8_conversion | indent}} - if ({{argument.name}}Handle.IsEmpty()) { + v8::Handle<v8::Value> {{argument.handle}} = {{argument.cpp_value_to_v8_value}}; + if ({{argument.handle}}.IsEmpty()) { if (!isScriptControllerTerminating()) CRASH(); {{return_default}}; } {% endfor %} {% if method.arguments %} - v8::Handle<v8::Value> argv[] = { {{method.handles | join(', ')}} }; + v8::Handle<v8::Value> argv[] = { {{method.arguments | join(', ', 'handle')}} }; {% else %} v8::Handle<v8::Value> *argv = 0; {% endif %} - {% set this_handle_parameter = 'v8::Handle<v8::Object>::Cast(thisHandle), ' if method.call_with_this_handle else '' %} - {% if method.return_idl_type == 'boolean' %} - return invokeCallback(m_callback.newLocal(isolate), {{this_handle_parameter}}{{method.arguments | length}}, argv, executionContext(), isolate); + {% set this_handle_parameter = 'thisHandle, ' if method.call_with_this_handle else '' %} + {% if method.idl_type == 'boolean' %} + return invokeCallback(m_scriptState.get(), m_callback.newLocal(isolate), {{this_handle_parameter}}{{method.arguments | length}}, argv); {% else %}{# void #} - invokeCallback(m_callback.newLocal(isolate), {{this_handle_parameter}}{{method.arguments | length}}, argv, executionContext(), isolate); + invokeCallback(m_scriptState.get(), m_callback.newLocal(isolate), {{this_handle_parameter}}{{method.arguments | length}}, argv); {% endif %} } diff --git a/chromium/third_party/WebKit/Source/bindings/templates/callback_interface.h b/chromium/third_party/WebKit/Source/bindings/templates/callback_interface.h index acd58673bea..f3b172da294 100644 --- a/chromium/third_party/WebKit/Source/bindings/templates/callback_interface.h +++ b/chromium/third_party/WebKit/Source/bindings/templates/callback_interface.h @@ -1,36 +1,8 @@ -{# http://www.chromium.org/blink/coding-style#TOC-License #} -/* - * Copyright (C) 2013 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. - */ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -{# FIXME: Rename to Python when switch #} -// This file has been auto-generated by code_generator_v8.pm. DO NOT MODIFY! +// This file has been auto-generated by {{code_generator}}. DO NOT MODIFY! #ifndef {{v8_class}}_h #define {{v8_class}}_h @@ -42,26 +14,23 @@ namespace WebCore { -class ExecutionContext; - -class {{v8_class}} : public {{cpp_class}}, public ActiveDOMCallback { +class {{v8_class}} FINAL : public {{cpp_class}}, public ActiveDOMCallback { public: - static PassOwnPtr<{{v8_class}}> create(v8::Handle<v8::Function> callback, ExecutionContext* context) + static PassOwnPtr<{{v8_class}}> create(v8::Handle<v8::Function> callback, ScriptState* scriptState) { - ASSERT(context); - return adoptPtr(new {{v8_class}}(callback, context)); + return adoptPtr(new {{v8_class}}(callback, scriptState)); } virtual ~{{v8_class}}(); {% for method in methods %} - virtual {{method.return_cpp_type}} {{method.name}}({{method.argument_declarations | join(', ')}}); + virtual {{method.cpp_type}} {{method.name}}({{method.argument_declarations | join(', ')}}) OVERRIDE; {% endfor %} private: - {{v8_class}}(v8::Handle<v8::Function>, ExecutionContext*); + {{v8_class}}(v8::Handle<v8::Function>, ScriptState*); ScopedPersistent<v8::Function> m_callback; - RefPtr<DOMWrapperWorld> m_world; + RefPtr<ScriptState> m_scriptState; }; } diff --git a/chromium/third_party/WebKit/Source/bindings/templates/interface.cpp b/chromium/third_party/WebKit/Source/bindings/templates/interface.cpp index 5a2703cb96f..7312827a63b 100644 --- a/chromium/third_party/WebKit/Source/bindings/templates/interface.cpp +++ b/chromium/third_party/WebKit/Source/bindings/templates/interface.cpp @@ -7,7 +7,10 @@ '%sV8Internal::%sAttributeGetterCallback' % (cpp_class, attribute.name) if not attribute.constructor_type else - '{0}V8Internal::{0}ConstructorGetter'.format(interface_name) %} + ('%sV8Internal::%sConstructorGetterCallback' % + (cpp_class, attribute.name) + if attribute.needs_constructor_getter_callback else + '{0}V8Internal::{0}ConstructorGetter'.format(cpp_class)) %} {% set getter_callback_for_main_world = '%sV8Internal::%sAttributeGetterCallbackForMainWorld' % (cpp_class, attribute.name) @@ -16,7 +19,8 @@ {% set setter_callback_for_main_world = '%sV8Internal::%sAttributeSetterCallbackForMainWorld' % (cpp_class, attribute.name) - if attribute.is_per_world_bindings and not attribute.is_read_only else '0' %} + if attribute.is_per_world_bindings and + (not attribute.is_read_only or attribute.put_forwards) else '0' %} {% set wrapper_type_info = 'const_cast<WrapperTypeInfo*>(&V8%s::wrapperTypeInfo)' % attribute.constructor_type @@ -25,9 +29,24 @@ ' | '.join(attribute.access_control_list) %} {% set property_attribute = 'static_cast<v8::PropertyAttribute>(%s)' % ' | '.join(attribute.property_attributes) %} -{% set on_prototype = ', 0 /* on instance */' - if not attribute.is_expose_js_accessors else '' %} -{"{{attribute.name}}", {{getter_callback}}, {{setter_callback}}, {{getter_callback_for_main_world}}, {{setter_callback_for_main_world}}, {{wrapper_type_info}}, {{access_control}}, {{property_attribute}}{{on_prototype}}} +{% set on_prototype = '1 /* on prototype */' + if interface_name == 'Window' and attribute.idl_type == 'EventHandler' + else '0 /* on instance */' %} +{% set attribute_configuration_list = [ + '"%s"' % attribute.name, + getter_callback, + setter_callback, + getter_callback_for_main_world, + setter_callback_for_main_world, + wrapper_type_info, + access_control, + property_attribute, + ] %} +{% if not attribute.is_expose_js_accessors %} +{% set attribute_configuration_list = attribute_configuration_list + + [on_prototype] %} +{% endif %} +{{'{'}}{{attribute_configuration_list | join(', ')}}{{'}'}} {%- endmacro %} @@ -38,14 +57,14 @@ {% set method_callback_for_main_world = '%sV8Internal::%sMethodCallbackForMainWorld' % (cpp_class, method.name) if method.is_per_world_bindings else '0' %} -{"{{method.name}}", {{method_callback}}, {{method_callback_for_main_world}}, {{method.number_of_required_or_variadic_arguments}}} +{"{{method.name}}", {{method_callback}}, {{method_callback_for_main_world}}, {{method.length}}} {%- endmacro %} {##############################################################################} {% block constructor_getter %} {% if has_constructor_attributes %} -static void {{interface_name}}ConstructorGetter(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info) +static void {{cpp_class}}ConstructorGetter(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>& info) { v8::Handle<v8::Value> data = info.Data(); ASSERT(data->IsExternal()); @@ -63,15 +82,26 @@ static void {{interface_name}}ConstructorGetter(v8::Local<v8::String>, const v8: {% block replaceable_attribute_setter_and_callback %} {% if has_replaceable_attributes or has_constructor_attributes %} {# FIXME: rename to ForceSetAttributeOnThis, since also used for Constructors #} -static void {{interface_name}}ReplaceableAttributeSetter(v8::Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info) +static void {{cpp_class}}ReplaceableAttributeSetter(v8::Local<v8::String> name, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info) { - info.This()->ForceSet(name, jsValue); + {% if is_check_security %} + {{cpp_class}}* impl = {{v8_class}}::toNative(info.Holder()); + v8::Isolate* isolate = info.GetIsolate(); + v8::String::Utf8Value attributeName(name); + ExceptionState exceptionState(ExceptionState::SetterContext, *attributeName, "{{interface_name}}", info.Holder(), isolate); + if (!BindingSecurity::shouldAllowAccessToFrame(isolate, impl->frame(), exceptionState)) { + exceptionState.throwIfNeeded(); + return; + } + {% endif %} + if (info.This()->IsObject()) + v8::Handle<v8::Object>::Cast(info.This())->ForceSet(name, v8Value); } {# FIXME: rename to ForceSetAttributeOnThisCallback, since also used for Constructors #} -static void {{interface_name}}ReplaceableAttributeSetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info) +static void {{cpp_class}}ReplaceableAttributeSetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info) { - {{interface_name}}V8Internal::{{interface_name}}ReplaceableAttributeSetter(name, jsValue, info); + {{cpp_class}}V8Internal::{{cpp_class}}ReplaceableAttributeSetter(name, v8Value, info); } {% endif %} @@ -83,14 +113,409 @@ static void {{interface_name}}ReplaceableAttributeSetterCallback(v8::Local<v8::S {% if is_check_security and interface_name != 'Window' %} bool indexedSecurityCheck(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value>) { - {{cpp_class}}* imp = {{v8_class}}::toNative(host); - return BindingSecurity::shouldAllowAccessToFrame(imp->frame(), DoNotReportSecurityError); + {{cpp_class}}* impl = {{v8_class}}::toNative(host); + return BindingSecurity::shouldAllowAccessToFrame(v8::Isolate::GetCurrent(), impl->frame(), DoNotReportSecurityError); } bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value>) { - {{cpp_class}}* imp = {{v8_class}}::toNative(host); - return BindingSecurity::shouldAllowAccessToFrame(imp->frame(), DoNotReportSecurityError); + {{cpp_class}}* impl = {{v8_class}}::toNative(host); + return BindingSecurity::shouldAllowAccessToFrame(v8::Isolate::GetCurrent(), impl->frame(), DoNotReportSecurityError); +} + +{% endif %} +{% endblock %} + + +{##############################################################################} +{% block indexed_property_getter %} +{% if indexed_property_getter and not indexed_property_getter.is_custom %} +{% set getter = indexed_property_getter %} +static void indexedPropertyGetter(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) +{ + {{cpp_class}}* impl = {{v8_class}}::toNative(info.Holder()); + {% if getter.is_raises_exception %} + ExceptionState exceptionState(ExceptionState::IndexedGetterContext, "{{interface_name}}", info.Holder(), info.GetIsolate()); + {% endif %} + {% set getter_name = getter.name or 'anonymousIndexedGetter' %} + {% set getter_arguments = ['index', 'exceptionState'] + if getter.is_raises_exception else ['index'] %} + {{getter.cpp_type}} result = impl->{{getter_name}}({{getter_arguments | join(', ')}}); + {% if getter.is_raises_exception %} + if (exceptionState.throwIfNeeded()) + return; + {% endif %} + if ({{getter.is_null_expression}}) + return; + {{getter.v8_set_return_value}}; +} + +{% endif %} +{% endblock %} + + +{##############################################################################} +{% block indexed_property_getter_callback %} +{% if indexed_property_getter %} +{% set getter = indexed_property_getter %} +static void indexedPropertyGetterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) +{ + TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMIndexedProperty"); + {% if getter.is_custom %} + {{v8_class}}::indexedPropertyGetterCustom(index, info); + {% else %} + {{cpp_class}}V8Internal::indexedPropertyGetter(index, info); + {% endif %} + TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution"); +} + +{% endif %} +{% endblock %} + + +{##############################################################################} +{% block indexed_property_setter %} +{% if indexed_property_setter and not indexed_property_setter.is_custom %} +{% set setter = indexed_property_setter %} +static void indexedPropertySetter(uint32_t index, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<v8::Value>& info) +{ + {{cpp_class}}* impl = {{v8_class}}::toNative(info.Holder()); + {{setter.v8_value_to_local_cpp_value}}; + {% if setter.has_exception_state %} + ExceptionState exceptionState(ExceptionState::IndexedSetterContext, "{{interface_name}}", info.Holder(), info.GetIsolate()); + {% endif %} + {% if setter.has_type_checking_interface %} + {# Type checking for interface types (if interface not implemented, throw + TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #} + if (!isUndefinedOrNull(v8Value) && !V8{{setter.idl_type}}::hasInstance(v8Value, info.GetIsolate())) { + exceptionState.throwTypeError("The provided value is not of type '{{setter.idl_type}}'."); + exceptionState.throwIfNeeded(); + return; + } + {% endif %} + {% set setter_name = setter.name or 'anonymousIndexedSetter' %} + {% set setter_arguments = ['index', 'propertyValue', 'exceptionState'] + if setter.is_raises_exception else ['index', 'propertyValue'] %} + bool result = impl->{{setter_name}}({{setter_arguments | join(', ')}}); + {% if setter.is_raises_exception %} + if (exceptionState.throwIfNeeded()) + return; + {% endif %} + if (!result) + return; + v8SetReturnValue(info, v8Value); +} + +{% endif %} +{% endblock %} + + +{##############################################################################} +{% block indexed_property_setter_callback %} +{% if indexed_property_setter %} +{% set setter = indexed_property_setter %} +static void indexedPropertySetterCallback(uint32_t index, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<v8::Value>& info) +{ + TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMIndexedProperty"); + {% if setter.is_custom %} + {{v8_class}}::indexedPropertySetterCustom(index, v8Value, info); + {% else %} + {{cpp_class}}V8Internal::indexedPropertySetter(index, v8Value, info); + {% endif %} + TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution"); +} + +{% endif %} +{% endblock %} + + +{##############################################################################} +{% block indexed_property_deleter %} +{% if indexed_property_deleter and not indexed_property_deleter.is_custom %} +{% set deleter = indexed_property_deleter %} +static void indexedPropertyDeleter(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info) +{ + {{cpp_class}}* impl = {{v8_class}}::toNative(info.Holder()); + {% if deleter.is_raises_exception %} + ExceptionState exceptionState(ExceptionState::IndexedDeletionContext, "{{interface_name}}", info.Holder(), info.GetIsolate()); + {% endif %} + {% set deleter_name = deleter.name or 'anonymousIndexedDeleter' %} + {% set deleter_arguments = ['index', 'exceptionState'] + if deleter.is_raises_exception else ['index'] %} + DeleteResult result = impl->{{deleter_name}}({{deleter_arguments | join(', ')}}); + {% if deleter.is_raises_exception %} + if (exceptionState.throwIfNeeded()) + return; + {% endif %} + if (result != DeleteUnknownProperty) + return v8SetReturnValueBool(info, result == DeleteSuccess); +} + +{% endif %} +{% endblock %} + + +{##############################################################################} +{% block indexed_property_deleter_callback %} +{% if indexed_property_deleter %} +{% set deleter = indexed_property_deleter %} +static void indexedPropertyDeleterCallback(uint32_t index, const v8::PropertyCallbackInfo<v8::Boolean>& info) +{ + TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMIndexedProperty"); + {% if deleter.is_custom %} + {{v8_class}}::indexedPropertyDeleterCustom(index, info); + {% else %} + {{cpp_class}}V8Internal::indexedPropertyDeleter(index, info); + {% endif %} + TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution"); +} + +{% endif %} +{% endblock %} + + +{##############################################################################} +{% from 'methods.cpp' import union_type_method_call_and_set_return_value %} +{% block named_property_getter %} +{% if named_property_getter and not named_property_getter.is_custom %} +{% set getter = named_property_getter %} +static void namedPropertyGetter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info) +{ + {% if not is_override_builtins %} + if (info.Holder()->HasRealNamedProperty(name)) + return; + if (!info.Holder()->GetRealNamedPropertyInPrototypeChain(name).IsEmpty()) + return; + + {% endif %} + {{cpp_class}}* impl = {{v8_class}}::toNative(info.Holder()); + AtomicString propertyName = toCoreAtomicString(name); + {% if getter.is_raises_exception %} + v8::String::Utf8Value namedProperty(name); + ExceptionState exceptionState(ExceptionState::GetterContext, *namedProperty, "{{interface_name}}", info.Holder(), info.GetIsolate()); + {% endif %} + {% if getter.union_arguments %} + {{union_type_method_call_and_set_return_value(getter) | indent}} + {% else %} + {{getter.cpp_type}} result = {{getter.cpp_value}}; + {% if getter.is_raises_exception %} + if (exceptionState.throwIfNeeded()) + return; + {% endif %} + if ({{getter.is_null_expression}}) + return; + {{getter.v8_set_return_value}}; + {% endif %} +} + +{% endif %} +{% endblock %} + + +{##############################################################################} +{% block named_property_getter_callback %} +{% if named_property_getter %} +{% set getter = named_property_getter %} +static void namedPropertyGetterCallback(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info) +{ + TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMNamedProperty"); + {% if getter.is_custom %} + {{v8_class}}::namedPropertyGetterCustom(name, info); + {% else %} + {{cpp_class}}V8Internal::namedPropertyGetter(name, info); + {% endif %} + TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution"); +} + +{% endif %} +{% endblock %} + + +{##############################################################################} +{% block named_property_setter %} +{% if named_property_setter and not named_property_setter.is_custom %} +{% set setter = named_property_setter %} +static void namedPropertySetter(v8::Local<v8::String> name, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<v8::Value>& info) +{ + {% if not is_override_builtins %} + if (info.Holder()->HasRealNamedProperty(name)) + return; + if (!info.Holder()->GetRealNamedPropertyInPrototypeChain(name).IsEmpty()) + return; + + {% endif %} + {{cpp_class}}* impl = {{v8_class}}::toNative(info.Holder()); + {# v8_value_to_local_cpp_value('DOMString', 'name', 'propertyName') #} + TOSTRING_VOID(V8StringResource<>, propertyName, name); + {{setter.v8_value_to_local_cpp_value}}; + {% if setter.has_exception_state %} + v8::String::Utf8Value namedProperty(name); + ExceptionState exceptionState(ExceptionState::SetterContext, *namedProperty, "{{interface_name}}", info.Holder(), info.GetIsolate()); + {% endif %} + {% set setter_name = setter.name or 'anonymousNamedSetter' %} + {% set setter_arguments = + ['propertyName', 'propertyValue', 'exceptionState'] + if setter.is_raises_exception else + ['propertyName', 'propertyValue'] %} + bool result = impl->{{setter_name}}({{setter_arguments | join(', ')}}); + {% if setter.is_raises_exception %} + if (exceptionState.throwIfNeeded()) + return; + {% endif %} + if (!result) + return; + v8SetReturnValue(info, v8Value); +} + +{% endif %} +{% endblock %} + + +{##############################################################################} +{% block named_property_setter_callback %} +{% if named_property_setter %} +{% set setter = named_property_setter %} +static void namedPropertySetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<v8::Value>& info) +{ + TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMNamedProperty"); + {% if setter.is_custom %} + {{v8_class}}::namedPropertySetterCustom(name, v8Value, info); + {% else %} + {{cpp_class}}V8Internal::namedPropertySetter(name, v8Value, info); + {% endif %} + TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution"); +} + +{% endif %} +{% endblock %} + + +{##############################################################################} +{% block named_property_query %} +{% if named_property_getter and named_property_getter.is_enumerable and + not named_property_getter.is_custom_property_query %} +{# If there is an enumerator, there MUST be a query method to properly + communicate property attributes. #} +static void namedPropertyQuery(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Integer>& info) +{ + {{cpp_class}}* impl = {{v8_class}}::toNative(info.Holder()); + AtomicString propertyName = toCoreAtomicString(name); + v8::String::Utf8Value namedProperty(name); + ExceptionState exceptionState(ExceptionState::GetterContext, *namedProperty, "{{interface_name}}", info.Holder(), info.GetIsolate()); + bool result = impl->namedPropertyQuery(propertyName, exceptionState); + if (exceptionState.throwIfNeeded()) + return; + if (!result) + return; + v8SetReturnValueInt(info, v8::None); +} + +{% endif %} +{% endblock %} + + +{##############################################################################} +{% block named_property_query_callback %} +{% if named_property_getter and named_property_getter.is_enumerable %} +{% set getter = named_property_getter %} +static void namedPropertyQueryCallback(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Integer>& info) +{ + TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMNamedProperty"); + {% if getter.is_custom_property_query %} + {{v8_class}}::namedPropertyQueryCustom(name, info); + {% else %} + {{cpp_class}}V8Internal::namedPropertyQuery(name, info); + {% endif %} + TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution"); +} + +{% endif %} +{% endblock %} + + +{##############################################################################} +{% block named_property_deleter %} +{% if named_property_deleter and not named_property_deleter.is_custom %} +{% set deleter = named_property_deleter %} +static void namedPropertyDeleter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Boolean>& info) +{ + {{cpp_class}}* impl = {{v8_class}}::toNative(info.Holder()); + AtomicString propertyName = toCoreAtomicString(name); + {% if deleter.is_raises_exception %} + v8::String::Utf8Value namedProperty(name); + ExceptionState exceptionState(ExceptionState::DeletionContext, *namedProperty, "{{interface_name}}", info.Holder(), info.GetIsolate()); + {% endif %} + {% set deleter_name = deleter.name or 'anonymousNamedDeleter' %} + {% set deleter_arguments = ['propertyName', 'exceptionState'] + if deleter.is_raises_exception else ['propertyName'] %} + DeleteResult result = impl->{{deleter_name}}({{deleter_arguments | join(', ')}}); + {% if deleter.is_raises_exception %} + if (exceptionState.throwIfNeeded()) + return; + {% endif %} + if (result != DeleteUnknownProperty) + return v8SetReturnValueBool(info, result == DeleteSuccess); +} + +{% endif %} +{% endblock %} + + +{##############################################################################} +{% block named_property_deleter_callback %} +{% if named_property_deleter %} +{% set deleter = named_property_deleter %} +static void namedPropertyDeleterCallback(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Boolean>& info) +{ + TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMNamedProperty"); + {% if deleter.is_custom %} + {{v8_class}}::namedPropertyDeleterCustom(name, info); + {% else %} + {{cpp_class}}V8Internal::namedPropertyDeleter(name, info); + {% endif %} + TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution"); +} + +{% endif %} +{% endblock %} + + +{##############################################################################} +{% block named_property_enumerator %} +{% if named_property_getter and named_property_getter.is_enumerable and + not named_property_getter.is_custom_property_enumerator %} +static void namedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) +{ + {{cpp_class}}* impl = {{v8_class}}::toNative(info.Holder()); + v8::Isolate* isolate = info.GetIsolate(); + Vector<String> names; + ExceptionState exceptionState(ExceptionState::EnumerationContext, "{{interface_name}}", info.Holder(), isolate); + impl->namedPropertyEnumerator(names, exceptionState); + if (exceptionState.throwIfNeeded()) + return; + v8::Handle<v8::Array> v8names = v8::Array::New(isolate, names.size()); + for (size_t i = 0; i < names.size(); ++i) + v8names->Set(v8::Integer::New(isolate, i), v8String(isolate, names[i])); + v8SetReturnValue(info, v8names); +} + +{% endif %} +{% endblock %} + + +{##############################################################################} +{% block named_property_enumerator_callback %} +{% if named_property_getter and named_property_getter.is_enumerable %} +{% set getter = named_property_getter %} +static void namedPropertyEnumeratorCallback(const v8::PropertyCallbackInfo<v8::Array>& info) +{ + TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMNamedProperty"); + {% if getter.is_custom_property_enumerator %} + {{v8_class}}::namedPropertyEnumeratorCustom(info); + {% else %} + {{cpp_class}}V8Internal::namedPropertyEnumerator(info); + {% endif %} + TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution"); } {% endif %} @@ -100,28 +525,29 @@ bool namedSecurityCheck(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8 {##############################################################################} {% block origin_safe_method_setter %} {% if has_origin_safe_method_setter %} -static void {{cpp_class}}OriginSafeMethodSetter(v8::Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info) +static void {{cpp_class}}OriginSafeMethodSetter(v8::Local<v8::String> name, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info) { - {# FIXME: don't call GetIsolate 3 times #} - v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain({{v8_class}}::domTemplate(info.GetIsolate(), worldType(info.GetIsolate()))); + v8::Isolate* isolate = info.GetIsolate(); + v8::Handle<v8::Object> holder = {{v8_class}}::findInstanceInPrototypeChain(info.This(), isolate); if (holder.IsEmpty()) return; - {{cpp_class}}* imp = {{v8_class}}::toNative(holder); + {{cpp_class}}* impl = {{v8_class}}::toNative(holder); v8::String::Utf8Value attributeName(name); - ExceptionState exceptionState(ExceptionState::SetterContext, *attributeName, "{{interface_name}}", info.Holder(), info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame(), exceptionState)) { + ExceptionState exceptionState(ExceptionState::SetterContext, *attributeName, "{{interface_name}}", info.Holder(), isolate); + if (!BindingSecurity::shouldAllowAccessToFrame(isolate, impl->frame(), exceptionState)) { exceptionState.throwIfNeeded(); return; } - info.This()->SetHiddenValue(name, jsValue); + {# The findInstanceInPrototypeChain() call above only returns a non-empty handle if info.This() is an Object. #} + V8HiddenValue::setHiddenValue(isolate, v8::Handle<v8::Object>::Cast(info.This()), name, v8Value); } -static void {{cpp_class}}OriginSafeMethodSetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> jsValue, const v8::PropertyCallbackInfo<void>& info) +static void {{cpp_class}}OriginSafeMethodSetterCallback(v8::Local<v8::String> name, v8::Local<v8::Value> v8Value, const v8::PropertyCallbackInfo<void>& info) { TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMSetter"); - {{cpp_class}}V8Internal::{{cpp_class}}OriginSafeMethodSetter(name, jsValue, info); - TRACE_EVENT_SET_SAMPLING_STATE("V8", "Execution"); + {{cpp_class}}V8Internal::{{cpp_class}}OriginSafeMethodSetter(name, v8Value, info); + TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution"); } {% endif %} @@ -134,29 +560,27 @@ static void {{cpp_class}}OriginSafeMethodSetterCallback(v8::Local<v8::String> na {% if named_constructor %} {% set to_active_dom_object = '%s::toActiveDOMObject' % v8_class if is_active_dom_object else '0' %} -const WrapperTypeInfo {{v8_class}}Constructor::wrapperTypeInfo = { gin::kEmbedderBlink, {{v8_class}}Constructor::domTemplate, {{v8_class}}::derefObject, {{to_active_dom_object}}, 0, 0, {{v8_class}}::installPerContextEnabledMethods, 0, WrapperTypeObjectPrototype }; +{% set to_event_target = '%s::toEventTarget' % v8_class + if is_event_target else '0' %} +const WrapperTypeInfo {{v8_class}}Constructor::wrapperTypeInfo = { gin::kEmbedderBlink, {{v8_class}}Constructor::domTemplate, {{v8_class}}::derefObject, {{to_active_dom_object}}, {{to_event_target}}, 0, {{v8_class}}::installPerContextEnabledMethods, 0, WrapperTypeObjectPrototype, {{gc_type}} }; {{named_constructor_callback(named_constructor)}} -v8::Handle<v8::FunctionTemplate> {{v8_class}}Constructor::domTemplate(v8::Isolate* isolate, WrapperWorldType currentWorldType) +v8::Handle<v8::FunctionTemplate> {{v8_class}}Constructor::domTemplate(v8::Isolate* isolate) { - // This is only for getting a unique pointer which we can pass to privateTemplate. - static int privateTemplateUniqueKey; + static int domTemplateKey; // This address is used for a key to look up the dom template. V8PerIsolateData* data = V8PerIsolateData::from(isolate); - v8::Local<v8::FunctionTemplate> result = data->privateTemplateIfExists(currentWorldType, &privateTemplateUniqueKey); + v8::Local<v8::FunctionTemplate> result = data->existingDOMTemplate(&domTemplateKey); if (!result.IsEmpty()) return result; TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); - v8::EscapableHandleScope scope(isolate); result = v8::FunctionTemplate::New(isolate, {{v8_class}}ConstructorCallback); - v8::Local<v8::ObjectTemplate> instanceTemplate = result->InstanceTemplate(); instanceTemplate->SetInternalFieldCount({{v8_class}}::internalFieldCount); - result->SetClassName(v8::String::NewFromUtf8(isolate, "{{cpp_class}}", v8::String::kInternalizedString)); - result->Inherit({{v8_class}}::domTemplate(isolate, currentWorldType)); - data->setPrivateTemplate(currentWorldType, &privateTemplateUniqueKey, result); - - return scope.Escape(result); + result->SetClassName(v8AtomicString(isolate, "{{cpp_class}}")); + result->Inherit({{v8_class}}::domTemplate(isolate)); + data->setDOMTemplate(&domTemplateKey, result); + return result; } {% endif %} @@ -164,27 +588,43 @@ v8::Handle<v8::FunctionTemplate> {{v8_class}}Constructor::domTemplate(v8::Isolat {##############################################################################} {% block overloaded_constructor %} -{% if constructors|length > 1 %} +{% if constructor_overloads %} static void constructor(const v8::FunctionCallbackInfo<v8::Value>& info) { - {% for constructor in constructors %} - if ({{constructor.overload_resolution_expression}}) { - {{cpp_class}}V8Internal::constructor{{constructor.overload_index}}(info); - return; - } + v8::Isolate* isolate = info.GetIsolate(); + ExceptionState exceptionState(ExceptionState::ConstructionContext, "{{interface_name}}", info.Holder(), isolate); + {# 2. Initialize argcount to be min(maxarg, n). #} + switch (std::min({{constructor_overloads.maxarg}}, info.Length())) { + {# 3. Remove from S all entries whose type list is not of length argcount. #} + {% for length, tests_constructors in constructor_overloads.length_tests_methods %} + case {{length}}: + {# Then resolve by testing argument #} + {% for test, constructor in tests_constructors %} + {# 10. If i = d, then: #} + if ({{test}}) { + {{cpp_class}}V8Internal::constructor{{constructor.overload_index}}(info); + return; + } + {% endfor %} + break; {% endfor %} - {% if interface_length %} - ExceptionState exceptionState(ExceptionState::ConstructionContext, "{{interface_name}}", info.Holder(), info.GetIsolate()); - if (UNLIKELY(info.Length() < {{interface_length}})) { - exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments({{interface_length}}, info.Length())); + default: + {# Invalid arity, throw error #} + {# Report full list of valid arities if gaps and above minimum #} + {% if constructor_overloads.valid_arities %} + if (info.Length() >= {{constructor_overloads.minarg}}) { + throwArityTypeError(exceptionState, "{{constructor_overloads.valid_arities}}", info.Length()); + return; + } + {% endif %} + {# Otherwise just report "not enough arguments" #} + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments({{constructor_overloads.minarg}}, info.Length())); exceptionState.throwIfNeeded(); return; } + {# No match, throw error #} exceptionState.throwTypeError("No matching constructor signature."); exceptionState.throwIfNeeded(); - {% else %} - throwTypeError(ExceptionMessages::failedToConstruct("{{interface_name}}", "No matching constructor signature."), info.GetIsolate()); - {% endif %} } {% endif %} @@ -196,21 +636,22 @@ static void constructor(const v8::FunctionCallbackInfo<v8::Value>& info) {% if has_event_constructor %} static void constructor(const v8::FunctionCallbackInfo<v8::Value>& info) { - ExceptionState exceptionState(ExceptionState::ConstructionContext, "{{interface_name}}", info.Holder(), info.GetIsolate()); + v8::Isolate* isolate = info.GetIsolate(); + ExceptionState exceptionState(ExceptionState::ConstructionContext, "{{interface_name}}", info.Holder(), isolate); if (info.Length() < 1) { exceptionState.throwTypeError("An event name must be provided."); exceptionState.throwIfNeeded(); return; } - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, info[0]); + TOSTRING_VOID(V8StringResource<>, type, info[0]); {% for attribute in any_type_attributes %} v8::Local<v8::Value> {{attribute.name}}; {% endfor %} {{cpp_class}}Init eventInit; if (info.Length() >= 2) { - V8TRYCATCH_VOID(Dictionary, options, Dictionary(info[1], info.GetIsolate())); - if (!initialize{{cpp_class}}(eventInit, options, exceptionState)) { + TONATIVE_VOID(Dictionary, options, Dictionary(info[1], isolate)); + if (!initialize{{cpp_class}}(eventInit, options, exceptionState, info)) { exceptionState.throwIfNeeded(); return; } @@ -219,15 +660,15 @@ static void constructor(const v8::FunctionCallbackInfo<v8::Value>& info) {% for attribute in any_type_attributes %} options.get("{{attribute.name}}", {{attribute.name}}); if (!{{attribute.name}}.IsEmpty()) - info.Holder()->SetHiddenValue(V8HiddenPropertyName::{{attribute.name}}(info.GetIsolate()), {{attribute.name}}); + V8HiddenValue::setHiddenValue(isolate, info.Holder(), v8AtomicString(isolate, "{{attribute.name}}"), {{attribute.name}}); {% endfor %} } {% if is_constructor_raises_exception %} - RefPtr<{{cpp_class}}> event = {{cpp_class}}::create(type, eventInit, exceptionState); + RefPtrWillBeRawPtr<{{cpp_class}}> event = {{cpp_class}}::create(type, eventInit, exceptionState); if (exceptionState.throwIfNeeded()) return; {% else %} - RefPtr<{{cpp_class}}> event = {{cpp_class}}::create(type, eventInit); + RefPtrWillBeRawPtr<{{cpp_class}}> event = {{cpp_class}}::create(type, eventInit); {% endif %} {% if any_type_attributes and not interface_name == 'ErrorEvent' %} {# If we're in an isolated world, create a SerializedScriptValue and store @@ -239,16 +680,16 @@ static void constructor(const v8::FunctionCallbackInfo<v8::Value>& info) thus passing it around would cause leakage. 2) Errors cannot be cloned (or serialized): http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#safe-passing-of-structured-data #} - if (isolatedWorldForIsolate(info.GetIsolate())) { + if (DOMWrapperWorld::current(isolate).isIsolatedWorld()) { {% for attribute in any_type_attributes %} if (!{{attribute.name}}.IsEmpty()) - event->setSerialized{{attribute.name | blink_capitalize}}(SerializedScriptValue::createAndSwallowExceptions({{attribute.name}}, info.GetIsolate())); + event->setSerialized{{attribute.name | blink_capitalize}}(SerializedScriptValue::createAndSwallowExceptions({{attribute.name}}, isolate)); {% endfor %} } {% endif %} v8::Handle<v8::Object> wrapper = info.Holder(); - V8DOMWrapper::associateObjectWithWrapper<{{v8_class}}>(event.release(), &{{v8_class}}::wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent); + V8DOMWrapper::associateObjectWithWrapper<{{v8_class}}>(event.release(), &{{v8_class}}::wrapperTypeInfo, wrapper, isolate, {{wrapper_configuration}}); v8SetReturnValue(info, wrapper); } @@ -258,14 +699,30 @@ static void constructor(const v8::FunctionCallbackInfo<v8::Value>& info) {##############################################################################} {% block visit_dom_wrapper %} -{% if generate_visit_dom_wrapper_function %} +{% if reachable_node_function or set_wrapper_reference_to_list %} void {{v8_class}}::visitDOMWrapper(void* object, const v8::Persistent<v8::Object>& wrapper, v8::Isolate* isolate) { {{cpp_class}}* impl = fromInternalPointer(object); - if (Node* owner = impl->{{generate_visit_dom_wrapper_function}}()) { - setObjectGroup(V8GCController::opaqueRootForGC(owner, isolate), wrapper, isolate); + {% if set_wrapper_reference_to_list %} + v8::Local<v8::Object> creationContext = v8::Local<v8::Object>::New(isolate, wrapper); + V8WrapperInstantiationScope scope(creationContext, isolate); + {% for set_wrapper_reference_to in set_wrapper_reference_to_list %} + {{set_wrapper_reference_to.cpp_type}} {{set_wrapper_reference_to.name}} = impl->{{set_wrapper_reference_to.name}}(); + if ({{set_wrapper_reference_to.name}}) { + if (!DOMDataStore::containsWrapper<{{set_wrapper_reference_to.v8_type}}>({{set_wrapper_reference_to.name}}, isolate)) + wrap({{set_wrapper_reference_to.name}}, creationContext, isolate); + DOMDataStore::setWrapperReference<{{set_wrapper_reference_to.v8_type}}>(wrapper, {{set_wrapper_reference_to.name}}, isolate); + } + {% endfor %} + {% endif %} + {% if reachable_node_function %} + // The {{reachable_node_function}}() method may return a reference or a pointer. + if (Node* owner = WTF::getPtr(impl->{{reachable_node_function}}())) { + Node* root = V8GCController::opaqueRootForGC(owner, isolate); + isolate->SetReferenceFromGroup(v8::UniqueId(reinterpret_cast<intptr_t>(root)), wrapper); return; } + {% endif %} setObjectGroup(object, wrapper, isolate); } @@ -274,15 +731,29 @@ void {{v8_class}}::visitDOMWrapper(void* object, const v8::Persistent<v8::Object {##############################################################################} +{% block shadow_attributes %} +{% if interface_name == 'Window' %} +static const V8DOMConfiguration::AttributeConfiguration shadowAttributes[] = { + {% for attribute in attributes if attribute.is_unforgeable %} + {{attribute_configuration(attribute)}}, + {% endfor %} +}; + +{% endif %} +{% endblock %} + + +{##############################################################################} {% block class_attributes %} {# FIXME: rename to install_attributes and put into configure_class_template #} -{% if attributes %} +{% if has_attribute_configuration %} static const V8DOMConfiguration::AttributeConfiguration {{v8_class}}Attributes[] = { {% for attribute in attributes if not (attribute.is_expose_js_accessors or attribute.is_static or attribute.runtime_enabled_function or - attribute.per_context_enabled_function) %} + attribute.per_context_enabled_function or + (interface_name == 'Window' and attribute.is_unforgeable)) %} {% filter conditional(attribute.conditional_string) %} {{attribute_configuration(attribute)}}, {% endfilter %} @@ -310,9 +781,9 @@ static const V8DOMConfiguration::AccessorConfiguration {{v8_class}}Accessors[] = {##############################################################################} {% block class_methods %} {# FIXME: rename to install_methods and put into configure_class_template #} -{% if has_method_configuration %} +{% if method_configuration_methods %} static const V8DOMConfiguration::MethodConfiguration {{v8_class}}Methods[] = { - {% for method in methods if method.do_generate_method_configuration %} + {% for method in method_configuration_methods %} {% filter conditional(method.conditional_string) %} {{method_configuration(method)}}, {% endfilter %} @@ -326,11 +797,11 @@ static const V8DOMConfiguration::MethodConfiguration {{v8_class}}Methods[] = { {##############################################################################} {% block initialize_event %} {% if has_event_constructor %} -bool initialize{{cpp_class}}({{cpp_class}}Init& eventInit, const Dictionary& options, ExceptionState& exceptionState, const String& forEventName) +bool initialize{{cpp_class}}({{cpp_class}}Init& eventInit, const Dictionary& options, ExceptionState& exceptionState, const v8::FunctionCallbackInfo<v8::Value>& info, const String& forEventName) { Dictionary::ConversionContext conversionContext(forEventName.isEmpty() ? String("{{interface_name}}") : forEventName, "", exceptionState); {% if parent_interface %}{# any Event interface except Event itself #} - if (!initialize{{parent_interface}}(eventInit, options, exceptionState, forEventName.isEmpty() ? String("{{interface_name}}") : forEventName)) + if (!initialize{{parent_interface}}(eventInit, options, exceptionState, info, forEventName.isEmpty() ? String("{{interface_name}}") : forEventName)) return false; {% endif %} @@ -341,7 +812,7 @@ bool initialize{{cpp_class}}({{cpp_class}}Init& eventInit, const Dictionary& opt {% if attribute.deprecate_as %} if (options.convert(conversionContext.setConversionType("{{attribute.idl_type}}", {{is_nullable}}), "{{attribute.name}}", eventInit.{{attribute.cpp_name}})) { if (options.hasProperty("{{attribute.name}}")) - UseCounter::countDeprecation(activeExecutionContext(), UseCounter::{{attribute.deprecate_as}}); + UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{attribute.deprecate_as}}); } else { return false; } @@ -364,14 +835,14 @@ void {{v8_class}}::constructorCallback(const v8::FunctionCallbackInfo<v8::Value> { TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMConstructor"); {% if measure_as %} - UseCounter::count(activeDOMWindow(), UseCounter::{{measure_as}}); + UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{measure_as}}); {% endif %} if (!info.IsConstructCall()) { - throwTypeError(ExceptionMessages::failedToConstruct("{{interface_name}}", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate()); + throwTypeError(ExceptionMessages::constructorNotCallableAsFunction("{{interface_name}}"), info.GetIsolate()); return; } - if (ConstructorMode::current() == ConstructorMode::WrapExistingObject) { + if (ConstructorMode::current(info.GetIsolate()) == ConstructorMode::WrapExistingObject) { v8SetReturnValue(info, info.Holder()); return; } @@ -388,29 +859,50 @@ void {{v8_class}}::constructorCallback(const v8::FunctionCallbackInfo<v8::Value> {##############################################################################} +{% block configure_shadow_object_template %} +{% if interface_name == 'Window' %} +static void configureShadowObjectTemplate(v8::Handle<v8::ObjectTemplate> templ, v8::Isolate* isolate) +{ + V8DOMConfiguration::installAttributes(templ, v8::Handle<v8::ObjectTemplate>(), shadowAttributes, WTF_ARRAY_LENGTH(shadowAttributes), isolate); + + // Install a security handler with V8. + templ->SetAccessCheckCallbacks(V8Window::namedSecurityCheckCustom, V8Window::indexedSecurityCheckCustom, v8::External::New(isolate, const_cast<WrapperTypeInfo*>(&V8Window::wrapperTypeInfo))); + templ->SetInternalFieldCount(V8Window::internalFieldCount); +} + +{% endif %} +{% endblock %} + + +{##############################################################################} {% block configure_class_template %} {# FIXME: rename to install_dom_template and Install{{v8_class}}DOMTemplate #} -static v8::Handle<v8::FunctionTemplate> Configure{{v8_class}}Template(v8::Handle<v8::FunctionTemplate> functionTemplate, v8::Isolate* isolate, WrapperWorldType currentWorldType) +static void configure{{v8_class}}Template(v8::Handle<v8::FunctionTemplate> functionTemplate, v8::Isolate* isolate) { functionTemplate->ReadOnlyPrototype(); v8::Local<v8::Signature> defaultSignature; {% set parent_template = - 'V8%s::domTemplate(isolate, currentWorldType)' % parent_interface + 'V8%s::domTemplate(isolate)' % parent_interface if parent_interface else 'v8::Local<v8::FunctionTemplate>()' %} {% if runtime_enabled_function %} if (!{{runtime_enabled_function}}()) - defaultSignature = V8DOMConfiguration::installDOMClassTemplate(functionTemplate, "", {{parent_template}}, {{v8_class}}::internalFieldCount, 0, 0, 0, 0, 0, 0, isolate, currentWorldType); + defaultSignature = V8DOMConfiguration::installDOMClassTemplate(functionTemplate, "", {{parent_template}}, {{v8_class}}::internalFieldCount, 0, 0, 0, 0, 0, 0, isolate); else {% endif %} {% set runtime_enabled_indent = 4 if runtime_enabled_function else 0 %} {% filter indent(runtime_enabled_indent, true) %} defaultSignature = V8DOMConfiguration::installDOMClassTemplate(functionTemplate, "{{interface_name}}", {{parent_template}}, {{v8_class}}::internalFieldCount, - {# Test needed as size 0 constant arrays are not allowed in VC++ #} + {# Test needed as size 0 arrays definitions are not allowed per standard + (so objects have distinct addresses), which is enforced by MSVC. + 8.5.1 Aggregates [dcl.init.aggr] + An array of unknown size initialized with a brace-enclosed + initializer-list containing n initializer-clauses, where n shall be + greater than zero, is defined as having n elements (8.3.4). #} {% set attributes_name, attributes_length = ('%sAttributes' % v8_class, 'WTF_ARRAY_LENGTH(%sAttributes)' % v8_class) - if attributes else (0, 0) %} + if has_attribute_configuration else (0, 0) %} {% set accessors_name, accessors_length = ('%sAccessors' % v8_class, 'WTF_ARRAY_LENGTH(%sAccessors)' % v8_class) @@ -418,51 +910,96 @@ static v8::Handle<v8::FunctionTemplate> Configure{{v8_class}}Template(v8::Handle {% set methods_name, methods_length = ('%sMethods' % v8_class, 'WTF_ARRAY_LENGTH(%sMethods)' % v8_class) - if has_method_configuration else (0, 0) %} + if method_configuration_methods else (0, 0) %} {{attributes_name}}, {{attributes_length}}, {{accessors_name}}, {{accessors_length}}, {{methods_name}}, {{methods_length}}, - isolate, currentWorldType); + isolate); {% endfilter %} {% if constructors or has_custom_constructor or has_event_constructor %} functionTemplate->SetCallHandler({{v8_class}}::constructorCallback); functionTemplate->SetLength({{interface_length}}); {% endif %} - v8::Local<v8::ObjectTemplate> ALLOW_UNUSED instanceTemplate = functionTemplate->InstanceTemplate(); - v8::Local<v8::ObjectTemplate> ALLOW_UNUSED prototypeTemplate = functionTemplate->PrototypeTemplate(); + v8::Local<v8::ObjectTemplate> instanceTemplate ALLOW_UNUSED = functionTemplate->InstanceTemplate(); + v8::Local<v8::ObjectTemplate> prototypeTemplate ALLOW_UNUSED = functionTemplate->PrototypeTemplate(); {% if is_check_security and interface_name != 'Window' %} instanceTemplate->SetAccessCheckCallbacks({{cpp_class}}V8Internal::namedSecurityCheck, {{cpp_class}}V8Internal::indexedSecurityCheck, v8::External::New(isolate, const_cast<WrapperTypeInfo*>(&{{v8_class}}::wrapperTypeInfo))); {% endif %} - {% for attribute in attributes if attribute.runtime_enabled_function %} + {% for attribute in attributes + if attribute.runtime_enabled_function and + not attribute.per_context_enabled_function and + not attribute.is_static %} {% filter conditional(attribute.conditional_string) %} if ({{attribute.runtime_enabled_function}}()) { static const V8DOMConfiguration::AttributeConfiguration attributeConfiguration =\ {{attribute_configuration(attribute)}}; - V8DOMConfiguration::installAttribute(instanceTemplate, prototypeTemplate, attributeConfiguration, isolate, currentWorldType); + V8DOMConfiguration::installAttribute(instanceTemplate, prototypeTemplate, attributeConfiguration, isolate); } {% endfilter %} {% endfor %} {% if constants %} {{install_constants() | indent}} {% endif %} - {% for method in methods if not method.do_not_check_signature %} - {% if method.custom_signature and not method.overload_index %} - {# No custom signature needed for overloaded methods; - separate check because depends on global check for overloads #} - - // Custom Signature '{{method.name}}' - const int {{method.name}}Argc = {{method.arguments | length}}; - v8::Handle<v8::FunctionTemplate> {{method.name}}Argv[{{method.name}}Argc] = { {{method.custom_signature}} }; - v8::Handle<v8::Signature> {{method.name}}Signature = v8::Signature::New(isolate, functionTemplate, {{method.name}}Argc, {{method.name}}Argv); + {# Special operations #} + {# V8 has access-check callback API and it's used on Window instead of + deleters or enumerators; see ObjectTemplate::SetAccessCheckCallbacks. + In addition, the getter should be set on the prototype template, to get + the implementation straight out of the Window prototype, regardless of + what prototype is actually set on the object. #} + {% set set_on_template = 'PrototypeTemplate' if interface_name == 'Window' + else 'InstanceTemplate' %} + {% if indexed_property_getter %} + {# if have indexed properties, MUST have an indexed property getter #} + {% set indexed_property_getter_callback = + '%sV8Internal::indexedPropertyGetterCallback' % cpp_class %} + {% set indexed_property_setter_callback = + '%sV8Internal::indexedPropertySetterCallback' % cpp_class + if indexed_property_setter else '0' %} + {% set indexed_property_query_callback = '0' %}{# Unused #} + {% set indexed_property_deleter_callback = + '%sV8Internal::indexedPropertyDeleterCallback' % cpp_class + if indexed_property_deleter else '0' %} + {% set indexed_property_enumerator_callback = + 'indexedPropertyEnumerator<%s>' % cpp_class + if indexed_property_getter.is_enumerable else '0' %} + functionTemplate->{{set_on_template}}()->SetIndexedPropertyHandler({{indexed_property_getter_callback}}, {{indexed_property_setter_callback}}, {{indexed_property_query_callback}}, {{indexed_property_deleter_callback}}, {{indexed_property_enumerator_callback}}); + {% endif %} + {% if named_property_getter %} + {# if have named properties, MUST have a named property getter #} + {% set named_property_getter_callback = + '%sV8Internal::namedPropertyGetterCallback' % cpp_class %} + {% set named_property_setter_callback = + '%sV8Internal::namedPropertySetterCallback' % cpp_class + if named_property_setter else '0' %} + {% set named_property_query_callback = + '%sV8Internal::namedPropertyQueryCallback' % cpp_class + if named_property_getter.is_enumerable else '0' %} + {% set named_property_deleter_callback = + '%sV8Internal::namedPropertyDeleterCallback' % cpp_class + if named_property_deleter else '0' %} + {% set named_property_enumerator_callback = + '%sV8Internal::namedPropertyEnumeratorCallback' % cpp_class + if named_property_getter.is_enumerable else '0' %} + functionTemplate->{{set_on_template}}()->SetNamedPropertyHandler({{named_property_getter_callback}}, {{named_property_setter_callback}}, {{named_property_query_callback}}, {{named_property_deleter_callback}}, {{named_property_enumerator_callback}}); {% endif %} + {# End special operations #} + {% if has_custom_legacy_call_as_function %} + functionTemplate->InstanceTemplate()->SetCallAsFunctionHandler({{v8_class}}::legacyCallCustom); + {% endif %} + {% if interface_name == 'HTMLAllCollection' %} + {# Needed for legacy support of document.all #} + functionTemplate->InstanceTemplate()->MarkAsUndetectable(); + {% endif %} + {% for method in custom_registration_methods %} {# install_custom_signature #} - {% if not method.overload_index or method.overload_index == 1 %} - {# For overloaded methods, only generate one accessor #} {% filter conditional(method.conditional_string) %} + {% filter runtime_enabled(method.overloads.runtime_enabled_function_all + if method.overloads else + method.runtime_enabled_function) %} {% if method.is_do_not_check_security %} {% if method.is_per_world_bindings %} - if (currentWorldType == MainWorld) { + if (DOMWrapperWorld::current(isolate).isMainWorld()) { {{install_do_not_check_security_signature(method, 'ForMainWorld')}} } else { {{install_do_not_check_security_signature(method)}} @@ -472,40 +1009,43 @@ static v8::Handle<v8::FunctionTemplate> Configure{{v8_class}}Template(v8::Handle {% endif %} {% else %}{# is_do_not_check_security #} {% if method.is_per_world_bindings %} - if (currentWorldType == MainWorld) { - {% filter runtime_enabled(method.runtime_enabled_function) %} + if (DOMWrapperWorld::current(isolate).isMainWorld()) { {{install_custom_signature(method, 'ForMainWorld')}} - {% endfilter %} } else { - {% filter runtime_enabled(method.runtime_enabled_function) %} {{install_custom_signature(method)}} - {% endfilter %} } {% else %} - {% filter runtime_enabled(method.runtime_enabled_function) %} {{install_custom_signature(method)}} - {% endfilter %} {% endif %} {% endif %}{# is_do_not_check_security #} - {% endfilter %} - {% endif %}{# install_custom_signature #} + {% endfilter %}{# runtime_enabled() #} + {% endfilter %}{# conditional() #} {% endfor %} {% for attribute in attributes if attribute.is_static %} {% set getter_callback = '%sV8Internal::%sAttributeGetterCallback' % - (interface_name, attribute.name) %} - functionTemplate->SetNativeDataProperty(v8::String::NewFromUtf8(isolate, "{{attribute.name}}", v8::String::kInternalizedString), {{getter_callback}}, {{attribute.setter_callback}}, v8::External::New(isolate, 0), static_cast<v8::PropertyAttribute>(v8::None), v8::Handle<v8::AccessorSignature>(), static_cast<v8::AccessControl>(v8::DEFAULT)); + (cpp_class, attribute.name) %} + {% filter conditional(attribute.conditional_string) %} + functionTemplate->SetNativeDataProperty(v8AtomicString(isolate, "{{attribute.name}}"), {{getter_callback}}, {{attribute.setter_callback}}, v8::External::New(isolate, 0), static_cast<v8::PropertyAttribute>(v8::None), v8::Handle<v8::AccessorSignature>(), static_cast<v8::AccessControl>(v8::DEFAULT)); + {% endfilter %} {% endfor %} - {% if has_custom_legacy_call_as_function %} - functionTemplate->InstanceTemplate()->SetCallAsFunctionHandler({{v8_class}}::legacyCallCustom); - {% endif %} - {% if interface_name == 'HTMLAllCollection' %} - {# Needed for legacy support of document.all #} - functionTemplate->InstanceTemplate()->MarkAsUndetectable(); + {# Special interfaces #} + {% if interface_name == 'Window' %} + + prototypeTemplate->SetInternalFieldCount(V8Window::internalFieldCount); + functionTemplate->SetHiddenPrototype(true); + instanceTemplate->SetInternalFieldCount(V8Window::internalFieldCount); + // Set access check callbacks, but turned off initially. + // When a context is detached from a frame, turn on the access check. + // Turning on checks also invalidates inline caches of the object. + instanceTemplate->SetAccessCheckCallbacks(V8Window::namedSecurityCheckCustom, V8Window::indexedSecurityCheckCustom, v8::External::New(isolate, const_cast<WrapperTypeInfo*>(&V8Window::wrapperTypeInfo)), false); + {% elif interface_name in [ + 'HTMLDocument', 'DedicatedWorkerGlobalScope', + 'SharedWorkerGlobalScope', 'ServiceWorkerGlobalScope'] %} + functionTemplate->SetHiddenPrototype(true); {% endif %} // Custom toString template - functionTemplate->Set(v8::String::NewFromUtf8(isolate, "toString", v8::String::kInternalizedString), V8PerIsolateData::current()->toStringTemplate()); - return functionTemplate; + functionTemplate->Set(v8AtomicString(isolate, "toString"), V8PerIsolateData::from(isolate)->toStringTemplate()); } {% endblock %} @@ -527,7 +1067,7 @@ static v8::Handle<v8::FunctionTemplate> Configure{{v8_class}}Template(v8::Handle {% set property_attribute = 'static_cast<v8::PropertyAttribute>(%s)' % ' | '.join(method.property_attributes or ['v8::DontDelete']) %} -{{method.function_template}}->SetAccessor(v8::String::NewFromUtf8(isolate, "{{method.name}}", v8::String::kInternalizedString), {{getter_callback}}, {{setter_callback}}, v8Undefined(), v8::ALL_CAN_READ, {{property_attribute}}); +{{method.function_template}}->SetAccessor(v8AtomicString(isolate, "{{method.name}}"), {{getter_callback}}, {{setter_callback}}, v8Undefined(), v8::ALL_CAN_READ, {{property_attribute}}); {%- endmacro %} @@ -535,10 +1075,10 @@ static v8::Handle<v8::FunctionTemplate> Configure{{v8_class}}Template(v8::Handle {% macro install_custom_signature(method, world_suffix) %} {# FIXME: move to V8DOMConfiguration::installDOMCallbacksWithCustomSignature #} {% set method_callback = '%sV8Internal::%sMethodCallback%s' % - (interface_name, method.name, world_suffix) %} + (cpp_class, method.name, world_suffix) %} {% set property_attribute = 'static_cast<v8::PropertyAttribute>(%s)' % ' | '.join(method.property_attributes) %} -{{method.function_template}}->Set(v8::String::NewFromUtf8(isolate, "{{method.name}}", v8::String::kInternalizedString), v8::FunctionTemplate::New(isolate, {{method_callback}}, v8Undefined(), {{method.signature}}, {{method.number_of_required_or_variadic_arguments}}){% if method.property_attributes %}, {{property_attribute}}{% endif %}); +{{method.function_template}}->Set(v8AtomicString(isolate, "{{method.name}}"), v8::FunctionTemplate::New(isolate, {{method_callback}}, v8Undefined(), {{method.signature}}, {{method.length}}){% if method.property_attributes %}, {{property_attribute}}{% endif %}); {%- endmacro %} @@ -562,7 +1102,8 @@ if ({{constant.runtime_enabled_function}}()) { {# Check constants #} {% if not do_not_check_constants %} {% for constant in constants %} -COMPILE_ASSERT({{constant.value}} == {{cpp_class}}::{{constant.reflected_name}}, TheValueOf{{cpp_class}}_{{constant.reflected_name}}DoesntMatchWithImplementation); +{% set constant_cpp_class = constant.cpp_class or cpp_class %} +COMPILE_ASSERT({{constant.value}} == {{constant_cpp_class}}::{{constant.reflected_name}}, TheValueOf{{cpp_class}}_{{constant.reflected_name}}DoesntMatchWithImplementation); {% endfor %} {% endif %} {% endmacro %} @@ -571,36 +1112,34 @@ COMPILE_ASSERT({{constant.value}} == {{cpp_class}}::{{constant.reflected_name}}, {##############################################################################} {% block get_template %} {# FIXME: rename to get_dom_template and GetDOMTemplate #} -v8::Handle<v8::FunctionTemplate> {{v8_class}}::domTemplate(v8::Isolate* isolate, WrapperWorldType currentWorldType) +v8::Handle<v8::FunctionTemplate> {{v8_class}}::domTemplate(v8::Isolate* isolate) { - V8PerIsolateData* data = V8PerIsolateData::from(isolate); - V8PerIsolateData::TemplateMap::iterator result = data->templateMap(currentWorldType).find(&wrapperTypeInfo); - if (result != data->templateMap(currentWorldType).end()) - return result->value.newLocal(isolate); - - TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); - v8::EscapableHandleScope handleScope(isolate); - v8::Local<v8::FunctionTemplate> templ = - Configure{{v8_class}}Template(data->rawDOMTemplate(&wrapperTypeInfo, currentWorldType), isolate, currentWorldType); - data->templateMap(currentWorldType).add(&wrapperTypeInfo, UnsafePersistent<v8::FunctionTemplate>(isolate, templ)); - return handleScope.Escape(templ); + return V8DOMConfiguration::domClassTemplate(isolate, const_cast<WrapperTypeInfo*>(&wrapperTypeInfo), configure{{v8_class}}Template); } {% endblock %} {##############################################################################} -{% block has_instance_and_has_instance_in_any_world %} -bool {{v8_class}}::hasInstance(v8::Handle<v8::Value> jsValue, v8::Isolate* isolate, WrapperWorldType currentWorldType) +{% block has_instance %} +bool {{v8_class}}::hasInstance(v8::Handle<v8::Value> v8Value, v8::Isolate* isolate) +{ + return V8PerIsolateData::from(isolate)->hasInstance(&wrapperTypeInfo, v8Value); +} + +v8::Handle<v8::Object> {{v8_class}}::findInstanceInPrototypeChain(v8::Handle<v8::Value> v8Value, v8::Isolate* isolate) { - return V8PerIsolateData::from(isolate)->hasInstance(&wrapperTypeInfo, jsValue, currentWorldType); + return V8PerIsolateData::from(isolate)->findInstanceInPrototypeChain(&wrapperTypeInfo, v8Value); } -bool {{v8_class}}::hasInstanceInAnyWorld(v8::Handle<v8::Value> jsValue, v8::Isolate* isolate) +{% endblock %} + + +{##############################################################################} +{% block to_native_with_type_check %} +{{cpp_class}}* {{v8_class}}::toNativeWithTypeCheck(v8::Isolate* isolate, v8::Handle<v8::Value> value) { - return V8PerIsolateData::from(isolate)->hasInstance(&wrapperTypeInfo, jsValue, MainWorld) - || V8PerIsolateData::from(isolate)->hasInstance(&wrapperTypeInfo, jsValue, IsolatedWorld) - || V8PerIsolateData::from(isolate)->hasInstance(&wrapperTypeInfo, jsValue, WorkerWorld); + return hasInstance(value, isolate) ? fromInternalPointer(v8::Handle<v8::Object>::Cast(value)->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex)) : 0; } {% endblock %} @@ -627,16 +1166,16 @@ void {{v8_class}}::installPerContextEnabledProperties(v8::Handle<v8::Object> ins {##############################################################################} {% block install_per_context_methods %} -{% if has_per_context_enabled_methods %} +{% if per_context_enabled_methods %} void {{v8_class}}::installPerContextEnabledMethods(v8::Handle<v8::Object> prototypeTemplate, v8::Isolate* isolate) { {# Define per-context enabled operations #} - v8::Local<v8::Signature> defaultSignature = v8::Signature::New(isolate, domTemplate(isolate, worldType(isolate))); + v8::Local<v8::Signature> defaultSignature = v8::Signature::New(isolate, domTemplate(isolate)); ExecutionContext* context = toExecutionContext(prototypeTemplate->CreationContext()); - {% for method in methods if method.per_context_enabled_function %} + {% for method in per_context_enabled_methods %} if (context && context->isDocument() && {{method.per_context_enabled_function}}(toDocument(context))) - prototypeTemplate->Set(v8::String::NewFromUtf8(isolate, "{{method.name}}", v8::String::kInternalizedString), v8::FunctionTemplate::New(isolate, {{cpp_class}}V8Internal::{{method.name}}MethodCallback, v8Undefined(), defaultSignature, {{method.number_of_required_arguments}})->GetFunction()); + prototypeTemplate->Set(v8AtomicString(isolate, "{{method.name}}"), v8::FunctionTemplate::New(isolate, {{cpp_class}}V8Internal::{{method.name}}MethodCallback, v8Undefined(), defaultSignature, {{method.number_of_required_arguments}})->GetFunction()); {% endfor %} } @@ -669,8 +1208,40 @@ EventTarget* {{v8_class}}::toEventTarget(v8::Handle<v8::Object> object) {##############################################################################} +{% block get_shadow_object_template %} +{% if interface_name == 'Window' %} +v8::Handle<v8::ObjectTemplate> V8Window::getShadowObjectTemplate(v8::Isolate* isolate) +{ + if (DOMWrapperWorld::current(isolate).isMainWorld()) { + DEFINE_STATIC_LOCAL(v8::Persistent<v8::ObjectTemplate>, V8WindowShadowObjectCacheForMainWorld, ()); + if (V8WindowShadowObjectCacheForMainWorld.IsEmpty()) { + TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); + v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate); + configureShadowObjectTemplate(templ, isolate); + V8WindowShadowObjectCacheForMainWorld.Reset(isolate, templ); + return templ; + } + return v8::Local<v8::ObjectTemplate>::New(isolate, V8WindowShadowObjectCacheForMainWorld); + } else { + DEFINE_STATIC_LOCAL(v8::Persistent<v8::ObjectTemplate>, V8WindowShadowObjectCacheForNonMainWorld, ()); + if (V8WindowShadowObjectCacheForNonMainWorld.IsEmpty()) { + TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); + v8::Handle<v8::ObjectTemplate> templ = v8::ObjectTemplate::New(isolate); + configureShadowObjectTemplate(templ, isolate); + V8WindowShadowObjectCacheForNonMainWorld.Reset(isolate, templ); + return templ; + } + return v8::Local<v8::ObjectTemplate>::New(isolate, V8WindowShadowObjectCacheForNonMainWorld); + } +} + +{% endif %} +{% endblock %} + + +{##############################################################################} {% block wrap %} -{% if special_wrap_for %} +{% if special_wrap_for or is_document %} v8::Handle<v8::Object> wrap({{cpp_class}}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { ASSERT(impl); @@ -679,9 +1250,26 @@ v8::Handle<v8::Object> wrap({{cpp_class}}* impl, v8::Handle<v8::Object> creation return wrap(to{{special_wrap_interface}}(impl), creationContext, isolate); {% endfor %} v8::Handle<v8::Object> wrapper = {{v8_class}}::createWrapper(impl, creationContext, isolate); + {% if is_document %} + if (wrapper.IsEmpty()) + return wrapper; + DOMWrapperWorld& world = DOMWrapperWorld::current(isolate); + if (world.isMainWorld()) { + if (LocalFrame* frame = impl->frame()) + frame->script().windowShell(world)->updateDocumentWrapper(wrapper); + } + {% endif %} return wrapper; } +{% elif not has_custom_to_v8 and not has_custom_wrap %} +v8::Handle<v8::Object> wrap({{cpp_class}}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) +{ + ASSERT(impl); + ASSERT(!DOMDataStore::containsWrapper<{{v8_class}}>(impl, isolate)); + return {{v8_class}}::createWrapper(impl, creationContext, isolate); +} + {% endif %} {% endblock %} @@ -689,27 +1277,42 @@ v8::Handle<v8::Object> wrap({{cpp_class}}* impl, v8::Handle<v8::Object> creation {##############################################################################} {% block create_wrapper %} {% if not has_custom_to_v8 %} -v8::Handle<v8::Object> {{v8_class}}::createWrapper(PassRefPtr<{{cpp_class}}> impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) +v8::Handle<v8::Object> {{v8_class}}::createWrapper({{pass_cpp_type}} impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { ASSERT(impl); ASSERT(!DOMDataStore::containsWrapper<{{v8_class}}>(impl.get(), isolate)); if (ScriptWrappable::wrapperCanBeStoredInObject(impl.get())) { - const WrapperTypeInfo* actualInfo = ScriptWrappable::getTypeInfoFromObject(impl.get()); + const WrapperTypeInfo* actualInfo = ScriptWrappable::fromObject(impl.get())->typeInfo(); // Might be a XXXConstructor::wrapperTypeInfo instead of an XXX::wrapperTypeInfo. These will both have // the same object de-ref functions, though, so use that as the basis of the check. RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(actualInfo->derefObjectFunction == wrapperTypeInfo.derefObjectFunction); } + {% if is_document %} + if (LocalFrame* frame = impl->frame()) { + if (frame->script().initializeMainWorld()) { + // initializeMainWorld may have created a wrapper for the object, retry from the start. + v8::Handle<v8::Object> wrapper = DOMDataStore::getWrapper<{{v8_class}}>(impl.get(), isolate); + if (!wrapper.IsEmpty()) + return wrapper; + } + } + {% endif %} v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationContext, &wrapperTypeInfo, toInternalPointer(impl.get()), isolate); if (UNLIKELY(wrapper.IsEmpty())) return wrapper; + {% if is_audio_buffer %} + {# We only setDeallocationObservers on array buffers that are held by some + object in the V8 heap, not in the ArrayBuffer constructor itself. + This is because V8 GC only cares about memory it can free on GC, and + until the object is exposed to JavaScript, V8 GC doesn't affect it. #} + for (unsigned i = 0, n = impl->numberOfChannels(); i < n; i++) { + Float32Array* channelData = impl->getChannelData(i); + channelData->buffer()->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instanceTemplate()); + } + {% endif %} installPerContextEnabledProperties(wrapper, impl.get(), isolate); - {% set wrapper_configuration = 'WrapperConfiguration::Dependent' - if (has_visit_dom_wrapper or - is_active_dom_object or - is_dependent_lifetime) else - 'WrapperConfiguration::Independent' %} V8DOMWrapper::associateObjectWithWrapper<{{v8_class}}>(impl, &wrapperTypeInfo, wrapper, isolate, {{wrapper_configuration}}); return wrapper; } @@ -722,7 +1325,13 @@ v8::Handle<v8::Object> {{v8_class}}::createWrapper(PassRefPtr<{{cpp_class}}> imp {% block deref_object_and_to_v8_no_inline %} void {{v8_class}}::derefObject(void* object) { +{% if gc_type == 'RefCountedObject' %} fromInternalPointer(object)->deref(); +{% elif gc_type == 'WillBeGarbageCollectedObject' %} +{% filter conditional('!ENABLE(OILPAN)') %} + fromInternalPointer(object)->deref(); +{% endfilter %} +{% endif %} } template<> diff --git a/chromium/third_party/WebKit/Source/bindings/templates/interface.h b/chromium/third_party/WebKit/Source/bindings/templates/interface.h index 0160f37d269..653a2d42935 100644 --- a/chromium/third_party/WebKit/Source/bindings/templates/interface.h +++ b/chromium/third_party/WebKit/Source/bindings/templates/interface.h @@ -1,36 +1,8 @@ -{# http://www.chromium.org/blink/coding-style#TOC-License #} -/* - * Copyright (C) 2013 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. - */ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -{# FIXME: Rename to Python when switch #} -// This file has been auto-generated by code_generator_v8.pm. DO NOT MODIFY! +// This file has been auto-generated by {{code_generator}}. DO NOT MODIFY! #ifndef {{v8_class}}_h #define {{v8_class}}_h @@ -48,22 +20,23 @@ class Dictionary; {% if named_constructor %} class {{v8_class}}Constructor { public: - static v8::Handle<v8::FunctionTemplate> domTemplate(v8::Isolate*, WrapperWorldType); + static v8::Handle<v8::FunctionTemplate> domTemplate(v8::Isolate*); static const WrapperTypeInfo wrapperTypeInfo; }; {% endif %} class {{v8_class}} { public: - static bool hasInstance(v8::Handle<v8::Value>, v8::Isolate*, WrapperWorldType); - static bool hasInstanceInAnyWorld(v8::Handle<v8::Value>, v8::Isolate*); - static v8::Handle<v8::FunctionTemplate> domTemplate(v8::Isolate*, WrapperWorldType); + static bool hasInstance(v8::Handle<v8::Value>, v8::Isolate*); + static v8::Handle<v8::Object> findInstanceInPrototypeChain(v8::Handle<v8::Value>, v8::Isolate*); + static v8::Handle<v8::FunctionTemplate> domTemplate(v8::Isolate*); static {{cpp_class}}* toNative(v8::Handle<v8::Object> object) { return fromInternalPointer(object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex)); } - static void derefObject(void*); + static {{cpp_class}}* toNativeWithTypeCheck(v8::Isolate*, v8::Handle<v8::Value>); static const WrapperTypeInfo wrapperTypeInfo; + static void derefObject(void*); {% if has_visit_dom_wrapper %} static void visitDOMWrapper(void*, const v8::Persistent<v8::Object>&, v8::Isolate*); {% endif %} @@ -73,6 +46,9 @@ public: {% if is_event_target %} static EventTarget* toEventTarget(v8::Handle<v8::Object>); {% endif %} + {% if interface_name == 'Window' %} + static v8::Handle<v8::ObjectTemplate> getShadowObjectTemplate(v8::Isolate*); + {% endif %} {% for method in methods if method.is_custom %} {% filter conditional(method.conditional_string) %} static void {{method.name}}MethodCustom(const v8::FunctionCallbackInfo<v8::Value>&); @@ -96,16 +72,63 @@ public: {% endfilter %} {% endif %} {% endfor %} + {# Custom special operations #} + {% if indexed_property_getter and indexed_property_getter.is_custom %} + static void indexedPropertyGetterCustom(uint32_t, const v8::PropertyCallbackInfo<v8::Value>&); + {% endif %} + {% if indexed_property_setter and indexed_property_setter.is_custom %} + static void indexedPropertySetterCustom(uint32_t, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&); + {% endif %} + {% if indexed_property_deleter and indexed_property_deleter.is_custom %} + static void indexedPropertyDeleterCustom(uint32_t, const v8::PropertyCallbackInfo<v8::Boolean>&); + {% endif %} + {% if named_property_getter and named_property_getter.is_custom %} + static void namedPropertyGetterCustom(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Value>&); + {% endif %} + {% if named_property_setter and named_property_setter.is_custom %} + static void namedPropertySetterCustom(v8::Local<v8::String>, v8::Local<v8::Value>, const v8::PropertyCallbackInfo<v8::Value>&); + {% endif %} + {% if named_property_getter and + named_property_getter.is_custom_property_query %} + static void namedPropertyQueryCustom(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Integer>&); + {% endif %} + {% if named_property_deleter and named_property_deleter.is_custom %} + static void namedPropertyDeleterCustom(v8::Local<v8::String>, const v8::PropertyCallbackInfo<v8::Boolean>&); + {% endif %} + {% if named_property_getter and + named_property_getter.is_custom_property_enumerator %} + static void namedPropertyEnumeratorCustom(const v8::PropertyCallbackInfo<v8::Array>&); + {% endif %} + {# END custom special operations #} {% if has_custom_legacy_call_as_function %} static void legacyCallCustom(const v8::FunctionCallbackInfo<v8::Value>&); {% endif %} + {# Custom internal fields #} {% set custom_internal_field_counter = 0 %} {% if is_event_target and not is_node %} {# Event listeners on DOM nodes are explicitly supported in the GC controller. #} - static const int eventListenerCacheIndex = v8DefaultWrapperInternalFieldCount + 0; + static const int eventListenerCacheIndex = v8DefaultWrapperInternalFieldCount + {{custom_internal_field_counter}}; {% set custom_internal_field_counter = custom_internal_field_counter + 1 %} {% endif %} + {# persistentHandleIndex must be the last field, if it is present. + Detailed explanation: https://codereview.chromium.org/139173012 + FIXME: Remove this internal field, and share one field for either: + * a persistent handle (if the object is in oilpan) or + * a C++ pointer to the DOM object (if the object is not in oilpan) #} + {% if gc_type == 'GarbageCollectedObject' %} + static const int persistentHandleIndex = v8DefaultWrapperInternalFieldCount + {{custom_internal_field_counter}}; + static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + {{custom_internal_field_counter}} + 1; + {% elif gc_type == 'WillBeGarbageCollectedObject' %} +#if ENABLE(OILPAN) + static const int persistentHandleIndex = v8DefaultWrapperInternalFieldCount + {{custom_internal_field_counter}}; + static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + {{custom_internal_field_counter}} + 1; +#else static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + {{custom_internal_field_counter}}; +#endif + {% else %} + static const int internalFieldCount = v8DefaultWrapperInternalFieldCount + {{custom_internal_field_counter}}; + {% endif %} + {# End custom internal fields #} static inline void* toInternalPointer({{cpp_class}}* impl) { {% if parent_interface %} @@ -123,26 +146,38 @@ public: return static_cast<{{cpp_class}}*>(object); {% endif %} } + {% if interface_name == 'Window' %} + static bool namedSecurityCheckCustom(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType, v8::Local<v8::Value> data); + static bool indexedSecurityCheckCustom(v8::Local<v8::Object> host, uint32_t index, v8::AccessType, v8::Local<v8::Value> data); + {% endif %} static void installPerContextEnabledProperties(v8::Handle<v8::Object>, {{cpp_class}}*, v8::Isolate*){% if has_per_context_enabled_attributes %}; {% else %} { } {% endif %} - static void installPerContextEnabledMethods(v8::Handle<v8::Object>, v8::Isolate*){% if has_per_context_enabled_attributes %}; + static void installPerContextEnabledMethods(v8::Handle<v8::Object>, v8::Isolate*){% if per_context_enabled_methods %}; {% else %} { } {% endif %} + {# Element wrappers #} + {% if interface_name == 'HTMLElement' %} + friend v8::Handle<v8::Object> createV8HTMLWrapper(HTMLElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*); + friend v8::Handle<v8::Object> createV8HTMLDirectWrapper(HTMLElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*); + {% elif interface_name == 'SVGElement' %} + friend v8::Handle<v8::Object> createV8SVGWrapper(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*); + friend v8::Handle<v8::Object> createV8SVGDirectWrapper(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*); + friend v8::Handle<v8::Object> createV8SVGFallbackWrapper(SVGElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*); + {% elif interface_name == 'HTMLUnknownElement' %} + friend v8::Handle<v8::Object> createV8HTMLFallbackWrapper(HTMLUnknownElement*, v8::Handle<v8::Object> creationContext, v8::Isolate*); + {% elif interface_name == 'Element' %} + // This is a performance optimization hack. See V8Element::wrap. + friend v8::Handle<v8::Object> wrap(Node*, v8::Handle<v8::Object> creationContext, v8::Isolate*); + {% endif %} private: {% if not has_custom_to_v8 %} friend v8::Handle<v8::Object> wrap({{cpp_class}}*, v8::Handle<v8::Object> creationContext, v8::Isolate*); - static v8::Handle<v8::Object> createWrapper(PassRefPtr<{{cpp_class}}>, v8::Handle<v8::Object> creationContext, v8::Isolate*); + static v8::Handle<v8::Object> createWrapper({{pass_cpp_type}}, v8::Handle<v8::Object> creationContext, v8::Isolate*); {% endif %} }; -template<> -class WrapperTypeTraits<{{cpp_class}} > { -public: - static const WrapperTypeInfo* wrapperTypeInfo() { return &{{v8_class}}::wrapperTypeInfo; } -}; - {% if has_custom_to_v8 %} class {{cpp_class}}; v8::Handle<v8::Value> toV8({{cpp_class}}*, v8::Handle<v8::Object> creationContext, v8::Isolate*); @@ -165,16 +200,7 @@ inline void v8SetReturnValueFast(const CallbackInfo& callbackInfo, {{cpp_class}} v8SetReturnValue(callbackInfo, toV8(impl, callbackInfo.Holder(), callbackInfo.GetIsolate())); } {% else %}{# has_custom_to_v8 #} -{% if has_custom_wrap or special_wrap_for %} v8::Handle<v8::Object> wrap({{cpp_class}}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate*); -{% else %} -inline v8::Handle<v8::Object> wrap({{cpp_class}}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) -{ - ASSERT(impl); - ASSERT(!DOMDataStore::containsWrapper<{{v8_class}}>(impl, isolate)); - return {{v8_class}}::createWrapper(impl, creationContext, isolate); -} -{% endif %} inline v8::Handle<v8::Value> toV8({{cpp_class}}* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { @@ -202,7 +228,7 @@ inline void v8SetReturnValue(const CallbackInfo& callbackInfo, {{cpp_class}}* im template<typename CallbackInfo> inline void v8SetReturnValueForMainWorld(const CallbackInfo& callbackInfo, {{cpp_class}}* impl) { - ASSERT(worldType(callbackInfo.GetIsolate()) == MainWorld); + ASSERT(DOMWrapperWorld::current(callbackInfo.GetIsolate()).isMainWorld()); if (UNLIKELY(!impl)) { v8SetReturnValueNull(callbackInfo); return; @@ -227,31 +253,31 @@ inline void v8SetReturnValueFast(const CallbackInfo& callbackInfo, {{cpp_class}} } {% endif %}{# has_custom_to_v8 #} -inline v8::Handle<v8::Value> toV8(PassRefPtr<{{cpp_class}} > impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) +inline v8::Handle<v8::Value> toV8({{pass_cpp_type}} impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { return toV8(impl.get(), creationContext, isolate); } template<class CallbackInfo> -inline void v8SetReturnValue(const CallbackInfo& callbackInfo, PassRefPtr<{{cpp_class}} > impl) +inline void v8SetReturnValue(const CallbackInfo& callbackInfo, {{pass_cpp_type}} impl) { v8SetReturnValue(callbackInfo, impl.get()); } template<class CallbackInfo> -inline void v8SetReturnValueForMainWorld(const CallbackInfo& callbackInfo, PassRefPtr<{{cpp_class}} > impl) +inline void v8SetReturnValueForMainWorld(const CallbackInfo& callbackInfo, {{pass_cpp_type}} impl) { v8SetReturnValueForMainWorld(callbackInfo, impl.get()); } template<class CallbackInfo, class Wrappable> -inline void v8SetReturnValueFast(const CallbackInfo& callbackInfo, PassRefPtr<{{cpp_class}} > impl, Wrappable* wrappable) +inline void v8SetReturnValueFast(const CallbackInfo& callbackInfo, {{pass_cpp_type}} impl, Wrappable* wrappable) { v8SetReturnValueFast(callbackInfo, impl.get(), wrappable); } {% if has_event_constructor %} -bool initialize{{cpp_class}}({{cpp_class}}Init&, const Dictionary&, ExceptionState&, const String& = ""); +bool initialize{{cpp_class}}({{cpp_class}}Init&, const Dictionary&, ExceptionState&, const v8::FunctionCallbackInfo<v8::Value>& info, const String& = ""); {% endif %} } diff --git a/chromium/third_party/WebKit/Source/bindings/templates/interface_base.cpp b/chromium/third_party/WebKit/Source/bindings/templates/interface_base.cpp index 0751bfacf87..dce2cc91b85 100644 --- a/chromium/third_party/WebKit/Source/bindings/templates/interface_base.cpp +++ b/chromium/third_party/WebKit/Source/bindings/templates/interface_base.cpp @@ -1,42 +1,14 @@ -{# http://www.chromium.org/blink/coding-style#TOC-License #} -/* - * Copyright (C) 2013 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. - */ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. -{# FIXME: Rename to Python when switch #} -// This file has been auto-generated by code_generator_v8.pm. DO NOT MODIFY! +// This file has been auto-generated by {{code_generator}}. DO NOT MODIFY! #include "config.h" {% filter conditional(conditional_string) %} #include "{{v8_class}}.h" -{% for filename in cpp_includes %} +{% for filename in cpp_includes if filename != '%s.h' % v8_class %} #include "{{filename}}" {% endfor %} @@ -45,17 +17,21 @@ namespace WebCore { static void initializeScriptWrappableForInterface({{cpp_class}}* object) { if (ScriptWrappable::wrapperCanBeStoredInObject(object)) - ScriptWrappable::setTypeInfoInObject(object, &{{v8_class}}::wrapperTypeInfo); + ScriptWrappable::fromObject(object)->setTypeInfo(&{{v8_class}}::wrapperTypeInfo); else ASSERT_NOT_REACHED(); } } // namespace WebCore -// In ScriptWrappable::init, the use of a local function declaration has an issue on Windows: -// the local declaration does not pick up the surrounding namespace. Therefore, we provide this function -// in the global namespace. -// (More info on the MSVC bug here: http://connect.microsoft.com/VisualStudio/feedback/details/664619/the-namespace-of-local-function-declarations-in-c) +{# +In ScriptWrappable::init, the use of a local function declaration has an +issue on Windows: the local declaration does not pick up the surrounding +namespace. Therefore, we provide this function in the global namespace. +More info on the MSVC bug here (Bug 664619): +The namespace of local function declarations in C++ by Uray M. János +http://connect.microsoft.com/VisualStudio/feedback/details/664619/the-namespace-of-local-function-declarations-in-c +#} void webCoreInitializeScriptWrappableForInterface(WebCore::{{cpp_class}}* object) { WebCore::initializeScriptWrappableForInterface(object); @@ -70,14 +46,17 @@ namespace WebCore { if has_visit_dom_wrapper else '0' %} {% set parent_wrapper_type_info = '&V8%s::wrapperTypeInfo' % parent_interface if parent_interface else '0' %} -const WrapperTypeInfo {{v8_class}}::wrapperTypeInfo = { gin::kEmbedderBlink, {{v8_class}}::domTemplate, {{v8_class}}::derefObject, {{to_active_dom_object}}, {{to_event_target}}, {{visit_dom_wrapper}}, {{v8_class}}::installPerContextEnabledMethods, {{parent_wrapper_type_info}}, WrapperTypeObjectPrototype }; +{% set wrapper_type_prototype = 'WrapperTypeExceptionPrototype' if is_exception else + 'WrapperTypeObjectPrototype' %} +const WrapperTypeInfo {{v8_class}}::wrapperTypeInfo = { gin::kEmbedderBlink, {{v8_class}}::domTemplate, {{v8_class}}::derefObject, {{to_active_dom_object}}, {{to_event_target}}, {{visit_dom_wrapper}}, {{v8_class}}::installPerContextEnabledMethods, {{parent_wrapper_type_info}}, {{wrapper_type_prototype}}, {{gc_type}} }; namespace {{cpp_class}}V8Internal { template <typename T> void V8_USE(T) { } {# Attributes #} -{% from 'attributes.cpp' import attribute_getter, attribute_getter_callback, +{% from 'attributes.cpp' import constructor_getter_callback, + attribute_getter, attribute_getter_callback, attribute_setter, attribute_setter_callback with context %} {% for attribute in attributes if not attribute.constructor_type %} @@ -86,7 +65,7 @@ template <typename T> void V8_USE(T) { } {{attribute_getter(attribute, world_suffix)}} {% endif %} {{attribute_getter_callback(attribute, world_suffix)}} -{% if not attribute.is_read_only %} +{% if not attribute.is_read_only or attribute.put_forwards %} {% if not attribute.has_custom_setter %} {{attribute_setter(attribute, world_suffix)}} {% endif %} @@ -95,6 +74,11 @@ template <typename T> void V8_USE(T) { } {% endfor %} {% endfor %} {% block constructor_getter %}{% endblock %} +{% for attribute in attributes if attribute.needs_constructor_getter_callback %} +{% for world_suffix in attribute.world_suffixes %} +{{constructor_getter_callback(attribute, world_suffix)}} +{% endfor %} +{% endfor %} {% block replaceable_attribute_setter_and_callback %}{% endblock %} {% block security_check_functions %}{% endblock %} {# Methods #} @@ -125,22 +109,43 @@ template <typename T> void V8_USE(T) { } {% endfor %} {% block overloaded_constructor %}{% endblock %} {% block event_constructor %}{% endblock %} +{# Special operations (methods) #} +{% block indexed_property_getter %}{% endblock %} +{% block indexed_property_getter_callback %}{% endblock %} +{% block indexed_property_setter %}{% endblock %} +{% block indexed_property_setter_callback %}{% endblock %} +{% block indexed_property_deleter %}{% endblock %} +{% block indexed_property_deleter_callback %}{% endblock %} +{% block named_property_getter %}{% endblock %} +{% block named_property_getter_callback %}{% endblock %} +{% block named_property_setter %}{% endblock %} +{% block named_property_setter_callback %}{% endblock %} +{% block named_property_query %}{% endblock %} +{% block named_property_query_callback %}{% endblock %} +{% block named_property_deleter %}{% endblock %} +{% block named_property_deleter_callback %}{% endblock %} +{% block named_property_enumerator %}{% endblock %} +{% block named_property_enumerator_callback %}{% endblock %} } // namespace {{cpp_class}}V8Internal {% block visit_dom_wrapper %}{% endblock %} +{% block shadow_attributes %}{% endblock %} {% block class_attributes %}{% endblock %} {% block class_accessors %}{% endblock %} {% block class_methods %}{% endblock %} {% block named_constructor %}{% endblock %} {% block initialize_event %}{% endblock %} {% block constructor_callback %}{% endblock %} +{% block configure_shadow_object_template %}{% endblock %} {% block configure_class_template %}{% endblock %} {% block get_template %}{% endblock %} -{% block has_instance_and_has_instance_in_any_world %}{% endblock %} +{% block has_instance %}{% endblock %} +{% block to_native_with_type_check %}{% endblock %} {% block install_per_context_attributes %}{% endblock %} {% block install_per_context_methods %}{% endblock %} {% block to_active_dom_object %}{% endblock %} {% block to_event_target %}{% endblock %} +{% block get_shadow_object_template %}{% endblock %} {% block wrap %}{% endblock %} {% block create_wrapper %}{% endblock %} {% block deref_object_and_to_v8_no_inline %}{% endblock %} diff --git a/chromium/third_party/WebKit/Source/bindings/templates/methods.cpp b/chromium/third_party/WebKit/Source/bindings/templates/methods.cpp index f534272324c..4a44e7228dc 100644 --- a/chromium/third_party/WebKit/Source/bindings/templates/methods.cpp +++ b/chromium/third_party/WebKit/Source/bindings/templates/methods.cpp @@ -3,139 +3,225 @@ {% filter conditional(method.conditional_string) %} static void {{method.name}}{{method.overload_index}}Method{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>& info) { - {% if method.is_raises_exception or method.is_check_security_for_frame or - method.name in ['addEventListener', 'removeEventListener'] %} + {# Local variables #} + {% if method.has_exception_state %} ExceptionState exceptionState(ExceptionState::ExecutionContext, "{{method.name}}", "{{interface_name}}", info.Holder(), info.GetIsolate()); {% endif %} - {% if method.name in ['addEventListener', 'removeEventListener'] %} - {{add_remove_event_listener_method(method.name) | indent}} - {% else %} - {% if method.number_of_required_arguments %} + {# Overloaded methods have length checked during overload resolution #} + {% if method.number_of_required_arguments and not method.overload_index %} if (UNLIKELY(info.Length() < {{method.number_of_required_arguments}})) { - {{throw_type_error(method, - 'ExceptionMessages::notEnoughArguments(%s, info.Length())' % - method.number_of_required_arguments)}} + {{throw_minimum_arity_type_error(method, method.number_of_required_arguments)}}; return; } {% endif %} {% if not method.is_static %} - {{cpp_class}}* imp = {{v8_class}}::toNative(info.Holder()); + {{cpp_class}}* impl = {{v8_class}}::toNative(info.Holder()); {% endif %} {% if method.is_custom_element_callbacks %} CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope; {% endif %} - {% if method.is_check_security_for_frame %} - if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame(), exceptionState)) { - exceptionState.throwIfNeeded(); + {# Security checks #} + {# FIXME: change to method.is_check_security_for_window #} + {% if interface_name == 'EventTarget' %} + if (LocalDOMWindow* window = impl->toDOMWindow()) { + if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), window->frame(), exceptionState)) { + {{throw_from_exception_state(method)}}; + return; + } + if (!window->document()) + return; + } + {% elif method.is_check_security_for_frame %} + if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), impl->frame(), exceptionState)) { + {{throw_from_exception_state(method)}}; return; } {% endif %} {% if method.is_check_security_for_node %} - if (!BindingSecurity::shouldAllowAccessToNode(imp->{{method.name}}(exceptionState), exceptionState)) { + if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), impl->{{method.name}}(exceptionState), exceptionState)) { v8SetReturnValueNull(info); - exceptionState.throwIfNeeded(); + {{throw_from_exception_state(method)}}; return; } {% endif %} - {% for argument in method.arguments %} - {{generate_argument(method, argument) | indent}} - {% endfor %} + {# Call method #} + {% if method.arguments %} + {{generate_arguments(method, world_suffix) | indent}} + {% endif %} + {% if world_suffix %} + {{cpp_method_call(method, method.v8_set_return_value_for_main_world, method.cpp_value) | indent}} + {% else %} {{cpp_method_call(method, method.v8_set_return_value, method.cpp_value) | indent}} - {% endif %}{# addEventListener, removeEventListener #} + {% endif %} + {# Post-call #} + {% if method.has_event_listener_argument %} + {{hidden_dependency_action(method.name) | indent}} + {% endif %} } {% endfilter %} {% endmacro %} {######################################} -{% macro add_remove_event_listener_method(method_name) %} -{# Set template values for addEventListener vs. removeEventListener #} -{% set listener_lookup_type, listener, hidden_dependency_action = - ('ListenerFindOrCreate', 'listener', 'createHiddenDependency') - if method_name == 'addEventListener' else - ('ListenerFindOnly', 'listener.get()', 'removeHiddenDependency') -%} -EventTarget* impl = {{v8_class}}::toNative(info.Holder()); -if (DOMWindow* window = impl->toDOMWindow()) { - if (!BindingSecurity::shouldAllowAccessToFrame(window->frame(), exceptionState)) { - exceptionState.throwIfNeeded(); - return; - } - if (!window->document()) - return; -} -RefPtr<EventListener> listener = V8EventListenerList::getEventListener(info[1], false, {{listener_lookup_type}}); -if (listener) { - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, eventName, info[0]); - impl->{{method_name}}(eventName, {{listener}}, info[2]->BooleanValue()); - if (!impl->toNode()) - {{hidden_dependency_action}}(info.Holder(), info[1], {{v8_class}}::eventListenerCacheIndex, info.GetIsolate()); +{% macro hidden_dependency_action(method_name) %} +if (listener && !impl->toNode()) + {% if method_name == 'addEventListener' %} + addHiddenValueToArray(info.Holder(), info[1], {{v8_class}}::eventListenerCacheIndex, info.GetIsolate()); + {% else %}{# method_name == 'removeEventListener' #} + removeHiddenValueFromArray(info.Holder(), info[1], {{v8_class}}::eventListenerCacheIndex, info.GetIsolate()); + {% endif %} +{% endmacro %} + + +{######################################} +{% macro generate_arguments(method, world_suffix) %} +{% for argument in method.arguments %} +{{generate_argument_var_declaration(argument)}}; +{% endfor %} +{ + {% if method.arguments_need_try_catch %} + v8::TryCatch block; + V8RethrowTryCatchScope rethrow(block); + {% endif %} + {% for argument in method.arguments %} + {{generate_argument(method, argument, world_suffix) | indent}} + {% endfor %} } {% endmacro %} {######################################} -{% macro generate_argument(method, argument) %} +{% macro generate_argument_var_declaration(argument) %} +{% if argument.is_callback_interface %} +{# FIXME: remove EventListener special case #} +{% if argument.idl_type == 'EventListener' %} +RefPtr<{{argument.idl_type}}> {{argument.name}} +{%- else %} +OwnPtr<{{argument.idl_type}}> {{argument.name}} +{%- endif %}{# argument.idl_type == 'EventListener' #} +{%- elif argument.is_clamp %}{# argument.is_callback_interface #} +{# NaN is treated as 0: http://www.w3.org/TR/WebIDL/#es-type-mapping #} +{{argument.cpp_type}} {{argument.name}} = 0 +{%- else %} +{{argument.cpp_type}} {{argument.name}} +{%- endif %} +{% endmacro %} + + +{######################################} +{% macro generate_argument(method, argument, world_suffix) %} {% if argument.is_optional and not argument.has_default and - argument.idl_type != 'Dictionary' %} + argument.idl_type != 'Dictionary' and + not argument.is_callback_interface %} {# Optional arguments without a default value generate an early call with fewer arguments if they are omitted. Optional Dictionary arguments default to empty dictionary. #} if (UNLIKELY(info.Length() <= {{argument.index}})) { + {% if world_suffix %} + {{cpp_method_call(method, argument.v8_set_return_value_for_main_world, argument.cpp_value) | indent}} + {% else %} {{cpp_method_call(method, argument.v8_set_return_value, argument.cpp_value) | indent}} + {% endif %} + {% if argument.has_event_listener_argument %} + {{hidden_dependency_action(method.name) | indent}} + {% endif %} return; } {% endif %} -{% if method.is_strict_type_checking and argument.is_wrapper_type %} +{% if argument.has_type_checking_interface %} {# Type checking for wrapper interface types (if interface not implemented, - throw TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #} -if (info.Length() > {{argument.index}} && !isUndefinedOrNull(info[{{argument.index}}]) && !V8{{argument.idl_type}}::hasInstance(info[{{argument.index}}], info.GetIsolate(), worldType(info.GetIsolate()))) { + throw a TypeError), per http://www.w3.org/TR/WebIDL/#es-interface #} +if (info.Length() > {{argument.index}} && {% if argument.is_nullable %}!isUndefinedOrNull(info[{{argument.index}}]) && {% endif %}!V8{{argument.idl_type}}::hasInstance(info[{{argument.index}}], info.GetIsolate())) { {{throw_type_error(method, '"parameter %s is not of type \'%s\'."' % - (argument.index + 1, argument.idl_type))}} + (argument.index + 1, argument.idl_type)) | indent}} return; } -{% endif %} -{% if argument.is_clamp %} +{% endif %}{# argument.has_type_checking_interface #} +{% if argument.is_callback_interface %} +{# FIXME: remove EventListener special case #} +{% if argument.idl_type == 'EventListener' %} +{% if method.name == 'removeEventListener' %} +{{argument.name}} = V8EventListenerList::getEventListener(ScriptState::current(info.GetIsolate()), info[1], false, ListenerFindOnly); +{% else %}{# method.name == 'addEventListener' #} +{{argument.name}} = V8EventListenerList::getEventListener(ScriptState::current(info.GetIsolate()), info[1], false, ListenerFindOrCreate); +{% endif %}{# method.name #} +{% else %}{# argument.idl_type == 'EventListener' #} +{# Callback functions must be functions: + http://www.w3.org/TR/WebIDL/#es-callback-function #} +{% if argument.is_optional %} +if (info.Length() > {{argument.index}} && !isUndefinedOrNull(info[{{argument.index}}])) { + if (!info[{{argument.index}}]->IsFunction()) { + {{throw_type_error(method, + '"The callback provided as parameter %s is not a function."' % + (argument.index + 1)) | indent(8)}} + return; + } + {{argument.name}} = V8{{argument.idl_type}}::create(v8::Handle<v8::Function>::Cast(info[{{argument.index}}]), ScriptState::current(info.GetIsolate())); +} +{% else %}{# argument.is_optional #} +if (info.Length() <= {{argument.index}} || !{% if argument.is_nullable %}(info[{{argument.index}}]->IsFunction() || info[{{argument.index}}]->IsNull()){% else %}info[{{argument.index}}]->IsFunction(){% endif %}) { + {{throw_type_error(method, + '"The callback provided as parameter %s is not a function."' % + (argument.index + 1)) | indent }} + return; +} +{{argument.name}} = {% if argument.is_nullable %}info[{{argument.index}}]->IsNull() ? nullptr : {% endif %}V8{{argument.idl_type}}::create(v8::Handle<v8::Function>::Cast(info[{{argument.index}}]), ScriptState::current(info.GetIsolate())); +{% endif %}{# argument.is_optional #} +{% endif %}{# argument.idl_type == 'EventListener' #} +{% elif argument.is_clamp %}{# argument.is_callback_interface #} {# NaN is treated as 0: http://www.w3.org/TR/WebIDL/#es-type-mapping #} -{{argument.cpp_type}} {{argument.name}} = 0; -V8TRYCATCH_VOID(double, {{argument.name}}NativeValue, info[{{argument.index}}]->NumberValue()); +double {{argument.name}}NativeValue; +TONATIVE_VOID_INTERNAL({{argument.name}}NativeValue, info[{{argument.index}}]->NumberValue()); if (!std::isnan({{argument.name}}NativeValue)) {# IDL type is used for clamping, for the right bounds, since different IDL integer types have same internal C++ type (int or unsigned) #} {{argument.name}} = clampTo<{{argument.idl_type}}>({{argument.name}}NativeValue); {% elif argument.idl_type == 'SerializedScriptValue' %} -{% set did_throw = argument.name + 'DidThrow' %} -bool {{did_throw}} = false; -{{argument.cpp_type}} {{argument.name}} = SerializedScriptValue::create(info[{{argument.index}}], 0, 0, {{did_throw}}, info.GetIsolate()); -if ({{did_throw}}) +{{argument.name}} = SerializedScriptValue::create(info[{{argument.index}}], 0, 0, exceptionState, info.GetIsolate()); +if (exceptionState.hadException()) { + {{throw_from_exception_state(method)}}; return; +} {% elif argument.is_variadic_wrapper_type %} -Vector<{{argument.cpp_type}} > {{argument.name}}; for (int i = {{argument.index}}; i < info.Length(); ++i) { - if (!V8{{argument.idl_type}}::hasInstance(info[i], info.GetIsolate(), worldType(info.GetIsolate()))) { + if (!V8{{argument.idl_type}}::hasInstance(info[i], info.GetIsolate())) { {{throw_type_error(method, '"parameter %s is not of type \'%s\'."' % - (argument.index + 1, argument.idl_type))}} + (argument.index + 1, argument.idl_type)) | indent(8)}} return; } {{argument.name}}.append(V8{{argument.idl_type}}::toNative(v8::Handle<v8::Object>::Cast(info[i]))); } -{% else %} +{% else %}{# argument.is_nullable #} {{argument.v8_value_to_local_cpp_value}}; -{% endif %} -{% if argument.enum_validation_expression %} -{# Methods throw on invalid enum values: http://www.w3.org/TR/WebIDL/#idl-enums #} +{% endif %}{# argument.is_nullable #} +{# Type checking, possibly throw a TypeError, per: + http://www.w3.org/TR/WebIDL/#es-type-mapping #} +{% if argument.has_type_checking_unrestricted %} +{# Non-finite floating point values (NaN, +Infinity or −Infinity), per: + http://heycam.github.io/webidl/#es-float + http://heycam.github.io/webidl/#es-double #} +if (!std::isfinite({{argument.name}})) { + {{throw_type_error(method, '"%s parameter %s is non-finite."' % + (argument.idl_type, argument.index + 1)) | indent}} + return; +} +{% elif argument.enum_validation_expression %} +{# Invalid enum values: http://www.w3.org/TR/WebIDL/#idl-enums #} String string = {{argument.name}}; if (!({{argument.enum_validation_expression}})) { {{throw_type_error(method, '"parameter %s (\'" + string + "\') is not a valid enum value."' % - (argument.index + 1))}} + (argument.index + 1)) | indent}} return; } -{% endif %} -{% if argument.idl_type in ['Dictionary', 'Promise'] %} +{% elif argument.idl_type in ['Dictionary', 'Promise'] %} +{# Dictionaries must have type Undefined, Null or Object: +http://heycam.github.io/webidl/#es-dictionary +We also require this for our implementation of promises, though not in spec: +http://heycam.github.io/webidl/#es-promise #} if (!{{argument.name}}.isUndefinedOrNull() && !{{argument.name}}.isObject()) { {{throw_type_error(method, '"parameter %s (\'%s\') is not an object."' % - (argument.index + 1, argument.name))}} + (argument.index + 1, argument.name)) | indent}} return; } {% endif %} @@ -144,46 +230,102 @@ if (!{{argument.name}}.isUndefinedOrNull() && !{{argument.name}}.isObject()) { {######################################} {% macro cpp_method_call(method, v8_set_return_value, cpp_value) %} +{# Local variables #} {% if method.is_call_with_script_state %} -ScriptState* currentState = ScriptState::current(); -if (!currentState) - return; -ScriptState& state = *currentState; +ScriptState* scriptState = ScriptState::current(info.GetIsolate()); {% endif %} {% if method.is_call_with_execution_context %} -ExecutionContext* scriptContext = getExecutionContext(); +ExecutionContext* executionContext = currentExecutionContext(info.GetIsolate()); {% endif %} {% if method.is_call_with_script_arguments %} -RefPtr<ScriptArguments> scriptArguments(createScriptArguments(info, {{method.number_of_arguments}})); +RefPtrWillBeRawPtr<ScriptArguments> scriptArguments(createScriptArguments(scriptState, info, {{method.number_of_arguments}})); {% endif %} +{# Call #} {% if method.idl_type == 'void' %} {{cpp_value}}; -{% elif method.is_call_with_script_state %} +{% elif method.is_constructor %} +{{method.cpp_type}} impl = {{cpp_value}}; +{% elif method.is_call_with_script_state or method.is_raises_exception %} {# FIXME: consider always using a local variable #} {{method.cpp_type}} result = {{cpp_value}}; {% endif %} +{# Post-call #} {% if method.is_raises_exception %} -if (exceptionState.throwIfNeeded()) - return; -{% endif %} -{% if method.is_call_with_script_state %} -if (state.hadException()) { - v8::Local<v8::Value> exception = state.exception(); - state.clearException(); - throwError(exception, info.GetIsolate()); +if (exceptionState.hadException()) { + {{throw_from_exception_state(method)}}; return; } {% endif %} -{% if v8_set_return_value %}{{v8_set_return_value}};{% endif %}{# None for void #} +{# Set return value #} +{% if method.is_constructor %} +{{generate_constructor_wrapper(method)}}{% elif method.union_arguments %} +{{union_type_method_call_and_set_return_value(method)}} +{% elif v8_set_return_value %}{{v8_set_return_value}};{% endif %}{# None for void #} {% endmacro %} {######################################} +{% macro union_type_method_call_and_set_return_value(method) %} +{% for cpp_type in method.cpp_type %} +bool result{{loop.index0}}Enabled = false; +{{cpp_type}} result{{loop.index0}}; +{% endfor %} +{{method.cpp_value}}; +{% if method.is_null_expression %}{# used by getters #} +if ({{method.is_null_expression}}) + return; +{% endif %} +{% for v8_set_return_value in method.v8_set_return_value %} +if (result{{loop.index0}}Enabled) { + {{v8_set_return_value}}; + return; +} +{% endfor %} +{# Fall back to null if none of the union members results are returned #} +v8SetReturnValueNull(info); +{%- endmacro %} + + +{######################################} {% macro throw_type_error(method, error_message) %} -{% if method.is_constructor %} +{% if method.has_exception_state %} +exceptionState.throwTypeError({{error_message}}); +{{throw_from_exception_state(method)}}; +{% elif method.is_constructor %} throwTypeError(ExceptionMessages::failedToConstruct("{{interface_name}}", {{error_message}}), info.GetIsolate()); -{%- else %} +{% else %}{# method.has_exception_state #} throwTypeError(ExceptionMessages::failedToExecute("{{method.name}}", "{{interface_name}}", {{error_message}}), info.GetIsolate()); +{% endif %}{# method.has_exception_state #} +{% endmacro %} + + +{######################################} +{# FIXME: return a rejected Promise if method.idl_type == 'Promise' #} +{% macro throw_from_exception_state(method) %} +exceptionState.throwIfNeeded() +{%- endmacro %} + + +{######################################} +{% macro throw_arity_type_error(method, valid_arities) %} +{% if method.has_exception_state %} +throwArityTypeError(exceptionState, {{valid_arities}}, info.Length()) +{%- elif method.is_constructor %} +throwArityTypeErrorForConstructor("{{interface_name}}", {{valid_arities}}, info.Length(), info.GetIsolate()) +{%- else %} +throwArityTypeErrorForMethod("{{method.name}}", "{{interface_name}}", {{valid_arities}}, info.Length(), info.GetIsolate()) +{%- endif %} +{% endmacro %} + + +{######################################} +{% macro throw_minimum_arity_type_error(method, number_of_required_arguments) %} +{% if method.has_exception_state %} +throwMinimumArityTypeError(exceptionState, {{number_of_required_arguments}}, info.Length()) +{%- elif method.is_constructor %} +throwMinimumArityTypeErrorForConstructor("{{interface_name}}", {{number_of_required_arguments}}, info.Length(), info.GetIsolate()) +{%- else %} +throwMinimumArityTypeErrorForMethod("{{method.name}}", "{{interface_name}}", {{number_of_required_arguments}}, info.Length(), info.GetIsolate()) {%- endif %} {% endmacro %} @@ -192,24 +334,56 @@ throwTypeError(ExceptionMessages::failedToExecute("{{method.name}}", "{{interfac {% macro overload_resolution_method(overloads, world_suffix) %} static void {{overloads.name}}Method{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>& info) { - {% for method in overloads.methods %} - if ({{method.overload_resolution_expression}}) { - {{method.name}}{{method.overload_index}}Method{{world_suffix}}(info); - return; - } + v8::Isolate* isolate = info.GetIsolate(); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "{{overloads.name}}", "{{interface_name}}", info.Holder(), isolate); + {% if overloads.measure_all_as %} + UseCounter::count(callingExecutionContext(isolate), UseCounter::{{overloads.measure_all_as}}); + {% endif %} + {% if overloads.deprecate_all_as %} + UseCounter::countDeprecation(callingExecutionContext(isolate), UseCounter::{{overloads.deprecate_all_as}}); + {% endif %} + {# First resolve by length #} + {# 2. Initialize argcount to be min(maxarg, n). #} + switch (std::min({{overloads.maxarg}}, info.Length())) { + {# 3. Remove from S all entries whose type list is not of length argcount. #} + {% for length, tests_methods in overloads.length_tests_methods %} + {# 10. If i = d, then: #} + case {{length}}: + {# Then resolve by testing argument #} + {% for test, method in tests_methods %} + {% filter runtime_enabled(not overloads.runtime_enabled_function_all and + method.runtime_enabled_function) %} + if ({{test}}) { + {% if method.measure_as and not overloads.measure_all_as %} + UseCounter::count(callingExecutionContext(isolate), UseCounter::{{method.measure_as}}); + {% endif %} + {% if method.deprecate_as and not overloads.deprecate_all_as %} + UseCounter::countDeprecation(callingExecutionContext(isolate), UseCounter::{{method.deprecate_as}}); + {% endif %} + {{method.name}}{{method.overload_index}}Method{{world_suffix}}(info); + return; + } + {% endfilter %} + {% endfor %} + break; {% endfor %} - {% if overloads.minimum_number_of_required_arguments %} - ExceptionState exceptionState(ExceptionState::ExecutionContext, "{{overloads.name}}", "{{interface_name}}", info.Holder(), info.GetIsolate()); - if (UNLIKELY(info.Length() < {{overloads.minimum_number_of_required_arguments}})) { - exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments({{overloads.minimum_number_of_required_arguments}}, info.Length())); + default: + {# Invalid arity, throw error #} + {# Report full list of valid arities if gaps and above minimum #} + {% if overloads.valid_arities %} + if (info.Length() >= {{overloads.minarg}}) { + throwArityTypeError(exceptionState, "{{overloads.valid_arities}}", info.Length()); + return; + } + {% endif %} + {# Otherwise just report "not enough arguments" #} + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments({{overloads.minarg}}, info.Length())); exceptionState.throwIfNeeded(); return; } + {# No match, throw error #} exceptionState.throwTypeError("No function was found that matched the signature provided."); exceptionState.throwIfNeeded(); - {% else %} - {{throw_type_error(overloads, '"No function was found that matched the signature provided."')}} - {% endif %} } {% endmacro %} @@ -220,19 +394,26 @@ static void {{overloads.name}}Method{{world_suffix}}(const v8::FunctionCallbackI static void {{method.name}}MethodCallback{{world_suffix}}(const v8::FunctionCallbackInfo<v8::Value>& info) { TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMMethod"); + {% if not method.overloads %}{# Overloaded methods are measured in overload_resolution_method() #} {% if method.measure_as %} - UseCounter::count(activeDOMWindow(), UseCounter::{{method.measure_as}}); + UseCounter::count(callingExecutionContext(info.GetIsolate()), UseCounter::{{method.measure_as}}); {% endif %} {% if method.deprecate_as %} - UseCounter::countDeprecation(activeExecutionContext(), UseCounter::{{method.deprecate_as}}); + UseCounter::countDeprecation(callingExecutionContext(info.GetIsolate()), UseCounter::{{method.deprecate_as}}); {% endif %} + {% endif %}{# not method.overloads #} {% if world_suffix in method.activity_logging_world_list %} - V8PerContextData* contextData = V8PerContextData::from(info.GetIsolate()->GetCurrentContext()); + ScriptState* scriptState = ScriptState::from(info.GetIsolate()->GetCurrentContext()); + V8PerContextData* contextData = scriptState->perContextData(); + {% if method.activity_logging_world_check %} + if (scriptState->world().isIsolatedWorld() && contextData && contextData->activityLogger()) + {% else %} if (contextData && contextData->activityLogger()) { + {% endif %} {# FIXME: replace toVectorOfArguments with toNativeArguments(info, 0) and delete toVectorOfArguments #} Vector<v8::Handle<v8::Value> > loggerArgs = toNativeArguments<v8::Handle<v8::Value> >(info, 0); - contextData->activityLogger()->log("{{interface_name}}.{{method.name}}", info.Length(), loggerArgs.data(), "Method"); + contextData->activityLogger()->logMethod("{{interface_name}}.{{method.name}}", info.Length(), loggerArgs.data()); } {% endif %} {% if method.is_custom %} @@ -240,7 +421,7 @@ static void {{method.name}}MethodCallback{{world_suffix}}(const v8::FunctionCall {% else %} {{cpp_class}}V8Internal::{{method.name}}Method{{world_suffix}}(info); {% endif %} - TRACE_EVENT_SET_SAMPLING_STATE("V8", "Execution"); + TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution"); } {% endfilter %} {% endmacro %} @@ -250,30 +431,32 @@ static void {{method.name}}MethodCallback{{world_suffix}}(const v8::FunctionCall {% macro origin_safe_method_getter(method, world_suffix) %} static void {{method.name}}OriginSafeMethodGetter{{world_suffix}}(const v8::PropertyCallbackInfo<v8::Value>& info) { - {# FIXME: don't call GetIsolate() so often #} - // This is only for getting a unique pointer which we can pass to privateTemplate. - static int privateTemplateUniqueKey; - WrapperWorldType currentWorldType = worldType(info.GetIsolate()); - V8PerIsolateData* data = V8PerIsolateData::from(info.GetIsolate()); + {% set signature = 'v8::Local<v8::Signature>()' + if method.is_do_not_check_signature else + 'v8::Signature::New(isolate, %s::domTemplate(isolate))' % v8_class %} + v8::Isolate* isolate = info.GetIsolate(); + static int domTemplateKey; // This address is used for a key to look up the dom template. + V8PerIsolateData* data = V8PerIsolateData::from(isolate); {# FIXME: 1 case of [DoNotCheckSignature] in Window.idl may differ #} - v8::Handle<v8::FunctionTemplate> privateTemplate = data->privateTemplate(currentWorldType, &privateTemplateUniqueKey, {{cpp_class}}V8Internal::{{method.name}}MethodCallback{{world_suffix}}, v8Undefined(), v8::Signature::New(info.GetIsolate(), V8PerIsolateData::from(info.GetIsolate())->rawDOMTemplate(&{{v8_class}}::wrapperTypeInfo, currentWorldType)), {{method.number_of_required_or_variadic_arguments}}); + v8::Handle<v8::FunctionTemplate> privateTemplate = data->domTemplate(&domTemplateKey, {{cpp_class}}V8Internal::{{method.name}}MethodCallback{{world_suffix}}, v8Undefined(), {{signature}}, {{method.length}}); - v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain({{v8_class}}::domTemplate(info.GetIsolate(), currentWorldType)); + v8::Handle<v8::Object> holder = {{v8_class}}::findInstanceInPrototypeChain(info.This(), isolate); if (holder.IsEmpty()) { // This is only reachable via |object.__proto__.func|, in which case it // has already passed the same origin security check v8SetReturnValue(info, privateTemplate->GetFunction()); return; } - {{cpp_class}}* imp = {{v8_class}}::toNative(holder); - if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame(), DoNotReportSecurityError)) { - static int sharedTemplateUniqueKey; - v8::Handle<v8::FunctionTemplate> sharedTemplate = data->privateTemplate(currentWorldType, &sharedTemplateUniqueKey, {{cpp_class}}V8Internal::{{method.name}}MethodCallback{{world_suffix}}, v8Undefined(), v8::Signature::New(info.GetIsolate(), V8PerIsolateData::from(info.GetIsolate())->rawDOMTemplate(&{{v8_class}}::wrapperTypeInfo, currentWorldType)), {{method.number_of_required_or_variadic_arguments}}); + {{cpp_class}}* impl = {{v8_class}}::toNative(holder); + if (!BindingSecurity::shouldAllowAccessToFrame(isolate, impl->frame(), DoNotReportSecurityError)) { + static int sharedTemplateKey; // This address is used for a key to look up the dom template. + v8::Handle<v8::FunctionTemplate> sharedTemplate = data->domTemplate(&sharedTemplateKey, {{cpp_class}}V8Internal::{{method.name}}MethodCallback{{world_suffix}}, v8Undefined(), {{signature}}, {{method.length}}); v8SetReturnValue(info, sharedTemplate->GetFunction()); return; } - v8::Local<v8::Value> hiddenValue = info.This()->GetHiddenValue(v8::String::NewFromUtf8(info.GetIsolate(), "{{method.name}}", v8::String::kInternalizedString)); + {# The findInstanceInPrototypeChain() call above only returns a non-empty handle if info.This() is an Object. #} + v8::Local<v8::Value> hiddenValue = v8::Handle<v8::Object>::Cast(info.This())->GetHiddenValue(v8AtomicString(isolate, "{{method.name}}")); if (!hiddenValue.IsEmpty()) { v8SetReturnValue(info, hiddenValue); return; @@ -286,7 +469,7 @@ static void {{method.name}}OriginSafeMethodGetterCallback{{world_suffix}}(v8::Lo { TRACE_EVENT_SET_SAMPLING_STATE("Blink", "DOMGetter"); {{cpp_class}}V8Internal::{{method.name}}OriginSafeMethodGetter{{world_suffix}}(info); - TRACE_EVENT_SET_SAMPLING_STATE("V8", "Execution"); + TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8Execution"); } {% endmacro %} @@ -295,69 +478,94 @@ static void {{method.name}}OriginSafeMethodGetterCallback{{world_suffix}}(v8::Lo {% macro generate_constructor(constructor) %} static void constructor{{constructor.overload_index}}(const v8::FunctionCallbackInfo<v8::Value>& info) { + v8::Isolate* isolate = info.GetIsolate(); + {% if constructor.has_exception_state %} + ExceptionState exceptionState(ExceptionState::ConstructionContext, "{{interface_name}}", info.Holder(), isolate); + {% endif %} + {# Overloaded constructors have length checked during overload resolution #} {% if interface_length and not constructor.overload_index %} - {# FIXME: remove this UNLIKELY: constructors are heavy, so no difference. #} + {# FIXME: remove UNLIKELY: constructors are expensive, so no difference. #} if (UNLIKELY(info.Length() < {{interface_length}})) { - {{throw_type_error({'name': 'Constructor'}, - 'ExceptionMessages::notEnoughArguments(%s, info.Length())' % - interface_length)}} + {{throw_minimum_arity_type_error(constructor, interface_length)}}; return; } {% endif %} - {% if is_constructor_raises_exception %} - ExceptionState exceptionState(ExceptionState::ConstructionContext, "{{interface_name}}", info.Holder(), info.GetIsolate()); + {% if constructor.arguments %} + {{generate_arguments(constructor) | indent}} {% endif %} - {% for argument in constructor.arguments %} - {{generate_argument(constructor, argument) | indent}} - {% endfor %} {% if is_constructor_call_with_execution_context %} - ExecutionContext* context = getExecutionContext(); + ExecutionContext* executionContext = currentExecutionContext(isolate); {% endif %} {% if is_constructor_call_with_document %} - Document& document = *toDocument(getExecutionContext()); + Document& document = *toDocument(currentExecutionContext(isolate)); {% endif %} - RefPtr<{{cpp_class}}> impl = {{cpp_class}}::create({{constructor.argument_list | join(', ')}}); - v8::Handle<v8::Object> wrapper = info.Holder(); + {{constructor.cpp_type}} impl = {{constructor.cpp_value}}; {% if is_constructor_raises_exception %} if (exceptionState.throwIfNeeded()) return; {% endif %} - {# FIXME: Should probably be Independent unless [ActiveDOMObject] - or [DependentLifetime]. #} - V8DOMWrapper::associateObjectWithWrapper<{{v8_class}}>(impl.release(), &{{v8_class}}::wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent); - v8SetReturnValue(info, wrapper); + {{generate_constructor_wrapper(constructor) | indent}} } {% endmacro %} {##############################################################################} +{% macro generate_constructor_wrapper(constructor) %} +{% if has_custom_wrap %} +v8::Handle<v8::Object> wrapper = wrap(impl.get(), info.Holder(), isolate); +{% else %} +{% set constructor_class = v8_class + ('Constructor' + if constructor.is_named_constructor else + '') %} +v8::Handle<v8::Object> wrapper = info.Holder(); +V8DOMWrapper::associateObjectWithWrapper<{{v8_class}}>(impl.release(), &{{constructor_class}}::wrapperTypeInfo, wrapper, isolate, {{wrapper_configuration}}); +{% endif %} +v8SetReturnValue(info, wrapper); +{% endmacro %} + + +{##############################################################################} {% macro named_constructor_callback(constructor) %} static void {{v8_class}}ConstructorCallback(const v8::FunctionCallbackInfo<v8::Value>& info) { + v8::Isolate* isolate = info.GetIsolate(); if (!info.IsConstructCall()) { - throwTypeError(ExceptionMessages::failedToConstruct("{{constructor.name}}", "Please use the 'new' operator, this DOM object constructor cannot be called as a function."), info.GetIsolate()); + throwTypeError(ExceptionMessages::constructorNotCallableAsFunction("{{constructor.name}}"), isolate); return; } - if (ConstructorMode::current() == ConstructorMode::WrapExistingObject) { + if (ConstructorMode::current(isolate) == ConstructorMode::WrapExistingObject) { v8SetReturnValue(info, info.Holder()); return; } - Document* document = currentDocument(); - ASSERT(document); + Document* documentPtr = currentDOMWindow(isolate)->document(); + ASSERT(documentPtr); + Document& document = *documentPtr; // Make sure the document is added to the DOM Node map. Otherwise, the {{cpp_class}} instance // may end up being the only node in the map and get garbage-collected prematurely. - toV8(document, info.Holder(), info.GetIsolate()); + toV8(documentPtr, info.Holder(), isolate); - {# FIXME: arguments #} - {% set argument_list = ['*document'] %} - RefPtr<{{cpp_class}}> impl = {{cpp_class}}::createForJSConstructor({{argument_list | join(', ')}}); - v8::Handle<v8::Object> wrapper = info.Holder(); + {% if constructor.has_exception_state %} + ExceptionState exceptionState(ExceptionState::ConstructionContext, "{{interface_name}}", info.Holder(), isolate); + {% endif %} + {% if constructor.number_of_required_arguments %} + if (UNLIKELY(info.Length() < {{constructor.number_of_required_arguments}})) { + {{throw_minimum_arity_type_error(constructor, constructor.number_of_required_arguments)}}; + return; + } + {% endif %} + {% if constructor.arguments %} + {{generate_arguments(constructor) | indent}} + {% endif %} + {{constructor.cpp_type}} impl = {{constructor.cpp_value}}; + {% if is_constructor_raises_exception %} + if (exceptionState.throwIfNeeded()) + return; + {% endif %} - V8DOMWrapper::associateObjectWithWrapper<{{v8_class}}>(impl.release(), &{{v8_class}}Constructor::wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent); - v8SetReturnValue(info, wrapper); + {{generate_constructor_wrapper(constructor) | indent}} } {% endmacro %} diff --git a/chromium/third_party/WebKit/Source/bindings/templates/templates.gni b/chromium/third_party/WebKit/Source/bindings/templates/templates.gni new file mode 100644 index 00000000000..133c5065329 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/templates/templates.gni @@ -0,0 +1,17 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# Paths should be absolute so this file can be imported from anywhere. +code_generator_template_files = + get_path_info( + [ + "attributes.cpp", + "callback_interface.cpp", + "callback_interface.h", + "interface_base.cpp", + "interface.cpp", + "interface.h", + "methods.cpp", + ], + "abspath") diff --git a/chromium/third_party/WebKit/Source/bindings/templates/templates.gypi b/chromium/third_party/WebKit/Source/bindings/templates/templates.gypi new file mode 100644 index 00000000000..a019fab8d28 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/templates/templates.gypi @@ -0,0 +1,17 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + 'code_generator_template_files': [ + 'attributes.cpp', + 'callback_interface.cpp', + 'callback_interface.h', + 'interface_base.cpp', + 'interface.cpp', + 'interface.h', + 'methods.cpp', + ], + }, +} diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ArrayValue.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ArrayValue.cpp index 1280548b9f6..065fd2f8815 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ArrayValue.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ArrayValue.cpp @@ -62,7 +62,7 @@ bool ArrayValue::get(size_t index, Dictionary& value) const ASSERT(m_isolate); ASSERT(m_isolate == v8::Isolate::GetCurrent()); - v8::Local<v8::Value> indexedValue = m_array->Get(v8::Integer::NewFromUnsigned(index, m_isolate)); + v8::Local<v8::Value> indexedValue = m_array->Get(v8::Integer::NewFromUnsigned(m_isolate, index)); if (indexedValue.IsEmpty() || !indexedValue->IsObject()) return false; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/BindingSecurity.cpp b/chromium/third_party/WebKit/Source/bindings/v8/BindingSecurity.cpp index 7f9db62257d..126b2ba6519 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/BindingSecurity.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/BindingSecurity.cpp @@ -34,65 +34,69 @@ #include "bindings/v8/V8Binding.h" #include "core/dom/Document.h" #include "core/html/HTMLFrameElementBase.h" -#include "core/frame/DOMWindow.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" #include "platform/weborigin/SecurityOrigin.h" namespace WebCore { -static bool isDocumentAccessibleFromDOMWindow(Document* targetDocument, DOMWindow* activeWindow) +static bool isDocumentAccessibleFromDOMWindow(Document* targetDocument, LocalDOMWindow* callingWindow) { if (!targetDocument) return false; - if (!activeWindow) + if (!callingWindow) return false; - if (activeWindow->document()->securityOrigin()->canAccess(targetDocument->securityOrigin())) + if (callingWindow->document()->securityOrigin()->canAccess(targetDocument->securityOrigin())) return true; return false; } -static bool canAccessDocument(Document* targetDocument, ExceptionState& exceptionState) +static bool canAccessDocument(v8::Isolate* isolate, Document* targetDocument, ExceptionState& exceptionState) { - DOMWindow* activeWindow = activeDOMWindow(); - if (isDocumentAccessibleFromDOMWindow(targetDocument, activeWindow)) + LocalDOMWindow* callingWindow = callingDOMWindow(isolate); + if (isDocumentAccessibleFromDOMWindow(targetDocument, callingWindow)) return true; if (targetDocument->domWindow()) - exceptionState.throwSecurityError(targetDocument->domWindow()->sanitizedCrossDomainAccessErrorMessage(activeWindow), targetDocument->domWindow()->crossDomainAccessErrorMessage(activeWindow)); + exceptionState.throwSecurityError(targetDocument->domWindow()->sanitizedCrossDomainAccessErrorMessage(callingWindow), targetDocument->domWindow()->crossDomainAccessErrorMessage(callingWindow)); return false; } -static bool canAccessDocument(Document* targetDocument, SecurityReportingOption reportingOption = ReportSecurityError) +static bool canAccessDocument(v8::Isolate* isolate, Document* targetDocument, SecurityReportingOption reportingOption = ReportSecurityError) { - DOMWindow* activeWindow = activeDOMWindow(); - if (isDocumentAccessibleFromDOMWindow(targetDocument, activeWindow)) + LocalDOMWindow* callingWindow = callingDOMWindow(isolate); + if (isDocumentAccessibleFromDOMWindow(targetDocument, callingWindow)) return true; if (reportingOption == ReportSecurityError && targetDocument->domWindow()) { - if (Frame* frame = targetDocument->frame()) - frame->domWindow()->printErrorMessage(targetDocument->domWindow()->crossDomainAccessErrorMessage(activeWindow)); + if (LocalFrame* frame = targetDocument->frame()) + frame->domWindow()->printErrorMessage(targetDocument->domWindow()->crossDomainAccessErrorMessage(callingWindow)); } return false; } -bool BindingSecurity::shouldAllowAccessToFrame(Frame* target, SecurityReportingOption reportingOption) +bool BindingSecurity::shouldAllowAccessToFrame(v8::Isolate* isolate, Frame* target, SecurityReportingOption reportingOption) { - return target && canAccessDocument(target->document(), reportingOption); + if (!target || !target->isLocalFrame()) + return false; + return canAccessDocument(isolate, toLocalFrame(target)->document(), reportingOption); } -bool BindingSecurity::shouldAllowAccessToFrame(Frame* target, ExceptionState& exceptionState) +bool BindingSecurity::shouldAllowAccessToFrame(v8::Isolate* isolate, Frame* target, ExceptionState& exceptionState) { - return target && canAccessDocument(target->document(), exceptionState); + if (!target || !target->isLocalFrame()) + return false; + return canAccessDocument(isolate, toLocalFrame(target)->document(), exceptionState); } -bool BindingSecurity::shouldAllowAccessToNode(Node* target, ExceptionState& exceptionState) +bool BindingSecurity::shouldAllowAccessToNode(v8::Isolate* isolate, Node* target, ExceptionState& exceptionState) { - return target && canAccessDocument(&target->document(), exceptionState); + return target && canAccessDocument(isolate, &target->document(), exceptionState); } } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/BindingSecurity.h b/chromium/third_party/WebKit/Source/bindings/v8/BindingSecurity.h index 253a7f25781..b6e5bba893d 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/BindingSecurity.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/BindingSecurity.h @@ -31,13 +31,15 @@ #ifndef BindingSecurity_h #define BindingSecurity_h +// FIXME: The LocalFrame include should not be necessary, clients should be including it where they use it. +#include "core/frame/LocalFrame.h" #include "wtf/text/WTFString.h" +#include <v8.h> namespace WebCore { -class DOMWindow; +class LocalDOMWindow; class ExceptionState; -class Frame; class Node; enum SecurityReportingOption { @@ -47,9 +49,9 @@ enum SecurityReportingOption { class BindingSecurity { public: - static bool shouldAllowAccessToNode(Node*, ExceptionState&); - static bool shouldAllowAccessToFrame(Frame*, SecurityReportingOption = ReportSecurityError); - static bool shouldAllowAccessToFrame(Frame*, ExceptionState&); + static bool shouldAllowAccessToNode(v8::Isolate*, Node*, ExceptionState&); + static bool shouldAllowAccessToFrame(v8::Isolate*, Frame*, SecurityReportingOption = ReportSecurityError); + static bool shouldAllowAccessToFrame(v8::Isolate*, Frame*, ExceptionState&); }; } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/CallbackPromiseAdapter.h b/chromium/third_party/WebKit/Source/bindings/v8/CallbackPromiseAdapter.h index 19b5a543918..21719792209 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/CallbackPromiseAdapter.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/CallbackPromiseAdapter.h @@ -31,8 +31,7 @@ #ifndef CallbackPromiseAdapter_h #define CallbackPromiseAdapter_h -#include "bindings/v8/DOMRequestState.h" -#include "bindings/v8/ScriptPromiseResolver.h" +#include "bindings/v8/ScriptPromiseResolverWithContext.h" #include "public/platform/WebCallbacks.h" namespace WebCore { @@ -40,16 +39,25 @@ namespace WebCore { // This class provides an easy way to convert from a Script-exposed // class (i.e. a class that has a toV8() overload) that uses Promises // to a WebKit API class that uses WebCallbacks. You can define -// seperate Success and Error classes, but this example just uses one +// separate Success and Error classes, but this example just uses one // object for both. // // To use: // // class MyClass ... { // typedef blink::WebMyClass WebType; -// static PassRefPtr<MyClass> from(blink::WebMyClass* webInstance) { +// static PassRefPtr<MyClass> from(ScriptPromiseResolverWithContext* resolver, +// blink::WebMyClass* webInstance) { // // convert/create as appropriate, but often it's just: // return MyClass::create(adoptPtr(webInstance)); +// +// // Since promise resolving is done as an async task, it's not +// // guaranteed that the script context has seen the promise resolve +// // immediately after calling onSuccess/onError. You can use the +// // ScriptPromise from the resolver to schedule a task that executes +// // after resolving: +// ScriptState::Scope scope(resolver->scriptState()); +// resolver->promise().then(...); // } // // Now when calling into a WebKit API that requires a WebCallbacks<blink::WebMyClass, blink::WebMyClass>*: @@ -61,28 +69,24 @@ namespace WebCore { // example that ownership of the WebCallbacks instance is being passed // in and it is up to the callee to free the WebCallbacks instace. template<typename S, typename T> -class CallbackPromiseAdapter : public blink::WebCallbacks<typename S::WebType, typename T::WebType> { +class CallbackPromiseAdapter FINAL : public blink::WebCallbacks<typename S::WebType, typename T::WebType> { public: - explicit CallbackPromiseAdapter(PassRefPtr<ScriptPromiseResolver> resolver, ExecutionContext* context) + CallbackPromiseAdapter(PassRefPtr<ScriptPromiseResolverWithContext> resolver) : m_resolver(resolver) - , m_requestState(context) { } virtual ~CallbackPromiseAdapter() { } virtual void onSuccess(typename S::WebType* result) OVERRIDE { - DOMRequestState::Scope scope(m_requestState); - m_resolver->resolve(S::from(result)); + m_resolver->resolve(S::from(m_resolver.get(), result)); } - void onError(typename T::WebType* error) OVERRIDE + virtual void onError(typename T::WebType* error) OVERRIDE { - DOMRequestState::Scope scope(m_requestState); - m_resolver->reject(T::from(error)); + m_resolver->reject(T::from(m_resolver.get(), error)); } private: - RefPtr<ScriptPromiseResolver> m_resolver; - DOMRequestState m_requestState; + RefPtr<ScriptPromiseResolverWithContext> m_resolver; WTF_MAKE_NONCOPYABLE(CallbackPromiseAdapter); }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementBinding.cpp b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementBinding.cpp index 25ba61792f3..7a692394496 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementBinding.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementBinding.cpp @@ -43,7 +43,7 @@ CustomElementBinding::CustomElementBinding(v8::Isolate* isolate, v8::Handle<v8:: , m_prototype(isolate, prototype) , m_wrapperType(wrapperType) { - ASSERT(m_prototype.value()); + ASSERT(!m_prototype.isEmpty()); ASSERT(m_wrapperType); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementBinding.h b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementBinding.h index 3fa394a0b09..b989e361823 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementBinding.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementBinding.h @@ -31,7 +31,7 @@ #ifndef CustomElementBinding_h #define CustomElementBinding_h -#include "bindings/v8/UnsafePersistent.h" +#include "bindings/v8/ScopedPersistent.h" #include "wtf/PassOwnPtr.h" #include <v8.h> @@ -43,7 +43,7 @@ class CustomElementBinding { public: static PassOwnPtr<CustomElementBinding> create(v8::Isolate*, v8::Handle<v8::Object> prototype, const WrapperTypeInfo*); - ~CustomElementBinding() { m_prototype.dispose(); } + ~CustomElementBinding() { } v8::Handle<v8::Object> prototype() { return m_prototype.newLocal(m_isolate); } const WrapperTypeInfo* wrapperType() { return m_wrapperType; } @@ -52,7 +52,7 @@ private: CustomElementBinding(v8::Isolate*, v8::Handle<v8::Object> prototype, const WrapperTypeInfo*); v8::Isolate* m_isolate; - UnsafePersistent<v8::Object> m_prototype; + ScopedPersistent<v8::Object> m_prototype; const WrapperTypeInfo* m_wrapperType; }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.cpp b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.cpp index b13466635ae..a8e43a1012e 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.cpp @@ -31,20 +31,18 @@ #include "config.h" #include "bindings/v8/CustomElementConstructorBuilder.h" -#include "HTMLNames.h" -#include "SVGNames.h" -#include "V8Document.h" -#include "V8HTMLElementWrapperFactory.h" -#include "V8SVGElementWrapperFactory.h" +#include "bindings/core/v8/V8Document.h" #include "bindings/v8/CustomElementBinding.h" #include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/Dictionary.h" #include "bindings/v8/ExceptionState.h" -#include "bindings/v8/ScriptState.h" -#include "bindings/v8/UnsafePersistent.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "bindings/v8/V8PerContextData.h" +#include "core/HTMLNames.h" +#include "core/SVGNames.h" +#include "core/V8HTMLElementWrapperFactory.h" // FIXME: should be bindings/core/v8 +#include "core/V8SVGElementWrapperFactory.h" // FIXME: should be bindings/core/v8 #include "core/dom/Document.h" #include "core/dom/custom/CustomElementCallbackDispatcher.h" #include "core/dom/custom/CustomElementDefinition.h" @@ -56,44 +54,58 @@ namespace WebCore { static void constructCustomElement(const v8::FunctionCallbackInfo<v8::Value>&); -CustomElementConstructorBuilder::CustomElementConstructorBuilder(ScriptState* state, const Dictionary* options) - : m_context(state->context()) +CustomElementConstructorBuilder::CustomElementConstructorBuilder(ScriptState* scriptState, const Dictionary* options) + : m_scriptState(scriptState) , m_options(options) , m_wrapperType(0) { - ASSERT(m_context == v8::Isolate::GetCurrent()->GetCurrentContext()); + ASSERT(m_scriptState->context() == m_scriptState->isolate()->GetCurrentContext()); } bool CustomElementConstructorBuilder::isFeatureAllowed() const { - // Check that we are in the main world - return !DOMWrapperWorld::isolatedWorld(m_context); + return m_scriptState->world().isMainWorld(); } bool CustomElementConstructorBuilder::validateOptions(const AtomicString& type, QualifiedName& tagName, ExceptionState& exceptionState) { ASSERT(m_prototype.IsEmpty()); + v8::TryCatch tryCatch; + ScriptValue prototypeScriptValue; if (m_options->get("prototype", prototypeScriptValue) && !prototypeScriptValue.isNull()) { + ASSERT(!tryCatch.HasCaught()); if (!prototypeScriptValue.isObject()) { CustomElementException::throwException(CustomElementException::PrototypeNotAnObject, type, exceptionState); + tryCatch.ReThrow(); return false; } m_prototype = prototypeScriptValue.v8Value().As<v8::Object>(); - } else { - m_prototype = v8::Object::New(); - v8::Local<v8::Object> basePrototype = V8PerContextData::from(m_context)->prototypeForType(&V8HTMLElement::wrapperTypeInfo); + } else if (!tryCatch.HasCaught()) { + m_prototype = v8::Object::New(m_scriptState->isolate()); + v8::Local<v8::Object> basePrototype = m_scriptState->perContextData()->prototypeForType(&V8HTMLElement::wrapperTypeInfo); if (!basePrototype.IsEmpty()) m_prototype->SetPrototype(basePrototype); } - String extends; + if (tryCatch.HasCaught()) { + tryCatch.ReThrow(); + return false; + } + + AtomicString extends; bool extendsProvidedAndNonNull = m_options->get("extends", extends); - if (!V8PerContextData::from(m_context)) { + if (tryCatch.HasCaught()) { + tryCatch.ReThrow(); + return false; + } + + if (!m_scriptState->perContextData()) { // FIXME: This should generate an InvalidContext exception at a later point. CustomElementException::throwException(CustomElementException::ContextDestroyedCheckingPrototype, type, exceptionState); + tryCatch.ReThrow(); return false; } @@ -101,6 +113,8 @@ bool CustomElementConstructorBuilder::validateOptions(const AtomicString& type, if (hasValidPrototypeChainFor(&V8SVGElement::wrapperTypeInfo)) namespaceURI = SVGNames::svgNamespaceURI; + ASSERT(!tryCatch.HasCaught()); + AtomicString localName; if (extendsProvidedAndNonNull) { @@ -108,15 +122,18 @@ bool CustomElementConstructorBuilder::validateOptions(const AtomicString& type, if (!Document::isValidName(localName)) { CustomElementException::throwException(CustomElementException::ExtendsIsInvalidName, type, exceptionState); + tryCatch.ReThrow(); return false; } if (CustomElement::isValidName(localName)) { CustomElementException::throwException(CustomElementException::ExtendsIsCustomElementName, type, exceptionState); + tryCatch.ReThrow(); return false; } } else { if (namespaceURI == SVGNames::svgNamespaceURI) { CustomElementException::throwException(CustomElementException::ExtendsIsInvalidName, type, exceptionState); + tryCatch.ReThrow(); return false; } localName = type; @@ -129,6 +146,7 @@ bool CustomElementConstructorBuilder::validateOptions(const AtomicString& type, else m_wrapperType = findWrapperTypeForSVGTagName(localName); + ASSERT(!tryCatch.HasCaught()); ASSERT(m_wrapperType); tagName = QualifiedName(nullAtom, localName, namespaceURI); return m_wrapperType; @@ -138,18 +156,16 @@ PassRefPtr<CustomElementLifecycleCallbacks> CustomElementConstructorBuilder::cre { ASSERT(!m_prototype.IsEmpty()); - RefPtr<ExecutionContext> executionContext(toExecutionContext(m_context)); - v8::TryCatch exceptionCatcher; exceptionCatcher.SetVerbose(true); - v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Isolate* isolate = m_scriptState->isolate(); v8::Handle<v8::Function> created = retrieveCallback(isolate, "createdCallback"); v8::Handle<v8::Function> attached = retrieveCallback(isolate, "attachedCallback"); v8::Handle<v8::Function> detached = retrieveCallback(isolate, "detachedCallback"); v8::Handle<v8::Function> attributeChanged = retrieveCallback(isolate, "attributeChangedCallback"); - m_callbacks = V8CustomElementLifecycleCallbacks::create(executionContext.get(), m_prototype, created, attached, detached, attributeChanged); + m_callbacks = V8CustomElementLifecycleCallbacks::create(m_scriptState.get(), m_prototype, created, attached, detached, attributeChanged); return m_callbacks.get(); } @@ -167,7 +183,7 @@ bool CustomElementConstructorBuilder::createConstructor(Document* document, Cust ASSERT(m_constructor.IsEmpty()); ASSERT(document); - v8::Isolate* isolate = m_context->GetIsolate(); + v8::Isolate* isolate = m_scriptState->isolate(); if (!prototypeIsValid(definition->descriptor().type(), exceptionState)) return false; @@ -191,10 +207,10 @@ bool CustomElementConstructorBuilder::createConstructor(Document* document, Cust m_constructor->SetName(v8Type->IsNull() ? v8TagName : v8Type.As<v8::String>()); - V8HiddenPropertyName::setNamedHiddenReference(m_constructor, "customElementDocument", toV8(document, m_context->Global(), isolate)); - V8HiddenPropertyName::setNamedHiddenReference(m_constructor, "customElementNamespaceURI", v8String(isolate, descriptor.namespaceURI())); - V8HiddenPropertyName::setNamedHiddenReference(m_constructor, "customElementTagName", v8TagName); - V8HiddenPropertyName::setNamedHiddenReference(m_constructor, "customElementType", v8Type); + V8HiddenValue::setHiddenValue(isolate, m_constructor, V8HiddenValue::customElementDocument(isolate), toV8(document, m_scriptState->context()->Global(), isolate)); + V8HiddenValue::setHiddenValue(isolate, m_constructor, V8HiddenValue::customElementNamespaceURI(isolate), v8String(isolate, descriptor.namespaceURI())); + V8HiddenValue::setHiddenValue(isolate, m_constructor, V8HiddenValue::customElementTagName(isolate), v8TagName); + V8HiddenValue::setHiddenValue(isolate, m_constructor, V8HiddenValue::customElementType(isolate), v8Type); v8::Handle<v8::String> prototypeKey = v8String(isolate, "prototype"); ASSERT(m_constructor->HasOwnProperty(prototypeKey)); @@ -207,7 +223,7 @@ bool CustomElementConstructorBuilder::createConstructor(Document* document, Cust // property. m_constructor->ForceSet(prototypeKey, m_prototype, v8::PropertyAttribute(v8::ReadOnly | v8::DontEnum | v8::DontDelete)); - V8HiddenPropertyName::setNamedHiddenReference(m_prototype, "customElementIsInterfacePrototypeObject", v8::True(isolate)); + V8HiddenValue::setHiddenValue(isolate, m_prototype, V8HiddenValue::customElementIsInterfacePrototypeObject(isolate), v8::True(isolate)); m_prototype->ForceSet(v8String(isolate, "constructor"), m_constructor, v8::DontEnum); return true; @@ -215,12 +231,12 @@ bool CustomElementConstructorBuilder::createConstructor(Document* document, Cust bool CustomElementConstructorBuilder::prototypeIsValid(const AtomicString& type, ExceptionState& exceptionState) const { - if (m_prototype->InternalFieldCount() || !m_prototype->GetHiddenValue(V8HiddenPropertyName::customElementIsInterfacePrototypeObject(m_context->GetIsolate())).IsEmpty()) { + if (m_prototype->InternalFieldCount() || !V8HiddenValue::getHiddenValue(m_scriptState->isolate(), m_prototype, V8HiddenValue::customElementIsInterfacePrototypeObject(m_scriptState->isolate())).IsEmpty()) { CustomElementException::throwException(CustomElementException::PrototypeInUse, type, exceptionState); return false; } - if (m_prototype->GetPropertyAttributes(v8String(m_context->GetIsolate(), "constructor")) & v8::DontDelete) { + if (m_prototype->GetPropertyAttributes(v8String(m_scriptState->isolate(), "constructor")) & v8::DontDelete) { CustomElementException::throwException(CustomElementException::ConstructorPropertyNotConfigurable, type, exceptionState); return false; } @@ -232,17 +248,17 @@ bool CustomElementConstructorBuilder::didRegisterDefinition(CustomElementDefinit { ASSERT(!m_constructor.IsEmpty()); - return m_callbacks->setBinding(definition, CustomElementBinding::create(m_context->GetIsolate(), m_prototype, m_wrapperType)); + return m_callbacks->setBinding(definition, CustomElementBinding::create(m_scriptState->isolate(), m_prototype, m_wrapperType)); } ScriptValue CustomElementConstructorBuilder::bindingsReturnValue() const { - return ScriptValue(m_constructor, m_context->GetIsolate()); + return ScriptValue(m_scriptState.get(), m_constructor); } bool CustomElementConstructorBuilder::hasValidPrototypeChainFor(const WrapperTypeInfo* type) const { - v8::Handle<v8::Object> elementPrototype = V8PerContextData::from(m_context)->prototypeForType(type); + v8::Handle<v8::Object> elementPrototype = m_scriptState->perContextData()->prototypeForType(type); if (elementPrototype.IsEmpty()) return false; @@ -266,22 +282,28 @@ static void constructCustomElement(const v8::FunctionCallbackInfo<v8::Value>& in } if (info.Length() > 0) { - throwUninformativeAndGenericTypeError(isolate); + throwTypeError("This constructor should be called without arguments.", isolate); return; } - Document* document = V8Document::toNative(info.Callee()->GetHiddenValue(V8HiddenPropertyName::customElementDocument(isolate)).As<v8::Object>()); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, namespaceURI, info.Callee()->GetHiddenValue(V8HiddenPropertyName::customElementNamespaceURI(isolate))); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, tagName, info.Callee()->GetHiddenValue(V8HiddenPropertyName::customElementTagName(isolate))); - v8::Handle<v8::Value> maybeType = info.Callee()->GetHiddenValue(V8HiddenPropertyName::customElementType(isolate)); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, maybeType); + Document* document = V8Document::toNative(V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Callee(), V8HiddenValue::customElementDocument(isolate)).As<v8::Object>()); + TOSTRING_VOID(V8StringResource<>, namespaceURI, V8HiddenValue::getHiddenValue(isolate, info.Callee(), V8HiddenValue::customElementNamespaceURI(isolate))); + TOSTRING_VOID(V8StringResource<>, tagName, V8HiddenValue::getHiddenValue(isolate, info.Callee(), V8HiddenValue::customElementTagName(isolate))); + v8::Handle<v8::Value> maybeType = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Callee(), V8HiddenValue::customElementType(isolate)); + TOSTRING_VOID(V8StringResource<>, type, maybeType); ExceptionState exceptionState(ExceptionState::ConstructionContext, "CustomElement", info.Holder(), info.GetIsolate()); CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope; - RefPtr<Element> element = document->createElementNS(namespaceURI, tagName, maybeType->IsNull() ? nullAtom : type, exceptionState); + RefPtrWillBeRawPtr<Element> element = document->createElementNS(namespaceURI, tagName, maybeType->IsNull() ? nullAtom : type, exceptionState); if (exceptionState.throwIfNeeded()) return; +#if ENABLE(OILPAN) + // FIXME: Oilpan: We don't have RawPtr<Eement> version of + // v8SetReturnValueFast until Node.idl has WillBeGarbageCollected. + v8SetReturnValueFast(info, element.get(), document); +#else v8SetReturnValueFast(info, element.release(), document); +#endif } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.h b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.h index 21f81e8c787..623244d2a70 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementConstructorBuilder.h @@ -49,7 +49,6 @@ class Document; class Element; class ExceptionState; class QualifiedName; -class ScriptState; class V8PerContextData; struct WrapperTypeInfo; @@ -82,7 +81,7 @@ private: bool prototypeIsValid(const AtomicString& type, ExceptionState&) const; v8::Handle<v8::Function> retrieveCallback(v8::Isolate*, const char* name); - v8::Handle<v8::Context> m_context; + RefPtr<ScriptState> m_scriptState; const Dictionary* m_options; v8::Handle<v8::Object> m_prototype; const WrapperTypeInfo* m_wrapperType; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementWrapper.cpp b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementWrapper.cpp index 128c1e417e2..abd8830ea8b 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementWrapper.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementWrapper.cpp @@ -31,13 +31,13 @@ #include "config.h" #include "bindings/v8/CustomElementWrapper.h" -#include "V8HTMLElement.h" -#include "V8HTMLElementWrapperFactory.h" -#include "V8SVGElement.h" -#include "V8SVGElementWrapperFactory.h" +#include "bindings/core/v8/V8HTMLElement.h" +#include "bindings/core/v8/V8SVGElement.h" #include "bindings/v8/DOMDataStore.h" #include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/V8PerContextData.h" +#include "core/V8HTMLElementWrapperFactory.h" // FIXME: should be bindings/core/v8 +#include "core/V8SVGElementWrapperFactory.h" // FIXME: should be bindings/core/v8 #include "core/dom/custom/CustomElement.h" #include "core/html/HTMLElement.h" #include "core/html/HTMLUnknownElement.h" @@ -86,23 +86,21 @@ v8::Handle<v8::Object> createUpgradeCandidateWrapper(ElementType* element, v8::H } template<typename ElementType, typename WrapperType> -v8::Handle<v8::Object> CustomElementWrapper<ElementType, WrapperType>::wrap(PassRefPtr<ElementType> element, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate, v8::Handle<v8::Object> (*createSpecificWrapper)(ElementType* element, v8::Handle<v8::Object> creationContext, v8::Isolate*)) +v8::Handle<v8::Object> CustomElementWrapper<ElementType, WrapperType>::wrap(PassRefPtrWillBeRawPtr<ElementType> element, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate, v8::Handle<v8::Object> (*createSpecificWrapper)(ElementType* element, v8::Handle<v8::Object> creationContext, v8::Isolate*)) { ASSERT(DOMDataStore::getWrapper<V8Element>(element.get(), isolate).IsEmpty()); - // FIXME: creationContext.IsEmpty() should never happen. Remove - // this when callers (like InspectorController::inspect) are fixed - // to never pass an empty creation context. - v8::Handle<v8::Context> context = creationContext.IsEmpty() ? isolate->GetCurrentContext() : creationContext->CreationContext(); + ASSERT(!creationContext.IsEmpty()); + v8::Handle<v8::Context> context = creationContext->CreationContext(); - if (!element->isUpgradedCustomElement() || DOMWrapperWorld::isolatedWorld(context)) + if (!element->isUpgradedCustomElement() || DOMWrapperWorld::world(context).isIsolatedWorld()) return createUpgradeCandidateWrapper(element.get(), creationContext, isolate, createSpecificWrapper); V8PerContextData* perContextData = V8PerContextData::from(context); if (!perContextData) return v8::Handle<v8::Object>(); - CustomElementBinding* binding = perContextData->customElementBinding(CustomElement::definitionFor(element.get())); + CustomElementBinding* binding = perContextData->customElementBinding(element->customElementDefinition()); v8::Handle<v8::Object> wrapper = V8DOMWrapper::createWrapper(creationContext, binding->wrapperType(), element.get(), isolate); if (wrapper.IsEmpty()) return v8::Handle<v8::Object>(); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementWrapper.h b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementWrapper.h index c3cbbe8e58d..bf3ba6e8dce 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/CustomElementWrapper.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/CustomElementWrapper.h @@ -31,6 +31,7 @@ #ifndef CustomElementWrapper_h #define CustomElementWrapper_h +#include "platform/heap/Handle.h" #include "wtf/PassRefPtr.h" #include <v8.h> @@ -47,7 +48,7 @@ private: friend v8::Handle<v8::Object> createV8HTMLWrapper(HTMLElement*, v8::Handle<v8::Object>, v8::Isolate*); friend v8::Handle<v8::Object> createV8SVGWrapper(SVGElement*, v8::Handle<v8::Object>, v8::Isolate*); - static v8::Handle<v8::Object> wrap(PassRefPtr<ElementType>, v8::Handle<v8::Object> creationContext, v8::Isolate*, v8::Handle<v8::Object> (*createSpecificWrapper)(ElementType* element, v8::Handle<v8::Object> creationContext, v8::Isolate*)); + static v8::Handle<v8::Object> wrap(PassRefPtrWillBeRawPtr<ElementType>, v8::Handle<v8::Object> creationContext, v8::Isolate*, v8::Handle<v8::Object> (*createSpecificWrapper)(ElementType* element, v8::Handle<v8::Object> creationContext, v8::Isolate*)); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/DOMDataStore.cpp b/chromium/third_party/WebKit/Source/bindings/v8/DOMDataStore.cpp index fcfb12f00e7..c9ef7c4195c 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/DOMDataStore.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/DOMDataStore.cpp @@ -37,40 +37,21 @@ namespace WebCore { -DOMDataStore::DOMDataStore(WrapperWorldType type) - : m_type(type) +DOMDataStore::DOMDataStore(bool isMainWorld) + : m_isMainWorld(isMainWorld) , m_wrapperMap(v8::Isolate::GetCurrent()) // FIXME Don't call GetCurrent twice. { - V8PerIsolateData::current()->registerDOMDataStore(this); } DOMDataStore::~DOMDataStore() { - ASSERT(m_type != MainWorld); // We never actually destruct the main world's DOMDataStore. - V8PerIsolateData::current()->unregisterDOMDataStore(this); + ASSERT(!m_isMainWorld); // We never actually destruct the main world's DOMDataStore. m_wrapperMap.clear(); } -DOMDataStore& DOMDataStore::mainWorldStore() -{ - DEFINE_STATIC_LOCAL(DOMDataStore, mainWorldDOMDataStore, (MainWorld)); - ASSERT(isMainThread()); - return mainWorldDOMDataStore; -} - DOMDataStore& DOMDataStore::current(v8::Isolate* isolate) { - V8PerIsolateData* data = isolate ? V8PerIsolateData::from(isolate) : V8PerIsolateData::current(); - if (UNLIKELY(!!data->workerDOMDataStore())) - return *data->workerDOMDataStore(); - - if (DOMWrapperWorld::isolatedWorldsExist()) { - DOMWrapperWorld* isolatedWorld = DOMWrapperWorld::isolatedWorld(isolate->GetEnteredContext()); - if (UNLIKELY(!!isolatedWorld)) - return isolatedWorld->isolatedWorldDOMDataStore(); - } - - return mainWorldStore(); + return DOMWrapperWorld::current(isolate).domDataStore(); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/DOMDataStore.h b/chromium/third_party/WebKit/Source/bindings/v8/DOMDataStore.h index a75d38f02d5..852e8110a32 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/DOMDataStore.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/DOMDataStore.h @@ -46,24 +46,39 @@ class Node; class DOMDataStore { WTF_MAKE_NONCOPYABLE(DOMDataStore); public: - explicit DOMDataStore(WrapperWorldType); + explicit DOMDataStore(bool isMainWorld); ~DOMDataStore(); static DOMDataStore& current(v8::Isolate*); + // We can use a wrapper stored in a ScriptWrappable when we're in the main world. + // This method does the fast check if we're in the main world. If this method returns true, + // it is guaranteed that we're in the main world. On the other hand, if this method returns + // false, nothing is guaranteed (we might be in the main world). + template<typename T> + static bool canUseScriptWrappable(T* object) + { + return !DOMWrapperWorld::isolatedWorldsExist() + && !canExistInWorker(object) + && ScriptWrappable::wrapperCanBeStoredInObject(object); + } + template<typename V8T, typename T, typename Wrappable> static bool setReturnValueFromWrapperFast(v8::ReturnValue<v8::Value> returnValue, T* object, v8::Local<v8::Object> holder, Wrappable* wrappable) { - // What we'd really like to check here is whether we're in the - // main world or in an isolated world. The fastest way to do that - // is to check that there is no isolated world and the 'object' - // is an object that can exist in the main world. The second fastest - // way is to check whether the wrappable's wrapper is the same as - // the holder. - if ((!DOMWrapperWorld::isolatedWorldsExist() && !canExistInWorker(object)) || holderContainsWrapper(holder, wrappable)) { - if (ScriptWrappable::wrapperCanBeStoredInObject(object)) - return ScriptWrappable::setReturnValueWithSecurityCheck<V8T>(returnValue, object); - return mainWorldStore().m_wrapperMap.setReturnValueFrom(returnValue, V8T::toInternalPointer(object)); + if (canUseScriptWrappable(object)) { + ScriptWrappable::assertWrapperSanity<V8T, T>(object, object); + return ScriptWrappable::fromObject(object)->setReturnValue(returnValue); + } + // The second fastest way to check if we're in the main world is to check if + // the wrappable's wrapper is the same as the holder. + // FIXME: Investigate if it's worth having this check for performance. + if (holderContainsWrapper(holder, wrappable)) { + if (ScriptWrappable::wrapperCanBeStoredInObject(object)) { + ScriptWrappable::assertWrapperSanity<V8T, T>(object, object); + return ScriptWrappable::fromObject(object)->setReturnValue(returnValue); + } + return DOMWrapperWorld::mainWorld().domDataStore().m_wrapperMap.setReturnValueFrom(returnValue, V8T::toInternalPointer(object)); } return current(returnValue.GetIsolate()).template setReturnValueFrom<V8T>(returnValue, object); } @@ -71,9 +86,9 @@ public: template<typename V8T, typename T> static bool setReturnValueFromWrapper(v8::ReturnValue<v8::Value> returnValue, T* object) { - if (ScriptWrappable::wrapperCanBeStoredInObject(object) && !canExistInWorker(object)) { - if (LIKELY(!DOMWrapperWorld::isolatedWorldsExist())) - return ScriptWrappable::setReturnValueWithSecurityCheck<V8T>(returnValue, object); + if (canUseScriptWrappable(object)) { + ScriptWrappable::assertWrapperSanity<V8T, T>(object, object); + return ScriptWrappable::fromObject(object)->setReturnValue(returnValue); } return current(returnValue.GetIsolate()).template setReturnValueFrom<V8T>(returnValue, object); } @@ -82,20 +97,18 @@ public: static bool setReturnValueFromWrapperForMainWorld(v8::ReturnValue<v8::Value> returnValue, T* object) { if (ScriptWrappable::wrapperCanBeStoredInObject(object)) - return ScriptWrappable::setReturnValue(returnValue, object); - return mainWorldStore().m_wrapperMap.setReturnValueFrom(returnValue, V8T::toInternalPointer(object)); + return ScriptWrappable::fromObject(object)->setReturnValue(returnValue); + return DOMWrapperWorld::mainWorld().domDataStore().m_wrapperMap.setReturnValueFrom(returnValue, V8T::toInternalPointer(object)); } template<typename V8T, typename T> static v8::Handle<v8::Object> getWrapper(T* object, v8::Isolate* isolate) { - if (ScriptWrappable::wrapperCanBeStoredInObject(object) && !canExistInWorker(object)) { - if (LIKELY(!DOMWrapperWorld::isolatedWorldsExist())) { - v8::Handle<v8::Object> result = ScriptWrappable::getUnsafeWrapperFromObject(object).newLocal(isolate); - // Security: always guard against malicious tampering. - RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(result.IsEmpty() || result->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex) == V8T::toInternalPointer(object)); - return result; - } + if (canUseScriptWrappable(object)) { + v8::Handle<v8::Object> result = ScriptWrappable::fromObject(object)->newLocalWrapper(isolate); + // Security: always guard against malicious tampering. + ScriptWrappable::assertWrapperSanity<V8T, T>(result, object); + return result; } return current(isolate).template get<V8T>(object, isolate); } @@ -103,13 +116,10 @@ public: template<typename V8T, typename T> static void setWrapperReference(const v8::Persistent<v8::Object>& parent, T* child, v8::Isolate* isolate) { - if (ScriptWrappable::wrapperCanBeStoredInObject(child) && !canExistInWorker(child)) { - if (LIKELY(!DOMWrapperWorld::isolatedWorldsExist())) { - UnsafePersistent<v8::Object> unsafePersistent = ScriptWrappable::getUnsafeWrapperFromObject(child); - // Security: always guard against malicious tampering. - RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(unsafePersistent.isEmpty() || unsafePersistent.value()->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex) == V8T::toInternalPointer(child)); - unsafePersistent.setReferenceFrom(parent, isolate); - } + if (canUseScriptWrappable(child)) { + ScriptWrappable::assertWrapperSanity<V8T, T>(child, child); + ScriptWrappable::fromObject(child)->setReference(parent, isolate); + return; } current(isolate).template setReference<V8T>(parent, child, isolate); } @@ -117,11 +127,9 @@ public: template<typename V8T, typename T> static void setWrapper(T* object, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, const WrapperConfiguration& configuration) { - if (ScriptWrappable::wrapperCanBeStoredInObject(object) && !canExistInWorker(object)) { - if (LIKELY(!DOMWrapperWorld::isolatedWorldsExist())) { - ScriptWrappable::setWrapperInObject(object, wrapper, isolate, configuration); - return; - } + if (canUseScriptWrappable(object)) { + ScriptWrappable::fromObject(object)->setWrapper(wrapper, isolate, configuration); + return; } return current(isolate).template set<V8T>(object, wrapper, isolate, configuration); } @@ -135,16 +143,16 @@ public: template<typename V8T, typename T> inline v8::Handle<v8::Object> get(T* object, v8::Isolate* isolate) { - if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_type == MainWorld) - return ScriptWrappable::getUnsafeWrapperFromObject(object).newLocal(isolate); + if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_isMainWorld) + return ScriptWrappable::fromObject(object)->newLocalWrapper(isolate); return m_wrapperMap.newLocal(V8T::toInternalPointer(object), isolate); } template<typename V8T, typename T> inline void setReference(const v8::Persistent<v8::Object>& parent, T* child, v8::Isolate* isolate) { - if (ScriptWrappable::wrapperCanBeStoredInObject(child) && m_type == MainWorld) { - ScriptWrappable::getUnsafeWrapperFromObject(child).setReferenceFrom(parent, isolate); + if (ScriptWrappable::wrapperCanBeStoredInObject(child) && m_isMainWorld) { + ScriptWrappable::fromObject(child)->setReference(parent, isolate); return; } m_wrapperMap.setReference(parent, V8T::toInternalPointer(child), isolate); @@ -153,16 +161,16 @@ public: template<typename V8T, typename T> inline bool setReturnValueFrom(v8::ReturnValue<v8::Value> returnValue, T* object) { - if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_type == MainWorld) - return ScriptWrappable::setReturnValue(returnValue, object); + if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_isMainWorld) + return ScriptWrappable::fromObject(object)->setReturnValue(returnValue); return m_wrapperMap.setReturnValueFrom(returnValue, V8T::toInternalPointer(object)); } template<typename V8T, typename T> inline bool containsWrapper(T* object) { - if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_type == MainWorld) - return !ScriptWrappable::getUnsafeWrapperFromObject(object).isEmpty(); + if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_isMainWorld) + return ScriptWrappable::fromObject(object)->containsWrapper(); return m_wrapperMap.containsKey(V8T::toInternalPointer(object)); } @@ -172,15 +180,13 @@ private: { ASSERT(!!object); ASSERT(!wrapper.IsEmpty()); - if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_type == MainWorld) { - ScriptWrappable::setWrapperInObject(object, wrapper, isolate, configuration); + if (ScriptWrappable::wrapperCanBeStoredInObject(object) && m_isMainWorld) { + ScriptWrappable::fromObject(object)->setWrapper(wrapper, isolate, configuration); return; } m_wrapperMap.set(V8T::toInternalPointer(object), wrapper, configuration); } - static DOMDataStore& mainWorldStore(); - static bool canExistInWorker(void*) { return true; } static bool canExistInWorker(Node*) { return false; } @@ -192,12 +198,12 @@ private: static bool holderContainsWrapper(v8::Local<v8::Object> holder, ScriptWrappable* wrappable) { // Verify our assumptions about the main world. - UnsafePersistent<v8::Object> unsafePersistent = wrappable->unsafePersistent(); - ASSERT(unsafePersistent.isEmpty() || !(holder == *unsafePersistent.persistent()) || current(v8::Isolate::GetCurrent()).m_type == MainWorld); - return holder == *unsafePersistent.persistent(); + ASSERT(wrappable); + ASSERT(!wrappable->containsWrapper() || !wrappable->isEqualTo(holder) || current(v8::Isolate::GetCurrent()).m_isMainWorld); + return wrappable->isEqualTo(holder); } - WrapperWorldType m_type; + bool m_isMainWorld; DOMWrapperMap<void> m_wrapperMap; }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/DOMRequestState.h b/chromium/third_party/WebKit/Source/bindings/v8/DOMRequestState.h deleted file mode 100644 index 710f3d371b0..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/DOMRequestState.h +++ /dev/null @@ -1,85 +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 DOMRequestState_h -#define DOMRequestState_h - -#include "bindings/v8/DOMWrapperWorld.h" -#include "bindings/v8/V8Binding.h" -#include "core/dom/ExecutionContext.h" -#include "v8.h" -#include "wtf/RefPtr.h" - -namespace WebCore { - -class DOMRequestState { -public: - explicit DOMRequestState(ExecutionContext* executionContext) - : m_executionContext(executionContext) - , m_world(DOMWrapperWorld::current()) - , m_isolate(toIsolate(executionContext)) - { - ASSERT(m_executionContext); - } - - void clear() - { - m_executionContext = 0; - m_world.clear(); - } - - class Scope { - public: - explicit Scope(DOMRequestState& state) - : m_handleScope(state.isolate()) - , m_contextScope(state.context()) - { - } - private: - v8::HandleScope m_handleScope; - v8::Context::Scope m_contextScope; - }; - - v8::Local<v8::Context> context() - { - ASSERT(m_executionContext); - return toV8Context(m_executionContext, m_world.get()); - } - - v8::Isolate* isolate() const - { - return m_isolate; - } - - bool isValid() const { return m_executionContext; } - -private: - ExecutionContext* m_executionContext; - RefPtr<DOMWrapperWorld> m_world; - v8::Isolate* m_isolate; -}; - -} -#endif diff --git a/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperMap.h b/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperMap.h index 5987f57ace8..1ebbc53fb7c 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperMap.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperMap.h @@ -31,9 +31,8 @@ #ifndef DOMWrapperMap_h #define DOMWrapperMap_h -#include "bindings/v8/UnsafePersistent.h" -#include "bindings/v8/V8Utilities.h" #include "bindings/v8/WrapperTypeInfo.h" +#include <v8-util.h> #include <v8.h> #include "wtf/HashMap.h" @@ -42,96 +41,127 @@ namespace WebCore { template<class KeyType> class DOMWrapperMap { public: - typedef HashMap<KeyType*, UnsafePersistent<v8::Object> > MapType; - explicit DOMWrapperMap(v8::Isolate* isolate) : m_isolate(isolate) + , m_map(isolate) { } v8::Handle<v8::Object> newLocal(KeyType* key, v8::Isolate* isolate) { - return m_map.get(key).newLocal(isolate); + return m_map.Get(key); } bool setReturnValueFrom(v8::ReturnValue<v8::Value> returnValue, KeyType* key) { - typename MapType::iterator it = m_map.find(key); - if (it == m_map.end()) - return false; - returnValue.Set(*(it->value.persistent())); - return true; + return m_map.SetReturnValue(key, returnValue); } void setReference(const v8::Persistent<v8::Object>& parent, KeyType* key, v8::Isolate* isolate) { - m_map.get(key).setReferenceFrom(parent, isolate); + m_map.SetReference(key, parent); } bool containsKey(KeyType* key) { - return m_map.find(key) != m_map.end(); - } - - bool containsKeyAndValue(KeyType* key, v8::Handle<v8::Object> value) - { - typename MapType::iterator it = m_map.find(key); - if (it == m_map.end()) - return false; - return *(it->value.persistent()) == value; + return m_map.Contains(key); } void set(KeyType* key, v8::Handle<v8::Object> wrapper, const WrapperConfiguration& configuration) { ASSERT(static_cast<KeyType*>(toNative(wrapper)) == key); - v8::Persistent<v8::Object> persistent(m_isolate, wrapper); - configuration.configureWrapper(&persistent); - persistent.SetWeak(this, &setWeakCallback); - typename MapType::AddResult result = m_map.add(key, UnsafePersistent<v8::Object>()); - ASSERT(result.isNewEntry); - // FIXME: Stop handling this case once duplicate wrappers are guaranteed not to be created. - if (!result.isNewEntry) - result.iterator->value.dispose(); - result.iterator->value = UnsafePersistent<v8::Object>(persistent); + RELEASE_ASSERT(!containsKey(key)); // See crbug.com/368095 + v8::UniquePersistent<v8::Object> unique(m_isolate, wrapper); + configuration.configureWrapper(&unique); + m_map.Set(key, unique.Pass()); } void clear() { - while (!m_map.isEmpty()) { - // Swap out m_map on each iteration to ensure any wrappers added due to side effects of the loop are cleared. - MapType map; - map.swap(m_map); - for (typename MapType::iterator it = map.begin(); it != map.end(); ++it) { - toWrapperTypeInfo(*(it->value.persistent()))->derefObject(it->key); - it->value.dispose(); - } - } + m_map.Clear(); } void removeAndDispose(KeyType* key) { - typename MapType::iterator it = m_map.find(key); - ASSERT_WITH_SECURITY_IMPLICATION(it != m_map.end()); - it->value.dispose(); - m_map.remove(it); + ASSERT(containsKey(key)); + m_map.Remove(key); } private: - static void setWeakCallback(const v8::WeakCallbackData<v8::Object, DOMWrapperMap<KeyType> >&); + class PersistentValueMapTraits { + public: + // Map traits: + typedef HashMap<KeyType*, v8::PersistentContainerValue> Impl; + typedef typename Impl::iterator Iterator; + static size_t Size(const Impl* impl) { return impl->size(); } + static bool Empty(Impl* impl) { return impl->isEmpty(); } + static void Swap(Impl& impl, Impl& other) { impl.swap(other); } + static Iterator Begin(Impl* impl) { return impl->begin(); } + static Iterator End(Impl* impl) { return impl->end(); } + static v8::PersistentContainerValue Value(Iterator& iter) + { + return iter->value; + } + static KeyType* Key(Iterator& iter) { return iter->key; } + static v8::PersistentContainerValue Set( + Impl* impl, KeyType* key, v8::PersistentContainerValue value) + { + v8::PersistentContainerValue oldValue = Get(impl, key); + impl->set(key, value); + return oldValue; + } + static v8::PersistentContainerValue Get(const Impl* impl, KeyType* key) + { + return impl->get(key); + } + + static v8::PersistentContainerValue Remove(Impl* impl, KeyType* key) + { + return impl->take(key); + } + + // Weak traits: + static const v8::PersistentContainerCallbackType kCallbackType = v8::kWeak; + typedef v8::PersistentValueMap<KeyType*, v8::Object, PersistentValueMapTraits> MapType; + typedef MapType WeakCallbackDataType; + + static WeakCallbackDataType* WeakCallbackParameter(MapType* map, KeyType* key, v8::Local<v8::Object>& value) + { + return map; + } + + static void DisposeCallbackData(WeakCallbackDataType* callbackData) { } + + static MapType* MapFromWeakCallbackData( + const v8::WeakCallbackData<v8::Object, WeakCallbackDataType>& data) + { + return data.GetParameter(); + } + + static KeyType* KeyFromWeakCallbackData( + const v8::WeakCallbackData<v8::Object, WeakCallbackDataType>& data) + { + return static_cast<KeyType*>(toNative(data.GetValue())); + } + + // Dispose traits: + // Generally nothing to do, but see below for a specialization for + // DomWrapperMap<void>. + static void Dispose(v8::Isolate* isolate, v8::UniquePersistent<v8::Object> value, KeyType* key) { } + }; v8::Isolate* m_isolate; - MapType m_map; + typename PersistentValueMapTraits::MapType m_map; }; -template<> -inline void DOMWrapperMap<void>::setWeakCallback(const v8::WeakCallbackData<v8::Object, DOMWrapperMap<void> >& data) +template <> +inline void DOMWrapperMap<void>::PersistentValueMapTraits::Dispose( + v8::Isolate* isolate, + v8::UniquePersistent<v8::Object> value, + void* key) { - const WrapperTypeInfo* type = toWrapperTypeInfo(data.GetValue()); - ASSERT(type->derefObjectFunction); - void* key = static_cast<void*>(toNative(data.GetValue())); - ASSERT(*(data.GetParameter()->m_map.get(key).persistent()) == data.GetValue()); - data.GetParameter()->removeAndDispose(key); - type->derefObject(key); + RELEASE_ASSERT(!value.IsEmpty()); // See crbug.com/368095. + releaseObject(v8::Local<v8::Object>::New(isolate, value)); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperWorld.cpp b/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperWorld.cpp index d014206817f..59cb4505716 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperWorld.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperWorld.cpp @@ -31,7 +31,7 @@ #include "config.h" #include "bindings/v8/DOMWrapperWorld.h" -#include "V8Window.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/DOMDataStore.h" #include "bindings/v8/ScriptController.h" #include "bindings/v8/V8Binding.h" @@ -41,70 +41,30 @@ #include "bindings/v8/WrapperTypeInfo.h" #include "core/dom/ExecutionContext.h" #include "wtf/HashTraits.h" -#include "wtf/MainThread.h" #include "wtf/StdLibExtras.h" namespace WebCore { unsigned DOMWrapperWorld::isolatedWorldCount = 0; -static bool initializingWindow = false; +DOMWrapperWorld* DOMWrapperWorld::worldOfInitializingWindow = 0; -void DOMWrapperWorld::setInitializingWindow(bool initializing) +PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::create(int worldId, int extensionGroup) { - initializingWindow = initializing; -} - -PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::createMainWorld() -{ - return adoptRef(new DOMWrapperWorld(MainWorldId, mainWorldExtensionGroup)); + return adoptRef(new DOMWrapperWorld(worldId, extensionGroup)); } DOMWrapperWorld::DOMWrapperWorld(int worldId, int extensionGroup) : m_worldId(worldId) , m_extensionGroup(extensionGroup) + , m_domDataStore(adoptPtr(new DOMDataStore(isMainWorld()))) { - if (isIsolatedWorld()) - m_domDataStore = adoptPtr(new DOMDataStore(IsolatedWorld)); -} - -DOMWrapperWorld* DOMWrapperWorld::current() -{ - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - ASSERT(isolate->InContext()); - v8::Handle<v8::Context> context = isolate->GetCurrentContext(); - if (!V8DOMWrapper::isWrapperOfType(toInnerGlobalObject(context), &V8Window::wrapperTypeInfo)) - return 0; - ASSERT(isMainThread()); - if (DOMWrapperWorld* world = isolatedWorld(context)) - return world; - return mainThreadNormalWorld(); } -DOMWrapperWorld* mainThreadNormalWorld() +DOMWrapperWorld& DOMWrapperWorld::mainWorld() { ASSERT(isMainThread()); - DEFINE_STATIC_REF(DOMWrapperWorld, cachedNormalWorld, (DOMWrapperWorld::createMainWorld())); - return cachedNormalWorld; -} - -// FIXME: Remove this function. There is currently an issue with the inspector related to the call to dispatchDidClearWindowObjectInWorld in ScriptController::windowShell. -DOMWrapperWorld* existingWindowShellWorkaroundWorld() -{ - DEFINE_STATIC_REF(DOMWrapperWorld, world, (adoptRef(new DOMWrapperWorld(MainWorldId - 1, DOMWrapperWorld::mainWorldExtensionGroup - 1)))); - return world; -} - -bool DOMWrapperWorld::contextHasCorrectPrototype(v8::Handle<v8::Context> context) -{ - ASSERT(isMainThread()); - if (initializingWindow) - return true; - return V8DOMWrapper::isWrapperOfType(toInnerGlobalObject(context), &V8Window::wrapperTypeInfo); -} - -void DOMWrapperWorld::setIsolatedWorldField(v8::Handle<v8::Context> context) -{ - V8PerContextDataHolder::from(context)->setIsolatedWorld(isMainWorld() ? 0 : this); + DEFINE_STATIC_REF(DOMWrapperWorld, cachedMainWorld, (DOMWrapperWorld::create(MainWorldId, mainWorldExtensionGroup))); + return *cachedMainWorld; } typedef HashMap<int, DOMWrapperWorld*> WorldMap; @@ -115,9 +75,10 @@ static WorldMap& isolatedWorldMap() return map; } -void DOMWrapperWorld::getAllWorlds(Vector<RefPtr<DOMWrapperWorld> >& worlds) +void DOMWrapperWorld::allWorldsInMainThread(Vector<RefPtr<DOMWrapperWorld> >& worlds) { - worlds.append(mainThreadNormalWorld()); + ASSERT(isMainThread()); + worlds.append(&mainWorld()); WorldMap& isolatedWorlds = isolatedWorldMap(); for (WorldMap::iterator it = isolatedWorlds.begin(); it != isolatedWorlds.end(); ++it) worlds.append(it->value); @@ -127,48 +88,57 @@ DOMWrapperWorld::~DOMWrapperWorld() { ASSERT(!isMainWorld()); + dispose(); + if (!isIsolatedWorld()) return; WorldMap& map = isolatedWorldMap(); - WorldMap::iterator i = map.find(m_worldId); - if (i == map.end()) { + WorldMap::iterator it = map.find(m_worldId); + if (it == map.end()) { ASSERT_NOT_REACHED(); return; } - ASSERT(i->value == this); + ASSERT(it->value == this); - map.remove(i); + map.remove(it); isolatedWorldCount--; ASSERT(map.size() == isolatedWorldCount); } +void DOMWrapperWorld::dispose() +{ + m_domDataStore.clear(); +} + +#ifndef NDEBUG +static bool isIsolatedWorldId(int worldId) +{ + return MainWorldId < worldId && worldId < IsolatedWorldIdLimit; +} +#endif + PassRefPtr<DOMWrapperWorld> DOMWrapperWorld::ensureIsolatedWorld(int worldId, int extensionGroup) { - ASSERT(worldId > MainWorldId); + ASSERT(isIsolatedWorldId(worldId)); WorldMap& map = isolatedWorldMap(); WorldMap::AddResult result = map.add(worldId, 0); - RefPtr<DOMWrapperWorld> world = result.iterator->value; + RefPtr<DOMWrapperWorld> world = result.storedValue->value; if (world) { ASSERT(world->worldId() == worldId); ASSERT(world->extensionGroup() == extensionGroup); return world.release(); } - world = adoptRef(new DOMWrapperWorld(worldId, extensionGroup)); - result.iterator->value = world.get(); + world = DOMWrapperWorld::create(worldId, extensionGroup); + result.storedValue->value = world.get(); isolatedWorldCount++; ASSERT(map.size() == isolatedWorldCount); return world.release(); } -v8::Handle<v8::Context> DOMWrapperWorld::context(ScriptController& controller) -{ - return controller.windowShell(this)->context(); -} - typedef HashMap<int, RefPtr<SecurityOrigin> > IsolatedWorldSecurityOriginMap; static IsolatedWorldSecurityOriginMap& isolatedWorldSecurityOrigins() { @@ -185,19 +155,13 @@ SecurityOrigin* DOMWrapperWorld::isolatedWorldSecurityOrigin() return it == origins.end() ? 0 : it->value.get(); } -void DOMWrapperWorld::setIsolatedWorldSecurityOrigin(int worldID, PassRefPtr<SecurityOrigin> securityOrigin) +void DOMWrapperWorld::setIsolatedWorldSecurityOrigin(int worldId, PassRefPtr<SecurityOrigin> securityOrigin) { - ASSERT(DOMWrapperWorld::isIsolatedWorldId(worldID)); + ASSERT(isIsolatedWorldId(worldId)); if (securityOrigin) - isolatedWorldSecurityOrigins().set(worldID, securityOrigin); + isolatedWorldSecurityOrigins().set(worldId, securityOrigin); else - isolatedWorldSecurityOrigins().remove(worldID); -} - -void DOMWrapperWorld::clearIsolatedWorldSecurityOrigin(int worldID) -{ - ASSERT(DOMWrapperWorld::isIsolatedWorldId(worldID)); - isolatedWorldSecurityOrigins().remove(worldID); + isolatedWorldSecurityOrigins().remove(worldId); } typedef HashMap<int, bool> IsolatedWorldContentSecurityPolicyMap; @@ -216,39 +180,13 @@ bool DOMWrapperWorld::isolatedWorldHasContentSecurityPolicy() return it == policies.end() ? false : it->value; } -void DOMWrapperWorld::setIsolatedWorldContentSecurityPolicy(int worldID, const String& policy) +void DOMWrapperWorld::setIsolatedWorldContentSecurityPolicy(int worldId, const String& policy) { - ASSERT(DOMWrapperWorld::isIsolatedWorldId(worldID)); + ASSERT(isIsolatedWorldId(worldId)); if (!policy.isEmpty()) - isolatedWorldContentSecurityPolicies().set(worldID, true); + isolatedWorldContentSecurityPolicies().set(worldId, true); else - isolatedWorldContentSecurityPolicies().remove(worldID); -} - -void DOMWrapperWorld::clearIsolatedWorldContentSecurityPolicy(int worldID) -{ - ASSERT(DOMWrapperWorld::isIsolatedWorldId(worldID)); - isolatedWorldContentSecurityPolicies().remove(worldID); -} - -typedef HashMap<int, OwnPtr<V8DOMActivityLogger>, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int> > DOMActivityLoggerMap; -static DOMActivityLoggerMap& domActivityLoggers() -{ - ASSERT(isMainThread()); - DEFINE_STATIC_LOCAL(DOMActivityLoggerMap, map, ()); - return map; -} - -void DOMWrapperWorld::setActivityLogger(int worldId, PassOwnPtr<V8DOMActivityLogger> logger) -{ - domActivityLoggers().set(worldId, logger); -} - -V8DOMActivityLogger* DOMWrapperWorld::activityLogger(int worldId) -{ - DOMActivityLoggerMap& loggers = domActivityLoggers(); - DOMActivityLoggerMap::iterator it = loggers.find(worldId); - return it == loggers.end() ? 0 : it->value.get(); + isolatedWorldContentSecurityPolicies().remove(worldId); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperWorld.h b/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperWorld.h index 201e019309f..aa294a1fcfb 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperWorld.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/DOMWrapperWorld.h @@ -31,54 +31,67 @@ #ifndef DOMWrapperWorld_h #define DOMWrapperWorld_h -#include "bindings/v8/V8DOMActivityLogger.h" -#include "bindings/v8/V8PerContextData.h" +#include "bindings/v8/ScriptState.h" #include "platform/weborigin/SecurityOrigin.h" -#include <v8.h> +#include "wtf/MainThread.h" #include "wtf/PassRefPtr.h" #include "wtf/RefCounted.h" #include "wtf/RefPtr.h" #include "wtf/text/WTFString.h" +#include <v8.h> namespace WebCore { class DOMDataStore; -class ScriptController; class ExecutionContext; +class ScriptController; enum WorldIdConstants { MainWorldId = 0, + // Embedder isolated worlds can use IDs in [1, 1<<29). EmbedderWorldIdLimit = (1 << 29), - ScriptPreprocessorIsolatedWorldId + ScriptPreprocessorIsolatedWorldId, + IsolatedWorldIdLimit, + WorkerWorldId, + TestingWorldId, }; // This class represent a collection of DOM wrappers for a specific world. class DOMWrapperWorld : public RefCounted<DOMWrapperWorld> { public: + static PassRefPtr<DOMWrapperWorld> create(int worldId = -1, int extensionGroup = -1); + static const int mainWorldExtensionGroup = 0; static PassRefPtr<DOMWrapperWorld> ensureIsolatedWorld(int worldId, int extensionGroup); ~DOMWrapperWorld(); + void dispose(); static bool isolatedWorldsExist() { return isolatedWorldCount; } - static bool isIsolatedWorldId(int worldId) { return worldId > MainWorldId; } - static void getAllWorlds(Vector<RefPtr<DOMWrapperWorld> >& worlds); + static void allWorldsInMainThread(Vector<RefPtr<DOMWrapperWorld> >& worlds); - void setIsolatedWorldField(v8::Handle<v8::Context>); + static DOMWrapperWorld& world(v8::Handle<v8::Context> context) + { + return ScriptState::from(context)->world(); + } - static DOMWrapperWorld* isolatedWorld(v8::Handle<v8::Context> context) + static DOMWrapperWorld& current(v8::Isolate* isolate) { - ASSERT(contextHasCorrectPrototype(context)); - return V8PerContextDataHolder::from(context)->isolatedWorld(); + if (isMainThread() && worldOfInitializingWindow) { + // It's possible that current() is being called while window is being initialized. + // In order to make current() workable during the initialization phase, + // we cache the world of the initializing window on worldOfInitializingWindow. + // If there is no initiazing window, worldOfInitializingWindow is 0. + return *worldOfInitializingWindow; + } + return world(isolate->GetCurrentContext()); } - // Will return null if there is no DOMWrapperWorld for the current v8::Context - static DOMWrapperWorld* current(); + static DOMWrapperWorld& mainWorld(); // Associates an isolated world (see above for description) with a security // origin. XMLHttpRequest instances used in that world will be considered // to come from that origin, not the frame's. - static void setIsolatedWorldSecurityOrigin(int worldID, PassRefPtr<SecurityOrigin>); - static void clearIsolatedWorldSecurityOrigin(int worldID); + static void setIsolatedWorldSecurityOrigin(int worldId, PassRefPtr<SecurityOrigin>); SecurityOrigin* isolatedWorldSecurityOrigin(); // Associated an isolated world with a Content Security Policy. Resources @@ -89,50 +102,36 @@ public: // FIXME: Right now, resource injection simply bypasses the main world's // DOM. More work is necessary to allow the isolated world's policy to be // applied correctly. - static void setIsolatedWorldContentSecurityPolicy(int worldID, const String& policy); - static void clearIsolatedWorldContentSecurityPolicy(int worldID); + static void setIsolatedWorldContentSecurityPolicy(int worldId, const String& policy); bool isolatedWorldHasContentSecurityPolicy(); - // Associate a logger with the world identified by worldId (worlId may be 0 - // identifying the main world). - static void setActivityLogger(int worldId, PassOwnPtr<V8DOMActivityLogger>); - static V8DOMActivityLogger* activityLogger(int worldId); - bool isMainWorld() const { return m_worldId == MainWorldId; } - bool isIsolatedWorld() const { return isIsolatedWorldId(m_worldId); } + bool isWorkerWorld() const { return m_worldId == WorkerWorldId; } + bool isIsolatedWorld() const { return MainWorldId < m_worldId && m_worldId < IsolatedWorldIdLimit; } int worldId() const { return m_worldId; } int extensionGroup() const { return m_extensionGroup; } - DOMDataStore& isolatedWorldDOMDataStore() const + DOMDataStore& domDataStore() const { return *m_domDataStore; } + + static void setWorldOfInitializingWindow(DOMWrapperWorld* world) { - ASSERT(isIsolatedWorld()); - return *m_domDataStore; + ASSERT(isMainThread()); + worldOfInitializingWindow = world; } - v8::Handle<v8::Context> context(ScriptController&); - - static void setInitializingWindow(bool); + // FIXME: Remove this method once we fix crbug.com/345014. + static bool windowIsBeingInitialized() { return !!worldOfInitializingWindow; } private: - static unsigned isolatedWorldCount; - static PassRefPtr<DOMWrapperWorld> createMainWorld(); - static bool contextHasCorrectPrototype(v8::Handle<v8::Context>); - DOMWrapperWorld(int worldId, int extensionGroup); + static unsigned isolatedWorldCount; + static DOMWrapperWorld* worldOfInitializingWindow; + const int m_worldId; const int m_extensionGroup; OwnPtr<DOMDataStore> m_domDataStore; - - friend DOMWrapperWorld* mainThreadNormalWorld(); - friend DOMWrapperWorld* existingWindowShellWorkaroundWorld(); }; -DOMWrapperWorld* mainThreadNormalWorld(); - -// FIXME: this is a workaround for a problem in ScriptController -// Do not use this anywhere else!! -DOMWrapperWorld* existingWindowShellWorkaroundWorld(); - } // namespace WebCore #endif // DOMWrapperWorld_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/DebuggerScript.js b/chromium/third_party/WebKit/Source/bindings/v8/DebuggerScript.js index 2f92b48013e..bec40048c12 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/DebuggerScript.js +++ b/chromium/third_party/WebKit/Source/bindings/v8/DebuggerScript.js @@ -33,11 +33,17 @@ var DebuggerScript = {}; DebuggerScript.PauseOnExceptionsState = { - DontPauseOnExceptions : 0, - PauseOnAllExceptions : 1, + DontPauseOnExceptions: 0, + PauseOnAllExceptions: 1, PauseOnUncaughtExceptions: 2 }; +DebuggerScript.ScopeInfoDetails = { + AllScopes: 0, + FastAsyncScopes: 1, + NoScopes: 2 +}; + DebuggerScript._pauseOnExceptionsState = DebuggerScript.PauseOnExceptionsState.DontPauseOnExceptions; Debug.clearBreakOnException(); Debug.clearBreakOnUncaughtException(); @@ -70,10 +76,10 @@ DebuggerScript.getFunctionScopes = function(fun) return null; var result = []; for (var i = 0; i < count; i++) { - var scopeMirror = mirror.scope(i); + var scopeDetails = mirror.scope(i).details(); result[i] = { - type: scopeMirror.scopeType(), - object: DebuggerScript._buildScopeObject(scopeMirror) + type: scopeDetails.type(), + object: DebuggerScript._buildScopeObject(scopeDetails.type(), scopeDetails.object()) }; } return result; @@ -199,15 +205,23 @@ DebuggerScript.setPauseOnExceptionsState = function(newState) Debug.clearBreakOnUncaughtException(); } -DebuggerScript.currentCallFrame = function(execState, maximumLimit) +DebuggerScript.frameCount = function(execState) { + return execState.frameCount(); +} + +DebuggerScript.currentCallFrame = function(execState, data) +{ + var maximumLimit = data >> 2; + var scopeDetailsLevel = data & 3; + var frameCount = execState.frameCount(); - if (maximumLimit >= 0 && maximumLimit < frameCount) + if (maximumLimit && maximumLimit < frameCount) frameCount = maximumLimit; var topFrame = undefined; for (var i = frameCount - 1; i >= 0; i--) { var frameMirror = execState.frame(i); - topFrame = DebuggerScript._frameMirrorToJSCallFrame(frameMirror, topFrame); + topFrame = DebuggerScript._frameMirrorToJSCallFrame(frameMirror, topFrame, scopeDetailsLevel); } return topFrame; } @@ -219,14 +233,12 @@ DebuggerScript.stepIntoStatement = function(execState) DebuggerScript.stepOverStatement = function(execState, callFrame) { - var frameMirror = callFrame ? callFrame.frameMirror : undefined; - execState.prepareStep(Debug.StepAction.StepNext, 1, frameMirror); + execState.prepareStep(Debug.StepAction.StepNext, 1); } DebuggerScript.stepOutOfFunction = function(execState, callFrame) { - var frameMirror = callFrame ? callFrame.frameMirror : undefined; - execState.prepareStep(Debug.StepAction.StepOut, 1, frameMirror); + execState.prepareStep(Debug.StepAction.StepOut, 1); } // Returns array in form: @@ -310,43 +322,95 @@ DebuggerScript.isEvalCompilation = function(eventData) return (script.compilationType() === Debug.ScriptCompilationType.Eval); } -DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror, callerFrame) +// NOTE: This function is performance critical, as it can be run on every +// statement that generates an async event (like addEventListener) to support +// asynchronous call stacks. Thus, when possible, initialize the data lazily. +DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror, callerFrame, scopeDetailsLevel) { - // Get function name and display name. + // Stuff that can not be initialized lazily (i.e. valid while paused with a valid break_id). + // The frameMirror and scopeMirror can be accessed only while paused on the debugger. + var frameDetails = frameMirror.details(); + + var funcObject = frameDetails.func(); + var sourcePosition = frameDetails.sourcePosition(); + var thisObject = frameDetails.receiver(); + + var isAtReturn = !!frameDetails.isAtReturn(); + var returnValue = isAtReturn ? frameDetails.returnValue() : undefined; + + var scopeMirrors = (scopeDetailsLevel === DebuggerScript.ScopeInfoDetails.NoScopes ? [] : frameMirror.allScopes(scopeDetailsLevel === DebuggerScript.ScopeInfoDetails.FastAsyncScopes)); + var scopeTypes = new Array(scopeMirrors.length); + var scopeObjects = new Array(scopeMirrors.length); + for (var i = 0; i < scopeMirrors.length; ++i) { + var scopeDetails = scopeMirrors[i].details(); + scopeTypes[i] = scopeDetails.type(); + scopeObjects[i] = scopeDetails.object(); + } + + // Calculated lazily. + var scopeChain; var funcMirror; - var displayName; - try { - funcMirror = frameMirror.func(); - if (funcMirror) { - var valueMirror = funcMirror.property("displayName").value(); - if (valueMirror && valueMirror.isString()) - displayName = valueMirror.value(); + var location; + + function lazyScopeChain() + { + if (!scopeChain) { + scopeChain = []; + for (var i = 0; i < scopeObjects.length; ++i) + scopeChain.push(DebuggerScript._buildScopeObject(scopeTypes[i], scopeObjects[i])); + scopeObjects = null; // Free for GC. + } + return scopeChain; + } + + function ensureFuncMirror() + { + if (!funcMirror) { + funcMirror = MakeMirror(funcObject); + if (!funcMirror.isFunction()) + funcMirror = new UnresolvedFunctionMirror(funcObject); } - } catch(e) { + return funcMirror; } - var functionName; - if (funcMirror) - functionName = displayName || funcMirror.name() || funcMirror.inferredName(); - // Get script ID. - var script = funcMirror.script(); - var sourceID = script && script.id(); + function ensureLocation() + { + if (!location) { + var script = ensureFuncMirror().script(); + if (script) + location = script.locationFromPosition(sourcePosition, true); + if (!location) + location = { line: 0, column: 0 }; + } + return location; + } - // Get location. - var location = frameMirror.sourceLocation(); + function line() + { + return ensureLocation().line; + } - // Get this object. - var thisObject = frameMirror.details_.receiver(); + function column() + { + return ensureLocation().column; + } - var isAtReturn = !!frameMirror.details_.isAtReturn(); - var returnValue = isAtReturn ? frameMirror.details_.returnValue() : undefined; + function sourceID() + { + var script = ensureFuncMirror().script(); + return script && script.id(); + } - var scopeChain = []; - var scopeType = []; - for (var i = 0; i < frameMirror.scopeCount(); i++) { - var scopeMirror = frameMirror.scope(i); - scopeType.push(scopeMirror.scopeType()); - scopeChain.push(DebuggerScript._buildScopeObject(scopeMirror)); + function functionName() + { + var func = ensureFuncMirror(); + if (!func.resolved()) + return undefined; + var displayName; + var valueMirror = func.property("displayName").value(); + if (valueMirror && valueMirror.isString()) + displayName = valueMirror.value(); + return displayName || func.name() || func.inferredName(); } function evaluate(expression) @@ -370,7 +434,7 @@ DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror, callerFrame) var stepInPositionsProtocol; if (stepInPositionsV8) { stepInPositionsProtocol = []; - var script = frameMirror.func().script(); + var script = ensureFuncMirror().script(); if (script) { var scriptId = String(script.id()); for (var i = 0; i < stepInPositionsV8.length; i++) { @@ -388,54 +452,55 @@ DebuggerScript._frameMirrorToJSCallFrame = function(frameMirror, callerFrame) return { "sourceID": sourceID, - "line": location ? location.line : 0, - "column": location ? location.column : 0, + "line": line, + "column": column, "functionName": functionName, "thisObject": thisObject, - "scopeChain": scopeChain, - "scopeType": scopeType, + "scopeChain": lazyScopeChain, + "scopeType": scopeTypes, "evaluate": evaluate, "caller": callerFrame, "restart": restart, "setVariableValue": setVariableValue, "stepInPositions": stepInPositions, "isAtReturn": isAtReturn, - "returnValue": returnValue, - "frameMirror": frameMirror + "returnValue": returnValue }; } -DebuggerScript._buildScopeObject = function(scopeMirror) { - var scopeObject; - switch (scopeMirror.scopeType()) { +DebuggerScript._buildScopeObject = function(scopeType, scopeObject) +{ + var result; + switch (scopeType) { case ScopeType.Local: case ScopeType.Closure: case ScopeType.Catch: // For transient objects we create a "persistent" copy that contains // the same properties. - scopeObject = {}; // Reset scope object prototype to null so that the proto properties // don't appear in the local scope section. - scopeObject.__proto__ = null; - var scopeObjectMirror = scopeMirror.scopeObject(); - var properties = scopeObjectMirror.properties(); + result = { __proto__: null }; + var properties = MakeMirror(scopeObject, true /* transient */).properties(); for (var j = 0; j < properties.length; j++) { var name = properties[j].name(); if (name.charAt(0) === ".") continue; // Skip internal variables like ".arguments" - scopeObject[name] = properties[j].value_; + result[name] = properties[j].value_; } break; case ScopeType.Global: case ScopeType.With: - scopeObject = scopeMirror.details_.object(); + result = scopeObject; break; case ScopeType.Block: // Unsupported yet. Mustn't be reachable. break; } - return scopeObject; + return result; } +// We never resolve Mirror by its handle so to avoid memory leaks caused by Mirrors in the cache we disable it. +ToggleMirrorCache(false); + return DebuggerScript; })(); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/Dictionary.cpp b/chromium/third_party/WebKit/Source/bindings/v8/Dictionary.cpp index 6431d5b1738..156eede687c 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/Dictionary.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/Dictionary.cpp @@ -26,36 +26,35 @@ #include "config.h" #include "bindings/v8/Dictionary.h" -#include "V8DOMError.h" -#include "V8EventTarget.h" -#include "V8IDBKeyRange.h" -#include "V8MIDIPort.h" -#include "V8MediaKeyError.h" -#include "V8SpeechRecognitionError.h" -#include "V8SpeechRecognitionResult.h" -#include "V8SpeechRecognitionResultList.h" -#include "V8Storage.h" -#include "V8VoidCallback.h" -#include "V8Window.h" +#include "bindings/core/v8/V8DOMError.h" +#include "bindings/core/v8/V8EventTarget.h" +#include "bindings/core/v8/V8MediaKeyError.h" +#include "bindings/core/v8/V8MessagePort.h" +#include "bindings/core/v8/V8Storage.h" +#include "bindings/core/v8/V8TextTrack.h" +#include "bindings/core/v8/V8VoidCallback.h" +#include "bindings/core/v8/V8Window.h" +#include "bindings/modules/v8/V8Gamepad.h" +#include "bindings/modules/v8/V8HeaderMap.h" +#include "bindings/modules/v8/V8IDBKeyRange.h" +#include "bindings/modules/v8/V8MIDIPort.h" +#include "bindings/modules/v8/V8MediaStream.h" +#include "bindings/modules/v8/V8SpeechRecognitionResult.h" +#include "bindings/modules/v8/V8SpeechRecognitionResultList.h" #include "bindings/v8/ArrayValue.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "bindings/v8/custom/V8ArrayBufferViewCustom.h" #include "bindings/v8/custom/V8Uint8ArrayCustom.h" +#include "core/html/track/TrackBase.h" +#include "modules/gamepad/Gamepad.h" #include "modules/indexeddb/IDBKeyRange.h" -#include "modules/speech/SpeechRecognitionError.h" +#include "modules/mediastream/MediaStream.h" #include "modules/speech/SpeechRecognitionResult.h" #include "modules/speech/SpeechRecognitionResultList.h" #include "wtf/MathExtras.h" -#include "V8TextTrack.h" -#include "core/html/track/TrackBase.h" - -#include "V8MediaStream.h" -#include "modules/mediastream/MediaStream.h" - namespace WebCore { Dictionary::Dictionary() @@ -174,7 +173,7 @@ bool Dictionary::get(const String& key, double& value, bool& hasValue) const } hasValue = true; - V8TRYCATCH_RETURN(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false); + TONATIVE_DEFAULT(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false); if (v8Number.IsEmpty()) return false; value = v8Number->Value(); @@ -199,17 +198,28 @@ bool Dictionary::convert(ConversionContext& context, const String& key, double& return true; } -bool Dictionary::get(const String& key, String& value) const +template<typename StringType> +inline bool Dictionary::getStringType(const String& key, StringType& value) const { v8::Local<v8::Value> v8Value; if (!getKey(key, v8Value)) return false; - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, v8Value, false); + TOSTRING_DEFAULT(V8StringResource<>, stringValue, v8Value, false); value = stringValue; return true; } +bool Dictionary::get(const String& key, String& value) const +{ + return getStringType(key, value); +} + +bool Dictionary::get(const String& key, AtomicString& value) const +{ + return getStringType(key, value); +} + bool Dictionary::convert(ConversionContext& context, const String& key, String& value) const { ConversionContextScope scope(context); @@ -218,7 +228,7 @@ bool Dictionary::convert(ConversionContext& context, const String& key, String& if (!getKey(key, v8Value)) return true; - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, v8Value, false); + TOSTRING_DEFAULT(V8StringResource<>, stringValue, v8Value, false); value = stringValue; return true; } @@ -229,7 +239,7 @@ bool Dictionary::get(const String& key, ScriptValue& value) const if (!getKey(key, v8Value)) return false; - value = ScriptValue(v8Value, m_isolate); + value = ScriptValue(ScriptState::current(m_isolate), v8Value); return true; } @@ -299,7 +309,7 @@ bool Dictionary::get(const String& key, unsigned long long& value) const if (!getKey(key, v8Value)) return false; - V8TRYCATCH_RETURN(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false); + TONATIVE_DEFAULT(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false); if (v8Number.IsEmpty()) return false; double d = v8Number->Value(); @@ -307,7 +317,7 @@ bool Dictionary::get(const String& key, unsigned long long& value) const return true; } -bool Dictionary::get(const String& key, RefPtr<DOMWindow>& value) const +bool Dictionary::get(const String& key, RefPtrWillBeMember<LocalDOMWindow>& value) const { v8::Local<v8::Value> v8Value; if (!getKey(key, v8Value)) @@ -315,25 +325,17 @@ bool Dictionary::get(const String& key, RefPtr<DOMWindow>& value) const // We need to handle a DOMWindow specially, because a DOMWindow wrapper // exists on a prototype chain of v8Value. - value = 0; - if (v8Value->IsObject()) { - v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value); - v8::Handle<v8::Object> window = wrapper->FindInstanceInPrototypeChain(V8Window::domTemplate(m_isolate, worldTypeInMainThread(m_isolate))); - if (!window.IsEmpty()) - value = V8Window::toNative(window); - } + value = toDOMWindow(v8Value, m_isolate); return true; } -bool Dictionary::get(const String& key, RefPtr<Storage>& value) const +bool Dictionary::get(const String& key, RefPtrWillBeMember<Storage>& value) const { v8::Local<v8::Value> v8Value; if (!getKey(key, v8Value)) return false; - value = 0; - if (V8Storage::hasInstance(v8Value, m_isolate, worldType(m_isolate))) - value = V8Storage::toNative(v8::Handle<v8::Object>::Cast(v8Value)); + value = V8Storage::toNativeWithTypeCheck(m_isolate, v8Value); return true; } @@ -345,7 +347,11 @@ bool Dictionary::get(const String& key, MessagePortArray& value) const ASSERT(m_isolate); ASSERT(m_isolate == v8::Isolate::GetCurrent()); - return getMessagePortArray(v8Value, key, value, m_isolate); + if (WebCore::isUndefinedOrNull(v8Value)) + return true; + bool success = false; + value = toRefPtrNativeArray<MessagePort, V8MessagePort>(v8Value, key, m_isolate, &success); + return success; } bool Dictionary::convert(ConversionContext& context, const String& key, MessagePortArray& value) const @@ -373,8 +379,8 @@ bool Dictionary::get(const String& key, HashSet<AtomicString>& value) const ASSERT(m_isolate == v8::Isolate::GetCurrent()); v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(v8Value); for (size_t i = 0; i < v8Array->Length(); ++i) { - v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Integer::New(i, m_isolate)); - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, indexedValue, false); + v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Integer::New(m_isolate, i)); + TOSTRING_DEFAULT(V8StringResource<>, stringValue, indexedValue, false); value.add(stringValue); } @@ -406,7 +412,7 @@ bool Dictionary::getWithUndefinedOrNullCheck(const String& key, String& value) c if (!getKey(key, v8Value) || WebCore::isUndefinedOrNull(v8Value)) return false; - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, v8Value, false); + TOSTRING_DEFAULT(V8StringResource<>, stringValue, v8Value, false); value = stringValue; return true; } @@ -417,9 +423,7 @@ bool Dictionary::get(const String& key, RefPtr<Uint8Array>& value) const if (!getKey(key, v8Value)) return false; - value = 0; - if (V8Uint8Array::hasInstance(v8Value, m_isolate, worldType(m_isolate))) - value = V8Uint8Array::toNative(v8::Handle<v8::Object>::Cast(v8Value)); + value = V8Uint8Array::toNativeWithTypeCheck(m_isolate, v8Value); return true; } @@ -429,21 +433,17 @@ bool Dictionary::get(const String& key, RefPtr<ArrayBufferView>& value) const if (!getKey(key, v8Value)) return false; - value = 0; - if (V8ArrayBufferView::hasInstance(v8Value, m_isolate, worldType(m_isolate))) - value = V8ArrayBufferView::toNative(v8::Handle<v8::Object>::Cast(v8Value)); + value = V8ArrayBufferView::toNativeWithTypeCheck(m_isolate, v8Value); return true; } -bool Dictionary::get(const String& key, RefPtr<MIDIPort>& value) const +bool Dictionary::get(const String& key, RefPtrWillBeMember<MIDIPort>& value) const { v8::Local<v8::Value> v8Value; if (!getKey(key, v8Value)) return false; - value = 0; - if (V8MIDIPort::hasInstance(v8Value, m_isolate, worldType(m_isolate))) - value = V8MIDIPort::toNative(v8::Handle<v8::Object>::Cast(v8Value)); + value = V8MIDIPort::toNativeWithTypeCheck(m_isolate, v8Value); return true; } @@ -453,13 +453,11 @@ bool Dictionary::get(const String& key, RefPtr<MediaKeyError>& value) const if (!getKey(key, v8Value)) return false; - value = 0; - if (V8MediaKeyError::hasInstance(v8Value, m_isolate, worldType(m_isolate))) - value = V8MediaKeyError::toNative(v8::Handle<v8::Object>::Cast(v8Value)); + value = V8MediaKeyError::toNativeWithTypeCheck(m_isolate, v8Value); return true; } -bool Dictionary::get(const String& key, RefPtr<TrackBase>& value) const +bool Dictionary::get(const String& key, RefPtrWillBeMember<TrackBase>& value) const { v8::Local<v8::Value> v8Value; if (!getKey(key, v8Value)) @@ -471,7 +469,7 @@ bool Dictionary::get(const String& key, RefPtr<TrackBase>& value) const // FIXME: this will need to be changed so it can also return an AudioTrack or a VideoTrack once // we add them. - v8::Handle<v8::Object> track = wrapper->FindInstanceInPrototypeChain(V8TextTrack::domTemplate(m_isolate, worldType(m_isolate))); + v8::Handle<v8::Object> track = V8TextTrack::findInstanceInPrototypeChain(wrapper, m_isolate); if (!track.IsEmpty()) source = V8TextTrack::toNative(track); } @@ -479,39 +477,33 @@ bool Dictionary::get(const String& key, RefPtr<TrackBase>& value) const return true; } -bool Dictionary::get(const String& key, RefPtr<SpeechRecognitionError>& value) const +bool Dictionary::get(const String& key, Member<SpeechRecognitionResult>& value) const { v8::Local<v8::Value> v8Value; if (!getKey(key, v8Value)) return false; - value = 0; - if (V8SpeechRecognitionError::hasInstance(v8Value, m_isolate, worldType(m_isolate))) - value = V8SpeechRecognitionError::toNative(v8::Handle<v8::Object>::Cast(v8Value)); + value = V8SpeechRecognitionResult::toNativeWithTypeCheck(m_isolate, v8Value); return true; } -bool Dictionary::get(const String& key, RefPtr<SpeechRecognitionResult>& value) const +bool Dictionary::get(const String& key, Member<SpeechRecognitionResultList>& value) const { v8::Local<v8::Value> v8Value; if (!getKey(key, v8Value)) return false; - value = 0; - if (V8SpeechRecognitionResult::hasInstance(v8Value, m_isolate, worldType(m_isolate))) - value = V8SpeechRecognitionResult::toNative(v8::Handle<v8::Object>::Cast(v8Value)); + value = V8SpeechRecognitionResultList::toNativeWithTypeCheck(m_isolate, v8Value); return true; } -bool Dictionary::get(const String& key, RefPtr<SpeechRecognitionResultList>& value) const +bool Dictionary::get(const String& key, Member<Gamepad>& value) const { v8::Local<v8::Value> v8Value; if (!getKey(key, v8Value)) return false; - value = 0; - if (V8SpeechRecognitionResultList::hasInstance(v8Value, m_isolate, worldType(m_isolate))) - value = V8SpeechRecognitionResultList::toNative(v8::Handle<v8::Object>::Cast(v8Value)); + value = V8Gamepad::toNativeWithTypeCheck(m_isolate, v8Value); return true; } @@ -521,24 +513,22 @@ bool Dictionary::get(const String& key, RefPtr<MediaStream>& value) const if (!getKey(key, v8Value)) return false; - value = 0; - if (V8MediaStream::hasInstance(v8Value, m_isolate, worldType(m_isolate))) - value = V8MediaStream::toNative(v8::Handle<v8::Object>::Cast(v8Value)); + value = V8MediaStream::toNativeWithTypeCheck(m_isolate, v8Value); return true; } -bool Dictionary::get(const String& key, RefPtr<EventTarget>& value) const +bool Dictionary::get(const String& key, RefPtrWillBeMember<EventTarget>& value) const { v8::Local<v8::Value> v8Value; if (!getKey(key, v8Value)) return false; - value = 0; - // We need to handle a DOMWindow specially, because a DOMWindow wrapper + value = nullptr; + // We need to handle a LocalDOMWindow specially, because a LocalDOMWindow wrapper // exists on a prototype chain of v8Value. if (v8Value->IsObject()) { v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value); - v8::Handle<v8::Object> window = wrapper->FindInstanceInPrototypeChain(V8Window::domTemplate(m_isolate, worldTypeInMainThread(m_isolate))); + v8::Handle<v8::Object> window = V8Window::findInstanceInPrototypeChain(wrapper, m_isolate); if (!window.IsEmpty()) { value = toWrapperTypeInfo(window)->toEventTarget(window); return true; @@ -567,6 +557,16 @@ bool Dictionary::get(const String& key, Dictionary& value) const return true; } +bool Dictionary::get(const String& key, RefPtr<HeaderMap>& value) const +{ + v8::Local<v8::Value> v8Value; + if (!getKey(key, v8Value)) + return false; + + value = V8HeaderMap::toNativeWithTypeCheck(m_isolate, v8Value); + return true; +} + bool Dictionary::convert(ConversionContext& context, const String& key, Dictionary& value) const { ConversionContextScope scope(context); @@ -596,8 +596,8 @@ bool Dictionary::get(const String& key, Vector<String>& value) const v8::Local<v8::Array> v8Array = v8::Local<v8::Array>::Cast(v8Value); for (size_t i = 0; i < v8Array->Length(); ++i) { - v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Uint32::New(i, m_isolate)); - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, indexedValue, false); + v8::Local<v8::Value> indexedValue = v8Array->Get(v8::Uint32::New(m_isolate, i)); + TOSTRING_DEFAULT(V8StringResource<>, stringValue, indexedValue, false); value.append(stringValue); } @@ -657,33 +657,13 @@ bool Dictionary::convert(ConversionContext& context, const String& key, ArrayVal return get(key, value); } -bool Dictionary::get(const String& key, RefPtr<DOMError>& value) const -{ - v8::Local<v8::Value> v8Value; - if (!getKey(key, v8Value)) - return false; - - DOMError* error = 0; - if (v8Value->IsObject()) { - v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(v8Value); - v8::Handle<v8::Object> domError = wrapper->FindInstanceInPrototypeChain(V8DOMError::domTemplate(m_isolate, worldType(m_isolate))); - if (!domError.IsEmpty()) - error = V8DOMError::toNative(domError); - } - value = error; - return true; -} - -bool Dictionary::get(const String& key, OwnPtr<VoidCallback>& value) const +bool Dictionary::get(const String& key, RefPtrWillBeMember<DOMError>& value) const { v8::Local<v8::Value> v8Value; if (!getKey(key, v8Value)) return false; - if (!v8Value->IsFunction()) - return false; - - value = V8VoidCallback::create(v8::Handle<v8::Function>::Cast(v8Value), getExecutionContext()); + value = V8DOMError::toNativeWithTypeCheck(m_isolate, v8Value); return true; } @@ -705,8 +685,8 @@ bool Dictionary::getOwnPropertiesAsStringHashMap(HashMap<String, String>& hashMa continue; v8::Local<v8::Value> value = options->Get(key); - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringKey, key, false); - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, value, false); + TOSTRING_DEFAULT(V8StringResource<>, stringKey, key, false); + TOSTRING_DEFAULT(V8StringResource<>, stringValue, value, false); if (!static_cast<const String&>(stringKey).isEmpty()) hashMap.set(stringKey, stringValue); } @@ -730,7 +710,7 @@ bool Dictionary::getOwnPropertyNames(Vector<String>& names) const v8::Local<v8::String> key = properties->Get(i)->ToString(); if (!options->Has(key)) continue; - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringKey, key, false); + TOSTRING_DEFAULT(V8StringResource<>, stringKey, key, false); names.append(stringKey); } @@ -758,12 +738,7 @@ Dictionary::ConversionContext& Dictionary::ConversionContext::setConversionType( void Dictionary::ConversionContext::throwTypeError(const String& detail) { - if (forConstructor()) { - exceptionState().throwTypeError(detail); - } else { - ASSERT(!methodName().isEmpty()); - exceptionState().throwTypeError(ExceptionMessages::failedToExecute(interfaceName(), methodName(), detail)); - } + exceptionState().throwTypeError(detail); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/Dictionary.h b/chromium/third_party/WebKit/Source/bindings/v8/Dictionary.h index 3f29651e876..2268c63bd2f 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/Dictionary.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/Dictionary.h @@ -28,6 +28,7 @@ #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" +#include "bindings/v8/Nullable.h" #include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8BindingMacros.h" @@ -44,12 +45,14 @@ namespace WebCore { class ArrayValue; class DOMError; -class DOMWindow; +class LocalDOMWindow; +class Gamepad; +class MediaStream; +class HeaderMap; class IDBKeyRange; class MIDIPort; class MediaKeyError; class Notification; -class SpeechRecognitionError; class SpeechRecognitionResult; class SpeechRecognitionResultList; class Storage; @@ -57,6 +60,7 @@ class TrackBase; class VoidCallback; class Dictionary { + ALLOW_ONLY_INLINE_ALLOCATION(); public: Dictionary(); Dictionary(const v8::Handle<v8::Value>& options, v8::Isolate*); @@ -72,32 +76,33 @@ public: bool get(const String&, double&, bool& hasValue) const; bool get(const String&, double&) const; bool get(const String&, String&) const; + bool get(const String&, AtomicString&) const; bool get(const String&, ScriptValue&) const; bool get(const String&, short&) const; bool get(const String&, unsigned short&) const; bool get(const String&, unsigned&) const; bool get(const String&, unsigned long&) const; bool get(const String&, unsigned long long&) const; - bool get(const String&, RefPtr<DOMWindow>&) const; - bool get(const String&, RefPtr<Storage>&) const; + bool get(const String&, RefPtrWillBeMember<LocalDOMWindow>&) const; + bool get(const String&, RefPtrWillBeMember<Storage>&) const; bool get(const String&, MessagePortArray&) const; bool get(const String&, RefPtr<Uint8Array>&) const; bool get(const String&, RefPtr<ArrayBufferView>&) const; - bool get(const String&, RefPtr<MIDIPort>&) const; + bool get(const String&, RefPtrWillBeMember<MIDIPort>&) const; bool get(const String&, RefPtr<MediaKeyError>&) const; - bool get(const String&, RefPtr<TrackBase>&) const; - bool get(const String&, RefPtr<SpeechRecognitionError>&) const; - bool get(const String&, RefPtr<SpeechRecognitionResult>&) const; - bool get(const String&, RefPtr<SpeechRecognitionResultList>&) const; + bool get(const String&, RefPtrWillBeMember<TrackBase>&) const; + bool get(const String&, Member<SpeechRecognitionResult>&) const; + bool get(const String&, Member<SpeechRecognitionResultList>&) const; + bool get(const String&, Member<Gamepad>&) const; bool get(const String&, RefPtr<MediaStream>&) const; - bool get(const String&, RefPtr<EventTarget>&) const; + bool get(const String&, RefPtrWillBeMember<EventTarget>&) const; bool get(const String&, HashSet<AtomicString>&) const; bool get(const String&, Dictionary&) const; bool get(const String&, Vector<String>&) const; bool get(const String&, ArrayValue&) const; - bool get(const String&, RefPtr<DOMError>&) const; - bool get(const String&, OwnPtr<VoidCallback>&) const; + bool get(const String&, RefPtrWillBeMember<DOMError>&) const; bool get(const String&, v8::Local<v8::Value>&) const; + bool get(const String&, RefPtr<HeaderMap>&) const; class ConversionContext { public: @@ -152,14 +157,20 @@ public: bool convert(ConversionContext&, const String&, ScriptValue&) const; template<typename IntegralType> - bool convert(ConversionContext &, const String&, IntegralType&) const; - bool convert(ConversionContext &, const String&, MessagePortArray&) const; - bool convert(ConversionContext &, const String&, HashSet<AtomicString>&) const; - bool convert(ConversionContext &, const String&, Dictionary&) const; - bool convert(ConversionContext &, const String&, Vector<String>&) const; - bool convert(ConversionContext &, const String&, ArrayValue&) const; - template<typename T> - bool convert(ConversionContext &, const String&, RefPtr<T>&) const; + bool convert(ConversionContext&, const String&, IntegralType&) const; + template<typename IntegralType> + bool convert(ConversionContext&, const String&, Nullable<IntegralType>&) const; + + bool convert(ConversionContext&, const String&, MessagePortArray&) const; + bool convert(ConversionContext&, const String&, HashSet<AtomicString>&) const; + bool convert(ConversionContext&, const String&, Dictionary&) const; + bool convert(ConversionContext&, const String&, Vector<String>&) const; + bool convert(ConversionContext&, const String&, ArrayValue&) const; + template<template <typename> class PointerType, typename T> + bool convert(ConversionContext&, const String&, PointerType<T>&) const; + + template<typename StringType> + bool getStringType(const String&, StringType&) const; bool getOwnPropertiesAsStringHashMap(HashMap<String, String>&) const; bool getOwnPropertyNames(Vector<String>&) const; @@ -168,13 +179,7 @@ public: bool hasProperty(const String&) const; - // Only allow inline allocation. - void* operator new(size_t, NotNullTag, void* location) { return location; } - private: - // Disallow new allocation. - void* operator new(size_t); - bool getKey(const String& key, v8::Local<v8::Value>&) const; v8::Handle<v8::Value> m_options; @@ -195,90 +200,90 @@ struct IntegralTypeTraits { template <> struct IntegralTypeTraits<uint8_t> { - static inline uint8_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) + static inline uint8_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toUInt8(value, configuration, ok); + return toUInt8(value, configuration, exceptionState); } static const String typeName() { return "UInt8"; } }; template <> struct IntegralTypeTraits<int8_t> { - static inline int8_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) + static inline int8_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toInt8(value, configuration, ok); + return toInt8(value, configuration, exceptionState); } static const String typeName() { return "Int8"; } }; template <> struct IntegralTypeTraits<unsigned short> { - static inline uint16_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) + static inline uint16_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toUInt16(value, configuration, ok); + return toUInt16(value, configuration, exceptionState); } static const String typeName() { return "UInt16"; } }; template <> struct IntegralTypeTraits<short> { - static inline int16_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) + static inline int16_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toInt16(value, configuration, ok); + return toInt16(value, configuration, exceptionState); } static const String typeName() { return "Int16"; } }; template <> struct IntegralTypeTraits<unsigned> { - static inline uint32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) + static inline uint32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toUInt32(value, configuration, ok); + return toUInt32(value, configuration, exceptionState); } static const String typeName() { return "UInt32"; } }; template <> struct IntegralTypeTraits<unsigned long> { - static inline uint32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) + static inline uint32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toUInt32(value, configuration, ok); + return toUInt32(value, configuration, exceptionState); } static const String typeName() { return "UInt32"; } }; template <> struct IntegralTypeTraits<int> { - static inline int32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) + static inline int32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toInt32(value, configuration, ok); + return toInt32(value, configuration, exceptionState); } static const String typeName() { return "Int32"; } }; template <> struct IntegralTypeTraits<long> { - static inline int32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) + static inline int32_t toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toInt32(value, configuration, ok); + return toInt32(value, configuration, exceptionState); } static const String typeName() { return "Int32"; } }; template <> struct IntegralTypeTraits<unsigned long long> { - static inline unsigned long long toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) + static inline unsigned long long toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toUInt64(value, configuration, ok); + return toUInt64(value, configuration, exceptionState); } static const String typeName() { return "UInt64"; } }; template <> struct IntegralTypeTraits<long long> { - static inline long long toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) + static inline long long toIntegral(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toInt64(value, configuration, ok); + return toInt64(value, configuration, exceptionState); } static const String typeName() { return "Int64"; } }; @@ -291,18 +296,36 @@ template<typename T> bool Dictionary::convert(ConversionContext& context, const if (!getKey(key, v8Value)) return true; - bool ok = false; - value = IntegralTypeTraits<T>::toIntegral(v8Value, NormalConversion, ok); - if (ok) + value = IntegralTypeTraits<T>::toIntegral(v8Value, NormalConversion, context.exceptionState()); + if (context.exceptionState().throwIfNeeded()) + return false; + + return true; +} + +template<typename T> bool Dictionary::convert(ConversionContext& context, const String& key, Nullable<T>& value) const +{ + ConversionContextScope scope(context); + + v8::Local<v8::Value> v8Value; + if (!getKey(key, v8Value)) return true; - V8TRYCATCH_RETURN(v8::Local<v8::Number>, v8Number, v8Value->ToNumber(), false); - ASSERT(v8Number.IsEmpty()); - context.throwTypeError(ExceptionMessages::incorrectPropertyType(key, "does not have type " + IntegralTypeTraits<T>::typeName() + ".")); - return false; + if (context.isNullable() && WebCore::isUndefinedOrNull(v8Value)) { + value = Nullable<T>(); + return true; + } + + T converted = IntegralTypeTraits<T>::toIntegral(v8Value, NormalConversion, context.exceptionState()); + + if (context.exceptionState().throwIfNeeded()) + return false; + + value = Nullable<T>(converted); + return true; } -template<typename T> bool Dictionary::convert(ConversionContext& context, const String& key, RefPtr<T>& value) const +template<template <typename> class PointerType, typename T> bool Dictionary::convert(ConversionContext& context, const String& key, PointerType<T>& value) const { ConversionContextScope scope(context); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionMessages.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionMessages.cpp index beea8bef6d3..c65e04703d4 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionMessages.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionMessages.cpp @@ -31,33 +31,59 @@ #include "config.h" #include "bindings/v8/ExceptionMessages.h" +#include "platform/Decimal.h" #include "wtf/MathExtras.h" namespace WebCore { -String ExceptionMessages::failedToConstruct(const String& type, const String& detail) +String ExceptionMessages::failedToConstruct(const char* type, const String& detail) { - return "Failed to construct '" + type + (!detail.isEmpty() ? String("': " + detail) : String("'")); + return "Failed to construct '" + String(type) + (!detail.isEmpty() ? String("': " + detail) : String("'")); } -String ExceptionMessages::failedToExecute(const String& method, const String& type, const String& detail) +String ExceptionMessages::failedToEnumerate(const char* type, const String& detail) { - return "Failed to execute '" + method + "' on '" + type + (!detail.isEmpty() ? String("': " + detail) : String("'")); + return "Failed to enumerate the properties of '" + String(type) + (!detail.isEmpty() ? String("': " + detail) : String("'")); } -String ExceptionMessages::failedToGet(const String& property, const String& type, const String& detail) +String ExceptionMessages::failedToExecute(const char* method, const char* type, const String& detail) { - return "Failed to read the '" + property + "' property from '" + type + "': " + detail; + return "Failed to execute '" + String(method) + "' on '" + String(type) + (!detail.isEmpty() ? String("': " + detail) : String("'")); } -String ExceptionMessages::failedToSet(const String& property, const String& type, const String& detail) +String ExceptionMessages::failedToGet(const char* property, const char* type, const String& detail) { - return "Failed to set the '" + property + "' property on '" + type + "': " + detail; + return "Failed to read the '" + String(property) + "' property from '" + String(type) + "': " + detail; } -String ExceptionMessages::failedToDelete(const String& property, const String& type, const String& detail) +String ExceptionMessages::failedToSet(const char* property, const char* type, const String& detail) { - return "Failed to delete the '" + property + "' property from '" + type + "': " + detail; + return "Failed to set the '" + String(property) + "' property on '" + String(type) + "': " + detail; +} + +String ExceptionMessages::failedToDelete(const char* property, const char* type, const String& detail) +{ + return "Failed to delete the '" + String(property) + "' property from '" + String(type) + "': " + detail; +} + +String ExceptionMessages::failedToGetIndexed(const char* type, const String& detail) +{ + return "Failed to read an indexed property from '" + String(type) + "': " + detail; +} + +String ExceptionMessages::failedToSetIndexed(const char* type, const String& detail) +{ + return "Failed to set an indexed property on '" + String(type) + "': " + detail; +} + +String ExceptionMessages::failedToDeleteIndexed(const char* type, const String& detail) +{ + return "Failed to delete an indexed property from '" + String(type) + "': " + detail; +} + +String ExceptionMessages::constructorNotCallableAsFunction(const char* type) +{ + return failedToConstruct(type, "Please use the 'new' operator, this DOM object constructor cannot be called as a function."); } String ExceptionMessages::incorrectPropertyType(const String& property, const String& detail) @@ -65,9 +91,14 @@ String ExceptionMessages::incorrectPropertyType(const String& property, const St return "The '" + property + "' property " + detail; } -String ExceptionMessages::incorrectArgumentType(int argumentIndex, const String& detail) +String ExceptionMessages::invalidArity(const char* expected, unsigned provided) { - return "The " + ordinalNumber(argumentIndex) + " argument " + detail; + return "Valid arities are: " + String(expected) + ", but " + String::number(provided) + " arguments provided."; +} + +String ExceptionMessages::argumentNullOrIncorrectType(int argumentIndex, const String& expectedType) +{ + return "The " + ordinalNumber(argumentIndex) + " argument provided is either null, or an invalid " + expectedType + " object."; } String ExceptionMessages::notAnArrayTypeArgumentOrValue(int argumentIndex) @@ -90,10 +121,16 @@ String ExceptionMessages::notEnoughArguments(unsigned expected, unsigned provide return String::number(expected) + " argument" + (expected > 1 ? "s" : "") + " required, but only " + String::number(provided) + " present."; } -String ExceptionMessages::notAFiniteNumber(double value) +String ExceptionMessages::notAFiniteNumber(double value, const char* name) { ASSERT(!std::isfinite(value)); - return std::isinf(value) ? "The value provided is infinite." : "The value provided is not a number."; + return String::format("The %s is %s.", name, std::isinf(value) ? "infinite" : "not a number"); +} + +String ExceptionMessages::notAFiniteNumber(const Decimal& value, const char* name) +{ + ASSERT(!value.isFinite()); + return String::format("The %s is %s.", name, value.isInfinity() ? "infinite" : "not a number"); } String ExceptionMessages::ordinalNumber(int number) @@ -116,4 +153,22 @@ String ExceptionMessages::ordinalNumber(int number) return String::number(number) + suffix; } +String ExceptionMessages::readOnly(const char* detail) +{ + DEFINE_STATIC_LOCAL(String, readOnly, ("This object is read-only.")); + return detail ? String::format("This object is read-only, because %s.", detail) : readOnly; +} + +template <> +String ExceptionMessages::formatNumber<float>(float number) +{ + return formatPotentiallyNonFiniteNumber(number); +} + +template <> +String ExceptionMessages::formatNumber<double>(double number) +{ + return formatPotentiallyNonFiniteNumber(number); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionMessages.h b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionMessages.h index 92f8a9f5879..a74819b3970 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionMessages.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionMessages.h @@ -31,33 +31,134 @@ #ifndef ExceptionMessages_h #define ExceptionMessages_h +#include "wtf/MathExtras.h" +#include "wtf/text/StringBuilder.h" #include "wtf/text/WTFString.h" namespace WebCore { +class Decimal; + class ExceptionMessages { public: - static String failedToConstruct(const String& type, const String& detail = String()); - static String failedToExecute(const String& method, const String& type, const String& detail = String()); - static String failedToGet(const String& property, const String& type, const String& detail); - static String failedToSet(const String& property, const String& type, const String& detail); - static String failedToDelete(const String& property, const String& type, const String& detail); + enum BoundType { + InclusiveBound, + ExclusiveBound, + }; + + static String argumentNullOrIncorrectType(int argumentIndex, const String& expectedType); + static String constructorNotCallableAsFunction(const char* type); + + static String failedToConstruct(const char* type, const String& detail); + static String failedToEnumerate(const char* type, const String& detail); + static String failedToExecute(const char* method, const char* type, const String& detail); + static String failedToGet(const char* property, const char* type, const String& detail); + static String failedToSet(const char* property, const char* type, const String& detail); + static String failedToDelete(const char* property, const char* type, const String& detail); + static String failedToGetIndexed(const char* type, const String& detail); + static String failedToSetIndexed(const char* type, const String& detail); + static String failedToDeleteIndexed(const char* type, const String& detail); + + template <typename NumType> + static String formatNumber(NumType number) + { + return formatFiniteNumber(number); + } - static String incorrectArgumentType(int argumentIndex, const String& detail); static String incorrectPropertyType(const String& property, const String& detail); + template <typename NumberType> + static String indexExceedsMaximumBound(const char* name, NumberType given, NumberType bound) + { + bool eq = given == bound; + StringBuilder result; + result.append("The "); + result.append(name); + result.append(" provided ("); + result.append(formatNumber(given)); + result.append(") is greater than "); + result.append(eq ? "or equal to " : ""); + result.append("the maximum bound ("); + result.append(formatNumber(bound)); + result.append(")."); + return result.toString(); + } + + template <typename NumberType> + static String indexExceedsMinimumBound(const char* name, NumberType given, NumberType bound) + { + bool eq = given == bound; + StringBuilder result; + result.append("The "); + result.append(name); + result.append(" provided ("); + result.append(formatNumber(given)); + result.append(") is less than "); + result.append(eq ? "or equal to " : ""); + result.append("the minimum bound ("); + result.append(formatNumber(bound)); + result.append(")."); + return result.toString(); + } + + template <typename NumberType> + static String indexOutsideRange(const char* name, NumberType given, NumberType lowerBound, BoundType lowerType, NumberType upperBound, BoundType upperType) + { + StringBuilder result; + result.append("The "); + result.append(name); + result.append(" provided ("); + result.append(formatNumber(given)); + result.append(") is outside the range "); + result.append(lowerType == ExclusiveBound ? '(' : '['); + result.append(formatNumber(lowerBound)); + result.append(", "); + result.append(formatNumber(upperBound)); + result.append(upperType == ExclusiveBound ? ')' : ']'); + result.append('.'); + return result.toString(); + } + + static String invalidArity(const char* expected, unsigned provided); + // If > 0, the argument index that failed type check (1-indexed.) // If == 0, a (non-argument) value (e.g., a setter) failed the same check. static String notAnArrayTypeArgumentOrValue(int argumentIndex); static String notASequenceTypeProperty(const String& propertyName); - static String notAFiniteNumber(double value); + static String notAFiniteNumber(double value, const char* name = "value provided"); + static String notAFiniteNumber(const Decimal& value, const char* name = "value provided"); static String notEnoughArguments(unsigned expected, unsigned providedleastNumMandatoryParams); + static String readOnly(const char* detail = 0); + private: + template <typename NumType> + static String formatFiniteNumber(NumType number) + { + if (number > 1e20 || number < -1e20) + return String::format("%e", 1.0*number); + return String::number(number); + } + + template <typename NumType> + static String formatPotentiallyNonFiniteNumber(NumType number) + { + if (std::isnan(number)) + return "NaN"; + if (std::isinf(number)) + return number > 0 ? "Infinity" : "-Infinity"; + if (number > 1e20 || number < -1e20) + return String::format("%e", number); + return String::number(number); + } + static String ordinalNumber(int number); }; +template <> String ExceptionMessages::formatNumber<float>(float number); +template <> String ExceptionMessages::formatNumber<double>(double number); + } // namespace WebCore #endif // ExceptionMessages_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionState.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionState.cpp index 77c9103d7be..d51325cc41d 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionState.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionState.cpp @@ -47,21 +47,26 @@ void ExceptionState::throwDOMException(const ExceptionCode& ec, const String& me { ASSERT(ec); ASSERT(m_isolate); + ASSERT(!m_creationContext.IsEmpty()); // SecurityError is thrown via ::throwSecurityError, and _careful_ consideration must be given to the data exposed to JavaScript via the 'sanitizedMessage'. ASSERT(ec != SecurityError); m_code = ec; String processedMessage = addExceptionContext(message); + m_message = processedMessage; setException(V8ThrowException::createDOMException(ec, processedMessage, m_creationContext, m_isolate)); } void ExceptionState::throwSecurityError(const String& sanitizedMessage, const String& unsanitizedMessage) { ASSERT(m_isolate); + ASSERT(!m_creationContext.IsEmpty()); m_code = SecurityError; String finalSanitized = addExceptionContext(sanitizedMessage); + m_message = finalSanitized; String finalUnsanitized = addExceptionContext(unsanitizedMessage); + setException(V8ThrowException::createDOMException(SecurityError, finalSanitized, finalUnsanitized, m_creationContext, m_isolate)); } @@ -76,26 +81,57 @@ void ExceptionState::setException(v8::Handle<v8::Value> exception) m_exception.set(m_isolate, exception); } +void ExceptionState::throwException() +{ + ASSERT(!m_exception.isEmpty()); + V8ThrowException::throwError(m_exception.newLocal(m_isolate), m_isolate); +} + void ExceptionState::throwTypeError(const String& message) { ASSERT(m_isolate); m_code = TypeError; + m_message = message; setException(V8ThrowException::createTypeError(addExceptionContext(message), m_isolate)); } +void NonThrowableExceptionState::throwDOMException(const ExceptionCode& ec, const String& message) +{ + ASSERT_NOT_REACHED(); + m_code = ec; + m_message = message; +} + +void NonThrowableExceptionState::throwTypeError(const String& message) +{ + ASSERT_NOT_REACHED(); + m_code = TypeError; + m_message = message; +} + +void NonThrowableExceptionState::throwSecurityError(const String& sanitizedMessage, const String&) +{ + ASSERT_NOT_REACHED(); + m_code = SecurityError; + m_message = sanitizedMessage; +} + void TrackExceptionState::throwDOMException(const ExceptionCode& ec, const String& message) { m_code = ec; + m_message = message; } -void TrackExceptionState::throwTypeError(const String&) +void TrackExceptionState::throwTypeError(const String& message) { m_code = TypeError; + m_message = message; } -void TrackExceptionState::throwSecurityError(const String&, const String&) +void TrackExceptionState::throwSecurityError(const String& sanitizedMessage, const String&) { m_code = SecurityError; + m_message = sanitizedMessage; } String ExceptionState::addExceptionContext(const String& message) const @@ -113,8 +149,17 @@ String ExceptionState::addExceptionContext(const String& message) const processedMessage = ExceptionMessages::failedToGet(propertyName(), interfaceName(), message); else if (m_context == SetterContext) processedMessage = ExceptionMessages::failedToSet(propertyName(), interfaceName(), message); - } else if (!propertyName() && interfaceName() && m_context == ConstructionContext) { - processedMessage = ExceptionMessages::failedToConstruct(interfaceName(), message); + } else if (!propertyName() && interfaceName()) { + if (m_context == ConstructionContext) + processedMessage = ExceptionMessages::failedToConstruct(interfaceName(), message); + else if (m_context == EnumerationContext) + processedMessage = ExceptionMessages::failedToEnumerate(interfaceName(), message); + else if (m_context == IndexedDeletionContext) + processedMessage = ExceptionMessages::failedToDeleteIndexed(interfaceName(), message); + else if (m_context == IndexedGetterContext) + processedMessage = ExceptionMessages::failedToGetIndexed(interfaceName(), message); + else if (m_context == IndexedSetterContext) + processedMessage = ExceptionMessages::failedToSetIndexed(interfaceName(), message); } return processedMessage; } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionState.h b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionState.h index bfe2790e16a..d9c2b05b8ef 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionState.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionState.h @@ -50,17 +50,14 @@ public: DeletionContext, GetterContext, SetterContext, + EnumerationContext, + QueryContext, + IndexedGetterContext, + IndexedSetterContext, + IndexedDeletionContext, UnknownContext, // FIXME: Remove this once we've flipped over to the new API. }; - explicit ExceptionState(const v8::Handle<v8::Object>& creationContext, v8::Isolate* isolate) - : m_code(0) - , m_context(UnknownContext) - , m_propertyName(0) - , m_interfaceName(0) - , m_creationContext(creationContext) - , m_isolate(isolate) { } - ExceptionState(Context context, const char* propertyName, const char* interfaceName, const v8::Handle<v8::Object>& creationContext, v8::Isolate* isolate) : m_code(0) , m_context(context) @@ -75,30 +72,23 @@ public: , m_propertyName(0) , m_interfaceName(interfaceName) , m_creationContext(creationContext) - , m_isolate(isolate) { ASSERT(m_context == ConstructionContext); } + , m_isolate(isolate) { ASSERT(m_context == ConstructionContext || m_context == EnumerationContext || m_context == IndexedSetterContext || m_context == IndexedGetterContext || m_context == IndexedDeletionContext); } virtual void throwDOMException(const ExceptionCode&, const String& message); virtual void throwTypeError(const String& message); virtual void throwSecurityError(const String& sanitizedMessage, const String& unsanitizedMessage = String()); - // Please don't use these methods. Use ::throwDOMException and ::throwTypeError, and pass in a useful exception message. - virtual void throwUninformativeAndGenericDOMException(const ExceptionCode& ec) { throwDOMException(ec, String()); } - virtual void throwUninformativeAndGenericTypeError() { throwTypeError(String()); } - bool hadException() const { return !m_exception.isEmpty() || m_code; } void clearException(); ExceptionCode code() const { return m_code; } + const String& message() const { return m_message; } bool throwIfNeeded() { - if (m_exception.isEmpty()) { - if (!m_code) - return false; - throwUninformativeAndGenericDOMException(m_code); - } - - V8ThrowException::throwError(m_exception.newLocal(m_isolate), m_isolate); + if (!hadException()) + return false; + throwException(); return true; } @@ -106,14 +96,21 @@ public: const char* propertyName() const { return m_propertyName; } const char* interfaceName() const { return m_interfaceName; } + void rethrowV8Exception(v8::Handle<v8::Value> value) + { + setException(value); + } + protected: ExceptionCode m_code; Context m_context; + String m_message; const char* m_propertyName; const char* m_interfaceName; private: void setException(v8::Handle<v8::Value>); + void throwException(); String addExceptionContext(const String&) const; @@ -122,12 +119,22 @@ private: v8::Isolate* m_isolate; }; -class TrackExceptionState : public ExceptionState { +// Used if exceptions can/should not be directly thrown. +class NonThrowableExceptionState FINAL : public ExceptionState { +public: + NonThrowableExceptionState(): ExceptionState(ExceptionState::UnknownContext, 0, 0, v8::Handle<v8::Object>(), v8::Isolate::GetCurrent()) { } + virtual void throwDOMException(const ExceptionCode&, const String& message) OVERRIDE; + virtual void throwTypeError(const String& message = String()) OVERRIDE; + virtual void throwSecurityError(const String& sanitizedMessage, const String& unsanitizedMessage = String()) OVERRIDE; +}; + +// Used if any exceptions thrown are ignorable. +class TrackExceptionState FINAL : public ExceptionState { public: - TrackExceptionState(): ExceptionState(v8::Handle<v8::Object>(), 0) { } - virtual void throwDOMException(const ExceptionCode&, const String& message) OVERRIDE FINAL; - virtual void throwTypeError(const String& message = String()) OVERRIDE FINAL; - virtual void throwSecurityError(const String& sanitizedMessage, const String& unsanitizedMessage = String()) OVERRIDE FINAL; + TrackExceptionState(): ExceptionState(ExceptionState::UnknownContext, 0, 0, v8::Handle<v8::Object>(), v8::Isolate::GetCurrent()) { } + virtual void throwDOMException(const ExceptionCode&, const String& message) OVERRIDE; + virtual void throwTypeError(const String& message = String()) OVERRIDE; + virtual void throwSecurityError(const String& sanitizedMessage, const String& unsanitizedMessage = String()) OVERRIDE; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionStatePlaceholder.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionStatePlaceholder.cpp index 9d33119c814..6cfb6b2452e 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionStatePlaceholder.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionStatePlaceholder.cpp @@ -33,10 +33,10 @@ namespace WebCore { -#if !ASSERT_DISABLED +#if ASSERT_ENABLED NoExceptionStateAssertionChecker::NoExceptionStateAssertionChecker(const char* file, int line) - : ExceptionState(v8::Handle<v8::Object>(), 0) + : ExceptionState(ExceptionState::UnknownContext, 0, 0, v8::Handle<v8::Object>(), 0) , m_file(file) , m_line(line) { } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionStatePlaceholder.h b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionStatePlaceholder.h index 84f6eb0b0f6..6df5b1ab9bb 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ExceptionStatePlaceholder.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ExceptionStatePlaceholder.h @@ -34,6 +34,7 @@ #include "bindings/v8/ExceptionState.h" #include "wtf/Assertions.h" #include "wtf/text/WTFString.h" +#include <v8.h> namespace WebCore { @@ -41,30 +42,26 @@ class ExceptionState; typedef int ExceptionCode; -class IgnorableExceptionState : public ExceptionState { +class IgnorableExceptionState FINAL : public ExceptionState { public: - IgnorableExceptionState(): ExceptionState(v8::Handle<v8::Object>(), 0) { } + IgnorableExceptionState(): ExceptionState(ExceptionState::UnknownContext, 0, 0, v8::Handle<v8::Object>(), 0) { } ExceptionState& returnThis() { return *this; } - virtual void throwDOMException(const ExceptionCode&, const String& message = String()) OVERRIDE FINAL { }; - virtual void throwTypeError(const String& message = String()) OVERRIDE FINAL { } - virtual void throwSecurityError(const String& sanitizedMessage, const String& unsanitizedMessage = String()) OVERRIDE FINAL { } + virtual void throwDOMException(const ExceptionCode&, const String& message = String()) OVERRIDE { } + virtual void throwTypeError(const String& message = String()) OVERRIDE { } + virtual void throwSecurityError(const String& sanitizedMessage, const String& unsanitizedMessage = String()) OVERRIDE { } }; #define IGNORE_EXCEPTION (::WebCore::IgnorableExceptionState().returnThis()) -#if ASSERT_DISABLED +#if ASSERT_ENABLED -#define ASSERT_NO_EXCEPTION (::WebCore::IgnorableExceptionState().returnThis()) - -#else - -class NoExceptionStateAssertionChecker : public ExceptionState { +class NoExceptionStateAssertionChecker FINAL : public ExceptionState { public: NoExceptionStateAssertionChecker(const char* file, int line); ExceptionState& returnThis() { return *this; } - virtual void throwDOMException(const ExceptionCode&, const String& message = String()) OVERRIDE FINAL; - virtual void throwTypeError(const String& message = String()) OVERRIDE FINAL; - virtual void throwSecurityError(const String& sanitizedMessage, const String& unsanitizedMessage = String()) OVERRIDE FINAL; + virtual void throwDOMException(const ExceptionCode&, const String& message = String()) OVERRIDE; + virtual void throwTypeError(const String& message = String()) OVERRIDE; + virtual void throwSecurityError(const String& sanitizedMessage, const String& unsanitizedMessage = String()) OVERRIDE; private: const char* m_file; @@ -73,6 +70,10 @@ private: #define ASSERT_NO_EXCEPTION (::WebCore::NoExceptionStateAssertionChecker(__FILE__, __LINE__).returnThis()) +#else + +#define ASSERT_NO_EXCEPTION (::WebCore::IgnorableExceptionState().returnThis()) + #endif } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilities.cpp b/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilities.cpp index 1676649e556..bc50f3c7a8a 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilities.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilities.cpp @@ -26,23 +26,25 @@ #include "config.h" #include "bindings/v8/IDBBindingUtilities.h" -#include "V8DOMStringList.h" -#include "V8IDBCursor.h" -#include "V8IDBCursorWithValue.h" -#include "V8IDBDatabase.h" -#include "V8IDBIndex.h" -#include "V8IDBKeyRange.h" -#include "V8IDBObjectStore.h" -#include "V8IDBTransaction.h" -#include "bindings/v8/DOMRequestState.h" +#include "bindings/core/v8/V8DOMStringList.h" +#include "bindings/modules/v8/V8IDBCursor.h" +#include "bindings/modules/v8/V8IDBCursorWithValue.h" +#include "bindings/modules/v8/V8IDBDatabase.h" +#include "bindings/modules/v8/V8IDBIndex.h" +#include "bindings/modules/v8/V8IDBKeyRange.h" +#include "bindings/modules/v8/V8IDBObjectStore.h" +#include "bindings/modules/v8/V8IDBRequest.h" +#include "bindings/modules/v8/V8IDBTransaction.h" #include "bindings/v8/SerializedScriptValue.h" #include "bindings/v8/V8Binding.h" +#include "bindings/v8/V8HiddenValue.h" #include "bindings/v8/custom/V8ArrayBufferViewCustom.h" #include "bindings/v8/custom/V8Uint8ArrayCustom.h" #include "modules/indexeddb/IDBKey.h" #include "modules/indexeddb/IDBKeyPath.h" #include "modules/indexeddb/IDBKeyRange.h" #include "modules/indexeddb/IDBTracing.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/SharedBuffer.h" #include "wtf/ArrayBufferView.h" #include "wtf/MathExtras.h" @@ -51,7 +53,7 @@ namespace WebCore { -v8::Handle<v8::Value> deserializeIDBValueBuffer(SharedBuffer*, v8::Isolate*); +static v8::Handle<v8::Value> deserializeIDBValueBuffer(v8::Isolate*, SharedBuffer*, const Vector<blink::WebBlobInfo>*); static v8::Handle<v8::Value> toV8(const IDBKeyPath& value, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { @@ -61,7 +63,7 @@ static v8::Handle<v8::Value> toV8(const IDBKeyPath& value, v8::Handle<v8::Object case IDBKeyPath::StringType: return v8String(isolate, value.string()); case IDBKeyPath::ArrayType: - RefPtr<DOMStringList> keyPaths = DOMStringList::create(); + RefPtrWillBeRawPtr<DOMStringList> keyPaths = DOMStringList::create(); for (Vector<String>::const_iterator it = value.array().begin(); it != value.array().end(); ++it) keyPaths->append(*it); return toV8(keyPaths.release(), creationContext, isolate); @@ -70,7 +72,7 @@ static v8::Handle<v8::Value> toV8(const IDBKeyPath& value, v8::Handle<v8::Object return v8::Undefined(isolate); } -v8::Handle<v8::Value> toV8(const IDBKey* key, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) +static v8::Handle<v8::Value> toV8(const IDBKey* key, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { if (!key) { // This should be undefined, not null. @@ -104,7 +106,7 @@ v8::Handle<v8::Value> toV8(const IDBKey* key, v8::Handle<v8::Object> creationCon return v8Undefined(); } -v8::Handle<v8::Value> toV8(const IDBAny* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) +static v8::Handle<v8::Value> toV8(const IDBAny* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { if (!impl) return v8::Null(isolate); @@ -116,10 +118,22 @@ v8::Handle<v8::Value> toV8(const IDBAny* impl, v8::Handle<v8::Object> creationCo return v8::Null(isolate); case IDBAny::DOMStringListType: return toV8(impl->domStringList(), creationContext, isolate); - case IDBAny::IDBCursorType: - return toV8(impl->idbCursor(), creationContext, isolate); - case IDBAny::IDBCursorWithValueType: - return toV8(impl->idbCursorWithValue(), creationContext, isolate); + case IDBAny::IDBCursorType: { + // Ensure request wrapper is kept alive at least as long as the cursor wrapper, + // so that event listeners are retained. + v8::Handle<v8::Value> cursor = toV8(impl->idbCursor(), creationContext, isolate); + v8::Handle<v8::Value> request = toV8(impl->idbCursor()->request(), creationContext, isolate); + V8HiddenValue::setHiddenValue(isolate, cursor->ToObject(), V8HiddenValue::idbCursorRequest(isolate), request); + return cursor; + } + case IDBAny::IDBCursorWithValueType: { + // Ensure request wrapper is kept alive at least as long as the cursor wrapper, + // so that event listeners are retained. + v8::Handle<v8::Value> cursor = toV8(impl->idbCursorWithValue(), creationContext, isolate); + v8::Handle<v8::Value> request = toV8(impl->idbCursorWithValue()->request(), creationContext, isolate); + V8HiddenValue::setHiddenValue(isolate, cursor->ToObject(), V8HiddenValue::idbCursorRequest(isolate), request); + return cursor; + } case IDBAny::IDBDatabaseType: return toV8(impl->idbDatabase(), creationContext, isolate); case IDBAny::IDBIndexType: @@ -129,7 +143,7 @@ v8::Handle<v8::Value> toV8(const IDBAny* impl, v8::Handle<v8::Object> creationCo case IDBAny::IDBTransactionType: return toV8(impl->idbTransaction(), creationContext, isolate); case IDBAny::BufferType: - return deserializeIDBValueBuffer(impl->buffer(), isolate); + return deserializeIDBValueBuffer(isolate, impl->buffer(), impl->blobInfo()); case IDBAny::StringType: return v8String(isolate, impl->string()); case IDBAny::IntegerType: @@ -139,9 +153,9 @@ v8::Handle<v8::Value> toV8(const IDBAny* impl, v8::Handle<v8::Object> creationCo case IDBAny::KeyPathType: return toV8(impl->keyPath(), creationContext, isolate); case IDBAny::BufferKeyAndKeyPathType: { - v8::Handle<v8::Value> value = deserializeIDBValueBuffer(impl->buffer(), isolate); + v8::Handle<v8::Value> value = deserializeIDBValueBuffer(isolate, impl->buffer(), impl->blobInfo()); v8::Handle<v8::Value> key = toV8(impl->key(), creationContext, isolate); - bool injected = injectV8KeyIntoV8Value(key, value, impl->keyPath(), isolate); + bool injected = injectV8KeyIntoV8Value(isolate, key, value, impl->keyPath()); ASSERT_UNUSED(injected, injected); return value; } @@ -153,7 +167,7 @@ v8::Handle<v8::Value> toV8(const IDBAny* impl, v8::Handle<v8::Object> creationCo static const size_t maximumDepth = 2000; -static PassRefPtr<IDBKey> createIDBKeyFromValue(v8::Handle<v8::Value> value, Vector<v8::Handle<v8::Array> >& stack, v8::Isolate* isolate) +static IDBKey* createIDBKeyFromValue(v8::Isolate* isolate, v8::Handle<v8::Value> value, Vector<v8::Handle<v8::Array> >& stack, bool allowExperimentalTypes = false) { if (value->IsNumber() && !std::isnan(value->NumberValue())) return IDBKey::createNumber(value->NumberValue()); @@ -161,6 +175,14 @@ static PassRefPtr<IDBKey> createIDBKeyFromValue(v8::Handle<v8::Value> value, Vec return IDBKey::createString(toCoreString(value.As<v8::String>())); if (value->IsDate() && !std::isnan(value->NumberValue())) return IDBKey::createDate(value->NumberValue()); + if (value->IsUint8Array() && (allowExperimentalTypes || RuntimeEnabledFeatures::indexedDBExperimentalEnabled())) { + // Per discussion in https://www.w3.org/Bugs/Public/show_bug.cgi?id=23332 the + // input type is constrained to Uint8Array to match the output type. + ArrayBufferView* view = WebCore::V8ArrayBufferView::toNative(value->ToObject()); + const char* start = static_cast<const char*>(view->baseAddress()); + size_t length = view->byteLength(); + return IDBKey::createBinary(SharedBuffer::create(start, length)); + } if (value->IsArray()) { v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value); @@ -173,8 +195,8 @@ static PassRefPtr<IDBKey> createIDBKeyFromValue(v8::Handle<v8::Value> value, Vec IDBKey::KeyArray subkeys; uint32_t length = array->Length(); for (uint32_t i = 0; i < length; ++i) { - v8::Local<v8::Value> item = array->Get(v8::Int32::New(i, isolate)); - RefPtr<IDBKey> subkey = createIDBKeyFromValue(item, stack, isolate); + v8::Local<v8::Value> item = array->Get(v8::Int32::New(isolate, i)); + IDBKey* subkey = createIDBKeyFromValue(isolate, item, stack, allowExperimentalTypes); if (!subkey) subkeys.append(IDBKey::createInvalid()); else @@ -187,11 +209,10 @@ static PassRefPtr<IDBKey> createIDBKeyFromValue(v8::Handle<v8::Value> value, Vec return 0; } -static PassRefPtr<IDBKey> createIDBKeyFromValue(v8::Handle<v8::Value> value, v8::Isolate* isolate) +static IDBKey* createIDBKeyFromValue(v8::Isolate* isolate, v8::Handle<v8::Value> value, bool allowExperimentalTypes = false) { Vector<v8::Handle<v8::Array> > stack; - RefPtr<IDBKey> key = createIDBKeyFromValue(value, stack, isolate); - if (key) + if (IDBKey* key = createIDBKeyFromValue(isolate, value, stack, allowExperimentalTypes)) return key; return IDBKey::createInvalid(); } @@ -213,7 +234,7 @@ static bool setValue(v8::Handle<v8::Value>& v8Object, T indexOrName, const v8::H return object->Set(indexOrName, v8Value); } -static bool get(v8::Handle<v8::Value>& object, const String& keyPathElement, v8::Handle<v8::Value>& result, v8::Isolate* isolate) +static bool get(v8::Isolate* isolate, v8::Handle<v8::Value>& object, const String& keyPathElement, v8::Handle<v8::Value>& result) { if (object->IsString() && keyPathElement == "length") { int32_t length = v8::Handle<v8::String>::Cast(object)->Length(); @@ -228,25 +249,25 @@ static bool canSet(v8::Handle<v8::Value>& object, const String& keyPathElement) return object->IsObject(); } -static bool set(v8::Handle<v8::Value>& object, const String& keyPathElement, const v8::Handle<v8::Value>& v8Value, v8::Isolate* isolate) +static bool set(v8::Isolate* isolate, v8::Handle<v8::Value>& object, const String& keyPathElement, const v8::Handle<v8::Value>& v8Value) { return canSet(object, keyPathElement) && setValue(object, v8String(isolate, keyPathElement), v8Value); } -static v8::Handle<v8::Value> getNthValueOnKeyPath(v8::Handle<v8::Value>& rootValue, const Vector<String>& keyPathElements, size_t index, v8::Isolate* isolate) +static v8::Handle<v8::Value> getNthValueOnKeyPath(v8::Isolate* isolate, v8::Handle<v8::Value>& rootValue, const Vector<String>& keyPathElements, size_t index) { v8::Handle<v8::Value> currentValue(rootValue); ASSERT(index <= keyPathElements.size()); for (size_t i = 0; i < index; ++i) { v8::Handle<v8::Value> parentValue(currentValue); - if (!get(parentValue, keyPathElements[i], currentValue, isolate)) + if (!get(isolate, parentValue, keyPathElements[i], currentValue)) return v8Undefined(); } return currentValue; } -static bool canInjectNthValueOnKeyPath(v8::Handle<v8::Value>& rootValue, const Vector<String>& keyPathElements, size_t index, v8::Isolate* isolate) +static bool canInjectNthValueOnKeyPath(v8::Isolate* isolate, v8::Handle<v8::Value>& rootValue, const Vector<String>& keyPathElements, size_t index) { if (!rootValue->IsObject()) return false; @@ -257,14 +278,14 @@ static bool canInjectNthValueOnKeyPath(v8::Handle<v8::Value>& rootValue, const V for (size_t i = 0; i < index; ++i) { v8::Handle<v8::Value> parentValue(currentValue); const String& keyPathElement = keyPathElements[i]; - if (!get(parentValue, keyPathElement, currentValue, isolate)) + if (!get(isolate, parentValue, keyPathElement, currentValue)) return canSet(parentValue, keyPathElement); } return true; } -static v8::Handle<v8::Value> ensureNthValueOnKeyPath(v8::Handle<v8::Value>& rootValue, const Vector<String>& keyPathElements, size_t index, v8::Isolate* isolate) +static v8::Handle<v8::Value> ensureNthValueOnKeyPath(v8::Isolate* isolate, v8::Handle<v8::Value>& rootValue, const Vector<String>& keyPathElements, size_t index) { v8::Handle<v8::Value> currentValue(rootValue); @@ -272,9 +293,9 @@ static v8::Handle<v8::Value> ensureNthValueOnKeyPath(v8::Handle<v8::Value>& root for (size_t i = 0; i < index; ++i) { v8::Handle<v8::Value> parentValue(currentValue); const String& keyPathElement = keyPathElements[i]; - if (!get(parentValue, keyPathElement, currentValue, isolate)) { - v8::Handle<v8::Object> object = v8::Object::New(); - if (!set(parentValue, keyPathElement, object, isolate)) + if (!get(isolate, parentValue, keyPathElement, currentValue)) { + v8::Handle<v8::Object> object = v8::Object::New(isolate); + if (!set(isolate, parentValue, keyPathElement, object)) return v8Undefined(); currentValue = object; } @@ -283,7 +304,7 @@ static v8::Handle<v8::Value> ensureNthValueOnKeyPath(v8::Handle<v8::Value>& root return currentValue; } -static PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(const ScriptValue& value, const String& keyPath, v8::Isolate* isolate) +static IDBKey* createIDBKeyFromScriptValueAndKeyPathInternal(v8::Isolate* isolate, const ScriptValue& value, const String& keyPath, bool allowExperimentalTypes) { Vector<String> keyPathElements; IDBKeyPathParseError error; @@ -293,24 +314,21 @@ static PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(const ScriptValu v8::HandleScope handleScope(isolate); v8::Handle<v8::Value> v8Value(value.v8Value()); - v8::Handle<v8::Value> v8Key(getNthValueOnKeyPath(v8Value, keyPathElements, keyPathElements.size(), isolate)); + v8::Handle<v8::Value> v8Key(getNthValueOnKeyPath(isolate, v8Value, keyPathElements, keyPathElements.size())); if (v8Key.IsEmpty()) return 0; - return createIDBKeyFromValue(v8Key, isolate); + return createIDBKeyFromValue(isolate, v8Key, allowExperimentalTypes); } -PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(DOMRequestState* state, const ScriptValue& value, const IDBKeyPath& keyPath) +static IDBKey* createIDBKeyFromScriptValueAndKeyPathInternal(v8::Isolate* isolate, const ScriptValue& value, const IDBKeyPath& keyPath, bool allowExperimentalTypes = false) { - IDB_TRACE("createIDBKeyFromScriptValueAndKeyPath"); ASSERT(!keyPath.isNull()); - v8::Isolate* isolate = state ? state->context()->GetIsolate() : v8::Isolate::GetCurrent(); - ASSERT(isolate->InContext()); v8::HandleScope handleScope(isolate); 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(value, array[i], isolate); + IDBKey* key = createIDBKeyFromScriptValueAndKeyPathInternal(isolate, value, array[i], allowExperimentalTypes); if (!key) return 0; result.append(key); @@ -319,10 +337,16 @@ PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(DOMRequestState* state, } ASSERT(keyPath.type() == IDBKeyPath::StringType); - return createIDBKeyFromScriptValueAndKeyPath(value, keyPath.string(), isolate); + return createIDBKeyFromScriptValueAndKeyPathInternal(isolate, value, keyPath.string(), allowExperimentalTypes); +} + +IDBKey* createIDBKeyFromScriptValueAndKeyPath(v8::Isolate* isolate, const ScriptValue& value, const IDBKeyPath& keyPath) +{ + IDB_TRACE("createIDBKeyFromScriptValueAndKeyPath"); + return createIDBKeyFromScriptValueAndKeyPathInternal(isolate, value, keyPath); } -v8::Handle<v8::Value> deserializeIDBValueBuffer(SharedBuffer* buffer, v8::Isolate* isolate) +static v8::Handle<v8::Value> deserializeIDBValueBuffer(v8::Isolate* isolate, SharedBuffer* buffer, const Vector<blink::WebBlobInfo>* blobInfo) { ASSERT(isolate->InContext()); if (!buffer) @@ -332,10 +356,10 @@ v8::Handle<v8::Value> deserializeIDBValueBuffer(SharedBuffer* buffer, v8::Isolat Vector<uint8_t> value; value.append(buffer->data(), buffer->size()); RefPtr<SerializedScriptValue> serializedValue = SerializedScriptValue::createFromWireBytes(value); - return serializedValue->deserialize(isolate); + return serializedValue->deserialize(isolate, 0, blobInfo); } -bool injectV8KeyIntoV8Value(v8::Handle<v8::Value> key, v8::Handle<v8::Value> value, const IDBKeyPath& keyPath, v8::Isolate* isolate) +bool injectV8KeyIntoV8Value(v8::Isolate* isolate, v8::Handle<v8::Value> key, v8::Handle<v8::Value> value, const IDBKeyPath& keyPath) { IDB_TRACE("injectIDBV8KeyIntoV8Value"); ASSERT(isolate->InContext()); @@ -350,17 +374,17 @@ bool injectV8KeyIntoV8Value(v8::Handle<v8::Value> key, v8::Handle<v8::Value> val return false; v8::HandleScope handleScope(isolate); - v8::Handle<v8::Value> parent(ensureNthValueOnKeyPath(value, keyPathElements, keyPathElements.size() - 1, isolate)); + v8::Handle<v8::Value> parent(ensureNthValueOnKeyPath(isolate, value, keyPathElements, keyPathElements.size() - 1)); if (parent.IsEmpty()) return false; - if (!set(parent, keyPathElements.last(), key, isolate)) + if (!set(isolate, parent, keyPathElements.last(), key)) return false; return true; } -bool canInjectIDBKeyIntoScriptValue(DOMRequestState* state, const ScriptValue& scriptValue, const IDBKeyPath& keyPath) +bool canInjectIDBKeyIntoScriptValue(v8::Isolate* isolate, const ScriptValue& scriptValue, const IDBKeyPath& keyPath) { IDB_TRACE("canInjectIDBKeyIntoScriptValue"); ASSERT(keyPath.type() == IDBKeyPath::StringType); @@ -373,63 +397,54 @@ bool canInjectIDBKeyIntoScriptValue(DOMRequestState* state, const ScriptValue& s return false; v8::Handle<v8::Value> v8Value(scriptValue.v8Value()); - return canInjectNthValueOnKeyPath(v8Value, keyPathElements, keyPathElements.size() - 1, state->context()->GetIsolate()); + return canInjectNthValueOnKeyPath(isolate, v8Value, keyPathElements, keyPathElements.size() - 1); } -ScriptValue idbAnyToScriptValue(DOMRequestState* state, PassRefPtr<IDBAny> any) +ScriptValue idbAnyToScriptValue(ScriptState* scriptState, IDBAny* any) { - v8::Isolate* isolate = state ? state->context()->GetIsolate() : v8::Isolate::GetCurrent(); - ASSERT(isolate->InContext()); - v8::Local<v8::Context> context = state ? state->context() : isolate->GetCurrentContext(); + v8::Isolate* isolate = scriptState->isolate(); v8::HandleScope handleScope(isolate); - v8::Handle<v8::Value> v8Value(toV8(any.get(), context->Global(), isolate)); - return ScriptValue(v8Value, isolate); + v8::Handle<v8::Value> v8Value(toV8(any, scriptState->context()->Global(), isolate)); + return ScriptValue(scriptState, v8Value); } -ScriptValue idbKeyToScriptValue(DOMRequestState* state, PassRefPtr<IDBKey> key) +ScriptValue idbKeyToScriptValue(ScriptState* scriptState, IDBKey* key) { - v8::Isolate* isolate = state ? state->context()->GetIsolate() : v8::Isolate::GetCurrent(); - ASSERT(isolate->InContext()); - v8::Local<v8::Context> context = state ? state->context() : isolate->GetCurrentContext(); + v8::Isolate* isolate = scriptState->isolate(); v8::HandleScope handleScope(isolate); - v8::Handle<v8::Value> v8Value(toV8(key.get(), context->Global(), isolate)); - return ScriptValue(v8Value, isolate); + v8::Handle<v8::Value> v8Value(toV8(key, scriptState->context()->Global(), isolate)); + return ScriptValue(scriptState, v8Value); } -PassRefPtr<IDBKey> scriptValueToIDBKey(DOMRequestState* state, const ScriptValue& scriptValue) +IDBKey* scriptValueToIDBKey(v8::Isolate* isolate, const ScriptValue& scriptValue) { - v8::Isolate* isolate = state ? state->context()->GetIsolate() : v8::Isolate::GetCurrent(); ASSERT(isolate->InContext()); v8::HandleScope handleScope(isolate); v8::Handle<v8::Value> v8Value(scriptValue.v8Value()); - return createIDBKeyFromValue(v8Value, isolate); + return createIDBKeyFromValue(isolate, v8Value); } -PassRefPtr<IDBKeyRange> scriptValueToIDBKeyRange(DOMRequestState* state, const ScriptValue& scriptValue) +IDBKeyRange* scriptValueToIDBKeyRange(v8::Isolate* isolate, const ScriptValue& scriptValue) { - v8::Isolate* isolate = state ? state->context()->GetIsolate() : v8::Isolate::GetCurrent(); v8::HandleScope handleScope(isolate); v8::Handle<v8::Value> value(scriptValue.v8Value()); - if (V8IDBKeyRange::hasInstance(value, isolate, worldType(isolate))) - return V8IDBKeyRange::toNative(value.As<v8::Object>()); - return 0; + return V8IDBKeyRange::toNativeWithTypeCheck(isolate, value); } #ifndef NDEBUG -void assertPrimaryKeyValidOrInjectable(DOMRequestState* state, PassRefPtr<SharedBuffer> buffer, PassRefPtr<IDBKey> prpKey, const IDBKeyPath& keyPath) +void assertPrimaryKeyValidOrInjectable(ScriptState* scriptState, PassRefPtr<SharedBuffer> buffer, const Vector<blink::WebBlobInfo>* blobInfo, IDBKey* key, const IDBKeyPath& keyPath) { - RefPtr<IDBKey> key(prpKey); - - DOMRequestState::Scope scope(*state); - v8::Isolate* isolate = state ? state->context()->GetIsolate() : v8::Isolate::GetCurrent(); - - ScriptValue keyValue = idbKeyToScriptValue(state, key); - ScriptValue scriptValue(deserializeIDBValueBuffer(buffer.get(), isolate), isolate); + ScriptState::Scope scope(scriptState); + v8::Isolate* isolate = scriptState->isolate(); + ScriptValue keyValue = idbKeyToScriptValue(scriptState, key); + ScriptValue scriptValue(scriptState, deserializeIDBValueBuffer(isolate, buffer.get(), blobInfo)); - RefPtr<IDBKey> expectedKey = createIDBKeyFromScriptValueAndKeyPath(state, scriptValue, keyPath); - ASSERT(!expectedKey || expectedKey->isEqual(key.get())); + // This assertion is about already persisted data, so allow experimental types. + const bool allowExperimentalTypes = true; + IDBKey* expectedKey = createIDBKeyFromScriptValueAndKeyPathInternal(isolate, scriptValue, keyPath, allowExperimentalTypes); + ASSERT(!expectedKey || expectedKey->isEqual(key)); - bool injected = injectV8KeyIntoV8Value(keyValue.v8Value(), scriptValue.v8Value(), keyPath, isolate); + bool injected = injectV8KeyIntoV8Value(isolate, keyValue.v8Value(), scriptValue.v8Value(), keyPath); ASSERT_UNUSED(injected, injected); } #endif diff --git a/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilities.h b/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilities.h index b36c71cb03d..fba64423937 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilities.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilities.h @@ -26,13 +26,19 @@ #ifndef IDBBindingUtilities_h #define IDBBindingUtilities_h +#include "bindings/v8/ScriptState.h" #include "bindings/v8/ScriptValue.h" #include <v8.h> #include "wtf/Forward.h" +namespace blink { + +class WebBlobInfo; + +} + namespace WebCore { -class DOMRequestState; class IDBAny; class IDBKey; class IDBKeyPath; @@ -41,18 +47,18 @@ class SerializedScriptValue; class SharedBuffer; // Exposed for unit testing: -bool injectV8KeyIntoV8Value(v8::Handle<v8::Value> key, v8::Handle<v8::Value>, const IDBKeyPath&, v8::Isolate*); +bool injectV8KeyIntoV8Value(v8::Isolate*, v8::Handle<v8::Value> key, v8::Handle<v8::Value>, const IDBKeyPath&); // For use by Source/modules/indexeddb: -PassRefPtr<IDBKey> createIDBKeyFromScriptValueAndKeyPath(DOMRequestState*, const ScriptValue&, const IDBKeyPath&); -bool canInjectIDBKeyIntoScriptValue(DOMRequestState*, const ScriptValue&, const IDBKeyPath&); -ScriptValue idbAnyToScriptValue(DOMRequestState*, PassRefPtr<IDBAny>); -ScriptValue idbKeyToScriptValue(DOMRequestState*, PassRefPtr<IDBKey>); -PassRefPtr<IDBKey> scriptValueToIDBKey(DOMRequestState*, const ScriptValue&); -PassRefPtr<IDBKeyRange> scriptValueToIDBKeyRange(DOMRequestState*, const ScriptValue&); +IDBKey* createIDBKeyFromScriptValueAndKeyPath(v8::Isolate*, const ScriptValue&, const IDBKeyPath&); +bool canInjectIDBKeyIntoScriptValue(v8::Isolate*, const ScriptValue&, const IDBKeyPath&); +ScriptValue idbAnyToScriptValue(ScriptState*, IDBAny*); +ScriptValue idbKeyToScriptValue(ScriptState*, IDBKey*); +IDBKey* scriptValueToIDBKey(v8::Isolate*, const ScriptValue&); +IDBKeyRange* scriptValueToIDBKeyRange(v8::Isolate*, const ScriptValue&); #ifndef NDEBUG -void assertPrimaryKeyValidOrInjectable(DOMRequestState*, PassRefPtr<SharedBuffer>, PassRefPtr<IDBKey>, const IDBKeyPath&); +void assertPrimaryKeyValidOrInjectable(ScriptState*, PassRefPtr<SharedBuffer>, const Vector<blink::WebBlobInfo>*, IDBKey*, const IDBKeyPath&); #endif } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilitiesTest.cpp b/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilitiesTest.cpp index 0f6ff63ee32..b984d04ceeb 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilitiesTest.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/IDBBindingUtilitiesTest.cpp @@ -28,64 +28,60 @@ #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8PerIsolateData.h" -#include "bindings/v8/V8Utilities.h" #include "modules/indexeddb/IDBKey.h" #include "modules/indexeddb/IDBKeyPath.h" - #include <gtest/gtest.h> using namespace WebCore; namespace { -PassRefPtr<IDBKey> checkKeyFromValueAndKeyPathInternal(const ScriptValue& value, const String& keyPath) +IDBKey* checkKeyFromValueAndKeyPathInternal(v8::Isolate* isolate, const ScriptValue& value, const String& keyPath) { IDBKeyPath idbKeyPath(keyPath); EXPECT_TRUE(idbKeyPath.isValid()); - return createIDBKeyFromScriptValueAndKeyPath(0, value, idbKeyPath); + return createIDBKeyFromScriptValueAndKeyPath(isolate, value, idbKeyPath); } -void checkKeyPathNullValue(const ScriptValue& value, const String& keyPath) +void checkKeyPathNullValue(v8::Isolate* isolate, const ScriptValue& value, const String& keyPath) { - RefPtr<IDBKey> idbKey = checkKeyFromValueAndKeyPathInternal(value, keyPath); - ASSERT_FALSE(idbKey.get()); + ASSERT_FALSE(checkKeyFromValueAndKeyPathInternal(isolate, value, keyPath)); } -bool injectKey(PassRefPtr<IDBKey> key, ScriptValue& value, const String& keyPath) +bool injectKey(ScriptState* scriptState, IDBKey* key, ScriptValue& value, const String& keyPath) { IDBKeyPath idbKeyPath(keyPath); EXPECT_TRUE(idbKeyPath.isValid()); - ScriptValue keyValue = idbKeyToScriptValue(0, key); - return injectV8KeyIntoV8Value(keyValue.v8Value(), value.v8Value(), idbKeyPath, v8::Isolate::GetCurrent()); + ScriptValue keyValue = idbKeyToScriptValue(scriptState, key); + return injectV8KeyIntoV8Value(scriptState->isolate(), keyValue.v8Value(), value.v8Value(), idbKeyPath); } -void checkInjection(PassRefPtr<IDBKey> prpKey, ScriptValue& value, const String& keyPath) +void checkInjection(ScriptState* scriptState, IDBKey* key, ScriptValue& value, const String& keyPath) { - RefPtr<IDBKey> key = prpKey; - bool result = injectKey(key, value, keyPath); + bool result = injectKey(scriptState, key, value, keyPath); ASSERT_TRUE(result); - RefPtr<IDBKey> extractedKey = checkKeyFromValueAndKeyPathInternal(value, keyPath); - EXPECT_TRUE(key->isEqual(extractedKey.get())); + IDBKey* extractedKey = checkKeyFromValueAndKeyPathInternal(scriptState->isolate(), value, keyPath); + EXPECT_TRUE(key->isEqual(extractedKey)); } -void checkInjectionFails(PassRefPtr<IDBKey> key, ScriptValue& value, const String& keyPath) +void checkInjectionFails(ScriptState* scriptState, IDBKey* key, ScriptValue& value, const String& keyPath) { - EXPECT_FALSE(injectKey(key, value, keyPath)); + EXPECT_FALSE(injectKey(scriptState, key, value, keyPath)); } -void checkKeyPathStringValue(const ScriptValue& value, const String& keyPath, const String& expected) +void checkKeyPathStringValue(v8::Isolate* isolate, const ScriptValue& value, const String& keyPath, const String& expected) { - RefPtr<IDBKey> idbKey = checkKeyFromValueAndKeyPathInternal(value, keyPath); - ASSERT_TRUE(idbKey.get()); + IDBKey* idbKey = checkKeyFromValueAndKeyPathInternal(isolate, value, keyPath); + ASSERT_TRUE(idbKey); ASSERT_EQ(IDBKey::StringType, idbKey->type()); ASSERT_TRUE(expected == idbKey->string()); } -void checkKeyPathNumberValue(const ScriptValue& value, const String& keyPath, int expected) +void checkKeyPathNumberValue(v8::Isolate* isolate, const ScriptValue& value, const String& keyPath, int expected) { - RefPtr<IDBKey> idbKey = checkKeyFromValueAndKeyPathInternal(value, keyPath); - ASSERT_TRUE(idbKey.get()); + IDBKey* idbKey = checkKeyFromValueAndKeyPathInternal(isolate, value, keyPath); + ASSERT_TRUE(idbKey); ASSERT_EQ(IDBKey::NumberType, idbKey->type()); ASSERT_TRUE(expected == idbKey->number()); } @@ -93,49 +89,52 @@ void checkKeyPathNumberValue(const ScriptValue& value, const String& keyPath, in class IDBKeyFromValueAndKeyPathTest : public testing::Test { public: IDBKeyFromValueAndKeyPathTest() - : m_handleScope(v8::Isolate::GetCurrent()) - , m_scope(v8::Context::New(v8::Isolate::GetCurrent())) + : m_scope(v8::Isolate::GetCurrent()) { } + ScriptState* scriptState() const { return m_scope.scriptState(); } + private: - v8::HandleScope m_handleScope; - v8::Context::Scope m_scope; + V8TestingScope m_scope; }; TEST_F(IDBKeyFromValueAndKeyPathTest, TopLevelPropertyStringValue) { - v8::Local<v8::Object> object = v8::Object::New(); - object->Set(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "foo"), v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "zoo")); + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Local<v8::Object> object = v8::Object::New(isolate); + object->Set(v8AtomicString(isolate, "foo"), v8AtomicString(isolate, "zoo")); - ScriptValue scriptValue(object, v8::Isolate::GetCurrent()); + ScriptValue scriptValue(scriptState(), object); - checkKeyPathStringValue(scriptValue, "foo", "zoo"); - checkKeyPathNullValue(scriptValue, "bar"); + checkKeyPathStringValue(isolate, scriptValue, "foo", "zoo"); + checkKeyPathNullValue(isolate, scriptValue, "bar"); } TEST_F(IDBKeyFromValueAndKeyPathTest, TopLevelPropertyNumberValue) { - v8::Local<v8::Object> object = v8::Object::New(); - object->Set(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "foo"), v8::Number::New(456)); + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Local<v8::Object> object = v8::Object::New(isolate); + object->Set(v8AtomicString(isolate, "foo"), v8::Number::New(isolate, 456)); - ScriptValue scriptValue(object, v8::Isolate::GetCurrent()); + ScriptValue scriptValue(scriptState(), object); - checkKeyPathNumberValue(scriptValue, "foo", 456); - checkKeyPathNullValue(scriptValue, "bar"); + checkKeyPathNumberValue(isolate, scriptValue, "foo", 456); + checkKeyPathNullValue(isolate, scriptValue, "bar"); } TEST_F(IDBKeyFromValueAndKeyPathTest, SubProperty) { - v8::Local<v8::Object> object = v8::Object::New(); - v8::Local<v8::Object> subProperty = v8::Object::New(); - subProperty->Set(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "bar"), v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "zee")); - object->Set(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "foo"), subProperty); + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Local<v8::Object> object = v8::Object::New(isolate); + v8::Local<v8::Object> subProperty = v8::Object::New(isolate); + subProperty->Set(v8AtomicString(isolate, "bar"), v8AtomicString(isolate, "zee")); + object->Set(v8AtomicString(isolate, "foo"), subProperty); - ScriptValue scriptValue(object, v8::Isolate::GetCurrent()); + ScriptValue scriptValue(scriptState(), object); - checkKeyPathStringValue(scriptValue, "foo.bar", "zee"); - checkKeyPathNullValue(scriptValue, "bar"); + checkKeyPathStringValue(isolate, scriptValue, "foo.bar", "zee"); + checkKeyPathNullValue(isolate, scriptValue, "bar"); } class InjectIDBKeyTest : public IDBKeyFromValueAndKeyPathTest { @@ -143,33 +142,35 @@ class InjectIDBKeyTest : public IDBKeyFromValueAndKeyPathTest { TEST_F(InjectIDBKeyTest, TopLevelPropertyStringValue) { - v8::Local<v8::Object> object = v8::Object::New(); - object->Set(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "foo"), v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "zoo")); + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Local<v8::Object> object = v8::Object::New(isolate); + object->Set(v8AtomicString(isolate, "foo"), v8AtomicString(isolate, "zoo")); - ScriptValue foozoo(object, v8::Isolate::GetCurrent()); - checkInjection(IDBKey::createString("myNewKey"), foozoo, "bar"); - checkInjection(IDBKey::createNumber(1234), foozoo, "bar"); + ScriptValue foozoo(scriptState(), object); + checkInjection(scriptState(), IDBKey::createString("myNewKey"), foozoo, "bar"); + checkInjection(scriptState(), IDBKey::createNumber(1234), foozoo, "bar"); - checkInjectionFails(IDBKey::createString("key"), foozoo, "foo.bar"); + checkInjectionFails(scriptState(), IDBKey::createString("key"), foozoo, "foo.bar"); } TEST_F(InjectIDBKeyTest, SubProperty) { - v8::Local<v8::Object> object = v8::Object::New(); - v8::Local<v8::Object> subProperty = v8::Object::New(); - subProperty->Set(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "bar"), v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "zee")); - object->Set(v8::String::NewFromUtf8(v8::Isolate::GetCurrent(), "foo"), subProperty); - - ScriptValue scriptObject(object, v8::Isolate::GetCurrent()); - checkInjection(IDBKey::createString("myNewKey"), scriptObject, "foo.baz"); - checkInjection(IDBKey::createNumber(789), scriptObject, "foo.baz"); - checkInjection(IDBKey::createDate(4567), scriptObject, "foo.baz"); - checkInjection(IDBKey::createDate(4567), scriptObject, "bar"); - checkInjection(IDBKey::createArray(IDBKey::KeyArray()), scriptObject, "foo.baz"); - checkInjection(IDBKey::createArray(IDBKey::KeyArray()), scriptObject, "bar"); - - checkInjectionFails(IDBKey::createString("zoo"), scriptObject, "foo.bar.baz"); - checkInjection(IDBKey::createString("zoo"), scriptObject, "foo.xyz.foo"); + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::Local<v8::Object> object = v8::Object::New(isolate); + v8::Local<v8::Object> subProperty = v8::Object::New(isolate); + subProperty->Set(v8AtomicString(isolate, "bar"), v8AtomicString(isolate, "zee")); + object->Set(v8AtomicString(isolate, "foo"), subProperty); + + ScriptValue scriptObject(scriptState(), object); + checkInjection(scriptState(), IDBKey::createString("myNewKey"), scriptObject, "foo.baz"); + checkInjection(scriptState(), IDBKey::createNumber(789), scriptObject, "foo.baz"); + checkInjection(scriptState(), IDBKey::createDate(4567), scriptObject, "foo.baz"); + checkInjection(scriptState(), IDBKey::createDate(4567), scriptObject, "bar"); + checkInjection(scriptState(), IDBKey::createArray(IDBKey::KeyArray()), scriptObject, "foo.baz"); + checkInjection(scriptState(), IDBKey::createArray(IDBKey::KeyArray()), scriptObject, "bar"); + + checkInjectionFails(scriptState(), IDBKey::createString("zoo"), scriptObject, "foo.bar.baz"); + checkInjection(scriptState(), IDBKey::createString("zoo"), scriptObject, "foo.xyz.foo"); } } // namespace diff --git a/chromium/third_party/WebKit/Source/bindings/v8/NPV8Object.cpp b/chromium/third_party/WebKit/Source/bindings/v8/NPV8Object.cpp index e094bf92563..11f34a44d97 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/NPV8Object.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/NPV8Object.cpp @@ -38,8 +38,8 @@ #include "bindings/v8/WrapperTypeInfo.h" #include "bindings/v8/npruntime_impl.h" #include "bindings/v8/npruntime_priv.h" -#include "core/frame/DOMWindow.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/LocalFrame.h" #include "platform/UserGestureIndicator.h" #include "wtf/OwnPtr.h" @@ -53,7 +53,7 @@ namespace WebCore { const WrapperTypeInfo* npObjectTypeInfo() { - static const WrapperTypeInfo typeInfo = { gin::kEmbedderBlink, 0, 0, 0, 0, 0, 0, 0, WrapperTypeObjectPrototype }; + static const WrapperTypeInfo typeInfo = { gin::kEmbedderBlink, 0, 0, 0, 0, 0, 0, 0, WrapperTypeObjectPrototype, RefCountedObject }; return &typeInfo; } @@ -77,14 +77,16 @@ static NPClass V8NPObjectClass = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static v8::Local<v8::Context> toV8Context(NPP npp, NPObject* npObject) +static ScriptState* mainWorldScriptState(v8::Isolate* isolate, NPP npp, NPObject* npObject) { ASSERT(npObject->_class == &V8NPObjectClass); V8NPObject* object = reinterpret_cast<V8NPObject*>(npObject); - DOMWindow* window = object->rootObject; + LocalDOMWindow* window = object->rootObject; if (!window || !window->isCurrentlyDisplayedInFrame()) - return v8::Local<v8::Context>(); - return ScriptController::mainWorldContext(object->rootObject->frame()); + return 0; + v8::HandleScope handleScope(isolate); + v8::Handle<v8::Context> context = toV8Context(object->rootObject->frame(), DOMWrapperWorld::mainWorld()); + return ScriptState::from(context); } static PassOwnPtr<v8::Handle<v8::Value>[]> createValueListFromVariantArgs(const NPVariant* arguments, uint32_t argumentCount, NPObject* owner, v8::Isolate* isolate) @@ -114,7 +116,7 @@ NPObject* v8ObjectToNPObject(v8::Handle<v8::Object> object) return reinterpret_cast<NPObject*>(object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex)); } -NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, DOMWindow* root, v8::Isolate* isolate) +NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, LocalDOMWindow* root, v8::Isolate* isolate) { // Check to see if this object is already wrapped. if (object->InternalFieldCount() == npObjectInternalFieldCount) { @@ -141,10 +143,10 @@ NPObject* npCreateV8ScriptObject(NPP npp, v8::Handle<v8::Object> object, DOMWind return reinterpret_cast<NPObject*>(v8npObject); } } + objectVector = &iter->value; } else { - iter = v8NPObjectMap->set(v8ObjectHash, V8NPObjectVector()).iterator; + objectVector = &v8NPObjectMap->set(v8ObjectHash, V8NPObjectVector()).storedValue->value; } - objectVector = &iter->value; } V8NPObject* v8npObject = reinterpret_cast<V8NPObject*>(_NPN_CreateObject(npp, &V8NPObjectClass)); @@ -230,13 +232,12 @@ bool _NPN_Invoke(NPP npp, NPObject* npObject, NPIdentifier methodName, const NPV return _NPN_Evaluate(npp, npObject, const_cast<NPString*>(&arguments[0].value.stringValue), result); } - v8::HandleScope handleScope(isolate); // FIXME: should use the plugin's owner frame as the security context. - v8::Handle<v8::Context> context = toV8Context(npp, npObject); - if (context.IsEmpty()) + ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject); + if (!scriptState) return false; - v8::Context::Scope scope(context); + ScriptState::Scope scope(scriptState); ExceptionCatcher exceptionCatcher; v8::Handle<v8::Object> v8Object = v8::Local<v8::Object>::New(isolate, v8NpObject->v8Object); @@ -250,7 +251,7 @@ bool _NPN_Invoke(NPP npp, NPObject* npObject, NPIdentifier methodName, const NPV return false; } - Frame* frame = v8NpObject->rootObject->frame(); + LocalFrame* frame = v8NpObject->rootObject->frame(); ASSERT(frame); // Call the function object. @@ -286,12 +287,11 @@ bool _NPN_InvokeDefault(NPP npp, NPObject* npObject, const NPVariant* arguments, VOID_TO_NPVARIANT(*result); - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> context = toV8Context(npp, npObject); - if (context.IsEmpty()) + ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject); + if (!scriptState) return false; - v8::Context::Scope scope(context); + ScriptState::Scope scope(scriptState); ExceptionCatcher exceptionCatcher; // Lookup the function object and call it. @@ -302,7 +302,7 @@ bool _NPN_InvokeDefault(NPP npp, NPObject* npObject, const NPVariant* arguments, v8::Local<v8::Value> resultObject; v8::Handle<v8::Function> function = v8::Local<v8::Function>::Cast(functionObject); if (!function->IsNull()) { - Frame* frame = v8NpObject->rootObject->frame(); + LocalFrame* frame = v8NpObject->rootObject->frame(); ASSERT(frame); OwnPtr<v8::Handle<v8::Value>[]> argv = createValueListFromVariantArgs(arguments, argumentCount, npObject, isolate); @@ -335,12 +335,11 @@ bool _NPN_EvaluateHelper(NPP npp, bool popupsAllowed, NPObject* npObject, NPStri return false; v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> context = toV8Context(npp, npObject); - if (context.IsEmpty()) + ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject); + if (!scriptState) return false; - v8::Context::Scope scope(context); + ScriptState::Scope scope(scriptState); ExceptionCatcher exceptionCatcher; // FIXME: Is this branch still needed after switching to using UserGestureIndicator? @@ -348,13 +347,13 @@ bool _NPN_EvaluateHelper(NPP npp, bool popupsAllowed, NPObject* npObject, NPStri if (!popupsAllowed) filename = "npscript"; - Frame* frame = v8NpObject->rootObject->frame(); + LocalFrame* frame = v8NpObject->rootObject->frame(); ASSERT(frame); String script = String::fromUTF8(npScript->UTF8Characters, npScript->UTF8Length); UserGestureIndicator gestureIndicator(popupsAllowed ? DefinitelyProcessingNewUserGesture : PossiblyProcessingUserGesture); - v8::Local<v8::Value> v8result = frame->script().executeScriptAndReturnValue(context, ScriptSourceCode(script, KURL(ParsedURLString, filename))); + v8::Local<v8::Value> v8result = frame->script().executeScriptAndReturnValue(scriptState->context(), ScriptSourceCode(script, KURL(ParsedURLString, filename))); if (v8result.IsEmpty()) return false; @@ -371,12 +370,11 @@ bool _NPN_GetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, NP if (V8NPObject* object = npObjectToV8NPObject(npObject)) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> context = toV8Context(npp, npObject); - if (context.IsEmpty()) + ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject); + if (!scriptState) return false; - v8::Context::Scope scope(context); + ScriptState::Scope scope(scriptState); ExceptionCatcher exceptionCatcher; v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object); @@ -405,16 +403,15 @@ bool _NPN_SetProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName, co if (V8NPObject* object = npObjectToV8NPObject(npObject)) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> context = toV8Context(npp, npObject); - if (context.IsEmpty()) + ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject); + if (!scriptState) return false; - v8::Context::Scope scope(context); + ScriptState::Scope scope(scriptState); ExceptionCatcher exceptionCatcher; v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object); - obj->Set(npIdentifierToV8Identifier(propertyName, context->GetIsolate()), convertNPVariantToV8Object(value, object->rootObject->frame()->script().windowScriptNPObject(), context->GetIsolate())); + obj->Set(npIdentifierToV8Identifier(propertyName, isolate), convertNPVariantToV8Object(value, object->rootObject->frame()->script().windowScriptNPObject(), isolate)); return true; } @@ -434,11 +431,10 @@ bool _NPN_RemoveProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName) return false; v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> context = toV8Context(npp, npObject); - if (context.IsEmpty()) + ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject); + if (!scriptState) return false; - v8::Context::Scope scope(context); + ScriptState::Scope scope(scriptState); ExceptionCatcher exceptionCatcher; v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object); @@ -454,11 +450,10 @@ bool _NPN_HasProperty(NPP npp, NPObject* npObject, NPIdentifier propertyName) if (V8NPObject* object = npObjectToV8NPObject(npObject)) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> context = toV8Context(npp, npObject); - if (context.IsEmpty()) + ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject); + if (!scriptState) return false; - v8::Context::Scope scope(context); + ScriptState::Scope scope(scriptState); ExceptionCatcher exceptionCatcher; v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object); @@ -477,11 +472,10 @@ bool _NPN_HasMethod(NPP npp, NPObject* npObject, NPIdentifier methodName) if (V8NPObject* object = npObjectToV8NPObject(npObject)) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> context = toV8Context(npp, npObject); - if (context.IsEmpty()) + ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject); + if (!scriptState) return false; - v8::Context::Scope scope(context); + ScriptState::Scope scope(scriptState); ExceptionCatcher exceptionCatcher; v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object); @@ -503,15 +497,15 @@ void _NPN_SetException(NPObject* npObject, const NPUTF8 *message) return; } - v8::HandleScope handleScope(v8::Isolate::GetCurrent()); - v8::Handle<v8::Context> context = toV8Context(0, npObject); - if (context.IsEmpty()) + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + ScriptState* scriptState = mainWorldScriptState(isolate, 0, npObject); + if (!scriptState) return; - v8::Context::Scope scope(context); + ScriptState::Scope scope(scriptState); ExceptionCatcher exceptionCatcher; - throwError(v8GeneralError, message, context->GetIsolate()); + throwError(v8GeneralError, message, isolate); } bool _NPN_Enumerate(NPP npp, NPObject* npObject, NPIdentifier** identifier, uint32_t* count) @@ -521,11 +515,10 @@ bool _NPN_Enumerate(NPP npp, NPObject* npObject, NPIdentifier** identifier, uint if (V8NPObject* object = npObjectToV8NPObject(npObject)) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::HandleScope handleScope(isolate); - v8::Local<v8::Context> context = toV8Context(npp, npObject); - if (context.IsEmpty()) + ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject); + if (!scriptState) return false; - v8::Context::Scope scope(context); + ScriptState::Scope scope(scriptState); ExceptionCatcher exceptionCatcher; v8::Handle<v8::Object> obj = v8::Local<v8::Object>::New(isolate, object->v8Object); @@ -542,22 +535,22 @@ bool _NPN_Enumerate(NPP npp, NPObject* npObject, NPIdentifier** identifier, uint " }" " return props;" "});"; - v8::Handle<v8::String> source = v8::String::NewFromUtf8(isolate, enumeratorCode); - v8::Handle<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(source, context->GetIsolate()); + v8::Handle<v8::String> source = v8AtomicString(isolate, enumeratorCode); + v8::Handle<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(source, isolate); ASSERT(!result.IsEmpty()); ASSERT(result->IsFunction()); v8::Handle<v8::Function> enumerator = v8::Handle<v8::Function>::Cast(result); v8::Handle<v8::Value> argv[] = { obj }; - v8::Local<v8::Value> propsObj = V8ScriptRunner::callInternalFunction(enumerator, v8::Handle<v8::Object>::Cast(result), WTF_ARRAY_LENGTH(argv), argv, context->GetIsolate()); + v8::Local<v8::Value> propsObj = V8ScriptRunner::callInternalFunction(enumerator, v8::Handle<v8::Object>::Cast(result), WTF_ARRAY_LENGTH(argv), argv, isolate); if (propsObj.IsEmpty()) return false; // Convert the results into an array of NPIdentifiers. v8::Handle<v8::Array> props = v8::Handle<v8::Array>::Cast(propsObj); *count = props->Length(); - *identifier = static_cast<NPIdentifier*>(malloc(sizeof(NPIdentifier*) * *count)); + *identifier = static_cast<NPIdentifier*>(calloc(*count, sizeof(NPIdentifier))); for (uint32_t i = 0; i < *count; ++i) { - v8::Local<v8::Value> name = props->Get(v8::Integer::New(i, context->GetIsolate())); + v8::Local<v8::Value> name = props->Get(v8::Integer::New(isolate, i)); (*identifier)[i] = getStringIdentifier(v8::Local<v8::String>::Cast(name)); } return true; @@ -577,11 +570,10 @@ bool _NPN_Construct(NPP npp, NPObject* npObject, const NPVariant* arguments, uin v8::Isolate* isolate = v8::Isolate::GetCurrent(); if (V8NPObject* object = npObjectToV8NPObject(npObject)) { - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> context = toV8Context(npp, npObject); - if (context.IsEmpty()) + ScriptState* scriptState = mainWorldScriptState(isolate, npp, npObject); + if (!scriptState) return false; - v8::Context::Scope scope(context); + ScriptState::Scope scope(scriptState); ExceptionCatcher exceptionCatcher; // Lookup the constructor function. @@ -593,10 +585,10 @@ bool _NPN_Construct(NPP npp, NPObject* npObject, const NPVariant* arguments, uin v8::Local<v8::Value> resultObject; v8::Handle<v8::Function> ctor = v8::Handle<v8::Function>::Cast(ctorObj); if (!ctor->IsNull()) { - Frame* frame = object->rootObject->frame(); + LocalFrame* frame = object->rootObject->frame(); ASSERT(frame); OwnPtr<v8::Handle<v8::Value>[]> argv = createValueListFromVariantArgs(arguments, argumentCount, npObject, isolate); - resultObject = V8ObjectConstructor::newInstanceInDocument(ctor, argumentCount, argv.get(), frame ? frame->document() : 0); + resultObject = V8ObjectConstructor::newInstanceInDocument(isolate, ctor, argumentCount, argv.get(), frame ? frame->document() : 0); } if (resultObject.IsEmpty()) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/NPV8Object.h b/chromium/third_party/WebKit/Source/bindings/v8/NPV8Object.h index 435f778d151..3e7db341956 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/NPV8Object.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/NPV8Object.h @@ -39,7 +39,7 @@ namespace WebCore { -class DOMWindow; +class LocalDOMWindow; static const int npObjectInternalFieldCount = v8DefaultWrapperInternalFieldCount + 0; @@ -53,7 +53,7 @@ struct V8NPObject { public: NPObject object; v8::Persistent<v8::Object> v8Object; - DOMWindow* rootObject; + LocalDOMWindow* rootObject; }; struct PrivateIdentifier { @@ -64,7 +64,7 @@ struct PrivateIdentifier { bool isString; }; -NPObject* npCreateV8ScriptObject(NPP, v8::Handle<v8::Object>, DOMWindow*, v8::Isolate*); +NPObject* npCreateV8ScriptObject(NPP, v8::Handle<v8::Object>, LocalDOMWindow*, v8::Isolate*); NPObject* v8ObjectToNPObject(v8::Handle<v8::Object>); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/Nullable.h b/chromium/third_party/WebKit/Source/bindings/v8/Nullable.h new file mode 100644 index 00000000000..0f8356c472d --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/Nullable.h @@ -0,0 +1,51 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef Nullable_h +#define Nullable_h + +#include "wtf/Assertions.h" + +namespace WebCore { + +template <typename T> +class Nullable { +public: + Nullable() + : m_value() + , m_isNull(true) { } + + Nullable(const T& value) + : m_value(value) + , m_isNull(false) { } + + Nullable(const Nullable& other) + : m_value(other.m_value) + , m_isNull(other.m_isNull) { } + + Nullable& operator=(const Nullable& other) + { + m_value = other.m_value; + m_isNull = other.m_isNull; + return *this; + } + + T get() const { ASSERT(!m_isNull); return m_value; } + bool isNull() const { return m_isNull; } + + operator bool() const { return !m_isNull && m_value; } + + bool operator==(const Nullable& other) const + { + return (m_isNull && other.m_isNull) || (!m_isNull && !other.m_isNull && m_value == other.m_value); + } + +private: + T m_value; + bool m_isNull; +}; + +} // namespace WebCore + +#endif // Nullable_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/PageScriptDebugServer.cpp b/chromium/third_party/WebKit/Source/bindings/v8/PageScriptDebugServer.cpp index 44a2b48a22c..5901fba1eaf 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/PageScriptDebugServer.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/PageScriptDebugServer.cpp @@ -32,15 +32,20 @@ #include "bindings/v8/PageScriptDebugServer.h" -#include "V8Window.h" +#include "bindings/core/v8/V8Window.h" +#include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/ScriptController.h" #include "bindings/v8/ScriptSourceCode.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8ScriptRunner.h" #include "bindings/v8/V8WindowShell.h" +#include "core/frame/FrameConsole.h" +#include "core/frame/FrameHost.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/UseCounter.h" #include "core/inspector/InspectorInstrumentation.h" +#include "core/inspector/InspectorTraceEvents.h" #include "core/inspector/ScriptDebugListener.h" -#include "core/frame/Frame.h" #include "core/page/Page.h" #include "wtf/OwnPtr.h" #include "wtf/PassOwnPtr.h" @@ -50,17 +55,20 @@ namespace WebCore { -static Frame* retrieveFrameWithGlobalObjectCheck(v8::Handle<v8::Context> context) +static LocalFrame* retrieveFrameWithGlobalObjectCheck(v8::Handle<v8::Context> context) { if (context.IsEmpty()) return 0; - // Test that context has associated global dom window object. - v8::Handle<v8::Object> global = context->Global(); - if (global.IsEmpty()) + // FIXME: This is a temporary hack for crbug.com/345014. + // Currently it's possible that V8 can trigger Debugger::ProcessDebugEvent for a context + // that is being initialized (i.e., inside Context::New() of the context). + // We should fix the V8 side so that it won't trigger the event for a half-baked context + // because there is no way in the embedder side to check if the context is half-baked or not. + if (isMainThread() && DOMWrapperWorld::windowIsBeingInitialized()) return 0; - global = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), worldTypeInMainThread(context->GetIsolate()))); + v8::Handle<v8::Value> global = V8Window::findInstanceInPrototypeChain(context->Global(), context->GetIsolate()); if (global.IsEmpty()) return 0; @@ -82,31 +90,44 @@ PageScriptDebugServer& PageScriptDebugServer::shared() return server; } +v8::Isolate* PageScriptDebugServer::s_mainThreadIsolate = 0; + +void PageScriptDebugServer::setMainThreadIsolate(v8::Isolate* isolate) +{ + s_mainThreadIsolate = isolate; +} + PageScriptDebugServer::PageScriptDebugServer() - : ScriptDebugServer(v8::Isolate::GetCurrent()) + : ScriptDebugServer(s_mainThreadIsolate) , m_pausedPage(0) { } +PageScriptDebugServer::~PageScriptDebugServer() +{ +} + void PageScriptDebugServer::addListener(ScriptDebugListener* listener, Page* page) { - ScriptController& scriptController = page->mainFrame()->script(); + ScriptController& scriptController = page->deprecatedLocalMainFrame()->script(); if (!scriptController.canExecuteScripts(NotAboutToExecuteScript)) return; v8::HandleScope scope(m_isolate); - v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); - v8::Context::Scope contextScope(debuggerContext); - v8::Local<v8::Object> debuggerScript = m_debuggerScript.newLocal(m_isolate); if (!m_listenersMap.size()) { + v8::Debug::SetDebugEventListener(&PageScriptDebugServer::v8DebugEventCallback, v8::External::New(m_isolate, this)); ensureDebuggerScriptCompiled(); - ASSERT(!debuggerScript->IsUndefined()); - v8::Debug::SetDebugEventListener2(&PageScriptDebugServer::v8DebugEventCallback, v8::External::New(m_isolate, this)); } + + v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); + v8::Context::Scope contextScope(debuggerContext); + + v8::Local<v8::Object> debuggerScript = m_debuggerScript.newLocal(m_isolate); + ASSERT(!debuggerScript->IsUndefined()); m_listenersMap.set(page, listener); - V8WindowShell* shell = scriptController.existingWindowShell(mainThreadNormalWorld()); + V8WindowShell* shell = scriptController.existingWindowShell(DOMWrapperWorld::mainWorld()); if (!shell || !shell->isContextInitialized()) return; v8::Local<v8::Context> context = shell->context(); @@ -118,7 +139,7 @@ void PageScriptDebugServer::addListener(ScriptDebugListener* listener, Page* pag ASSERT(!value->IsUndefined() && value->IsArray()); v8::Handle<v8::Array> scriptsArray = v8::Handle<v8::Array>::Cast(value); for (unsigned i = 0; i < scriptsArray->Length(); ++i) - dispatchDidParseSource(listener, v8::Handle<v8::Object>::Cast(scriptsArray->Get(v8::Integer::New(i, m_isolate)))); + dispatchDidParseSource(listener, v8::Handle<v8::Object>::Cast(scriptsArray->Get(v8::Integer::New(m_isolate, i)))); } void PageScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* page) @@ -131,9 +152,16 @@ void PageScriptDebugServer::removeListener(ScriptDebugListener* listener, Page* m_listenersMap.remove(page); - if (m_listenersMap.isEmpty()) - v8::Debug::SetDebugEventListener2(0); - // FIXME: Remove all breakpoints set by the agent. + if (m_listenersMap.isEmpty()) { + discardDebuggerScript(); + v8::Debug::SetDebugEventListener(0); + // FIXME: Remove all breakpoints set by the agent. + } +} + +void PageScriptDebugServer::interruptAndRun(PassOwnPtr<Task> task) +{ + ScriptDebugServer::interruptAndRun(task, s_mainThreadIsolate); } void PageScriptDebugServer::setClientMessageLoop(PassOwnPtr<ClientMessageLoop> clientMessageLoop) @@ -141,11 +169,11 @@ void PageScriptDebugServer::setClientMessageLoop(PassOwnPtr<ClientMessageLoop> c m_clientMessageLoop = clientMessageLoop; } -void PageScriptDebugServer::compileScript(ScriptState* state, const String& expression, const String& sourceURL, String* scriptId, String* exceptionMessage) +void PageScriptDebugServer::compileScript(ScriptState* scriptState, const String& expression, const String& sourceURL, String* scriptId, String* exceptionDetailsText, int* lineNumber, int* columnNumber, RefPtrWillBeRawPtr<ScriptCallStack>* stackTrace) { - ExecutionContext* executionContext = state->executionContext(); - RefPtr<Frame> protect = toDocument(executionContext)->frame(); - ScriptDebugServer::compileScript(state, expression, sourceURL, scriptId, exceptionMessage); + ExecutionContext* executionContext = scriptState->executionContext(); + RefPtr<LocalFrame> protect = toDocument(executionContext)->frame(); + ScriptDebugServer::compileScript(scriptState, expression, sourceURL, scriptId, exceptionDetailsText, lineNumber, columnNumber, stackTrace); if (!scriptId->isNull()) m_compiledScriptURLs.set(*scriptId, sourceURL); } @@ -156,27 +184,31 @@ void PageScriptDebugServer::clearCompiledScripts() m_compiledScriptURLs.clear(); } -void PageScriptDebugServer::runScript(ScriptState* state, const String& scriptId, ScriptValue* result, bool* wasThrown, String* exceptionMessage) +void PageScriptDebugServer::runScript(ScriptState* scriptState, const String& scriptId, ScriptValue* result, bool* wasThrown, String* exceptionDetailsText, int* lineNumber, int* columnNumber, RefPtrWillBeRawPtr<ScriptCallStack>* stackTrace) { String sourceURL = m_compiledScriptURLs.take(scriptId); - ExecutionContext* executionContext = state->executionContext(); - Frame* frame = toDocument(executionContext)->frame(); + ExecutionContext* executionContext = scriptState->executionContext(); + LocalFrame* frame = toDocument(executionContext)->frame(); + TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "EvaluateScript", "data", InspectorEvaluateScriptEvent::data(frame, sourceURL, TextPosition::minimumPosition().m_line.oneBasedInt())); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentationCookie cookie; if (frame) cookie = InspectorInstrumentation::willEvaluateScript(frame, sourceURL, TextPosition::minimumPosition().m_line.oneBasedInt()); - RefPtr<Frame> protect = frame; - ScriptDebugServer::runScript(state, scriptId, result, wasThrown, exceptionMessage); + RefPtr<LocalFrame> protect = frame; + ScriptDebugServer::runScript(scriptState, scriptId, result, wasThrown, exceptionDetailsText, lineNumber, columnNumber, stackTrace); if (frame) InspectorInstrumentation::didEvaluateScript(cookie); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data()); } ScriptDebugListener* PageScriptDebugServer::getDebugListenerForContext(v8::Handle<v8::Context> context) { v8::HandleScope scope(m_isolate); - Frame* frame = retrieveFrameWithGlobalObjectCheck(context); + LocalFrame* frame = retrieveFrameWithGlobalObjectCheck(context); if (!frame) return 0; return m_listenersMap.get(frame->page()); @@ -185,7 +217,7 @@ ScriptDebugListener* PageScriptDebugServer::getDebugListenerForContext(v8::Handl void PageScriptDebugServer::runMessageLoopOnPause(v8::Handle<v8::Context> context) { v8::HandleScope scope(m_isolate); - Frame* frame = retrieveFrameWithGlobalObjectCheck(context); + LocalFrame* frame = retrieveFrameWithGlobalObjectCheck(context); m_pausedPage = frame->page(); // Wait for continue or step command. @@ -206,7 +238,7 @@ void PageScriptDebugServer::quitMessageLoopOnPause() void PageScriptDebugServer::preprocessBeforeCompile(const v8::Debug::EventDetails& eventDetails) { v8::Handle<v8::Context> eventContext = eventDetails.GetEventContext(); - Frame* frame = retrieveFrameWithGlobalObjectCheck(eventContext); + LocalFrame* frame = retrieveFrameWithGlobalObjectCheck(eventContext); if (!frame) return; @@ -236,7 +268,7 @@ void PageScriptDebugServer::preprocessBeforeCompile(const v8::Debug::EventDetail static bool isCreatingPreprocessor = false; -bool PageScriptDebugServer::canPreprocess(Frame* frame) +bool PageScriptDebugServer::canPreprocess(LocalFrame* frame) { ASSERT(frame); @@ -247,7 +279,7 @@ bool PageScriptDebugServer::canPreprocess(Frame* frame) // Web page to ensure that the debugger's console initialization code has completed. if (!m_scriptPreprocessor) { TemporaryChange<bool> isPreprocessing(isCreatingPreprocessor, true); - m_scriptPreprocessor = adoptPtr(new ScriptPreprocessor(*m_preprocessorSourceCode.get(), frame->script(), frame->page()->console())); + m_scriptPreprocessor = adoptPtr(new ScriptPreprocessor(*m_preprocessorSourceCode.get(), frame)); } if (m_scriptPreprocessor->isValid()) @@ -260,7 +292,7 @@ bool PageScriptDebugServer::canPreprocess(Frame* frame) } // Source to Source processing iff debugger enabled and it has loaded a preprocessor. -PassOwnPtr<ScriptSourceCode> PageScriptDebugServer::preprocess(Frame* frame, const ScriptSourceCode& sourceCode) +PassOwnPtr<ScriptSourceCode> PageScriptDebugServer::preprocess(LocalFrame* frame, const ScriptSourceCode& sourceCode) { if (!canPreprocess(frame)) return PassOwnPtr<ScriptSourceCode>(); @@ -269,7 +301,7 @@ PassOwnPtr<ScriptSourceCode> PageScriptDebugServer::preprocess(Frame* frame, con return adoptPtr(new ScriptSourceCode(preprocessedSource, sourceCode.url())); } -String PageScriptDebugServer::preprocessEventListener(Frame* frame, const String& source, const String& url, const String& functionName) +String PageScriptDebugServer::preprocessEventListener(LocalFrame* frame, const String& source, const String& url, const String& functionName) { if (!canPreprocess(frame)) return source; @@ -277,4 +309,16 @@ String PageScriptDebugServer::preprocessEventListener(Frame* frame, const String return m_scriptPreprocessor->preprocessSourceCode(source, url, functionName); } +void PageScriptDebugServer::muteWarningsAndDeprecations() +{ + FrameConsole::mute(); + UseCounter::muteForInspector(); +} + +void PageScriptDebugServer::unmuteWarningsAndDeprecations() +{ + FrameConsole::unmute(); + UseCounter::unmuteForInspector(); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/PageScriptDebugServer.h b/chromium/third_party/WebKit/Source/bindings/v8/PageScriptDebugServer.h index 78fde09e688..96f8779f223 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/PageScriptDebugServer.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/PageScriptDebugServer.h @@ -31,11 +31,11 @@ #ifndef PageScriptDebugServer_h #define PageScriptDebugServer_h - #include "bindings/v8/ScriptDebugServer.h" #include "bindings/v8/ScriptPreprocessor.h" #include "wtf/Forward.h" #include "wtf/RefCounted.h" +#include <v8.h> namespace WebCore { @@ -44,14 +44,18 @@ class ScriptController; class ScriptPreprocessor; class ScriptSourceCode; -class PageScriptDebugServer : public ScriptDebugServer { +class PageScriptDebugServer FINAL : public ScriptDebugServer { WTF_MAKE_NONCOPYABLE(PageScriptDebugServer); public: static PageScriptDebugServer& shared(); + static void setMainThreadIsolate(v8::Isolate*); + void addListener(ScriptDebugListener*, Page*); void removeListener(ScriptDebugListener*, Page*); + static void interruptAndRun(PassOwnPtr<Task>); + class ClientMessageLoop { public: virtual ~ClientMessageLoop() { } @@ -60,21 +64,24 @@ public: }; void setClientMessageLoop(PassOwnPtr<ClientMessageLoop>); - virtual void compileScript(ScriptState*, const String& expression, const String& sourceURL, String* scriptId, String* exceptionMessage); - virtual void clearCompiledScripts(); - virtual void runScript(ScriptState*, const String& scriptId, ScriptValue* result, bool* wasThrown, String* exceptionMessage); - virtual void setPreprocessorSource(const String&); - virtual void preprocessBeforeCompile(const v8::Debug::EventDetails&); - virtual PassOwnPtr<ScriptSourceCode> preprocess(Frame*, const ScriptSourceCode&); - virtual String preprocessEventListener(Frame*, const String& source, const String& url, const String& functionName); + virtual void compileScript(ScriptState*, const String& expression, const String& sourceURL, String* scriptId, String* exceptionDetailsText, int* lineNumber, int* columnNumber, RefPtrWillBeRawPtr<ScriptCallStack>* stackTrace) OVERRIDE; + virtual void clearCompiledScripts() OVERRIDE; + virtual void runScript(ScriptState*, const String& scriptId, ScriptValue* result, bool* wasThrown, String* exceptionDetailsText, int* lineNumber, int* columnNumber, RefPtrWillBeRawPtr<ScriptCallStack>* stackTrace) OVERRIDE; + virtual void setPreprocessorSource(const String&) OVERRIDE; + virtual void preprocessBeforeCompile(const v8::Debug::EventDetails&) OVERRIDE; + virtual PassOwnPtr<ScriptSourceCode> preprocess(LocalFrame*, const ScriptSourceCode&) OVERRIDE; + virtual String preprocessEventListener(LocalFrame*, const String& source, const String& url, const String& functionName) OVERRIDE; + + virtual void muteWarningsAndDeprecations() OVERRIDE; + virtual void unmuteWarningsAndDeprecations() OVERRIDE; private: PageScriptDebugServer(); - virtual ~PageScriptDebugServer() { } + virtual ~PageScriptDebugServer(); - virtual ScriptDebugListener* getDebugListenerForContext(v8::Handle<v8::Context>); - virtual void runMessageLoopOnPause(v8::Handle<v8::Context>); - virtual void quitMessageLoopOnPause(); + virtual ScriptDebugListener* getDebugListenerForContext(v8::Handle<v8::Context>) OVERRIDE; + virtual void runMessageLoopOnPause(v8::Handle<v8::Context>) OVERRIDE; + virtual void quitMessageLoopOnPause() OVERRIDE; typedef HashMap<Page*, ScriptDebugListener*> ListenersMap; ListenersMap m_listenersMap; @@ -84,7 +91,8 @@ private: OwnPtr<ScriptSourceCode> m_preprocessorSourceCode; OwnPtr<ScriptPreprocessor> m_scriptPreprocessor; - bool canPreprocess(Frame*); + bool canPreprocess(LocalFrame*); + static v8::Isolate* s_mainThreadIsolate; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/RetainedDOMInfo.h b/chromium/third_party/WebKit/Source/bindings/v8/RetainedDOMInfo.h index 52709997cfc..2138c0b9937 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/RetainedDOMInfo.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/RetainedDOMInfo.h @@ -32,23 +32,24 @@ #define RetainedDOMInfo_h #include "bindings/v8/RetainedObjectInfo.h" +#include <v8-profiler.h> namespace WebCore { class Node; // Implements v8::RetainedObjectInfo. -class RetainedDOMInfo : public RetainedObjectInfo { +class RetainedDOMInfo FINAL : public RetainedObjectInfo { public: explicit RetainedDOMInfo(Node* root); virtual ~RetainedDOMInfo(); - virtual void Dispose(); - virtual bool IsEquivalent(v8::RetainedObjectInfo* other); - virtual intptr_t GetHash(); - virtual const char* GetGroupLabel(); - virtual const char* GetLabel(); - virtual intptr_t GetElementCount(); - virtual intptr_t GetEquivalenceClass(); + virtual void Dispose() OVERRIDE; + virtual bool IsEquivalent(v8::RetainedObjectInfo* other) OVERRIDE; + virtual intptr_t GetHash() OVERRIDE; + virtual const char* GetGroupLabel() OVERRIDE; + virtual const char* GetLabel() OVERRIDE; + virtual intptr_t GetElementCount() OVERRIDE; + virtual intptr_t GetEquivalenceClass() OVERRIDE; private: // V8 guarantees to keep RetainedObjectInfos alive only during a GC or heap snapshotting round, when renderer diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScheduledAction.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScheduledAction.cpp index 1de2039ec15..0f669f310e8 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScheduledAction.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScheduledAction.cpp @@ -38,41 +38,39 @@ #include "bindings/v8/V8ScriptRunner.h" #include "core/dom/Document.h" #include "core/dom/ExecutionContext.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" #include "core/workers/WorkerGlobalScope.h" #include "core/workers/WorkerThread.h" #include "platform/TraceEvent.h" namespace WebCore { -ScheduledAction::ScheduledAction(v8::Handle<v8::Context> context, v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[], v8::Isolate* isolate) - : m_context(isolate, context) +ScheduledAction::ScheduledAction(ScriptState* scriptState, v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[], v8::Isolate* isolate) + : m_scriptState(scriptState) , m_function(isolate, function) + , m_info(isolate) , m_code(String(), KURL(), TextPosition::belowRangePosition()) - , m_isolate(isolate) { - m_info.reserveCapacity(argc); + m_info.ReserveCapacity(argc); for (int i = 0; i < argc; ++i) - m_info.append(UnsafePersistent<v8::Value>(m_isolate, argv[i])); + m_info.Append(argv[i]); } -ScheduledAction::ScheduledAction(v8::Handle<v8::Context> context, const String& code, const KURL& url, v8::Isolate* isolate) - : m_context(isolate, context) +ScheduledAction::ScheduledAction(ScriptState* scriptState, const String& code, const KURL& url, v8::Isolate* isolate) + : m_scriptState(scriptState) + , m_info(isolate) , m_code(code, url) - , m_isolate(isolate) { } ScheduledAction::~ScheduledAction() { - for (size_t i = 0; i < m_info.size(); ++i) - m_info[i].dispose(); } void ScheduledAction::execute(ExecutionContext* context) { if (context->isDocument()) { - Frame* frame = toDocument(context)->frame(); + LocalFrame* frame = toDocument(context)->frame(); if (!frame) return; if (!frame->script().canExecuteScripts(AboutToExecuteScript)) @@ -83,23 +81,19 @@ void ScheduledAction::execute(ExecutionContext* context) } } -void ScheduledAction::execute(Frame* frame) +void ScheduledAction::execute(LocalFrame* frame) { - v8::HandleScope handleScope(m_isolate); - - v8::Handle<v8::Context> context = m_context.newLocal(m_isolate); - if (context.IsEmpty()) + if (m_scriptState->contextIsEmpty()) return; TRACE_EVENT0("v8", "ScheduledAction::execute"); - + ScriptState::Scope scope(m_scriptState.get()); if (!m_function.isEmpty()) { - v8::Context::Scope scope(context); Vector<v8::Handle<v8::Value> > info; createLocalHandlesForArgs(&info); - frame->script().callFunction(m_function.newLocal(m_isolate), context->Global(), info.size(), info.data()); + frame->script().callFunction(m_function.newLocal(m_scriptState->isolate()), m_scriptState->context()->Global(), info.size(), info.data()); } else { - frame->script().executeScriptAndReturnValue(context, ScriptSourceCode(m_code)); + frame->script().executeScriptAndReturnValue(m_scriptState->context(), ScriptSourceCode(m_code)); } // The frame might be invalid at this point because JavaScript could have released it. @@ -108,23 +102,22 @@ void ScheduledAction::execute(Frame* frame) void ScheduledAction::execute(WorkerGlobalScope* worker) { ASSERT(worker->thread()->isCurrentThread()); - v8::HandleScope handleScope(m_isolate); - v8::Handle<v8::Context> context = m_context.newLocal(m_isolate); - ASSERT(!context.IsEmpty()); - v8::Context::Scope scope(context); + ASSERT(!m_scriptState->contextIsEmpty()); if (!m_function.isEmpty()) { + ScriptState::Scope scope(m_scriptState.get()); Vector<v8::Handle<v8::Value> > info; createLocalHandlesForArgs(&info); - V8ScriptRunner::callFunction(m_function.newLocal(m_isolate), worker, context->Global(), info.size(), info.data(), m_isolate); - } else + V8ScriptRunner::callFunction(m_function.newLocal(m_scriptState->isolate()), worker, m_scriptState->context()->Global(), info.size(), info.data(), m_scriptState->isolate()); + } else { worker->script()->evaluate(m_code); + } } void ScheduledAction::createLocalHandlesForArgs(Vector<v8::Handle<v8::Value> >* handles) { - handles->reserveCapacity(m_info.size()); - for (size_t i = 0; i < m_info.size(); ++i) - handles->append(m_info[i].newLocal(m_isolate)); + handles->reserveCapacity(m_info.Size()); + for (size_t i = 0; i < m_info.Size(); ++i) + handles->append(m_info.Get(i)); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScheduledAction.h b/chromium/third_party/WebKit/Source/bindings/v8/ScheduledAction.h index 9b03a027305..351ef3bed7e 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScheduledAction.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScheduledAction.h @@ -33,36 +33,35 @@ #include "bindings/v8/ScopedPersistent.h" #include "bindings/v8/ScriptSourceCode.h" -#include "bindings/v8/UnsafePersistent.h" +#include "bindings/v8/ScriptState.h" +#include "bindings/v8/V8PersistentValueVector.h" #include <v8.h> #include "wtf/Forward.h" -#include "wtf/Vector.h" namespace WebCore { -class Frame; +class LocalFrame; class ExecutionContext; class WorkerGlobalScope; class ScheduledAction { WTF_MAKE_NONCOPYABLE(ScheduledAction); public: - ScheduledAction(v8::Handle<v8::Context>, v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[], v8::Isolate*); - ScheduledAction(v8::Handle<v8::Context>, const String&, const KURL&, v8::Isolate*); + ScheduledAction(ScriptState*, v8::Handle<v8::Function>, int argc, v8::Handle<v8::Value> argv[], v8::Isolate*); + ScheduledAction(ScriptState*, const String&, const KURL&, v8::Isolate*); ~ScheduledAction(); void execute(ExecutionContext*); private: - void execute(Frame*); + void execute(LocalFrame*); void execute(WorkerGlobalScope*); void createLocalHandlesForArgs(Vector<v8::Handle<v8::Value> >* handles); - ScopedPersistent<v8::Context> m_context; + ScriptStateProtectingContext m_scriptState; ScopedPersistent<v8::Function> m_function; - Vector<UnsafePersistent<v8::Value> > m_info; + V8PersistentValueVector<v8::Value> m_info; ScriptSourceCode m_code; - v8::Isolate* m_isolate; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScopedPersistent.h b/chromium/third_party/WebKit/Source/bindings/v8/ScopedPersistent.h index 84b6beea6ce..a383f780c37 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScopedPersistent.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScopedPersistent.h @@ -64,6 +64,7 @@ public: } bool isEmpty() const { return m_handle.IsEmpty(); } + bool isWeak() const { return m_handle.IsWeak(); } void set(v8::Isolate* isolate, v8::Handle<T> handle) { @@ -81,6 +82,12 @@ public: return m_handle == other.m_handle; } + template <class S> + bool operator==(const v8::Handle<S> other) const + { + return m_handle == other; + } + private: // FIXME: This function does an unsafe handle access. Remove it. friend class V8AbstractEventListener; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptCallStackFactory.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptCallStackFactory.cpp index 81dea4584c6..8c68a9ddd4a 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptCallStackFactory.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptCallStackFactory.cpp @@ -31,10 +31,8 @@ #include "config.h" #include "bindings/v8/ScriptCallStackFactory.h" -#include "bindings/v8/ScriptScope.h" #include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "core/inspector/InspectorInstrumentation.h" #include "core/inspector/ScriptArguments.h" #include "core/inspector/ScriptCallFrame.h" @@ -86,7 +84,7 @@ static void toScriptCallFramesVector(v8::Handle<v8::StackTrace> stackTrace, Vect } } -static PassRefPtr<ScriptCallStack> createScriptCallStack(v8::Handle<v8::StackTrace> stackTrace, size_t maxStackSize, bool emptyStackIsAllowed, v8::Isolate* isolate) +static PassRefPtrWillBeRawPtr<ScriptCallStack> createScriptCallStack(v8::Handle<v8::StackTrace> stackTrace, size_t maxStackSize, bool emptyStackIsAllowed, v8::Isolate* isolate) { ASSERT(isolate->InContext()); v8::HandleScope scope(isolate); @@ -95,44 +93,38 @@ static PassRefPtr<ScriptCallStack> createScriptCallStack(v8::Handle<v8::StackTra return ScriptCallStack::create(scriptCallFrames); } -PassRefPtr<ScriptCallStack> createScriptCallStack(v8::Handle<v8::StackTrace> stackTrace, size_t maxStackSize, v8::Isolate* isolate) +PassRefPtrWillBeRawPtr<ScriptCallStack> createScriptCallStack(v8::Handle<v8::StackTrace> stackTrace, size_t maxStackSize, v8::Isolate* isolate) { return createScriptCallStack(stackTrace, maxStackSize, true, isolate); } -PassRefPtr<ScriptCallStack> createScriptCallStack(size_t maxStackSize, bool emptyStackIsAllowed) +PassRefPtrWillBeRawPtr<ScriptCallStack> createScriptCallStack(size_t maxStackSize, bool emptyStackIsAllowed) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); if (!isolate->InContext()) - return 0; + return nullptr; v8::HandleScope handleScope(isolate); v8::Handle<v8::StackTrace> stackTrace(v8::StackTrace::CurrentStackTrace(isolate, maxStackSize, stackTraceOptions)); return createScriptCallStack(stackTrace, maxStackSize, emptyStackIsAllowed, isolate); } -PassRefPtr<ScriptCallStack> createScriptCallStackForConsole(size_t maxStackSize) +PassRefPtrWillBeRawPtr<ScriptCallStack> createScriptCallStackForConsole(ScriptState* scriptState, size_t maxStackSize) { size_t stackSize = 1; if (InspectorInstrumentation::hasFrontends()) { - ExecutionContext* executionContext = getExecutionContext(); - if (InspectorInstrumentation::consoleAgentEnabled(executionContext)) + if (InspectorInstrumentation::consoleAgentEnabled(scriptState->executionContext())) stackSize = maxStackSize; } return createScriptCallStack(stackSize); } -PassRefPtr<ScriptArguments> createScriptArguments(const v8::FunctionCallbackInfo<v8::Value>& v8arguments, unsigned skipArgumentCount) +PassRefPtrWillBeRawPtr<ScriptArguments> createScriptArguments(ScriptState* scriptState, const v8::FunctionCallbackInfo<v8::Value>& v8arguments, unsigned skipArgumentCount) { - v8::Isolate* isolate = v8arguments.GetIsolate(); - v8::HandleScope scope(isolate); - v8::Local<v8::Context> context = isolate->GetCurrentContext(); - ScriptState* state = ScriptState::forContext(context); - Vector<ScriptValue> arguments; for (int i = skipArgumentCount; i < v8arguments.Length(); ++i) - arguments.append(ScriptValue(v8arguments[i], isolate)); + arguments.append(ScriptValue(scriptState, v8arguments[i])); - return ScriptArguments::create(state, arguments); + return ScriptArguments::create(scriptState, arguments); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptCallStackFactory.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptCallStackFactory.h index ff225e30714..6654b67aab6 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptCallStackFactory.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptCallStackFactory.h @@ -48,10 +48,10 @@ const v8::StackTrace::StackTraceOptions stackTraceOptions = static_cast<v8::Stac | v8::StackTrace::kScriptNameOrSourceURL | v8::StackTrace::kFunctionName); -PassRefPtr<ScriptCallStack> createScriptCallStack(v8::Handle<v8::StackTrace>, size_t maxStackSize, v8::Isolate*); -PassRefPtr<ScriptCallStack> createScriptCallStack(size_t maxStackSize, bool emptyStackIsAllowed = false); -PassRefPtr<ScriptCallStack> createScriptCallStackForConsole(size_t maxStackSize = ScriptCallStack::maxCallStackSizeToCapture); -PassRefPtr<ScriptArguments> createScriptArguments(const v8::FunctionCallbackInfo<v8::Value>& v8arguments, unsigned skipArgumentCount); +PassRefPtrWillBeRawPtr<ScriptCallStack> createScriptCallStack(v8::Handle<v8::StackTrace>, size_t maxStackSize, v8::Isolate*); +PassRefPtrWillBeRawPtr<ScriptCallStack> createScriptCallStack(size_t maxStackSize, bool emptyStackIsAllowed = false); +PassRefPtrWillBeRawPtr<ScriptCallStack> createScriptCallStackForConsole(ScriptState*, size_t maxStackSize = ScriptCallStack::maxCallStackSizeToCapture); +PassRefPtrWillBeRawPtr<ScriptArguments> createScriptArguments(ScriptState*, const v8::FunctionCallbackInfo<v8::Value>& v8arguments, unsigned skipArgumentCount); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptController.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptController.cpp index b60a5c74cca..d7049069670 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptController.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptController.cpp @@ -32,9 +32,9 @@ #include "config.h" #include "bindings/v8/ScriptController.h" -#include "V8Event.h" -#include "V8HTMLElement.h" -#include "V8Window.h" +#include "bindings/core/v8/V8Event.h" +#include "bindings/core/v8/V8HTMLElement.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/BindingSecurity.h" #include "bindings/v8/NPV8Object.h" #include "bindings/v8/ScriptCallStackFactory.h" @@ -42,7 +42,6 @@ #include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8GCController.h" -#include "bindings/v8/V8HiddenPropertyName.h" #include "bindings/v8/V8NPObject.h" #include "bindings/v8/V8PerContextData.h" #include "bindings/v8/V8ScriptRunner.h" @@ -54,17 +53,17 @@ #include "core/dom/ScriptableDocumentParser.h" #include "core/events/Event.h" #include "core/events/EventListener.h" -#include "core/events/ThreadLocalEventNames.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/Settings.h" +#include "core/frame/csp/ContentSecurityPolicy.h" #include "core/html/HTMLPlugInElement.h" #include "core/inspector/InspectorInstrumentation.h" +#include "core/inspector/InspectorTraceEvents.h" #include "core/inspector/ScriptCallStack.h" #include "core/loader/DocumentLoader.h" #include "core/loader/FrameLoader.h" #include "core/loader/FrameLoaderClient.h" -#include "core/frame/ContentSecurityPolicy.h" -#include "core/frame/DOMWindow.h" -#include "core/frame/Frame.h" -#include "core/frame/Settings.h" #include "core/plugins/PluginView.h" #include "platform/NotImplemented.h" #include "platform/TraceEvent.h" @@ -81,23 +80,27 @@ namespace WebCore { -bool ScriptController::canAccessFromCurrentOrigin(Frame *frame) +bool ScriptController::canAccessFromCurrentOrigin(LocalFrame *frame) { - return !v8::Isolate::GetCurrent()->InContext() || BindingSecurity::shouldAllowAccessToFrame(frame); + if (!frame) + return false; + v8::Isolate* isolate = toIsolate(frame); + return !isolate->InContext() || BindingSecurity::shouldAllowAccessToFrame(isolate, frame); } -ScriptController::ScriptController(Frame* frame) +ScriptController::ScriptController(LocalFrame* frame) : m_frame(frame) , m_sourceURL(0) , m_isolate(v8::Isolate::GetCurrent()) - , m_windowShell(V8WindowShell::create(frame, mainThreadNormalWorld(), m_isolate)) + , m_windowShell(V8WindowShell::create(frame, DOMWrapperWorld::mainWorld(), m_isolate)) , m_windowScriptNPObject(0) { } ScriptController::~ScriptController() { - clearForClose(true); + // V8WindowShell::clearForClose() must be invoked before destruction starts. + ASSERT(!m_windowShell->isContextInitialized()); } void ScriptController::clearScriptObjects() @@ -120,61 +123,39 @@ void ScriptController::clearScriptObjects() } } -void ScriptController::clearForOutOfMemory() -{ - clearForClose(true); -} - -void ScriptController::clearForClose(bool destroyGlobal) -{ - m_windowShell->clearForClose(destroyGlobal); - for (IsolatedWorldMap::iterator iter = m_isolatedWorlds.begin(); iter != m_isolatedWorlds.end(); ++iter) - iter->value->clearForClose(destroyGlobal); - V8GCController::hintForCollectGarbage(); -} - void ScriptController::clearForClose() { double start = currentTime(); - clearForClose(false); + m_windowShell->clearForClose(); + for (IsolatedWorldMap::iterator iter = m_isolatedWorlds.begin(); iter != m_isolatedWorlds.end(); ++iter) + iter->value->clearForClose(); blink::Platform::current()->histogramCustomCounts("WebCore.ScriptController.clearForClose", (currentTime() - start) * 1000, 0, 10000, 50); } -void ScriptController::updateSecurityOrigin() +void ScriptController::updateSecurityOrigin(SecurityOrigin* origin) { - m_windowShell->updateSecurityOrigin(); + m_windowShell->updateSecurityOrigin(origin); } -v8::Local<v8::Value> ScriptController::callFunction(v8::Handle<v8::Function> function, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> info[]) +v8::Local<v8::Value> ScriptController::callFunction(v8::Handle<v8::Function> function, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[]) { - // Keep Frame (and therefore ScriptController) alive. - RefPtr<Frame> protect(m_frame); + // Keep LocalFrame (and therefore ScriptController) alive. + RefPtr<LocalFrame> protect(m_frame); return ScriptController::callFunction(m_frame->document(), function, receiver, argc, info, m_isolate); } -static bool resourceInfo(const v8::Handle<v8::Function> function, String& resourceName, int& lineNumber) -{ - v8::ScriptOrigin origin = function->GetScriptOrigin(); - if (origin.ResourceName().IsEmpty()) { - resourceName = "undefined"; - lineNumber = 1; - } else { - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringResourceName, origin.ResourceName(), false); - resourceName = stringResourceName; - lineNumber = function->GetScriptLineNumber() + 1; - } - return true; -} - -v8::Local<v8::Value> ScriptController::callFunction(ExecutionContext* context, v8::Handle<v8::Function> function, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> info[], v8::Isolate* isolate) +v8::Local<v8::Value> ScriptController::callFunction(ExecutionContext* context, v8::Handle<v8::Function> function, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[], v8::Isolate* isolate) { + TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "FunctionCall", "data", devToolsTraceEventData(context, function, isolate)); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentationCookie cookie; if (InspectorInstrumentation::timelineAgentEnabled(context)) { + int scriptId = 0; String resourceName; - int lineNumber; - if (!resourceInfo(function, resourceName, lineNumber)) - return v8::Local<v8::Value>(); - cookie = InspectorInstrumentation::willCallFunction(context, resourceName, lineNumber); + int lineNumber = 1; + GetDevToolsFunctionInfo(function, isolate, scriptId, resourceName, lineNumber); + cookie = InspectorInstrumentation::willCallFunction(context, scriptId, resourceName, lineNumber); } v8::Local<v8::Value> result = V8ScriptRunner::callFunction(function, context, receiver, argc, info, isolate); @@ -185,9 +166,10 @@ v8::Local<v8::Value> ScriptController::callFunction(ExecutionContext* context, v v8::Local<v8::Value> ScriptController::executeScriptAndReturnValue(v8::Handle<v8::Context> context, const ScriptSourceCode& source, AccessControlStatus corsStatus) { - v8::Context::Scope scope(context); - - InspectorInstrumentationCookie cookie = InspectorInstrumentation::willEvaluateScript(m_frame, source.url().isNull() ? String() : source.url().string(), source.startLine()); + TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "EvaluateScript", "data", InspectorEvaluateScriptEvent::data(m_frame, source.url().string(), source.startLine())); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. + InspectorInstrumentationCookie cookie = InspectorInstrumentation::willEvaluateScript(m_frame, source.url().string(), source.startLine()); v8::Local<v8::Value> result; { @@ -198,20 +180,16 @@ v8::Local<v8::Value> ScriptController::executeScriptAndReturnValue(v8::Handle<v8 v8::TryCatch tryCatch; tryCatch.SetVerbose(true); - v8::Handle<v8::String> code = v8String(m_isolate, source.source()); - OwnPtr<v8::ScriptData> scriptData = V8ScriptRunner::precompileScript(code, source.resource()); + v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(source, m_isolate, corsStatus); - // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at - // 1, whereas v8 starts at 0. - v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(code, source.url(), source.startPosition(), scriptData.get(), m_isolate, corsStatus); - - // Keep Frame (and therefore ScriptController) alive. - RefPtr<Frame> protect(m_frame); + // Keep LocalFrame (and therefore ScriptController) alive. + RefPtr<LocalFrame> protect(m_frame); result = V8ScriptRunner::runCompiledScript(script, m_frame->document(), m_isolate); ASSERT(!tryCatch.HasCaught() || result.IsEmpty()); } InspectorInstrumentation::didEvaluateScript(cookie); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data()); return result; } @@ -220,59 +198,47 @@ bool ScriptController::initializeMainWorld() { if (m_windowShell->isContextInitialized()) return false; - return windowShell(mainThreadNormalWorld())->isContextInitialized(); + return windowShell(DOMWrapperWorld::mainWorld())->isContextInitialized(); } -V8WindowShell* ScriptController::existingWindowShell(DOMWrapperWorld* world) +V8WindowShell* ScriptController::existingWindowShell(DOMWrapperWorld& world) { - ASSERT(world); - - if (world->isMainWorld()) + if (world.isMainWorld()) return m_windowShell->isContextInitialized() ? m_windowShell.get() : 0; - // FIXME: Remove this block. See comment with existingWindowShellWorkaroundWorld(). - if (world == existingWindowShellWorkaroundWorld()) - return m_windowShell.get(); - - IsolatedWorldMap::iterator iter = m_isolatedWorlds.find(world->worldId()); + IsolatedWorldMap::iterator iter = m_isolatedWorlds.find(world.worldId()); if (iter == m_isolatedWorlds.end()) return 0; return iter->value->isContextInitialized() ? iter->value.get() : 0; } -V8WindowShell* ScriptController::windowShell(DOMWrapperWorld* world) +V8WindowShell* ScriptController::windowShell(DOMWrapperWorld& world) { - ASSERT(world); - V8WindowShell* shell = 0; - if (world->isMainWorld()) + if (world.isMainWorld()) shell = m_windowShell.get(); else { - IsolatedWorldMap::iterator iter = m_isolatedWorlds.find(world->worldId()); + IsolatedWorldMap::iterator iter = m_isolatedWorlds.find(world.worldId()); if (iter != m_isolatedWorlds.end()) shell = iter->value.get(); else { OwnPtr<V8WindowShell> isolatedWorldShell = V8WindowShell::create(m_frame, world, m_isolate); shell = isolatedWorldShell.get(); - m_isolatedWorlds.set(world->worldId(), isolatedWorldShell.release()); - } - } - if (!shell->isContextInitialized() && shell->initializeIfNeeded()) { - if (world->isMainWorld()) { - // FIXME: Remove this if clause. See comment with existingWindowShellWorkaroundWorld(). - m_frame->loader().dispatchDidClearWindowObjectInWorld(existingWindowShellWorkaroundWorld()); - } else { - m_frame->loader().dispatchDidClearWindowObjectInWorld(world); + m_isolatedWorlds.set(world.worldId(), isolatedWorldShell.release()); } } + if (!shell->isContextInitialized() && shell->initializeIfNeeded() && world.isMainWorld()) + m_frame->loader().dispatchDidClearWindowObjectInMainWorld(); return shell; } bool ScriptController::shouldBypassMainWorldContentSecurityPolicy() { - if (DOMWrapperWorld* world = isolatedWorldForEnteredContext(m_isolate)) - return world->isolatedWorldHasContentSecurityPolicy(); - return false; + v8::Handle<v8::Context> context = m_isolate->GetCurrentContext(); + if (context.IsEmpty() || !toDOMWindow(context)) + return false; + DOMWrapperWorld& world = DOMWrapperWorld::current(m_isolate); + return world.isIsolatedWorld() ? world.isolatedWorldHasContentSecurityPolicy() : false; } TextPosition ScriptController::eventHandlerPosition() const @@ -283,57 +249,18 @@ TextPosition ScriptController::eventHandlerPosition() const return TextPosition::minimumPosition(); } -static inline v8::Local<v8::Context> contextForWorld(ScriptController& scriptController, DOMWrapperWorld* world) -{ - return scriptController.windowShell(world)->context(); -} - -v8::Local<v8::Context> ScriptController::currentWorldContext() -{ - if (!isolate()->InContext()) - return contextForWorld(*this, mainThreadNormalWorld()); - - v8::Handle<v8::Context> context = isolate()->GetEnteredContext(); - DOMWrapperWorld* isolatedWorld = DOMWrapperWorld::isolatedWorld(context); - if (!isolatedWorld) - return contextForWorld(*this, mainThreadNormalWorld()); - - Frame* frame = toFrameIfNotDetached(context); - if (m_frame == frame) - return v8::Local<v8::Context>::New(m_isolate, context); - - return contextForWorld(*this, isolatedWorld); -} - -v8::Local<v8::Context> ScriptController::mainWorldContext() -{ - return contextForWorld(*this, mainThreadNormalWorld()); -} - -v8::Local<v8::Context> ScriptController::mainWorldContext(Frame* frame) -{ - if (!frame) - return v8::Local<v8::Context>(); - - return contextForWorld(frame->script(), mainThreadNormalWorld()); -} - // Create a V8 object with an interceptor of NPObjectPropertyGetter. -void ScriptController::bindToWindowObject(Frame* frame, const String& key, NPObject* object) +void ScriptController::bindToWindowObject(LocalFrame* frame, const String& key, NPObject* object) { - v8::HandleScope handleScope(m_isolate); - - v8::Handle<v8::Context> v8Context = ScriptController::mainWorldContext(frame); - if (v8Context.IsEmpty()) + ScriptState* scriptState = ScriptState::forMainWorld(frame); + if (scriptState->contextIsEmpty()) return; - v8::Context::Scope scope(v8Context); - + ScriptState::Scope scope(scriptState); v8::Handle<v8::Object> value = createV8ObjectForNPObject(object, 0, m_isolate); // Attach to the global object. - v8::Handle<v8::Object> global = v8Context->Global(); - global->Set(v8String(m_isolate, key), value); + scriptState->context()->Global()->Set(v8String(m_isolate, key), value); } void ScriptController::enableEval() @@ -359,13 +286,13 @@ PassRefPtr<SharedPersistent<v8::Object> > ScriptController::createPluginWrapper( ASSERT(widget); if (!widget->isPluginView()) - return 0; + return nullptr; NPObject* npObject = toPluginView(widget)->scriptableObject(); if (!npObject) - return 0; + return nullptr; - // Frame Memory Management for NPObjects + // LocalFrame Memory Management for NPObjects // ------------------------------------- // NPObjects are treated differently than other objects wrapped by JS. // NPObjects can be created either by the browser (e.g. the main @@ -374,7 +301,7 @@ PassRefPtr<SharedPersistent<v8::Object> > ScriptController::createPluginWrapper( // is especially careful to ensure NPObjects terminate at frame teardown because // if a plugin leaks a reference, it could leak its objects (or the browser's objects). // - // The Frame maintains a list of plugin objects (m_pluginObjects) + // The LocalFrame maintains a list of plugin objects (m_pluginObjects) // which it can use to quickly find the wrapped embed object. // // Inside the NPRuntime, we've added a few methods for registering @@ -430,18 +357,16 @@ static NPObject* createNoScriptObject() return 0; } -static NPObject* createScriptObject(Frame* frame, v8::Isolate* isolate) +static NPObject* createScriptObject(LocalFrame* frame, v8::Isolate* isolate) { - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> v8Context = ScriptController::mainWorldContext(frame); - if (v8Context.IsEmpty()) + ScriptState* scriptState = ScriptState::forMainWorld(frame); + if (scriptState->contextIsEmpty()) return createNoScriptObject(); - v8::Context::Scope scope(v8Context); - DOMWindow* window = frame->domWindow(); - v8::Handle<v8::Value> global = toV8(window, v8::Handle<v8::Object>(), v8Context->GetIsolate()); + ScriptState::Scope scope(scriptState); + LocalDOMWindow* window = frame->domWindow(); + v8::Handle<v8::Value> global = toV8(window, scriptState->context()->Global(), scriptState->isolate()); ASSERT(global->IsObject()); - return npCreateV8ScriptObject(0, v8::Handle<v8::Object>::Cast(global), window, isolate); } @@ -470,18 +395,17 @@ NPObject* ScriptController::createScriptObjectForPluginElement(HTMLPlugInElement if (!canExecuteScripts(NotAboutToExecuteScript)) return createNoScriptObject(); - v8::HandleScope handleScope(m_isolate); - v8::Handle<v8::Context> v8Context = ScriptController::mainWorldContext(m_frame); - if (v8Context.IsEmpty()) + ScriptState* scriptState = ScriptState::forMainWorld(m_frame); + if (scriptState->contextIsEmpty()) return createNoScriptObject(); - v8::Context::Scope scope(v8Context); - DOMWindow* window = m_frame->domWindow(); - v8::Handle<v8::Value> v8plugin = toV8(plugin, v8::Handle<v8::Object>(), v8Context->GetIsolate()); + ScriptState::Scope scope(scriptState); + LocalDOMWindow* window = m_frame->domWindow(); + v8::Handle<v8::Value> v8plugin = toV8(plugin, scriptState->context()->Global(), scriptState->isolate()); if (!v8plugin->IsObject()) return createNoScriptObject(); - return npCreateV8ScriptObject(0, v8::Handle<v8::Object>::Cast(v8plugin), window, v8Context->GetIsolate()); + return npCreateV8ScriptObject(0, v8::Handle<v8::Object>::Cast(v8plugin), window, scriptState->isolate()); } void ScriptController::clearWindowShell() @@ -492,7 +416,7 @@ void ScriptController::clearWindowShell() m_windowShell->clearForNavigation(); for (IsolatedWorldMap::iterator iter = m_isolatedWorlds.begin(); iter != m_isolatedWorlds.end(); ++iter) iter->value->clearForNavigation(); - V8GCController::hintForCollectGarbage(); + clearScriptObjects(); blink::Platform::current()->histogramCustomCounts("WebCore.ScriptController.clearWindowShell", (currentTime() - start) * 1000, 0, 10000, 50); } @@ -503,17 +427,14 @@ void ScriptController::setCaptureCallStackForUncaughtExceptions(bool value) void ScriptController::collectIsolatedContexts(Vector<std::pair<ScriptState*, SecurityOrigin*> >& result) { - v8::HandleScope handleScope(m_isolate); for (IsolatedWorldMap::iterator it = m_isolatedWorlds.begin(); it != m_isolatedWorlds.end(); ++it) { V8WindowShell* isolatedWorldShell = it->value.get(); - SecurityOrigin* origin = isolatedWorldShell->world()->isolatedWorldSecurityOrigin(); + SecurityOrigin* origin = isolatedWorldShell->world().isolatedWorldSecurityOrigin(); if (!origin) continue; - v8::Local<v8::Context> v8Context = isolatedWorldShell->context(); - if (v8Context.IsEmpty()) + if (!isolatedWorldShell->isContextInitialized()) continue; - ScriptState* scriptState = ScriptState::forContext(v8Context); - result.append(std::pair<ScriptState*, SecurityOrigin*>(scriptState, origin)); + result.append(std::pair<ScriptState*, SecurityOrigin*>(isolatedWorldShell->scriptState(), origin)); } } @@ -534,22 +455,22 @@ int ScriptController::contextDebugId(v8::Handle<v8::Context> context) void ScriptController::updateDocument() { - // For an uninitialized main window shell, do not incur the cost of context initialization during FrameLoader::init(). - if ((!m_windowShell->isContextInitialized() || !m_windowShell->isGlobalInitialized()) && m_frame->loader().stateMachine()->creatingInitialEmptyDocument()) + // For an uninitialized main window shell, do not incur the cost of context initialization. + if (!m_windowShell->isGlobalInitialized()) return; if (!initializeMainWorld()) - windowShell(mainThreadNormalWorld())->updateDocument(); + windowShell(DOMWrapperWorld::mainWorld())->updateDocument(); } void ScriptController::namedItemAdded(HTMLDocument* doc, const AtomicString& name) { - windowShell(mainThreadNormalWorld())->namedItemAdded(doc, name); + windowShell(DOMWrapperWorld::mainWorld())->namedItemAdded(doc, name); } void ScriptController::namedItemRemoved(HTMLDocument* doc, const AtomicString& name) { - windowShell(mainThreadNormalWorld())->namedItemRemoved(doc, name); + windowShell(DOMWrapperWorld::mainWorld())->namedItemRemoved(doc, name); } bool ScriptController::canExecuteScripts(ReasonForCallingCanExecuteScripts reason) @@ -567,7 +488,7 @@ bool ScriptController::canExecuteScripts(ReasonForCallingCanExecuteScripts reaso } Settings* settings = m_frame->settings(); - const bool allowed = m_frame->loader().client()->allowScript(settings && settings->isScriptEnabled()); + const bool allowed = m_frame->loader().client()->allowScript(settings && settings->scriptEnabled()); if (!allowed && reason == AboutToExecuteScript) m_frame->loader().client()->didNotAllowScript(); return allowed; @@ -582,30 +503,30 @@ bool ScriptController::executeScriptIfJavaScriptURL(const KURL& url) || !m_frame->document()->contentSecurityPolicy()->allowJavaScriptURLs(m_frame->document()->url(), eventHandlerPosition().m_line)) return true; - // We need to hold onto the Frame here because executing script can + // We need to hold onto the LocalFrame here because executing script can // destroy the frame. - RefPtr<Frame> protector(m_frame); - RefPtr<Document> ownerDocument(m_frame->document()); + RefPtr<LocalFrame> protector(m_frame); + RefPtrWillBeRawPtr<Document> ownerDocument(m_frame->document()); const int javascriptSchemeLength = sizeof("javascript:") - 1; bool locationChangeBefore = m_frame->navigationScheduler().locationChangePending(); String decodedURL = decodeURLEscapeSequences(url.string()); - ScriptValue result = evaluateScriptInMainWorld(ScriptSourceCode(decodedURL.substring(javascriptSchemeLength)), NotSharableCrossOrigin, DoNotExecuteScriptWhenScriptsDisabled); + v8::HandleScope handleScope(m_isolate); + v8::Local<v8::Value> result = evaluateScriptInMainWorld(ScriptSourceCode(decodedURL.substring(javascriptSchemeLength)), NotSharableCrossOrigin, DoNotExecuteScriptWhenScriptsDisabled); // If executing script caused this frame to be removed from the page, we // don't want to try to replace its document! if (!m_frame->page()) return true; - String scriptResult; - if (!result.getString(scriptResult)) + if (result.IsEmpty() || !result->IsString()) return true; + String scriptResult = toCoreString(v8::Handle<v8::String>::Cast(result)); // We're still in a frame, so there should be a DocumentLoader. ASSERT(m_frame->document()->loader()); - if (!locationChangeBefore && m_frame->navigationScheduler().locationChangePending()) return true; @@ -620,80 +541,77 @@ bool ScriptController::executeScriptIfJavaScriptURL(const KURL& url) void ScriptController::executeScriptInMainWorld(const String& script, ExecuteScriptPolicy policy) { + v8::HandleScope handleScope(m_isolate); evaluateScriptInMainWorld(ScriptSourceCode(script), NotSharableCrossOrigin, policy); } void ScriptController::executeScriptInMainWorld(const ScriptSourceCode& sourceCode, AccessControlStatus corsStatus) { + v8::HandleScope handleScope(m_isolate); evaluateScriptInMainWorld(sourceCode, corsStatus, DoNotExecuteScriptWhenScriptsDisabled); } -ScriptValue ScriptController::executeScriptInMainWorldAndReturnValue(const ScriptSourceCode& sourceCode) +v8::Local<v8::Value> ScriptController::executeScriptInMainWorldAndReturnValue(const ScriptSourceCode& sourceCode) { return evaluateScriptInMainWorld(sourceCode, NotSharableCrossOrigin, DoNotExecuteScriptWhenScriptsDisabled); } -ScriptValue ScriptController::evaluateScriptInMainWorld(const ScriptSourceCode& sourceCode, AccessControlStatus corsStatus, ExecuteScriptPolicy policy) +v8::Local<v8::Value> ScriptController::evaluateScriptInMainWorld(const ScriptSourceCode& sourceCode, AccessControlStatus corsStatus, ExecuteScriptPolicy policy) { if (policy == DoNotExecuteScriptWhenScriptsDisabled && !canExecuteScripts(AboutToExecuteScript)) - return ScriptValue(); + return v8::Local<v8::Value>(); String sourceURL = sourceCode.url(); const String* savedSourceURL = m_sourceURL; m_sourceURL = &sourceURL; - v8::HandleScope handleScope(m_isolate); - v8::Handle<v8::Context> v8Context = ScriptController::mainWorldContext(m_frame); - if (v8Context.IsEmpty()) - return ScriptValue(); + ScriptState* scriptState = ScriptState::forMainWorld(m_frame); + if (scriptState->contextIsEmpty()) + return v8::Local<v8::Value>(); + + v8::EscapableHandleScope handleScope(scriptState->isolate()); + ScriptState::Scope scope(scriptState); - RefPtr<Frame> protect(m_frame); + RefPtr<LocalFrame> protect(m_frame); if (m_frame->loader().stateMachine()->isDisplayingInitialEmptyDocument()) m_frame->loader().didAccessInitialDocument(); OwnPtr<ScriptSourceCode> maybeProcessedSourceCode = InspectorInstrumentation::preprocess(m_frame, sourceCode); const ScriptSourceCode& sourceCodeToCompile = maybeProcessedSourceCode ? *maybeProcessedSourceCode : sourceCode; - v8::Local<v8::Value> object = executeScriptAndReturnValue(v8Context, sourceCodeToCompile, corsStatus); + v8::Local<v8::Value> object = executeScriptAndReturnValue(scriptState->context(), sourceCodeToCompile, corsStatus); m_sourceURL = savedSourceURL; if (object.IsEmpty()) - return ScriptValue(); + return v8::Local<v8::Value>(); - return ScriptValue(object, m_isolate); + return handleScope.Escape(object); } -void ScriptController::executeScriptInIsolatedWorld(int worldID, const Vector<ScriptSourceCode>& sources, int extensionGroup, Vector<ScriptValue>* results) +void ScriptController::executeScriptInIsolatedWorld(int worldID, const Vector<ScriptSourceCode>& sources, int extensionGroup, Vector<v8::Local<v8::Value> >* results) { ASSERT(worldID > 0); - v8::HandleScope handleScope(m_isolate); - v8::Local<v8::Array> v8Results; - { - v8::EscapableHandleScope evaluateHandleScope(m_isolate); - RefPtr<DOMWrapperWorld> world = DOMWrapperWorld::ensureIsolatedWorld(worldID, extensionGroup); - V8WindowShell* isolatedWorldShell = windowShell(world.get()); - - if (!isolatedWorldShell->isContextInitialized()) - return; - - v8::Local<v8::Context> context = isolatedWorldShell->context(); - v8::Context::Scope contextScope(context); - v8::Local<v8::Array> resultArray = v8::Array::New(m_isolate, sources.size()); + RefPtr<DOMWrapperWorld> world = DOMWrapperWorld::ensureIsolatedWorld(worldID, extensionGroup); + V8WindowShell* isolatedWorldShell = windowShell(*world); + if (!isolatedWorldShell->isContextInitialized()) + return; - for (size_t i = 0; i < sources.size(); ++i) { - v8::Local<v8::Value> evaluationResult = executeScriptAndReturnValue(context, sources[i]); - if (evaluationResult.IsEmpty()) - evaluationResult = v8::Local<v8::Value>::New(m_isolate, v8::Undefined(m_isolate)); - resultArray->Set(i, evaluationResult); - } + ScriptState* scriptState = isolatedWorldShell->scriptState(); + v8::EscapableHandleScope handleScope(scriptState->isolate()); + ScriptState::Scope scope(scriptState); + v8::Local<v8::Array> resultArray = v8::Array::New(m_isolate, sources.size()); - v8Results = evaluateHandleScope.Escape(resultArray); + for (size_t i = 0; i < sources.size(); ++i) { + v8::Local<v8::Value> evaluationResult = executeScriptAndReturnValue(scriptState->context(), sources[i]); + if (evaluationResult.IsEmpty()) + evaluationResult = v8::Local<v8::Value>::New(m_isolate, v8::Undefined(m_isolate)); + resultArray->Set(i, evaluationResult); } - if (results && !v8Results.IsEmpty()) { - for (size_t i = 0; i < v8Results->Length(); ++i) - results->append(ScriptValue(v8Results->Get(i), m_isolate)); + if (results) { + for (size_t i = 0; i < resultArray->Length(); ++i) + results->append(handleScope.Escape(resultArray->Get(i))); } } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptController.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptController.h index 83793c7a96a..3da4d2c6662 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptController.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptController.h @@ -49,12 +49,12 @@ namespace WebCore { class DOMWrapperWorld; class ExecutionContext; class Event; -class Frame; class HTMLDocument; class HTMLPlugInElement; class KURL; -class ScriptSourceCode; +class LocalFrame; class ScriptState; +class ScriptSourceCode; class SecurityOrigin; class V8WindowShell; class Widget; @@ -73,17 +73,17 @@ public: DoNotExecuteScriptWhenScriptsDisabled }; - ScriptController(Frame*); + ScriptController(LocalFrame*); ~ScriptController(); bool initializeMainWorld(); - V8WindowShell* windowShell(DOMWrapperWorld*); - V8WindowShell* existingWindowShell(DOMWrapperWorld*); + V8WindowShell* windowShell(DOMWrapperWorld&); + V8WindowShell* existingWindowShell(DOMWrapperWorld&); // Evaluate JavaScript in the main world. void executeScriptInMainWorld(const String&, ExecuteScriptPolicy = DoNotExecuteScriptWhenScriptsDisabled); void executeScriptInMainWorld(const ScriptSourceCode&, AccessControlStatus = NotSharableCrossOrigin); - ScriptValue executeScriptInMainWorldAndReturnValue(const ScriptSourceCode&); + v8::Local<v8::Value> executeScriptInMainWorldAndReturnValue(const ScriptSourceCode&); v8::Local<v8::Value> executeScriptAndReturnValue(v8::Handle<v8::Context>, const ScriptSourceCode&, AccessControlStatus = NotSharableCrossOrigin); // Executes JavaScript in an isolated world. The script gets its own global scope, @@ -94,13 +94,13 @@ public: // Otherwise, a new world is created. // // FIXME: Get rid of extensionGroup here. - void executeScriptInIsolatedWorld(int worldID, const Vector<ScriptSourceCode>& sources, int extensionGroup, Vector<ScriptValue>* results); + void executeScriptInIsolatedWorld(int worldID, const Vector<ScriptSourceCode>& sources, int extensionGroup, Vector<v8::Local<v8::Value> >* results); // Returns true if argument is a JavaScript URL. bool executeScriptIfJavaScriptURL(const KURL&); - v8::Local<v8::Value> callFunction(v8::Handle<v8::Function>, v8::Handle<v8::Object>, int argc, v8::Handle<v8::Value> argv[]); - static v8::Local<v8::Value> callFunction(ExecutionContext*, v8::Handle<v8::Function>, v8::Handle<v8::Object> receiver, int argc, v8::Handle<v8::Value> info[], v8::Isolate*); + v8::Local<v8::Value> callFunction(v8::Handle<v8::Function>, v8::Handle<v8::Value>, int argc, v8::Handle<v8::Value> argv[]); + static v8::Local<v8::Value> callFunction(ExecutionContext*, v8::Handle<v8::Function>, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[], v8::Isolate*); // Returns true if the current world is isolated, and has its own Content // Security Policy. In this case, the policy of the main world should be @@ -108,42 +108,33 @@ public: bool shouldBypassMainWorldContentSecurityPolicy(); // Creates a property of the global object of a frame. - void bindToWindowObject(Frame*, const String& key, NPObject*); + void bindToWindowObject(LocalFrame*, const String& key, NPObject*); PassRefPtr<SharedPersistent<v8::Object> > createPluginWrapper(Widget*); void enableEval(); void disableEval(const String& errorMessage); - static bool canAccessFromCurrentOrigin(Frame*); + static bool canAccessFromCurrentOrigin(LocalFrame*); static void setCaptureCallStackForUncaughtExceptions(bool); void collectIsolatedContexts(Vector<std::pair<ScriptState*, SecurityOrigin*> >&); bool canExecuteScripts(ReasonForCallingCanExecuteScripts); - // Returns V8 Context. If none exists, creates a new context. - // It is potentially slow and consumes memory. - static v8::Local<v8::Context> mainWorldContext(Frame*); - v8::Local<v8::Context> mainWorldContext(); - v8::Local<v8::Context> currentWorldContext(); - TextPosition eventHandlerPosition() const; - const String* sourceURL() const { return m_sourceURL; } // 0 if we are not evaluating any script. - void clearWindowShell(); void updateDocument(); void namedItemAdded(HTMLDocument*, const AtomicString&); void namedItemRemoved(HTMLDocument*, const AtomicString&); - void updateSecurityOrigin(); + void updateSecurityOrigin(SecurityOrigin*); void clearScriptObjects(); void cleanupScriptObjectsForPlugin(Widget*); void clearForClose(); - void clearForOutOfMemory(); NPObject* createScriptObjectForPluginElement(HTMLPlugInElement*); NPObject* windowScriptNPObject(); @@ -163,10 +154,9 @@ private: typedef HashMap<int, OwnPtr<V8WindowShell> > IsolatedWorldMap; typedef HashMap<Widget*, NPObject*> PluginObjectMap; - ScriptValue evaluateScriptInMainWorld(const ScriptSourceCode&, AccessControlStatus, ExecuteScriptPolicy); - void clearForClose(bool destroyGlobal); + v8::Local<v8::Value> evaluateScriptInMainWorld(const ScriptSourceCode&, AccessControlStatus, ExecuteScriptPolicy); - Frame* m_frame; + LocalFrame* m_frame; const String* m_sourceURL; v8::Isolate* m_isolate; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptDebugServer.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptDebugServer.cpp index 4195a44baa2..7b100c6cffb 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptDebugServer.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptDebugServer.cpp @@ -31,16 +31,18 @@ #include "config.h" #include "bindings/v8/ScriptDebugServer.h" -#include "DebuggerScriptSource.h" -#include "V8JavaScriptCallFrame.h" +#include "bindings/core/v8/V8JavaScriptCallFrame.h" #include "bindings/v8/ScopedPersistent.h" +#include "bindings/v8/ScriptCallStackFactory.h" #include "bindings/v8/ScriptController.h" -#include "bindings/v8/ScriptObject.h" #include "bindings/v8/ScriptSourceCode.h" +#include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8ScriptRunner.h" +#include "core/DebuggerScriptSource.h" #include "core/inspector/JavaScriptCallFrame.h" #include "core/inspector/ScriptDebugListener.h" +#include "platform/JSONValues.h" #include "wtf/StdLibExtras.h" #include "wtf/Vector.h" #include "wtf/dtoa/utils.h" @@ -89,16 +91,16 @@ String ScriptDebugServer::setBreakpoint(const String& sourceID, const ScriptBrea v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); v8::Context::Scope contextScope(debuggerContext); - v8::Local<v8::Object> info = v8::Object::New(); + v8::Local<v8::Object> info = v8::Object::New(m_isolate); info->Set(v8AtomicString(m_isolate, "sourceID"), v8String(debuggerContext->GetIsolate(), sourceID)); - info->Set(v8AtomicString(m_isolate, "lineNumber"), v8::Integer::New(scriptBreakpoint.lineNumber, debuggerContext->GetIsolate())); - info->Set(v8AtomicString(m_isolate, "columnNumber"), v8::Integer::New(scriptBreakpoint.columnNumber, debuggerContext->GetIsolate())); + info->Set(v8AtomicString(m_isolate, "lineNumber"), v8::Integer::New(debuggerContext->GetIsolate(), scriptBreakpoint.lineNumber)); + info->Set(v8AtomicString(m_isolate, "columnNumber"), v8::Integer::New(debuggerContext->GetIsolate(), scriptBreakpoint.columnNumber)); info->Set(v8AtomicString(m_isolate, "interstatementLocation"), v8Boolean(interstatementLocation, debuggerContext->GetIsolate())); info->Set(v8AtomicString(m_isolate, "condition"), v8String(debuggerContext->GetIsolate(), scriptBreakpoint.condition)); v8::Handle<v8::Function> setBreakpointFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "setBreakpoint"))); v8::Handle<v8::Value> breakpointId = v8::Debug::Call(setBreakpointFunction, info); - if (!breakpointId->IsString()) + if (breakpointId.IsEmpty() || !breakpointId->IsString()) return ""; *actualLineNumber = info->Get(v8AtomicString(m_isolate, "lineNumber"))->Int32Value(); *actualColumnNumber = info->Get(v8AtomicString(m_isolate, "columnNumber"))->Int32Value(); @@ -111,7 +113,7 @@ void ScriptDebugServer::removeBreakpoint(const String& breakpointId) v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); v8::Context::Scope contextScope(debuggerContext); - v8::Local<v8::Object> info = v8::Object::New(); + v8::Local<v8::Object> info = v8::Object::New(m_isolate); info->Set(v8AtomicString(m_isolate, "breakpointId"), v8String(debuggerContext->GetIsolate(), breakpointId)); v8::Handle<v8::Function> removeBreakpointFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "removeBreakpoint"))); @@ -136,7 +138,7 @@ void ScriptDebugServer::setBreakpointsActivated(bool activated) v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); v8::Context::Scope contextScope(debuggerContext); - v8::Local<v8::Object> info = v8::Object::New(); + v8::Local<v8::Object> info = v8::Object::New(m_isolate); info->Set(v8AtomicString(m_isolate, "enabled"), v8::Boolean::New(m_isolate, activated)); v8::Handle<v8::Function> setBreakpointsActivated = v8::Local<v8::Function>::Cast(m_debuggerScript.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "setBreakpointsActivated"))); v8::Debug::Call(setBreakpointsActivated, info); @@ -161,14 +163,13 @@ void ScriptDebugServer::setPauseOnExceptionsState(PauseOnExceptionsState pauseOn v8::HandleScope scope(m_isolate); v8::Context::Scope contextScope(v8::Debug::GetDebugContext()); - v8::Handle<v8::Value> argv[] = { v8::Int32::New(pauseOnExceptionsState, m_isolate) }; + v8::Handle<v8::Value> argv[] = { v8::Int32::New(m_isolate, pauseOnExceptionsState) }; callDebuggerMethod("setPauseOnExceptionsState", 1, argv); } void ScriptDebugServer::setPauseOnNextStatement(bool pause) { - if (isPaused()) - return; + ASSERT(!isPaused()); if (pause) v8::Debug::DebugBreak(m_isolate); else @@ -179,8 +180,7 @@ bool ScriptDebugServer::canBreakProgram() { if (!m_breakpointsActivated) return false; - v8::HandleScope scope(m_isolate); - return !m_isolate->GetCurrentContext().IsEmpty(); + return m_isolate->InContext(); } void ScriptDebugServer::breakProgram() @@ -195,65 +195,56 @@ void ScriptDebugServer::breakProgram() m_breakProgramCallbackTemplate.set(m_isolate, templ); } - m_pausedContext = m_isolate->GetCurrentContext(); v8::Handle<v8::Function> breakProgramFunction = m_breakProgramCallbackTemplate.newLocal(m_isolate)->GetFunction(); v8::Debug::Call(breakProgramFunction); - m_pausedContext.Clear(); } void ScriptDebugServer::continueProgram() { if (isPaused()) quitMessageLoopOnPause(); - m_executionState.clear(); + m_pausedScriptState.clear(); + m_executionState.Clear(); } void ScriptDebugServer::stepIntoStatement() { ASSERT(isPaused()); + ASSERT(!m_executionState.IsEmpty()); v8::HandleScope handleScope(m_isolate); - v8::Handle<v8::Value> argv[] = { m_executionState.newLocal(m_isolate) }; + v8::Handle<v8::Value> argv[] = { m_executionState }; callDebuggerMethod(stepIntoV8MethodName, 1, argv); continueProgram(); } -void ScriptDebugServer::stepCommandWithFrame(const char* functionName, const ScriptValue& frame) +void ScriptDebugServer::stepOverStatement() { ASSERT(isPaused()); + ASSERT(!m_executionState.IsEmpty()); v8::HandleScope handleScope(m_isolate); - v8::Handle<v8::Value> callFrame; - if (frame.hasNoValue()) { - callFrame = v8::Undefined(m_isolate); - } else { - JavaScriptCallFrame* impl = V8JavaScriptCallFrame::toNative(v8::Handle<v8::Object>::Cast(frame.v8Value())); - callFrame = impl->innerCallFrame(); - } - - v8::Handle<v8::Value> argv[] = { - m_executionState.newLocal(m_isolate), - callFrame - }; - - callDebuggerMethod(functionName, 2, argv); + v8::Handle<v8::Value> argv[] = { m_executionState }; + callDebuggerMethod("stepOverStatement", 1, argv); continueProgram(); } -void ScriptDebugServer::stepOverStatement(const ScriptValue& frame) +void ScriptDebugServer::stepOutOfFunction() { - stepCommandWithFrame("stepOverStatement", frame); -} - -void ScriptDebugServer::stepOutOfFunction(const ScriptValue& frame) -{ - stepCommandWithFrame(stepOutV8MethodName, frame); + ASSERT(isPaused()); + ASSERT(!m_executionState.IsEmpty()); + v8::HandleScope handleScope(m_isolate); + v8::Handle<v8::Value> argv[] = { m_executionState }; + callDebuggerMethod(stepOutV8MethodName, 1, argv); + continueProgram(); } -bool ScriptDebugServer::setScriptSource(const String& sourceID, const String& newContent, bool preview, String* error, RefPtr<TypeBuilder::Debugger::SetScriptSourceError>& errorData, ScriptValue* newCallFrames, ScriptObject* result) +bool ScriptDebugServer::setScriptSource(const String& sourceID, const String& newContent, bool preview, String* error, RefPtr<TypeBuilder::Debugger::SetScriptSourceError>& errorData, ScriptValue* newCallFrames, RefPtr<JSONObject>* result) { class EnableLiveEditScope { public: - EnableLiveEditScope() { v8::Debug::SetLiveEditEnabled(true); } - ~EnableLiveEditScope() { v8::Debug::SetLiveEditEnabled(false); } + explicit EnableLiveEditScope(v8::Isolate* isolate) : m_isolate(isolate) { v8::Debug::SetLiveEditEnabled(m_isolate, true); } + ~EnableLiveEditScope() { v8::Debug::SetLiveEditEnabled(m_isolate, false); } + private: + v8::Isolate* m_isolate; }; ensureDebuggerScriptCompiled(); @@ -264,11 +255,11 @@ bool ScriptDebugServer::setScriptSource(const String& sourceID, const String& ne if (!isPaused()) contextScope = adoptPtr(new v8::Context::Scope(debuggerContext)); - v8::Handle<v8::Value> argv[] = { v8String(debuggerContext->GetIsolate(), sourceID), v8String(debuggerContext->GetIsolate(), newContent), v8Boolean(preview, debuggerContext->GetIsolate()) }; + v8::Handle<v8::Value> argv[] = { v8String(m_isolate, sourceID), v8String(m_isolate, newContent), v8Boolean(preview, m_isolate) }; v8::Local<v8::Value> v8result; { - EnableLiveEditScope enableLiveEditScope; + EnableLiveEditScope enableLiveEditScope(m_isolate); v8::TryCatch tryCatch; tryCatch.SetVerbose(false); v8result = callDebuggerMethod("liveEditScriptSource", 3, argv); @@ -288,8 +279,9 @@ bool ScriptDebugServer::setScriptSource(const String& sourceID, const String& ne case 0: { v8::Local<v8::Value> normalResult = resultTuple->Get(1); - if (normalResult->IsObject()) - *result = ScriptObject(ScriptState::current(), normalResult->ToObject()); + RefPtr<JSONValue> jsonResult = v8ToJSONValue(m_isolate, normalResult, JSONValue::maxDepth); + if (jsonResult) + *result = jsonResult->asObject(); // Call stack may have changed after if the edited function was on the stack. if (!preview && isPaused()) *newCallFrames = currentCallFrames(); @@ -314,40 +306,71 @@ bool ScriptDebugServer::setScriptSource(const String& sourceID, const String& ne return false; } -PassRefPtr<JavaScriptCallFrame> ScriptDebugServer::wrapCallFrames(v8::Handle<v8::Object> executionState, int maximumLimit) +int ScriptDebugServer::frameCount() { + ASSERT(isPaused()); + ASSERT(!m_executionState.IsEmpty()); + v8::Handle<v8::Value> argv[] = { m_executionState }; + v8::Handle<v8::Value> result = callDebuggerMethod("frameCount", WTF_ARRAY_LENGTH(argv), argv); + if (result->IsInt32()) + return result->Int32Value(); + return 0; +} + +PassRefPtrWillBeRawPtr<JavaScriptCallFrame> ScriptDebugServer::wrapCallFrames(int maximumLimit, ScopeInfoDetails scopeDetails) +{ + const int scopeBits = 2; + COMPILE_ASSERT(NoScopes < (1 << scopeBits), not_enough_bits_to_encode_ScopeInfoDetails); + + ASSERT(maximumLimit >= 0); + int data = (maximumLimit << scopeBits) | scopeDetails; v8::Handle<v8::Value> currentCallFrameV8; - if (executionState.IsEmpty()) { + if (m_executionState.IsEmpty()) { v8::Handle<v8::Function> currentCallFrameFunction = v8::Local<v8::Function>::Cast(m_debuggerScript.newLocal(m_isolate)->Get(v8AtomicString(m_isolate, "currentCallFrame"))); - currentCallFrameV8 = v8::Debug::Call(currentCallFrameFunction, v8::Integer::New(maximumLimit, m_isolate)); + currentCallFrameV8 = v8::Debug::Call(currentCallFrameFunction, v8::Integer::New(m_isolate, data)); } else { - v8::Handle<v8::Value> argv[] = { executionState, v8::Integer::New(maximumLimit, m_isolate) }; - currentCallFrameV8 = callDebuggerMethod("currentCallFrame", 2, argv); + v8::Handle<v8::Value> argv[] = { m_executionState, v8::Integer::New(m_isolate, data) }; + currentCallFrameV8 = callDebuggerMethod("currentCallFrame", WTF_ARRAY_LENGTH(argv), argv); } ASSERT(!currentCallFrameV8.IsEmpty()); if (!currentCallFrameV8->IsObject()) - return PassRefPtr<JavaScriptCallFrame>(); + return nullptr; return JavaScriptCallFrame::create(v8::Debug::GetDebugContext(), v8::Handle<v8::Object>::Cast(currentCallFrameV8)); } -ScriptValue ScriptDebugServer::currentCallFrames() +ScriptValue ScriptDebugServer::currentCallFramesInner(ScopeInfoDetails scopeDetails) { - v8::HandleScope scope(m_isolate); - v8::Handle<v8::Context> pausedContext = m_pausedContext.IsEmpty() ? m_isolate->GetCurrentContext() : m_pausedContext; - if (pausedContext.IsEmpty()) + if (!m_isolate->InContext()) return ScriptValue(); + v8::HandleScope handleScope(m_isolate); - RefPtr<JavaScriptCallFrame> currentCallFrame = wrapCallFrames(m_executionState.newLocal(m_isolate), -1); + RefPtrWillBeRawPtr<JavaScriptCallFrame> currentCallFrame = wrapCallFrames(0, scopeDetails); if (!currentCallFrame) return ScriptValue(); - v8::Context::Scope contextScope(pausedContext); - return ScriptValue(toV8(currentCallFrame.release(), v8::Handle<v8::Object>(), pausedContext->GetIsolate()), pausedContext->GetIsolate()); + ScriptState* scriptState = m_pausedScriptState ? m_pausedScriptState.get() : ScriptState::current(m_isolate); + ScriptState::Scope scope(scriptState); + return ScriptValue(scriptState, toV8(currentCallFrame.release(), scriptState->context()->Global(), m_isolate)); +} + +ScriptValue ScriptDebugServer::currentCallFrames() +{ + return currentCallFramesInner(AllScopes); +} + +ScriptValue ScriptDebugServer::currentCallFramesForAsyncStack() +{ + return currentCallFramesInner(FastAsyncScopes); +} + +PassRefPtrWillBeRawPtr<JavaScriptCallFrame> ScriptDebugServer::topCallFrameNoScopes() +{ + return wrapCallFrames(1, NoScopes); } void ScriptDebugServer::interruptAndRun(PassOwnPtr<Task> task, v8::Isolate* isolate) { - v8::Debug::DebugBreakForCommand(new ClientDataImpl(task), isolate); + v8::Debug::DebugBreakForCommand(isolate, new ClientDataImpl(task)); } void ScriptDebugServer::runPendingTasks() @@ -365,18 +388,19 @@ void ScriptDebugServer::breakProgramCallback(const v8::FunctionCallbackInfo<v8:: { ASSERT(2 == info.Length()); ScriptDebugServer* thisPtr = toScriptDebugServer(info.Data()); + ScriptState* pausedScriptState = ScriptState::current(thisPtr->m_isolate); v8::Handle<v8::Value> exception; v8::Handle<v8::Array> hitBreakpoints; - thisPtr->handleProgramBreak(v8::Handle<v8::Object>::Cast(info[0]), exception, hitBreakpoints); + thisPtr->handleProgramBreak(pausedScriptState, v8::Handle<v8::Object>::Cast(info[0]), exception, hitBreakpoints); } -void ScriptDebugServer::handleProgramBreak(v8::Handle<v8::Object> executionState, v8::Handle<v8::Value> exception, v8::Handle<v8::Array> hitBreakpointNumbers) +void ScriptDebugServer::handleProgramBreak(ScriptState* pausedScriptState, v8::Handle<v8::Object> executionState, v8::Handle<v8::Value> exception, v8::Handle<v8::Array> hitBreakpointNumbers) { // Don't allow nested breaks. if (isPaused()) return; - ScriptDebugListener* listener = getDebugListenerForContext(m_pausedContext); + ScriptDebugListener* listener = getDebugListenerForContext(pausedScriptState->context()); if (!listener) return; @@ -390,20 +414,24 @@ void ScriptDebugServer::handleProgramBreak(v8::Handle<v8::Object> executionState } } - m_executionState.set(m_isolate, executionState); - ScriptState* currentCallFrameState = ScriptState::forContext(m_pausedContext); - listener->didPause(currentCallFrameState, currentCallFrames(), ScriptValue(exception, currentCallFrameState->isolate()), breakpointIds); - - m_runningNestedMessageLoop = true; - runMessageLoopOnPause(m_pausedContext); - m_runningNestedMessageLoop = false; -} - -void ScriptDebugServer::handleProgramBreak(const v8::Debug::EventDetails& eventDetails, v8::Handle<v8::Value> exception, v8::Handle<v8::Array> hitBreakpointNumbers) -{ - m_pausedContext = eventDetails.GetEventContext(); - handleProgramBreak(eventDetails.GetExecutionState(), exception, hitBreakpointNumbers); - m_pausedContext.Clear(); + m_pausedScriptState = pausedScriptState; + m_executionState = executionState; + ScriptDebugListener::SkipPauseRequest result = listener->didPause(pausedScriptState, currentCallFrames(), ScriptValue(pausedScriptState, exception), breakpointIds); + if (result == ScriptDebugListener::NoSkip) { + m_runningNestedMessageLoop = true; + runMessageLoopOnPause(pausedScriptState->context()); + m_runningNestedMessageLoop = false; + } + m_pausedScriptState.clear(); + m_executionState.Clear(); + + if (result == ScriptDebugListener::StepInto) { + v8::Handle<v8::Value> argv[] = { executionState }; + callDebuggerMethod(stepIntoV8MethodName, 1, argv); + } else if (result == ScriptDebugListener::StepOut) { + v8::Handle<v8::Value> argv[] = { executionState }; + callDebuggerMethod(stepOutV8MethodName, 1, argv); + } } void ScriptDebugServer::v8DebugEventCallback(const v8::Debug::EventDetails& eventDetails) @@ -412,22 +440,6 @@ void ScriptDebugServer::v8DebugEventCallback(const v8::Debug::EventDetails& even thisPtr->handleV8DebugEvent(eventDetails); } -bool ScriptDebugServer::executeSkipPauseRequest(ScriptDebugListener::SkipPauseRequest request, v8::Handle<v8::Object> executionState) -{ - switch (request) { - case ScriptDebugListener::NoSkip: - return false; - case ScriptDebugListener::Continue: - return true; - case ScriptDebugListener::StepInto: - case ScriptDebugListener::StepOut: - break; - } - v8::Handle<v8::Value> argv[] = { executionState }; - callDebuggerMethod(stepIntoV8MethodName, 1, argv); - return true; -} - void ScriptDebugServer::handleV8DebugEvent(const v8::Debug::EventDetails& eventDetails) { v8::DebugEvent event = eventDetails.GetEvent(); @@ -463,28 +475,17 @@ void ScriptDebugServer::handleV8DebugEvent(const v8::Debug::EventDetails& eventD // Stack trace is empty in case of syntax error. Silently continue execution in such cases. if (!stackTrace->GetFrameCount()) return; - RefPtr<JavaScriptCallFrame> topFrame = wrapCallFrames(eventDetails.GetExecutionState(), 1); - if (executeSkipPauseRequest(listener->shouldSkipExceptionPause(topFrame), eventDetails.GetExecutionState())) - return; v8::Handle<v8::Object> eventData = eventDetails.GetEventData(); v8::Handle<v8::Value> exceptionGetterValue = eventData->Get(v8AtomicString(m_isolate, "exception")); ASSERT(!exceptionGetterValue.IsEmpty() && exceptionGetterValue->IsFunction()); v8::Handle<v8::Value> exception = V8ScriptRunner::callInternalFunction(v8::Handle<v8::Function>::Cast(exceptionGetterValue), eventData, 0, 0, m_isolate); - handleProgramBreak(eventDetails, exception, v8::Handle<v8::Array>()); + handleProgramBreak(ScriptState::from(eventContext), eventDetails.GetExecutionState(), exception, v8::Handle<v8::Array>()); } else if (event == v8::Break) { v8::Handle<v8::Function> getBreakpointNumbersFunction = v8::Local<v8::Function>::Cast(debuggerScript->Get(v8AtomicString(m_isolate, "getBreakpointNumbers"))); v8::Handle<v8::Value> argv[] = { eventDetails.GetEventData() }; v8::Handle<v8::Value> hitBreakpoints = V8ScriptRunner::callInternalFunction(getBreakpointNumbersFunction, debuggerScript, WTF_ARRAY_LENGTH(argv), argv, m_isolate); ASSERT(hitBreakpoints->IsArray()); - RefPtr<JavaScriptCallFrame> topFrame = wrapCallFrames(eventDetails.GetExecutionState(), 1); - ScriptDebugListener::SkipPauseRequest skipRequest; - if (v8::Handle<v8::Array>::Cast(hitBreakpoints)->Length()) - skipRequest = listener->shouldSkipBreakpointPause(topFrame); - else - skipRequest = listener->shouldSkipStepPause(topFrame); - if (executeSkipPauseRequest(skipRequest, eventDetails.GetExecutionState())) - return; - handleProgramBreak(eventDetails, v8::Handle<v8::Value>(), hitBreakpoints.As<v8::Array>()); + handleProgramBreak(ScriptState::from(eventContext), eventDetails.GetExecutionState(), v8::Handle<v8::Value>(), hitBreakpoints.As<v8::Array>()); } } } @@ -522,6 +523,12 @@ void ScriptDebugServer::ensureDebuggerScriptCompiled() m_debuggerScript.set(m_isolate, v8::Handle<v8::Object>::Cast(value)); } +void ScriptDebugServer::discardDebuggerScript() +{ + ASSERT(!m_debuggerScript.isEmpty()); + m_debuggerScript.clear(); +} + v8::Local<v8::Value> ScriptDebugServer::functionScopes(v8::Handle<v8::Function> function) { ensureDebuggerScriptCompiled(); @@ -547,7 +554,7 @@ v8::Handle<v8::Value> ScriptDebugServer::setFunctionVariableValue(v8::Handle<v8: v8::Handle<v8::Value> argv[] = { functionValue, - v8::Handle<v8::Value>(v8::Integer::New(scopeNumber, debuggerContext->GetIsolate())), + v8::Handle<v8::Value>(v8::Integer::New(debuggerContext->GetIsolate(), scopeNumber)), v8String(debuggerContext->GetIsolate(), variableName), newValue }; @@ -557,30 +564,32 @@ v8::Handle<v8::Value> ScriptDebugServer::setFunctionVariableValue(v8::Handle<v8: bool ScriptDebugServer::isPaused() { - return !m_executionState.isEmpty(); + return m_pausedScriptState; } -void ScriptDebugServer::compileScript(ScriptState* state, const String& expression, const String& sourceURL, String* scriptId, String* exceptionMessage) +void ScriptDebugServer::compileScript(ScriptState* scriptState, const String& expression, const String& sourceURL, String* scriptId, String* exceptionDetailsText, int* lineNumber, int* columnNumber, RefPtrWillBeRawPtr<ScriptCallStack>* stackTrace) { - v8::HandleScope handleScope(m_isolate); - v8::Handle<v8::Context> context = state->context(); - if (context.IsEmpty()) + if (scriptState->contextIsEmpty()) return; - v8::Context::Scope contextScope(context); + ScriptState::Scope scope(scriptState); v8::Handle<v8::String> source = v8String(m_isolate, expression); v8::TryCatch tryCatch; v8::Local<v8::Script> script = V8ScriptRunner::compileScript(source, sourceURL, TextPosition(), 0, m_isolate); if (tryCatch.HasCaught()) { v8::Local<v8::Message> message = tryCatch.Message(); - if (!message.IsEmpty()) - *exceptionMessage = toCoreStringWithUndefinedOrNullCheck(message->Get()); + if (!message.IsEmpty()) { + *exceptionDetailsText = toCoreStringWithUndefinedOrNullCheck(message->Get()); + *lineNumber = message->GetLineNumber(); + *columnNumber = message->GetStartColumn(); + *stackTrace = createScriptCallStack(message->GetStackTrace(), message->GetStackTrace()->GetFrameCount(), m_isolate); + } return; } if (script.IsEmpty()) return; - *scriptId = String::number(script->GetId()); + *scriptId = String::number(script->GetUnboundScript()->GetId()); m_compiledScripts.set(*scriptId, adoptPtr(new ScopedPersistent<v8::Script>(m_isolate, script))); } @@ -589,7 +598,7 @@ void ScriptDebugServer::clearCompiledScripts() m_compiledScripts.clear(); } -void ScriptDebugServer::runScript(ScriptState* state, const String& scriptId, ScriptValue* result, bool* wasThrown, String* exceptionMessage) +void ScriptDebugServer::runScript(ScriptState* scriptState, const String& scriptId, ScriptValue* result, bool* wasThrown, String* exceptionDetailsText, int* lineNumber, int* columnNumber, RefPtrWillBeRawPtr<ScriptCallStack>* stackTrace) { if (!m_compiledScripts.contains(scriptId)) return; @@ -600,30 +609,33 @@ void ScriptDebugServer::runScript(ScriptState* state, const String& scriptId, Sc if (script.IsEmpty()) return; - v8::Handle<v8::Context> context = state->context(); - if (context.IsEmpty()) + if (scriptState->contextIsEmpty()) return; - v8::Context::Scope contextScope(context); + ScriptState::Scope scope(scriptState); v8::TryCatch tryCatch; - v8::Local<v8::Value> value = V8ScriptRunner::runCompiledScript(script, state->executionContext(), m_isolate); + v8::Local<v8::Value> value = V8ScriptRunner::runCompiledScript(script, scriptState->executionContext(), m_isolate); *wasThrown = false; if (tryCatch.HasCaught()) { *wasThrown = true; - *result = ScriptValue(tryCatch.Exception(), m_isolate); + *result = ScriptValue(scriptState, tryCatch.Exception()); v8::Local<v8::Message> message = tryCatch.Message(); - if (!message.IsEmpty()) - *exceptionMessage = toCoreStringWithUndefinedOrNullCheck(message->Get()); + if (!message.IsEmpty()) { + *exceptionDetailsText = toCoreStringWithUndefinedOrNullCheck(message->Get()); + *lineNumber = message->GetLineNumber(); + *columnNumber = message->GetStartColumn(); + *stackTrace = createScriptCallStack(message->GetStackTrace(), message->GetStackTrace()->GetFrameCount(), m_isolate); + } } else { - *result = ScriptValue(value, m_isolate); + *result = ScriptValue(scriptState, value); } } -PassOwnPtr<ScriptSourceCode> ScriptDebugServer::preprocess(Frame*, const ScriptSourceCode&) +PassOwnPtr<ScriptSourceCode> ScriptDebugServer::preprocess(LocalFrame*, const ScriptSourceCode&) { return PassOwnPtr<ScriptSourceCode>(); } -String ScriptDebugServer::preprocessEventListener(Frame*, const String& source, const String& url, const String& functionName) +String ScriptDebugServer::preprocessEventListener(LocalFrame*, const String& source, const String& url, const String& functionName) { return source; } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptDebugServer.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptDebugServer.h index 3d0e07a954f..ea8d35f3dcd 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptDebugServer.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptDebugServer.h @@ -31,25 +31,26 @@ #ifndef ScriptDebugServer_h #define ScriptDebugServer_h -#include "InspectorBackendDispatcher.h" #include "bindings/v8/ScopedPersistent.h" +#include "core/InspectorBackendDispatcher.h" #include "core/inspector/ScriptBreakpoint.h" +#include "core/inspector/ScriptCallStack.h" #include "core/inspector/ScriptDebugListener.h" -#include <v8-debug.h> #include "wtf/HashMap.h" #include "wtf/Noncopyable.h" #include "wtf/PassOwnPtr.h" #include "wtf/Vector.h" #include "wtf/text/StringHash.h" #include "wtf/text/WTFString.h" +#include <v8-debug.h> +#include <v8.h> namespace WebCore { +class ScriptState; class ScriptController; class ScriptDebugListener; -class ScriptObject; class ScriptSourceCode; -class ScriptState; class ScriptValue; class JavaScriptCallFrame; @@ -74,11 +75,14 @@ public: void breakProgram(); void continueProgram(); void stepIntoStatement(); - void stepOverStatement(const ScriptValue& frame); - void stepOutOfFunction(const ScriptValue& frame); + void stepOverStatement(); + void stepOutOfFunction(); - bool setScriptSource(const String& sourceID, const String& newContent, bool preview, String* error, RefPtr<TypeBuilder::Debugger::SetScriptSourceError>&, ScriptValue* newCallFrames, ScriptObject* result); + bool setScriptSource(const String& sourceID, const String& newContent, bool preview, String* error, RefPtr<TypeBuilder::Debugger::SetScriptSourceError>&, ScriptValue* newCallFrames, RefPtr<JSONObject>* result); ScriptValue currentCallFrames(); + ScriptValue currentCallFramesForAsyncStack(); + PassRefPtrWillBeRawPtr<JavaScriptCallFrame> topCallFrameNoScopes(); + int frameCount(); class Task { public: @@ -96,13 +100,16 @@ public: v8::Handle<v8::Value> setFunctionVariableValue(v8::Handle<v8::Value> functionValue, int scopeNumber, const String& variableName, v8::Handle<v8::Value> newValue); v8::Local<v8::Value> callDebuggerMethod(const char* functionName, int argc, v8::Handle<v8::Value> argv[]); - virtual void compileScript(ScriptState*, const String& expression, const String& sourceURL, String* scriptId, String* exceptionMessage); + virtual void compileScript(ScriptState*, const String& expression, const String& sourceURL, String* scriptId, String* exceptionDetailsText, int* lineNumber, int* columnNumber, RefPtrWillBeRawPtr<ScriptCallStack>* stackTrace); virtual void clearCompiledScripts(); - virtual void runScript(ScriptState*, const String& scriptId, ScriptValue* result, bool* wasThrown, String* exceptionMessage); + virtual void runScript(ScriptState*, const String& scriptId, ScriptValue* result, bool* wasThrown, String* exceptionDetailsText, int* lineNumber, int* columnNumber, RefPtrWillBeRawPtr<ScriptCallStack>* stackTrace); virtual void setPreprocessorSource(const String&) { } virtual void preprocessBeforeCompile(const v8::Debug::EventDetails&) { } - virtual PassOwnPtr<ScriptSourceCode> preprocess(Frame*, const ScriptSourceCode&); - virtual String preprocessEventListener(Frame*, const String& source, const String& url, const String& functionName); + virtual PassOwnPtr<ScriptSourceCode> preprocess(LocalFrame*, const ScriptSourceCode&); + virtual String preprocessEventListener(LocalFrame*, const String& source, const String& url, const String& functionName); + + virtual void muteWarningsAndDeprecations() { } + virtual void unmuteWarningsAndDeprecations() { } protected: explicit ScriptDebugServer(v8::Isolate*); @@ -113,8 +120,7 @@ protected: virtual void quitMessageLoopOnPause() = 0; static void breakProgramCallback(const v8::FunctionCallbackInfo<v8::Value>&); - void handleProgramBreak(v8::Handle<v8::Object> executionState, v8::Handle<v8::Value> exception, v8::Handle<v8::Array> hitBreakpoints); - void handleProgramBreak(const v8::Debug::EventDetails&, v8::Handle<v8::Value> exception, v8::Handle<v8::Array> hitBreakpointNumbers); + void handleProgramBreak(ScriptState* pausedScriptState, v8::Handle<v8::Object> executionState, v8::Handle<v8::Value> exception, v8::Handle<v8::Array> hitBreakpoints); static void v8DebugEventCallback(const v8::Debug::EventDetails& eventDetails); void handleV8DebugEvent(const v8::Debug::EventDetails& eventDetails); @@ -122,20 +128,27 @@ protected: void dispatchDidParseSource(ScriptDebugListener* listener, v8::Handle<v8::Object> sourceObject); void ensureDebuggerScriptCompiled(); + void discardDebuggerScript(); PauseOnExceptionsState m_pauseOnExceptionsState; ScopedPersistent<v8::Object> m_debuggerScript; - ScopedPersistent<v8::Object> m_executionState; - v8::Handle<v8::Context> m_pausedContext; + v8::Local<v8::Object> m_executionState; + RefPtr<ScriptState> m_pausedScriptState; bool m_breakpointsActivated; ScopedPersistent<v8::FunctionTemplate> m_breakProgramCallbackTemplate; HashMap<String, OwnPtr<ScopedPersistent<v8::Script> > > m_compiledScripts; v8::Isolate* m_isolate; private: - void stepCommandWithFrame(const char* functionName, const ScriptValue& frame); - PassRefPtr<JavaScriptCallFrame> wrapCallFrames(v8::Handle<v8::Object> executionState, int maximumLimit); - bool executeSkipPauseRequest(ScriptDebugListener::SkipPauseRequest, v8::Handle<v8::Object> executionState); + enum ScopeInfoDetails { + AllScopes, + FastAsyncScopes, + NoScopes // Should be the last option. + }; + + ScriptValue currentCallFramesInner(ScopeInfoDetails); + + PassRefPtrWillBeRawPtr<JavaScriptCallFrame> wrapCallFrames(int maximumLimit, ScopeInfoDetails); bool m_runningNestedMessageLoop; }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptEventListener.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptEventListener.cpp index 8329708acc5..f720c88a021 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptEventListener.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptEventListener.cpp @@ -32,7 +32,6 @@ #include "bindings/v8/ScriptEventListener.h" #include "bindings/v8/ScriptController.h" -#include "bindings/v8/ScriptScope.h" #include "bindings/v8/ScriptState.h" #include "bindings/v8/V8AbstractEventListener.h" #include "bindings/v8/V8Binding.h" @@ -40,58 +39,70 @@ #include "core/dom/Document.h" #include "core/dom/DocumentParser.h" #include "core/events/EventListener.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" +#include <v8.h> namespace WebCore { -static const AtomicString& eventParameterName(bool isSVGEvent) -{ - DEFINE_STATIC_LOCAL(const AtomicString, eventString, ("event")); - DEFINE_STATIC_LOCAL(const AtomicString, evtString, ("evt")); - return isSVGEvent ? evtString : eventString; -} - -PassRefPtr<V8LazyEventListener> createAttributeEventListener(Node* node, const QualifiedName& name, const AtomicString& value) +PassRefPtr<V8LazyEventListener> createAttributeEventListener(Node* node, const QualifiedName& name, const AtomicString& value, const AtomicString& eventParameterName) { ASSERT(node); if (value.isNull()) - return 0; + return nullptr; // FIXME: Very strange: we initialize zero-based number with '1'. TextPosition position(OrdinalNumber::fromZeroBasedInt(1), OrdinalNumber::first()); String sourceURL; v8::Isolate* isolate; - if (Frame* frame = node->document().frame()) { + if (LocalFrame* frame = node->document().frame()) { isolate = toIsolate(frame); ScriptController& scriptController = frame->script(); if (!scriptController.canExecuteScripts(AboutToExecuteScript)) - return 0; + return nullptr; position = scriptController.eventHandlerPosition(); sourceURL = node->document().url().string(); } else { isolate = v8::Isolate::GetCurrent(); } - return V8LazyEventListener::create(name.localName(), eventParameterName(node->isSVGElement()), value, sourceURL, position, node, isolate); + return V8LazyEventListener::create(name.localName(), eventParameterName, value, sourceURL, position, node, isolate); } -PassRefPtr<V8LazyEventListener> createAttributeEventListener(Frame* frame, const QualifiedName& name, const AtomicString& value) +PassRefPtr<V8LazyEventListener> createAttributeEventListener(LocalFrame* frame, const QualifiedName& name, const AtomicString& value, const AtomicString& eventParameterName) { if (!frame) - return 0; + return nullptr; if (value.isNull()) - return 0; + return nullptr; ScriptController& scriptController = frame->script(); if (!scriptController.canExecuteScripts(AboutToExecuteScript)) - return 0; + return nullptr; TextPosition position = scriptController.eventHandlerPosition(); String sourceURL = frame->document()->url().string(); - return V8LazyEventListener::create(name.localName(), eventParameterName(frame->document()->isSVGDocument()), value, sourceURL, position, 0, toIsolate(frame)); + return V8LazyEventListener::create(name.localName(), eventParameterName, value, sourceURL, position, 0, toIsolate(frame)); +} + +static v8::Handle<v8::Function> eventListenerEffectiveFunction(v8::Isolate* isolate, v8::Handle<v8::Object> listenerObject) +{ + v8::Handle<v8::Function> function; + if (listenerObject->IsFunction()) { + function = v8::Handle<v8::Function>::Cast(listenerObject); + } else if (listenerObject->IsObject()) { + // Try the "handleEvent" method (EventListener interface). + v8::Handle<v8::Value> property = listenerObject->Get(v8AtomicString(isolate, "handleEvent")); + if (property.IsEmpty() || !property->IsFunction()) { + // Fall back to the "constructor" property. + property = listenerObject->Get(v8AtomicString(isolate, "constructor")); + } + if (!property.IsEmpty() && property->IsFunction()) + function = v8::Handle<v8::Function>::Cast(property); + } + return function; } String eventListenerHandlerBody(Document* document, EventListener* listener) @@ -103,11 +114,14 @@ String eventListenerHandlerBody(Document* document, EventListener* listener) V8AbstractEventListener* v8Listener = static_cast<V8AbstractEventListener*>(listener); v8::Handle<v8::Context> context = toV8Context(document, v8Listener->world()); v8::Context::Scope contextScope(context); - v8::Handle<v8::Value> function = v8Listener->getListenerObject(document); + v8::Handle<v8::Object> object = v8Listener->getListenerObject(document); + if (object.IsEmpty()) + return ""; + v8::Handle<v8::Function> function = eventListenerEffectiveFunction(scope.GetIsolate(), object); if (function.IsEmpty()) return ""; - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<WithNullCheck>, functionString, function, ""); + TOSTRING_DEFAULT(V8StringResource<WithNullCheck>, functionString, function, ""); return functionString; } @@ -124,17 +138,17 @@ ScriptValue eventListenerHandler(Document* document, EventListener* listener) v8::Handle<v8::Object> function = v8Listener->getListenerObject(document); if (function.IsEmpty()) return ScriptValue(); - return ScriptValue(function, isolate); + return ScriptValue(ScriptState::from(context), function); } -ScriptState* eventListenerHandlerScriptState(Frame* frame, EventListener* listener) +ScriptState* eventListenerHandlerScriptState(LocalFrame* frame, EventListener* listener) { if (listener->type() != EventListener::JSEventListenerType) return 0; V8AbstractEventListener* v8Listener = static_cast<V8AbstractEventListener*>(listener); v8::HandleScope scope(toIsolate(frame)); v8::Handle<v8::Context> v8Context = frame->script().windowShell(v8Listener->world())->context(); - return ScriptState::forContext(v8Context); + return ScriptState::from(v8Context); } bool eventListenerHandlerLocation(Document* document, EventListener* listener, String& sourceName, String& scriptId, int& lineNumber) @@ -146,19 +160,21 @@ bool eventListenerHandlerLocation(Document* document, EventListener* listener, S V8AbstractEventListener* v8Listener = static_cast<V8AbstractEventListener*>(listener); v8::Handle<v8::Context> context = toV8Context(document, v8Listener->world()); v8::Context::Scope contextScope(context); - v8::Handle<v8::Object> object = v8Listener->getListenerObject(document); - if (object.IsEmpty() || !object->IsFunction()) + v8::Local<v8::Object> object = v8Listener->getListenerObject(document); + if (object.IsEmpty()) return false; - - v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(object); - int scriptIdValue = function->ScriptId(); + v8::Handle<v8::Function> function = eventListenerEffectiveFunction(scope.GetIsolate(), object); + if (function.IsEmpty()) + return false; + v8::Handle<v8::Function> originalFunction = getBoundFunction(function); + int scriptIdValue = originalFunction->ScriptId(); scriptId = String::number(scriptIdValue); - v8::ScriptOrigin origin = function->GetScriptOrigin(); + v8::ScriptOrigin origin = originalFunction->GetScriptOrigin(); if (!origin.ResourceName().IsEmpty() && origin.ResourceName()->IsString()) sourceName = toCoreString(origin.ResourceName().As<v8::String>()); else sourceName = ""; - lineNumber = function->GetScriptLineNumber(); + lineNumber = originalFunction->GetScriptLineNumber(); return true; } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptEventListener.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptEventListener.h index bfb75ebaa03..097675defbd 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptEventListener.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptEventListener.h @@ -33,22 +33,21 @@ #include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8LazyEventListener.h" - #include "wtf/PassRefPtr.h" namespace WebCore { class Document; class EventListener; - class Frame; + class LocalFrame; class Node; class QualifiedName; - PassRefPtr<V8LazyEventListener> createAttributeEventListener(Node*, const QualifiedName&, const AtomicString& value); - PassRefPtr<V8LazyEventListener> createAttributeEventListener(Frame*, const QualifiedName&, const AtomicString& value); + PassRefPtr<V8LazyEventListener> createAttributeEventListener(Node*, const QualifiedName&, const AtomicString& value, const AtomicString& eventParameterName); + PassRefPtr<V8LazyEventListener> createAttributeEventListener(LocalFrame*, const QualifiedName&, const AtomicString& value, const AtomicString& eventParameterName); String eventListenerHandlerBody(Document*, EventListener*); ScriptValue eventListenerHandler(Document*, EventListener*); - ScriptState* eventListenerHandlerScriptState(Frame*, EventListener*); + ScriptState* eventListenerHandlerScriptState(LocalFrame*, EventListener*); bool eventListenerHandlerLocation(Document*, EventListener*, String& sourceName, String& scriptId, int& lineNumber); } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunction.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunction.cpp new file mode 100644 index 00000000000..18315a4b6e3 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunction.cpp @@ -0,0 +1,32 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "bindings/v8/ScriptFunction.h" + +#include "bindings/v8/V8Binding.h" + +namespace WebCore { + +void ScriptFunction::callCallback(const v8::FunctionCallbackInfo<v8::Value>& args) +{ + v8::Isolate* isolate = args.GetIsolate(); + ASSERT(!args.Data().IsEmpty()); + ScriptFunction* function = ScriptFunction::Cast(args.Data()); + v8::Local<v8::Value> value = args.Length() > 0 ? args[0] : v8::Local<v8::Value>(v8::Undefined(isolate)); + + ScriptValue result = function->call(ScriptValue(ScriptState::current(isolate), value)); + + v8SetReturnValue(args, result.v8Value()); +} + +v8::Handle<v8::Function> ScriptFunction::adoptByGarbageCollector(PassOwnPtr<ScriptFunction> function) +{ + if (!function) + return v8::Handle<v8::Function>(); + v8::Isolate* isolate = function->isolate(); + return createClosure(&ScriptFunction::callCallback, function.leakPtr()->releaseToV8GarbageCollector(), isolate); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MIDIInputCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunction.h index 6ad179c447f..acb379d0f7d 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MIDIInputCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunction.h @@ -28,25 +28,29 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "V8MIDIInput.h" +#ifndef ScriptFunction_h +#define ScriptFunction_h -#include "V8MIDIAccess.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/ScriptValue.h" +#include "bindings/v8/V8GarbageCollected.h" +#include "wtf/RefCounted.h" +#include <v8.h> namespace WebCore { -v8::Handle<v8::Object> wrap(MIDIInput* input, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) -{ - ASSERT(input); - ASSERT(!DOMDataStore::containsWrapper<V8MIDIInput>(input, isolate)); +class ScriptFunction : public V8GarbageCollected<ScriptFunction> { +public: + virtual ~ScriptFunction() { } + static v8::Handle<v8::Function> adoptByGarbageCollector(PassOwnPtr<ScriptFunction>); - v8::Handle<v8::Object> wrapper = V8MIDIInput::createWrapper(input, creationContext, isolate); +protected: + ScriptFunction(v8::Isolate* isolate) : V8GarbageCollected<ScriptFunction>(isolate) { } - if (input->midiAccess()) - V8HiddenPropertyName::setNamedHiddenReference(wrapper, "access", toV8(input->midiAccess(), creationContext, isolate)); - - return wrapper; -} +private: + virtual ScriptValue call(ScriptValue) = 0; + static void callCallback(const v8::FunctionCallbackInfo<v8::Value>& args); +}; } // namespace WebCore + +#endif diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunctionCall.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunctionCall.cpp index e8c618e9030..56637ded2af 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunctionCall.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunctionCall.cpp @@ -32,19 +32,17 @@ #include "bindings/v8/ScriptFunctionCall.h" #include "bindings/v8/ScriptController.h" -#include "bindings/v8/ScriptScope.h" #include "bindings/v8/ScriptState.h" #include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8ObjectConstructor.h" #include "bindings/v8/V8ScriptRunner.h" -#include "bindings/v8/V8Utilities.h" #include <v8.h> namespace WebCore { -void ScriptCallArgumentHandler::appendArgument(const ScriptObject& argument) +void ScriptCallArgumentHandler::appendArgument(const ScriptValue& argument) { if (argument.scriptState() != m_scriptState) { ASSERT_NOT_REACHED(); @@ -53,67 +51,72 @@ void ScriptCallArgumentHandler::appendArgument(const ScriptObject& argument) m_arguments.append(argument); } -void ScriptCallArgumentHandler::appendArgument(const ScriptValue& argument) -{ - m_arguments.append(argument); -} - void ScriptCallArgumentHandler::appendArgument(const String& argument) { v8::Isolate* isolate = m_scriptState->isolate(); - ScriptScope scope(m_scriptState); - m_arguments.append(ScriptValue(v8String(isolate, argument), isolate)); + ScriptState::Scope scope(m_scriptState.get()); + m_arguments.append(ScriptValue(m_scriptState.get(), v8String(isolate, argument))); } void ScriptCallArgumentHandler::appendArgument(const char* argument) { v8::Isolate* isolate = m_scriptState->isolate(); - ScriptScope scope(m_scriptState); - m_arguments.append(ScriptValue(v8String(isolate, argument), isolate)); + ScriptState::Scope scope(m_scriptState.get()); + m_arguments.append(ScriptValue(m_scriptState.get(), v8String(isolate, argument))); } void ScriptCallArgumentHandler::appendArgument(long argument) { v8::Isolate* isolate = m_scriptState->isolate(); - ScriptScope scope(m_scriptState); - m_arguments.append(ScriptValue(v8::Number::New(isolate, argument), isolate)); + ScriptState::Scope scope(m_scriptState.get()); + m_arguments.append(ScriptValue(m_scriptState.get(), v8::Number::New(isolate, argument))); } void ScriptCallArgumentHandler::appendArgument(long long argument) { v8::Isolate* isolate = m_scriptState->isolate(); - ScriptScope scope(m_scriptState); - m_arguments.append(ScriptValue(v8::Number::New(isolate, argument), isolate)); + ScriptState::Scope scope(m_scriptState.get()); + m_arguments.append(ScriptValue(m_scriptState.get(), v8::Number::New(isolate, argument))); } -void ScriptCallArgumentHandler::appendArgument(unsigned int argument) +void ScriptCallArgumentHandler::appendArgument(unsigned argument) { v8::Isolate* isolate = m_scriptState->isolate(); - ScriptScope scope(m_scriptState); - m_arguments.append(ScriptValue(v8::Number::New(isolate, argument), isolate)); + ScriptState::Scope scope(m_scriptState.get()); + m_arguments.append(ScriptValue(m_scriptState.get(), v8::Number::New(isolate, argument))); } void ScriptCallArgumentHandler::appendArgument(unsigned long argument) { v8::Isolate* isolate = m_scriptState->isolate(); - ScriptScope scope(m_scriptState); - m_arguments.append(ScriptValue(v8::Number::New(isolate, argument), isolate)); + ScriptState::Scope scope(m_scriptState.get()); + m_arguments.append(ScriptValue(m_scriptState.get(), v8::Number::New(isolate, argument))); } void ScriptCallArgumentHandler::appendArgument(int argument) { v8::Isolate* isolate = m_scriptState->isolate(); - ScriptScope scope(m_scriptState); - m_arguments.append(ScriptValue(v8::Number::New(isolate, argument), isolate)); + ScriptState::Scope scope(m_scriptState.get()); + m_arguments.append(ScriptValue(m_scriptState.get(), v8::Number::New(isolate, argument))); } void ScriptCallArgumentHandler::appendArgument(bool argument) { v8::Isolate* isolate = m_scriptState->isolate(); - m_arguments.append(ScriptValue(v8Boolean(argument, isolate), isolate)); + m_arguments.append(ScriptValue(m_scriptState.get(), v8Boolean(argument, isolate))); } -ScriptFunctionCall::ScriptFunctionCall(const ScriptObject& thisObject, const String& name) +void ScriptCallArgumentHandler::appendArgument(const Vector<ScriptValue>& argument) +{ + v8::Isolate* isolate = m_scriptState->isolate(); + ScriptState::Scope scope(m_scriptState.get()); + v8::Handle<v8::Array> result = v8::Array::New(isolate, argument.size()); + for (size_t i = 0; i < argument.size(); ++i) + result->Set(v8::Integer::New(isolate, i), argument[i].v8Value()); + m_arguments.append(ScriptValue(m_scriptState.get(), result)); +} + +ScriptFunctionCall::ScriptFunctionCall(const ScriptValue& thisObject, const String& name) : ScriptCallArgumentHandler(thisObject.scriptState()) , m_thisObject(thisObject) , m_name(name) @@ -122,11 +125,13 @@ ScriptFunctionCall::ScriptFunctionCall(const ScriptObject& thisObject, const Str ScriptValue ScriptFunctionCall::call(bool& hadException, bool reportExceptions) { - ScriptScope scope(m_scriptState, reportExceptions); + ScriptState::Scope scope(m_scriptState.get()); + v8::TryCatch tryCatch; + tryCatch.SetVerbose(reportExceptions); - v8::Handle<v8::Object> thisObject = m_thisObject.v8Object(); + v8::Handle<v8::Object> thisObject = v8::Handle<v8::Object>::Cast(m_thisObject.v8Value()); v8::Local<v8::Value> value = thisObject->Get(v8String(m_scriptState->isolate(), m_name)); - if (!scope.success()) { + if (tryCatch.HasCaught()) { hadException = true; return ScriptValue(); } @@ -140,13 +145,13 @@ ScriptValue ScriptFunctionCall::call(bool& hadException, bool reportExceptions) ASSERT(!info[i].IsEmpty()); } - v8::Local<v8::Value> result = V8ScriptRunner::callFunction(function, getExecutionContext(), thisObject, m_arguments.size(), info.get(), m_scriptState->isolate()); - if (!scope.success()) { + v8::Local<v8::Value> result = V8ScriptRunner::callFunction(function, m_scriptState->executionContext(), thisObject, m_arguments.size(), info.get(), m_scriptState->isolate()); + if (tryCatch.HasCaught()) { hadException = true; return ScriptValue(); } - return ScriptValue(result, m_scriptState->isolate()); + return ScriptValue(m_scriptState.get(), result); } ScriptValue ScriptFunctionCall::call() @@ -155,15 +160,17 @@ ScriptValue ScriptFunctionCall::call() return call(hadException); } -ScriptObject ScriptFunctionCall::construct(bool& hadException, bool reportExceptions) +ScriptValue ScriptFunctionCall::construct(bool& hadException, bool reportExceptions) { - ScriptScope scope(m_scriptState, reportExceptions); + ScriptState::Scope scope(m_scriptState.get()); + v8::TryCatch tryCatch; + tryCatch.SetVerbose(reportExceptions); - v8::Handle<v8::Object> thisObject = m_thisObject.v8Object(); + v8::Handle<v8::Object> thisObject = v8::Handle<v8::Object>::Cast(m_thisObject.v8Value()); v8::Local<v8::Value> value = thisObject->Get(v8String(m_scriptState->isolate(), m_name)); - if (!scope.success()) { + if (tryCatch.HasCaught()) { hadException = true; - return ScriptObject(); + return ScriptValue(); } ASSERT(value->IsFunction()); @@ -173,39 +180,13 @@ ScriptObject ScriptFunctionCall::construct(bool& hadException, bool reportExcept for (size_t i = 0; i < m_arguments.size(); ++i) info[i] = m_arguments[i].v8Value(); - v8::Local<v8::Object> result = V8ObjectConstructor::newInstance(constructor, m_arguments.size(), info.get()); - if (!scope.success()) { + v8::Local<v8::Object> result = V8ObjectConstructor::newInstance(m_scriptState->isolate(), constructor, m_arguments.size(), info.get()); + if (tryCatch.HasCaught()) { hadException = true; - return ScriptObject(); + return ScriptValue(); } - return ScriptObject(m_scriptState, result); -} - -ScriptCallback::ScriptCallback(ScriptState* state, const ScriptValue& function) - : ScriptCallArgumentHandler(state) - , m_scriptState(state) - , m_function(function) -{ -} - -ScriptValue ScriptCallback::call() -{ - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - ASSERT(isolate->InContext()); - ASSERT(m_function.v8Value()->IsFunction()); - - v8::TryCatch exceptionCatcher; - exceptionCatcher.SetVerbose(true); - v8::Handle<v8::Object> object = isolate->GetCurrentContext()->Global(); - v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(m_function.v8Value()); - - OwnPtr<v8::Handle<v8::Value>[]> info = adoptArrayPtr(new v8::Handle<v8::Value>[m_arguments.size()]); - for (size_t i = 0; i < m_arguments.size(); ++i) - info[i] = m_arguments[i].v8Value(); - - v8::Handle<v8::Value> result = ScriptController::callFunction(m_scriptState->executionContext(), function, object, m_arguments.size(), info.get(), m_scriptState->isolate()); - return ScriptValue(result, m_scriptState->isolate()); + return ScriptValue(m_scriptState.get(), result); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunctionCall.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunctionCall.h index 032b6a0b0ce..f323c3f6359 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunctionCall.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptFunctionCall.h @@ -31,58 +31,46 @@ #ifndef ScriptFunctionCall_h #define ScriptFunctionCall_h -#include "bindings/v8/ScriptObject.h" +#include "bindings/v8/ScriptValue.h" #include "wtf/Vector.h" #include "wtf/text/WTFString.h" namespace WebCore { class ScriptValue; - class ScriptState; class ScriptCallArgumentHandler { public: ScriptCallArgumentHandler(ScriptState* scriptState) : m_scriptState(scriptState) { } - void appendArgument(const ScriptObject&); void appendArgument(const ScriptValue&); void appendArgument(const String&); void appendArgument(const char*); void appendArgument(long); void appendArgument(long long); - void appendArgument(unsigned int); + void appendArgument(unsigned); void appendArgument(unsigned long); void appendArgument(int); void appendArgument(bool); + void appendArgument(const Vector<ScriptValue>&); protected: - ScriptState* m_scriptState; + RefPtr<ScriptState> m_scriptState; Vector<ScriptValue> m_arguments; }; class ScriptFunctionCall : public ScriptCallArgumentHandler { public: - ScriptFunctionCall(const ScriptObject& thisObject, const String& name); + ScriptFunctionCall(const ScriptValue& thisObject, const String& name); ScriptValue call(bool& hadException, bool reportExceptions = true); ScriptValue call(); - ScriptObject construct(bool& hadException, bool reportExceptions = true); + ScriptValue construct(bool& hadException, bool reportExceptions = true); protected: - ScriptObject m_thisObject; + ScriptValue m_thisObject; String m_name; }; - class ScriptCallback : public ScriptCallArgumentHandler { - public: - ScriptCallback(ScriptState*, const ScriptValue&); - - ScriptValue call(); - - private: - ScriptState* m_scriptState; - ScriptValue m_function; - }; - } // namespace WebCore #endif // ScriptFunctionCall diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptGCEvent.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptGCEvent.cpp index 361d8e3e965..9cc90eb4672 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptGCEvent.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptGCEvent.cpp @@ -41,7 +41,7 @@ namespace WebCore { static GCEventData* isolateGCEventData() { - V8PerIsolateData* isolateData = V8PerIsolateData::current(); + V8PerIsolateData* isolateData = V8PerIsolateData::from(v8::Isolate::GetCurrent()); ASSERT(isolateData); return isolateData->gcEventData(); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptGCEvent.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptGCEvent.h index 3f95e7f46c7..ee042b5b8af 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptGCEvent.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptGCEvent.h @@ -31,8 +31,8 @@ #ifndef ScriptGCEvent_h #define ScriptGCEvent_h -#include "v8.h" #include "wtf/Vector.h" +#include <v8.h> namespace WebCore { @@ -80,6 +80,7 @@ private: }; +// FIXME(361045): remove ScriptGCEvent once DevTools Timeline migrates to tracing. class ScriptGCEvent { public: diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptHeapSnapshot.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptHeapSnapshot.cpp index 6077b57febd..b5c2c7f9e71 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptHeapSnapshot.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptHeapSnapshot.cpp @@ -51,25 +51,15 @@ String ScriptHeapSnapshot::title() const return toCoreString(m_snapshot->GetTitle()); } -unsigned int ScriptHeapSnapshot::uid() const -{ - return m_snapshot->GetUid(); -} - -SnapshotObjectId ScriptHeapSnapshot::maxSnapshotJSObjectId() const -{ - return m_snapshot->GetMaxSnapshotJSObjectId(); -} - namespace { -class OutputStreamAdapter : public v8::OutputStream { +class OutputStreamAdapter FINAL : public v8::OutputStream { public: OutputStreamAdapter(ScriptHeapSnapshot::OutputStream* output) : m_output(output) { } - void EndOfStream() { m_output->Close(); } - int GetChunkSize() { return 102400; } - WriteResult WriteAsciiChunk(char* data, int size) + virtual void EndOfStream() OVERRIDE { m_output->Close(); } + virtual int GetChunkSize() OVERRIDE { return 102400; } + virtual WriteResult WriteAsciiChunk(char* data, int size) OVERRIDE { m_output->Write(String(data, size)); return kContinue; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptHeapSnapshot.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptHeapSnapshot.h index 1e168599bdb..3ca4f5e9e81 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptHeapSnapshot.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptHeapSnapshot.h @@ -33,15 +33,10 @@ #include "wtf/RefCounted.h" #include "wtf/text/WTFString.h" - -namespace v8 { -class HeapSnapshot; -} +#include <v8-profiler.h> namespace WebCore { -typedef uint32_t SnapshotObjectId; - class ScriptHeapSnapshot FINAL : public RefCounted<ScriptHeapSnapshot> { public: class OutputStream { @@ -58,9 +53,7 @@ public: ~ScriptHeapSnapshot(); String title() const; - unsigned int uid() const; void writeJSON(OutputStream* stream); - SnapshotObjectId maxSnapshotJSObjectId() const; private: ScriptHeapSnapshot(const v8::HeapSnapshot* snapshot) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptObject.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptObject.h deleted file mode 100644 index 072313d49be..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptObject.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 ScriptObject_h -#define ScriptObject_h - -#include "bindings/v8/ScriptValue.h" - -#include <v8.h> - -namespace WebCore { - class InjectedScriptHost; - class InspectorFrontendHost; - class ScriptState; - - class ScriptObject : public ScriptValue { - public: - ScriptObject(ScriptState*, v8::Handle<v8::Object>); - ScriptObject(ScriptState*, const ScriptValue&); - ScriptObject() : m_scriptState(0) { }; - virtual ~ScriptObject() { } - - v8::Handle<v8::Object> v8Object() const; - ScriptState* scriptState() const { return m_scriptState; } - protected: - ScriptState* m_scriptState; - }; - - class ScriptGlobalObject { - public: - static bool set(ScriptState*, const char* name, InspectorFrontendHost*); - static bool get(ScriptState*, const char* name, ScriptObject&); - private: - ScriptGlobalObject() { } - }; - -} - -#endif // ScriptObject_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPreprocessor.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPreprocessor.cpp index c9674b96c7a..3c38767e8ff 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPreprocessor.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPreprocessor.cpp @@ -34,39 +34,41 @@ #include "bindings/v8/ScriptController.h" #include "bindings/v8/ScriptSourceCode.h" #include "bindings/v8/ScriptValue.h" +#include "bindings/v8/V8Binding.h" #include "bindings/v8/V8ScriptRunner.h" -#include "core/page/PageConsole.h" +#include "core/frame/FrameConsole.h" +#include "core/frame/FrameHost.h" +#include "core/frame/LocalFrame.h" #include "wtf/TemporaryChange.h" namespace WebCore { -ScriptPreprocessor::ScriptPreprocessor(const ScriptSourceCode& preprocessorSourceCode, ScriptController& controller, PageConsole& console) +ScriptPreprocessor::ScriptPreprocessor(const ScriptSourceCode& preprocessorSourceCode, LocalFrame* frame) : m_isPreprocessing(false) { + RefPtr<DOMWrapperWorld> world = DOMWrapperWorld::ensureIsolatedWorld(ScriptPreprocessorIsolatedWorldId, DOMWrapperWorld::mainWorldExtensionGroup); + m_scriptState = ScriptState::from(toV8Context(frame, *world)); + + v8::HandleScope handleScope(m_scriptState->isolate()); + ASSERT(frame); v8::TryCatch tryCatch; tryCatch.SetVerbose(true); Vector<ScriptSourceCode> sources; sources.append(preprocessorSourceCode); - Vector<ScriptValue> scriptResults; - controller.executeScriptInIsolatedWorld(ScriptPreprocessorIsolatedWorldId, sources, DOMWrapperWorld::mainWorldExtensionGroup, &scriptResults); + Vector<v8::Local<v8::Value> > scriptResults; + frame->script().executeScriptInIsolatedWorld(ScriptPreprocessorIsolatedWorldId, sources, DOMWrapperWorld::mainWorldExtensionGroup, &scriptResults); if (scriptResults.size() != 1) { - console.addMessage(JSMessageSource, ErrorMessageLevel, "ScriptPreprocessor internal error, one ScriptSourceCode must give exactly one result."); + frame->console().addMessage(JSMessageSource, ErrorMessageLevel, "ScriptPreprocessor internal error, one ScriptSourceCode must give exactly one result."); return; } - ScriptValue preprocessorFunction = scriptResults[0]; - if (!preprocessorFunction.isFunction()) { - console.addMessage(JSMessageSource, ErrorMessageLevel, "The preprocessor must compile to a function."); + v8::Local<v8::Value> preprocessorFunction = scriptResults[0]; + if (preprocessorFunction.IsEmpty() || !preprocessorFunction->IsFunction()) { + frame->console().addMessage(JSMessageSource, ErrorMessageLevel, "The preprocessor must compile to a function."); return; } - - m_world = DOMWrapperWorld::ensureIsolatedWorld(ScriptPreprocessorIsolatedWorldId, DOMWrapperWorld::mainWorldExtensionGroup); - v8::Local<v8::Context> context = m_world->context(controller); - m_isolate = context->GetIsolate(); - - m_context.set(m_isolate, context); - m_preprocessorFunction.set(m_isolate, v8::Handle<v8::Function>::Cast(preprocessorFunction.v8Value())); + m_preprocessorFunction.set(m_scriptState->isolate(), v8::Handle<v8::Function>::Cast(preprocessorFunction)); } String ScriptPreprocessor::preprocessSourceCode(const String& sourceCode, const String& sourceName) @@ -74,7 +76,7 @@ String ScriptPreprocessor::preprocessSourceCode(const String& sourceCode, const if (!isValid()) return sourceCode; - return preprocessSourceCode(sourceCode, sourceName, v8::Undefined(m_isolate)); + return preprocessSourceCode(sourceCode, sourceName, v8::Undefined(m_scriptState->isolate())); } String ScriptPreprocessor::preprocessSourceCode(const String& sourceCode, const String& sourceName, const String& functionName) @@ -82,7 +84,7 @@ String ScriptPreprocessor::preprocessSourceCode(const String& sourceCode, const if (!isValid()) return sourceCode; - v8::Handle<v8::String> functionNameString = v8String(m_isolate, functionName); + v8::Handle<v8::String> functionNameString = v8String(m_scriptState->isolate(), functionName); return preprocessSourceCode(sourceCode, sourceName, functionNameString); } @@ -91,17 +93,17 @@ String ScriptPreprocessor::preprocessSourceCode(const String& sourceCode, const if (!isValid()) return sourceCode; - v8::HandleScope handleScope(m_isolate); - v8::Context::Scope contextScope(m_context.newLocal(m_isolate)); + v8::Isolate* isolate = m_scriptState->isolate(); + ScriptState::Scope scope(m_scriptState.get()); - v8::Handle<v8::String> sourceCodeString = v8String(m_isolate, sourceCode); - v8::Handle<v8::String> sourceNameString = v8String(m_isolate, sourceName); + v8::Handle<v8::String> sourceCodeString = v8String(isolate, sourceCode); + v8::Handle<v8::String> sourceNameString = v8String(isolate, sourceName); v8::Handle<v8::Value> argv[] = { sourceCodeString, sourceNameString, functionName}; v8::TryCatch tryCatch; tryCatch.SetVerbose(true); TemporaryChange<bool> isPreprocessing(m_isPreprocessing, true); - v8::Handle<v8::Value> resultValue = V8ScriptRunner::callAsFunction(m_preprocessorFunction.newLocal(m_isolate), m_context.newLocal(m_isolate)->Global(), WTF_ARRAY_LENGTH(argv), argv); + v8::Handle<v8::Value> resultValue = V8ScriptRunner::callAsFunction(isolate, m_preprocessorFunction.newLocal(isolate), m_scriptState->context()->Global(), WTF_ARRAY_LENGTH(argv), argv); if (!resultValue.IsEmpty() && resultValue->IsString()) return toCoreStringWithNullCheck(resultValue.As<v8::String>()); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPreprocessor.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPreprocessor.h index 823c8be95ef..20e8ac09cb9 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPreprocessor.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPreprocessor.h @@ -40,12 +40,11 @@ namespace WebCore { class ScriptController; class ScriptSourceCode; class ScriptDebugServer; -class PageConsole; class ScriptPreprocessor { WTF_MAKE_NONCOPYABLE(ScriptPreprocessor); public: - ScriptPreprocessor(const ScriptSourceCode&, ScriptController&, PageConsole&); + ScriptPreprocessor(const ScriptSourceCode&, LocalFrame*); String preprocessSourceCode(const String& sourceCode, const String& sourceName); String preprocessSourceCode(const String& sourceCode, const String& sourceName, const String& functionName); bool isPreprocessing() { return m_isPreprocessing; } @@ -53,9 +52,7 @@ public: private: String preprocessSourceCode(const String& sourceCode, const String& sourceName, v8::Handle<v8::Value> functionName); - RefPtr<DOMWrapperWorld> m_world; - ScopedPersistent<v8::Context> m_context; - v8::Isolate* m_isolate; + RefPtr<ScriptState> m_scriptState; ScopedPersistent<v8::Function> m_preprocessorFunction; bool m_isPreprocessing; }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptProfiler.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptProfiler.cpp index 914a943a206..07a65f74a49 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptProfiler.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptProfiler.cpp @@ -31,12 +31,11 @@ #include "config.h" #include "bindings/v8/ScriptProfiler.h" -#include "V8Node.h" -#include "V8Window.h" +#include "bindings/core/v8/V8Node.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/RetainedDOMInfo.h" -#include "bindings/v8/ScriptObject.h" +#include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8DOMWrapper.h" #include "bindings/v8/WrapperTypeInfo.h" #include "core/dom/Document.h" #include "core/inspector/BindingVisitors.h" @@ -70,19 +69,19 @@ void ScriptProfiler::start(const String& title) if (!profiler) return; v8::HandleScope handleScope(isolate); - profiler->StartCpuProfiling(v8String(isolate, title), true); + profiler->StartProfiling(v8String(isolate, title), true); } -PassRefPtr<ScriptProfile> ScriptProfiler::stop(const String& title) +PassRefPtrWillBeRawPtr<ScriptProfile> ScriptProfiler::stop(const String& title) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::CpuProfiler* profiler = isolate->GetCpuProfiler(); if (!profiler) - return 0; + return nullptr; v8::HandleScope handleScope(isolate); - const v8::CpuProfile* profile = profiler->StopCpuProfiling(v8String(isolate, title)); + v8::CpuProfile* profile = profiler->StopProfiling(v8String(isolate, title)); if (!profile) - return 0; + return nullptr; String profileTitle = toCoreString(profile->GetTitle()); double idleTime = 0.0; @@ -101,28 +100,14 @@ void ScriptProfiler::collectGarbage() v8::V8::LowMemoryNotification(); } -ScriptObject ScriptProfiler::objectByHeapObjectId(unsigned id) +ScriptValue ScriptProfiler::objectByHeapObjectId(unsigned id) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::HeapProfiler* profiler = isolate->GetHeapProfiler(); - if (!profiler) - return ScriptObject(); - // As ids are unique, it doesn't matter which HeapSnapshot owns HeapGraphNode. - // We need to find first HeapSnapshot containing a node with the specified id. - const v8::HeapGraphNode* node = 0; - for (int i = 0, l = profiler->GetSnapshotCount(); i < l; ++i) { - const v8::HeapSnapshot* snapshot = profiler->GetHeapSnapshot(i); - node = snapshot->GetNodeById(id); - if (node) - break; - } - if (!node) - return ScriptObject(); - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Value> value = node->GetHeapValue(); - if (!value->IsObject()) - return ScriptObject(); + v8::Handle<v8::Value> value = profiler->FindObjectById(id); + if (value.IsEmpty() || !value->IsObject()) + return ScriptValue(); v8::Handle<v8::Object> object = value.As<v8::Object>(); @@ -131,11 +116,11 @@ ScriptObject ScriptProfiler::objectByHeapObjectId(unsigned id) // Skip wrapper boilerplates which are like regular wrappers but don't have // native object. if (!wrapper.IsEmpty() && wrapper->IsUndefined()) - return ScriptObject(); + return ScriptValue(); } - ScriptState* scriptState = ScriptState::forContext(object->CreationContext()); - return ScriptObject(scriptState, object); + ScriptState* scriptState = ScriptState::from(object->CreationContext()); + return ScriptValue(scriptState, object); } unsigned ScriptProfiler::getHeapObjectId(const ScriptValue& value) @@ -146,13 +131,20 @@ unsigned ScriptProfiler::getHeapObjectId(const ScriptValue& value) return id; } +void ScriptProfiler::clearHeapObjectIds() +{ + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + v8::HeapProfiler* profiler = isolate->GetHeapProfiler(); + profiler->ClearObjectIds(); +} + namespace { -class ActivityControlAdapter : public v8::ActivityControl { +class ActivityControlAdapter FINAL : public v8::ActivityControl { public: ActivityControlAdapter(ScriptProfiler::HeapSnapshotProgress* progress) : m_progress(progress), m_firstReport(true) { } - ControlOption ReportProgressValue(int done, int total) + virtual ControlOption ReportProgressValue(int done, int total) OVERRIDE { ControlOption result = m_progress->isCanceled() ? kAbort : kContinue; if (m_firstReport) { @@ -169,19 +161,16 @@ private: bool m_firstReport; }; -class GlobalObjectNameResolver : public v8::HeapProfiler::ObjectNameResolver { +class GlobalObjectNameResolver FINAL : public v8::HeapProfiler::ObjectNameResolver { public: - virtual const char* GetName(v8::Handle<v8::Object> object) + virtual const char* GetName(v8::Handle<v8::Object> object) OVERRIDE { - if (V8DOMWrapper::isWrapperOfType(object, &V8Window::wrapperTypeInfo)) { - DOMWindow* window = V8Window::toNative(object); - if (window) { - CString url = window->document()->url().string().utf8(); - m_strings.append(url); - return url.data(); - } - } - return 0; + LocalDOMWindow* window = toDOMWindow(object, v8::Isolate::GetCurrent()); + if (!window) + return 0; + CString url = window->document()->url().string().utf8(); + m_strings.append(url); + return url.data(); } private: @@ -190,9 +179,9 @@ private: } // namespace -void ScriptProfiler::startTrackingHeapObjects() +void ScriptProfiler::startTrackingHeapObjects(bool trackAllocations) { - v8::Isolate::GetCurrent()->GetHeapProfiler()->StartTrackingHeapObjects(); + v8::Isolate::GetCurrent()->GetHeapProfiler()->StartTrackingHeapObjects(trackAllocations); } namespace { @@ -244,13 +233,13 @@ PassRefPtr<ScriptHeapSnapshot> ScriptProfiler::takeHeapSnapshot(const String& ti v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::HeapProfiler* profiler = isolate->GetHeapProfiler(); if (!profiler) - return 0; + return nullptr; v8::HandleScope handleScope(isolate); ASSERT(control); ActivityControlAdapter adapter(control); GlobalObjectNameResolver resolver; const v8::HeapSnapshot* snapshot = profiler->TakeHeapSnapshot(v8String(isolate, title), &adapter, &resolver); - return snapshot ? ScriptHeapSnapshot::create(snapshot) : 0; + return snapshot ? ScriptHeapSnapshot::create(snapshot) : nullptr; } static v8::RetainedObjectInfo* retainedDOMInfo(uint16_t classId, v8::Handle<v8::Value> wrapper) @@ -292,7 +281,7 @@ void ScriptProfiler::visitNodeWrappers(WrappedNodeVisitor* visitor) // Casting to Handle is safe here, since the Persistent cannot get // GCd during visiting. v8::Handle<v8::Object>* wrapper = reinterpret_cast<v8::Handle<v8::Object>*>(value); - ASSERT_UNUSED(m_isolate, V8Node::hasInstanceInAnyWorld(*wrapper, m_isolate)); + ASSERT_UNUSED(m_isolate, V8Node::hasInstance(*wrapper, m_isolate)); ASSERT((*wrapper)->IsObject()); m_visitor->visitNode(V8Node::toNative(*wrapper)); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptProfiler.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptProfiler.h index f406c520764..167da66bf81 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptProfiler.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptProfiler.h @@ -32,7 +32,6 @@ #define ScriptProfiler_h #include "bindings/v8/ScriptHeapSnapshot.h" -#include "bindings/v8/ScriptState.h" #include "core/inspector/ScriptProfile.h" #include "wtf/Forward.h" @@ -41,11 +40,9 @@ namespace WebCore { -class ExternalArrayVisitor; class ExternalStringVisitor; class WrappedNodeVisitor; class Page; -class ScriptObject; class ScriptValue; class WorkerGlobalScope; @@ -68,13 +65,14 @@ public: }; static void collectGarbage(); - static ScriptObject objectByHeapObjectId(unsigned id); + static ScriptValue objectByHeapObjectId(unsigned id); static unsigned getHeapObjectId(const ScriptValue&); + static void clearHeapObjectIds(); static void setSamplingInterval(int intervalUs); static void start(const String& title); - static PassRefPtr<ScriptProfile> stop(const String& title); + static PassRefPtrWillBeRawPtr<ScriptProfile> stop(const String& title); static PassRefPtr<ScriptHeapSnapshot> takeHeapSnapshot(const String& title, HeapSnapshotProgress*); - static void startTrackingHeapObjects(); + static void startTrackingHeapObjects(bool trackAllocations); static void stopTrackingHeapObjects(); static unsigned requestHeapStatsUpdate(OutputStream*); static void initialize(); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromise.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromise.cpp index bdf4105edde..d6d8b317e0b 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromise.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromise.cpp @@ -31,31 +31,105 @@ #include "config.h" #include "bindings/v8/ScriptPromise.h" +#include "bindings/v8/ScriptPromiseResolver.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8DOMWrapper.h" -#include "bindings/v8/custom/V8PromiseCustom.h" +#include "core/dom/DOMException.h" #include <v8.h> namespace WebCore { -ScriptPromise ScriptPromise::createPending(ExecutionContext* context) +namespace { + +struct WithScriptState { + // Used by ToV8Value<WithScriptState, ScriptState*>. + static v8::Handle<v8::Object> getCreationContext(ScriptState* scriptState) + { + return scriptState->context()->Global(); + } +}; + +} // namespace + +ScriptPromise::ScriptPromise(ScriptState* scriptState, v8::Handle<v8::Value> value) + : m_scriptState(scriptState) +{ + if (value.IsEmpty()) + return; + + if (!value->IsPromise()) { + m_promise = ScriptValue(scriptState, v8::Handle<v8::Value>()); + V8ThrowException::throwTypeError("the given value is not a Promise", scriptState->isolate()); + return; + } + m_promise = ScriptValue(scriptState, value); +} + +ScriptPromise ScriptPromise::then(PassOwnPtr<ScriptFunction> onFulfilled, PassOwnPtr<ScriptFunction> onRejected) +{ + if (m_promise.isEmpty()) + return ScriptPromise(); + + v8::Local<v8::Object> promise = m_promise.v8Value().As<v8::Object>(); + v8::Local<v8::Function> v8OnFulfilled = ScriptFunction::adoptByGarbageCollector(onFulfilled); + v8::Local<v8::Function> v8OnRejected = ScriptFunction::adoptByGarbageCollector(onRejected); + + ASSERT(promise->IsPromise()); + // Return this Promise if no handlers are given. + // In fact it is not the exact bahavior of Promise.prototype.then + // but that is not a problem in this case. + v8::Local<v8::Promise> resultPromise = promise.As<v8::Promise>(); + if (!v8OnFulfilled.IsEmpty()) { + resultPromise = resultPromise->Then(v8OnFulfilled); + if (resultPromise.IsEmpty()) { + // v8::Promise::Then may return an empty value, for example when + // the stack is exhausted. + return ScriptPromise(); + } + } + if (!v8OnRejected.IsEmpty()) + resultPromise = resultPromise->Catch(v8OnRejected); + + return ScriptPromise(m_scriptState.get(), resultPromise); +} + +ScriptPromise ScriptPromise::cast(ScriptState* scriptState, const ScriptValue& value) +{ + return ScriptPromise::cast(scriptState, value.v8Value()); +} + +ScriptPromise ScriptPromise::cast(ScriptState* scriptState, v8::Handle<v8::Value> value) +{ + if (value.IsEmpty()) + return ScriptPromise(); + if (value->IsPromise()) { + return ScriptPromise(scriptState, value); + } + RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState); + ScriptPromise promise = resolver->promise(); + resolver->resolve(value); + return promise; +} + +ScriptPromise ScriptPromise::reject(ScriptState* scriptState, const ScriptValue& value) +{ + return ScriptPromise::reject(scriptState, value.v8Value()); +} + +ScriptPromise ScriptPromise::reject(ScriptState* scriptState, v8::Handle<v8::Value> value) { - ASSERT(context); - v8::Isolate* isolate = toIsolate(context); - ASSERT(isolate->InContext()); - v8::Handle<v8::Context> v8Context = toV8Context(context, DOMWrapperWorld::current()); - v8::Handle<v8::Object> creationContext = v8Context.IsEmpty() ? v8::Object::New() : v8Context->Global(); - v8::Handle<v8::Object> promise = V8PromiseCustom::createPromise(creationContext, isolate); - return ScriptPromise(promise, isolate); + if (value.IsEmpty()) + return ScriptPromise(); + RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState); + ScriptPromise promise = resolver->promise(); + resolver->reject(value); + return promise; } -ScriptPromise ScriptPromise::createPending() +ScriptPromise ScriptPromise::rejectWithDOMException(ScriptState* scriptState, PassRefPtrWillBeRawPtr<DOMException> exception) { - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - ASSERT(isolate->InContext()); - v8::Handle<v8::Object> promise = V8PromiseCustom::createPromise(v8::Object::New(), isolate); - return ScriptPromise(promise, isolate); + ASSERT(scriptState->isolate()->InContext()); + return reject(scriptState, ToV8Value<WithScriptState, v8::Handle<v8::Object> >::toV8Value(exception, scriptState->context()->Global(), scriptState->isolate())); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromise.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromise.h index 0a93b10f3b4..eb79e4e3b17 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromise.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromise.h @@ -31,14 +31,16 @@ #ifndef ScriptPromise_h #define ScriptPromise_h -#include "bindings/v8/ScopedPersistent.h" +#include "bindings/v8/ScriptFunction.h" #include "bindings/v8/ScriptValue.h" -#include "bindings/v8/V8ScriptRunner.h" +#include "platform/heap/Handle.h" +#include "wtf/PassOwnPtr.h" +#include "wtf/PassRefPtr.h" #include <v8.h> namespace WebCore { -class ExecutionContext; +class DOMException; // ScriptPromise is the class for representing Promise values in C++ world. // ScriptPromise holds a Promise. @@ -48,22 +50,13 @@ class ExecutionContext; class ScriptPromise { public: // Constructs an empty promise. - ScriptPromise() - : m_promise() - { - } + ScriptPromise() { } - explicit ScriptPromise(const ScriptValue& promise) - : m_promise(promise) - { - ASSERT(!m_promise.hasNoValue()); - } + // Constructs a ScriptPromise from |promise|. + // If |promise| is not a Promise object, throws a v8 TypeError. + ScriptPromise(ScriptState*, v8::Handle<v8::Value> promise); - ScriptPromise(v8::Handle<v8::Value> promise, v8::Isolate* isolate) - : m_promise(promise, isolate) - { - ASSERT(!m_promise.hasNoValue()); - } + ScriptPromise then(PassOwnPtr<ScriptFunction> onFulfilled, PassOwnPtr<ScriptFunction> onRejected = PassOwnPtr<ScriptFunction>()); bool isObject() const { @@ -90,9 +83,9 @@ public: return m_promise.isolate(); } - bool hasNoValue() const + bool isEmpty() const { - return m_promise.hasNoValue(); + return m_promise.isEmpty(); } void clear() @@ -100,10 +93,20 @@ public: m_promise.clear(); } - static ScriptPromise createPending(); - static ScriptPromise createPending(ExecutionContext*); + // Constructs and returns a ScriptPromise from |value|. + // if |value| is not a Promise object, returns a Promise object + // resolved with |value|. + // Returns |value| itself if it is a Promise. + static ScriptPromise cast(ScriptState*, const ScriptValue& /*value*/); + static ScriptPromise cast(ScriptState*, v8::Handle<v8::Value> /*value*/); + + static ScriptPromise reject(ScriptState*, const ScriptValue&); + static ScriptPromise reject(ScriptState*, v8::Handle<v8::Value>); + + static ScriptPromise rejectWithDOMException(ScriptState*, PassRefPtrWillBeRawPtr<DOMException>); private: + RefPtr<ScriptState> m_scriptState; ScriptValue m_promise; }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolver.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolver.cpp index fec672fcc15..ea7a6476b3f 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolver.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolver.cpp @@ -31,20 +31,21 @@ #include "config.h" #include "bindings/v8/ScriptPromiseResolver.h" -#include "bindings/v8/ScriptState.h" #include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8DOMWrapper.h" -#include "bindings/v8/custom/V8PromiseCustom.h" #include <v8.h> namespace WebCore { -ScriptPromiseResolver::ScriptPromiseResolver(ScriptPromise promise) - : m_isolate(promise.isolate()) - , m_promise(promise) +ScriptPromiseResolver::ScriptPromiseResolver(ScriptState* scriptState) + : m_scriptState(scriptState) { + v8::Isolate* isolate = m_scriptState->isolate(); + ASSERT(!m_scriptState->contextIsEmpty()); + ASSERT(isolate->InContext()); + m_resolver = ScriptValue(scriptState, v8::Promise::Resolver::New(isolate)); } ScriptPromiseResolver::~ScriptPromiseResolver() @@ -52,61 +53,42 @@ ScriptPromiseResolver::~ScriptPromiseResolver() // We don't call "reject" here because it requires a caller // to be in a v8 context. - m_promise.clear(); + m_resolver.clear(); } -PassRefPtr<ScriptPromiseResolver> ScriptPromiseResolver::create(ScriptPromise promise, ExecutionContext* context) +ScriptPromise ScriptPromiseResolver::promise() { - ASSERT(promise.isolate()->InContext()); - ASSERT(context); - return adoptRef(new ScriptPromiseResolver(promise)); + ASSERT(!m_scriptState->contextIsEmpty()); + ASSERT(m_scriptState->isolate()->InContext()); + if (!m_resolver.isEmpty()) { + v8::Local<v8::Promise::Resolver> v8Resolver = m_resolver.v8Value().As<v8::Promise::Resolver>(); + return ScriptPromise(m_scriptState.get(), v8Resolver->GetPromise()); + } + return ScriptPromise(); } -PassRefPtr<ScriptPromiseResolver> ScriptPromiseResolver::create(ScriptPromise promise) +PassRefPtr<ScriptPromiseResolver> ScriptPromiseResolver::create(ScriptState* scriptState) { - ASSERT(promise.isolate()->InContext()); - return adoptRef(new ScriptPromiseResolver(promise)); -} - -bool ScriptPromiseResolver::isPending() const -{ - ASSERT(m_isolate->InContext()); - if (m_promise.hasNoValue()) - return false; - v8::Local<v8::Object> promise = m_promise.v8Value().As<v8::Object>(); - v8::Local<v8::Object> internal = V8PromiseCustom::getInternal(promise); - V8PromiseCustom::PromiseState state = V8PromiseCustom::getState(internal); - return state == V8PromiseCustom::Pending; + ASSERT(scriptState->isolate()->InContext()); + return adoptRef(new ScriptPromiseResolver(scriptState)); } void ScriptPromiseResolver::resolve(v8::Handle<v8::Value> value) { - ASSERT(m_isolate->InContext()); - if (!isPending()) - return; - V8PromiseCustom::resolve(m_promise.v8Value().As<v8::Object>(), value, m_isolate); - m_promise.clear(); + ASSERT(m_scriptState->isolate()->InContext()); + if (!m_resolver.isEmpty()) { + m_resolver.v8Value().As<v8::Promise::Resolver>()->Resolve(value); + } + m_resolver.clear(); } void ScriptPromiseResolver::reject(v8::Handle<v8::Value> value) { - ASSERT(m_isolate->InContext()); - if (!isPending()) - return; - V8PromiseCustom::reject(m_promise.v8Value().As<v8::Object>(), value, m_isolate); - m_promise.clear(); -} - -void ScriptPromiseResolver::resolve(ScriptValue value) -{ - ASSERT(m_isolate->InContext()); - resolve(value.v8Value()); -} - -void ScriptPromiseResolver::reject(ScriptValue value) -{ - ASSERT(m_isolate->InContext()); - reject(value.v8Value()); + ASSERT(m_scriptState->isolate()->InContext()); + if (!m_resolver.isEmpty()) { + m_resolver.v8Value().As<v8::Promise::Resolver>()->Reject(value); + } + m_resolver.clear(); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolver.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolver.h index 0379b244be5..513abab924b 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolver.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolver.h @@ -31,9 +31,6 @@ #ifndef ScriptPromiseResolver_h #define ScriptPromiseResolver_h -#include "bindings/v8/DOMWrapperWorld.h" -#include "bindings/v8/ScopedPersistent.h" -#include "bindings/v8/ScriptObject.h" #include "bindings/v8/ScriptPromise.h" #include "bindings/v8/ScriptState.h" #include "bindings/v8/ScriptValue.h" @@ -50,25 +47,28 @@ class ExecutionContext; // (resolve / reject) from C++ world. // ScriptPromiseResolver holds a PromiseResolver. // Here is a typical usage: -// 1. Create a ScriptPromiseResolver from a ScriptPromise. -// 2. Pass the promise object of the holder to a JavaScript program +// 1. Create a ScriptPromiseResolver. +// 2. Pass the associated promise object to a JavaScript program // (such as XMLHttpRequest return value). // 3. Call resolve or reject when the operation completes or // the operation fails respectively. // // Most methods including constructors must be called within a v8 context. // To use ScriptPromiseResolver out of a v8 context the caller must -// enter a v8 context, for example by using ScriptScope and ScriptState. +// enter a v8 context. Please use ScriptPromiseResolverWithContext +// in such cases. // // To prevent memory leaks, you should release the reference manually // by calling resolve or reject. // Destroying the object will also release the reference. -// +// Note that ScriptPromiseResolver::promise returns an empty value when the +// resolver is already resolved or rejected. If you want to resolve a resolver +// immediately and return the associated promise, you should get the promise +// before resolving. class ScriptPromiseResolver : public RefCounted<ScriptPromiseResolver> { WTF_MAKE_NONCOPYABLE(ScriptPromiseResolver); public: - static PassRefPtr<ScriptPromiseResolver> create(ScriptPromise, ExecutionContext*); - static PassRefPtr<ScriptPromiseResolver> create(ScriptPromise); + static PassRefPtr<ScriptPromiseResolver> create(ScriptState*); // A ScriptPromiseResolver should be resolved / rejected before // its destruction. @@ -76,90 +76,75 @@ public: // entering a v8 context. ~ScriptPromiseResolver(); - // Return true if the promise object is in pending state. - bool isPending() const; + // Returns the underlying Promise. + // Note that the underlying Promise is cleared when |resolve| or |reject| + // is called. + ScriptPromise promise(); - ScriptPromise promise() + template<typename T> + void resolve(const T& value, ExecutionContext* executionContext) { - ASSERT(m_promise.isolate()->InContext()); - return m_promise; + ASSERT(m_scriptState->isolate()->InContext()); + // You should use ScriptPromiseResolverWithContext when you want + // to resolve a Promise in a non-original V8 context. + return resolve(value); } - - // To use following template methods, T must be a DOM class. - - // This method will be implemented by the code generator. - template<typename T> - void resolve(T* value, v8::Handle<v8::Object> creationContext) { resolve(toV8NoInline(value, creationContext, m_isolate)); } template<typename T> - void reject(T* value, v8::Handle<v8::Object> creationContext) { reject(toV8NoInline(value, creationContext, m_isolate)); } - + void reject(const T& value, ExecutionContext* executionContext) + { + ASSERT(m_scriptState->isolate()->InContext()); + // You should use ScriptPromiseResolverWithContext when you want + // to reject a Promise in a non-original V8 context. + return reject(value); + } template<typename T> - void resolve(PassRefPtr<T> value, v8::Handle<v8::Object> creationContext) { resolve(value.get(), creationContext); } + void resolve(const T& value) + { + ASSERT(m_scriptState->isolate()->InContext()); + resolve(toV8Value(value)); + } template<typename T> - void reject(PassRefPtr<T> value, v8::Handle<v8::Object> creationContext) { reject(value.get(), creationContext); } + void reject(const T& value) + { + ASSERT(m_scriptState->isolate()->InContext()); + reject(toV8Value(value)); + } + template<typename T> void resolve(const T& value, v8::Handle<v8::Object> creationContext) + { + ASSERT(m_scriptState->isolate()->InContext()); + resolve(toV8Value(value, creationContext)); + } + template<typename T> void reject(const T& value, v8::Handle<v8::Object> creationContext) + { + ASSERT(m_scriptState->isolate()->InContext()); + reject(toV8Value(value, creationContext)); + } - template<typename T> - inline void resolve(T* value, ExecutionContext*); - template<typename T> - inline void reject(T* value, ExecutionContext*); + v8::Isolate* isolate() const { return m_scriptState->isolate(); } - template<typename T> - void resolve(PassRefPtr<T> value, ExecutionContext* context) { resolve(value.get(), context); } - template<typename T> - void reject(PassRefPtr<T> value, ExecutionContext* context) { reject(value.get(), context); } + void resolve(v8::Handle<v8::Value>); + void reject(v8::Handle<v8::Value>); +private: template<typename T> - inline void resolve(T* value); - template<typename T> - inline void reject(T* value); + v8::Handle<v8::Value> toV8Value(const T& value, v8::Handle<v8::Object> creationContext) + { + return ToV8Value<ScriptPromiseResolver, v8::Handle<v8::Object> >::toV8Value(value, creationContext, m_scriptState->isolate()); + } template<typename T> - void resolve(PassRefPtr<T> value) { resolve(value.get()); } - template<typename T> - void reject(PassRefPtr<T> value) { reject(value.get()); } - - void resolve(ScriptValue); - void reject(ScriptValue); + v8::Handle<v8::Value> toV8Value(const T& value) + { + return ToV8Value<ScriptPromiseResolver, v8::Handle<v8::Object> >::toV8Value(value, m_scriptState->context()->Global(), m_scriptState->isolate()); + } -private: - ScriptPromiseResolver(ScriptPromise); - void resolve(v8::Handle<v8::Value>); - void reject(v8::Handle<v8::Value>); + explicit ScriptPromiseResolver(ScriptState*); - v8::Isolate* m_isolate; - ScriptPromise m_promise; + // FIXME: Remove this once ScriptValue::scriptState() becomes available. + RefPtr<ScriptState> m_scriptState; + ScriptValue m_resolver; }; -template<typename T> -void ScriptPromiseResolver::resolve(T* value, ExecutionContext* context) -{ - ASSERT(m_isolate->InContext()); - v8::Handle<v8::Context> v8Context = toV8Context(context, DOMWrapperWorld::current()); - resolve(value, v8Context->Global()); -} - -template<typename T> -void ScriptPromiseResolver::reject(T* value, ExecutionContext* context) -{ - ASSERT(m_isolate->InContext()); - v8::Handle<v8::Context> v8Context = toV8Context(context, DOMWrapperWorld::current()); - reject(value, v8Context->Global()); -} - -template<typename T> -void ScriptPromiseResolver::resolve(T* value) -{ - ASSERT(m_isolate->InContext()); - resolve(value, v8::Object::New(m_isolate)); -} - -template<typename T> -void ScriptPromiseResolver::reject(T* value) -{ - ASSERT(m_isolate->InContext()); - reject(value, v8::Object::New(m_isolate)); -} - } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolverTest.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolverTest.cpp index 26b796dd892..8a21cf7896b 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolverTest.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolverTest.cpp @@ -33,7 +33,6 @@ #include "bindings/v8/ScriptPromise.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/custom/V8PromiseCustom.h" #include <gtest/gtest.h> #include <v8.h> @@ -42,132 +41,145 @@ namespace WebCore { namespace { -class ScriptPromiseResolverTest : public testing::Test { +class Function : public ScriptFunction { public: - ScriptPromiseResolverTest() - : m_isolate(v8::Isolate::GetCurrent()) - , m_handleScope(m_isolate) - , m_context(m_isolate, v8::Context::New(m_isolate)) - , m_contextScope(m_context.newLocal(m_isolate)) + static PassOwnPtr<Function> create(v8::Isolate* isolate, String* value) { + return adoptPtr(new Function(isolate, value)); } - void SetUp() + virtual ScriptValue call(ScriptValue value) OVERRIDE { - v8::Handle<v8::Context> context(m_context.newLocal(m_isolate)); - V8PerContextDataHolder::install(context); - m_perContextData = V8PerContextData::create(context); - m_perContextData->init(); - m_promise = ScriptPromise::createPending(); - m_resolver = ScriptPromiseResolver::create(m_promise); + ASSERT(!value.isEmpty()); + *m_value = toCoreString(value.v8Value()->ToString()); + return value; } - void TearDown() - { - m_resolver = 0; - m_promise.clear(); - m_perContextData.clear(); - } +private: + Function(v8::Isolate* isolate, String* value) : ScriptFunction(isolate), m_value(value) { } - V8PromiseCustom::PromiseState state() - { - return V8PromiseCustom::getState(V8PromiseCustom::getInternal(promise())); - } + String* m_value; +}; - v8::Local<v8::Value> result() +class ScriptPromiseResolverTest : public testing::Test { +public: + ScriptPromiseResolverTest() + : m_scope(v8::Isolate::GetCurrent()) { - return V8PromiseCustom::getInternal(promise())->GetInternalField(V8PromiseCustom::InternalResultIndex); + m_resolver = ScriptPromiseResolver::create(m_scope.scriptState()); } - v8::Local<v8::Object> promise() + virtual ~ScriptPromiseResolverTest() { - ASSERT(!m_promise.hasNoValue()); - return m_promise.v8Value().As<v8::Object>(); + // Run all pending microtasks here. + isolate()->RunMicrotasks(); } + v8::Isolate* isolate() { return m_scope.isolate(); } + protected: - v8::Isolate* m_isolate; - v8::HandleScope m_handleScope; - ScopedPersistent<v8::Context> m_context; - v8::Context::Scope m_contextScope; RefPtr<ScriptPromiseResolver> m_resolver; - ScriptPromise m_promise; - OwnPtr<V8PerContextData> m_perContextData; + V8TestingScope m_scope; }; TEST_F(ScriptPromiseResolverTest, initialState) { - EXPECT_TRUE(m_resolver->isPending()); - EXPECT_EQ(V8PromiseCustom::Pending, state()); - EXPECT_TRUE(result()->IsUndefined()); + ScriptPromise promise = m_resolver->promise(); + ASSERT_FALSE(promise.isEmpty()); + String onFulfilled, onRejected; + promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); + + isolate()->RunMicrotasks(); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); } TEST_F(ScriptPromiseResolverTest, resolve) { - EXPECT_TRUE(m_resolver->isPending()); - EXPECT_EQ(V8PromiseCustom::Pending, state()); - EXPECT_TRUE(result()->IsUndefined()); + ScriptPromise promise = m_resolver->promise(); + ASSERT_FALSE(promise.isEmpty()); + String onFulfilled, onRejected; + promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); - m_resolver->resolve(ScriptValue(v8::Integer::New(3, m_isolate), m_isolate)); + m_resolver->resolve("hello"); + EXPECT_TRUE(m_resolver->promise().isEmpty()); + isolate()->RunMicrotasks(); - EXPECT_FALSE(m_resolver->isPending()); - EXPECT_EQ(V8PromiseCustom::Fulfilled, state()); - ASSERT_TRUE(result()->IsNumber()); - EXPECT_EQ(3, result().As<v8::Integer>()->Value()); + EXPECT_EQ("hello", onFulfilled); + EXPECT_EQ(String(), onRejected); } TEST_F(ScriptPromiseResolverTest, reject) { - EXPECT_TRUE(m_resolver->isPending()); - EXPECT_EQ(V8PromiseCustom::Pending, state()); - EXPECT_TRUE(result()->IsUndefined()); + ScriptPromise promise = m_resolver->promise(); + ASSERT_FALSE(promise.isEmpty()); + String onFulfilled, onRejected; + promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); - m_resolver->reject(ScriptValue(v8::Integer::New(3, m_isolate), m_isolate)); + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); - EXPECT_FALSE(m_resolver->isPending()); - EXPECT_EQ(V8PromiseCustom::Rejected, state()); - ASSERT_TRUE(result()->IsNumber()); - EXPECT_EQ(3, result().As<v8::Integer>()->Value()); + m_resolver->reject("hello"); + EXPECT_TRUE(m_resolver->promise().isEmpty()); + isolate()->RunMicrotasks(); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ("hello", onRejected); } TEST_F(ScriptPromiseResolverTest, resolveOverResolve) { - EXPECT_TRUE(m_resolver->isPending()); - EXPECT_EQ(V8PromiseCustom::Pending, state()); - EXPECT_TRUE(result()->IsUndefined()); - - m_resolver->resolve(ScriptValue(v8::Integer::New(3, m_isolate), m_isolate)); - - EXPECT_FALSE(m_resolver->isPending()); - EXPECT_EQ(V8PromiseCustom::Fulfilled, state()); - ASSERT_TRUE(result()->IsNumber()); - EXPECT_EQ(3, result().As<v8::Integer>()->Value()); - - m_resolver->resolve(ScriptValue(v8::Integer::New(4, m_isolate), m_isolate)); - EXPECT_FALSE(m_resolver->isPending()); - EXPECT_EQ(V8PromiseCustom::Fulfilled, state()); - ASSERT_TRUE(result()->IsNumber()); - EXPECT_EQ(3, result().As<v8::Integer>()->Value()); + ScriptPromise promise = m_resolver->promise(); + ASSERT_FALSE(promise.isEmpty()); + String onFulfilled, onRejected; + promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); + + m_resolver->resolve("hello"); + EXPECT_TRUE(m_resolver->promise().isEmpty()); + isolate()->RunMicrotasks(); + + EXPECT_EQ("hello", onFulfilled); + EXPECT_EQ(String(), onRejected); + + m_resolver->resolve("world"); + isolate()->RunMicrotasks(); + + EXPECT_EQ("hello", onFulfilled); + EXPECT_EQ(String(), onRejected); } TEST_F(ScriptPromiseResolverTest, rejectOverResolve) { - EXPECT_TRUE(m_resolver->isPending()); - EXPECT_EQ(V8PromiseCustom::Pending, state()); - EXPECT_TRUE(result()->IsUndefined()); - - m_resolver->resolve(ScriptValue(v8::Integer::New(3, m_isolate), m_isolate)); - - EXPECT_FALSE(m_resolver->isPending()); - EXPECT_EQ(V8PromiseCustom::Fulfilled, state()); - ASSERT_TRUE(result()->IsNumber()); - EXPECT_EQ(3, result().As<v8::Integer>()->Value()); - - m_resolver->reject(ScriptValue(v8::Integer::New(4, m_isolate), m_isolate)); - EXPECT_FALSE(m_resolver->isPending()); - EXPECT_EQ(V8PromiseCustom::Fulfilled, state()); - ASSERT_TRUE(result()->IsNumber()); - EXPECT_EQ(3, result().As<v8::Integer>()->Value()); + ScriptPromise promise = m_resolver->promise(); + ASSERT_FALSE(promise.isEmpty()); + String onFulfilled, onRejected; + promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); + + m_resolver->resolve("hello"); + EXPECT_TRUE(m_resolver->promise().isEmpty()); + isolate()->RunMicrotasks(); + + EXPECT_EQ("hello", onFulfilled); + EXPECT_EQ(String(), onRejected); + + m_resolver->reject("world"); + isolate()->RunMicrotasks(); + + EXPECT_EQ("hello", onFulfilled); + EXPECT_EQ(String(), onRejected); } } // namespace diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolverWithContext.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolverWithContext.cpp new file mode 100644 index 00000000000..6cd7ab8b5ef --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolverWithContext.cpp @@ -0,0 +1,101 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "bindings/v8/ScriptPromiseResolverWithContext.h" + +#include "bindings/v8/V8RecursionScope.h" + +namespace WebCore { + +ScriptPromiseResolverWithContext::ScriptPromiseResolverWithContext(ScriptState* scriptState) + : ActiveDOMObject(scriptState->executionContext()) + , m_state(Pending) + , m_scriptState(scriptState) + , m_mode(Default) + , m_timer(this, &ScriptPromiseResolverWithContext::onTimerFired) + , m_resolver(ScriptPromiseResolver::create(m_scriptState.get())) +#if ASSERTION_ENABLED + , m_isPromiseCalled(false) +#endif +{ + if (executionContext()->activeDOMObjectsAreStopped()) + m_state = ResolvedOrRejected; +} + +void ScriptPromiseResolverWithContext::suspend() +{ + m_timer.stop(); +} + +void ScriptPromiseResolverWithContext::resume() +{ + if (m_state == Resolving || m_state == Rejecting) + m_timer.startOneShot(0, FROM_HERE); +} + +void ScriptPromiseResolverWithContext::stop() +{ + m_timer.stop(); + clear(); +} + +void ScriptPromiseResolverWithContext::keepAliveWhilePending() +{ + if (m_state == ResolvedOrRejected || m_mode == KeepAliveWhilePending) + return; + + // Keep |this| while the promise is Pending. + // deref() will be called in clear(). + m_mode = KeepAliveWhilePending; + ref(); +} + +void ScriptPromiseResolverWithContext::onTimerFired(Timer<ScriptPromiseResolverWithContext>*) +{ + ScriptState::Scope scope(m_scriptState.get()); + resolveOrRejectImmediately(); +} + +void ScriptPromiseResolverWithContext::resolveOrRejectImmediately() +{ + ASSERT(!executionContext()->activeDOMObjectsAreStopped()); + ASSERT(!executionContext()->activeDOMObjectsAreSuspended()); + { + // FIXME: The V8RecursionScope is only necessary to force microtask delivery for promises + // resolved or rejected in workers. It can be removed once worker threads run microtasks + // at the end of every task (rather than just the main thread). + V8RecursionScope scope(m_scriptState->isolate(), m_scriptState->executionContext()); + if (m_state == Resolving) { + m_resolver->resolve(m_value.newLocal(m_scriptState->isolate())); + } else { + ASSERT(m_state == Rejecting); + m_resolver->reject(m_value.newLocal(m_scriptState->isolate())); + } + } + clear(); +} + +void ScriptPromiseResolverWithContext::clear() +{ + if (m_state == ResolvedOrRejected) + return; + ResolutionState state = m_state; + m_state = ResolvedOrRejected; + m_resolver.clear(); + m_value.clear(); + if (m_mode == KeepAliveWhilePending) { + // |ref| was called in |keepAliveWhilePending|. + deref(); + } + // |this| may be deleted here, but it is safe to check |state| because + // it doesn't depend on |this|. When |this| is deleted, |state| can't be + // |Resolving| nor |Rejecting| and hence |this->deref()| can't be executed. + if (state == Resolving || state == Rejecting) { + // |ref| was called in |resolveOrReject|. + deref(); + } +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolverWithContext.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolverWithContext.h new file mode 100644 index 00000000000..729fb15beed --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseResolverWithContext.h @@ -0,0 +1,145 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef ScriptPromiseResolverWithContext_h +#define ScriptPromiseResolverWithContext_h + +#include "bindings/v8/ScopedPersistent.h" +#include "bindings/v8/ScriptPromise.h" +#include "bindings/v8/ScriptPromiseResolver.h" +#include "bindings/v8/ScriptState.h" +#include "bindings/v8/V8Binding.h" +#include "core/dom/ActiveDOMObject.h" +#include "core/dom/ExecutionContext.h" +#include "platform/Timer.h" +#include "wtf/RefCounted.h" +#include "wtf/Vector.h" +#include <v8.h> + +namespace WebCore { + +// This class wraps ScriptPromiseResolver and provides the following +// functionalities in addition to ScriptPromiseResolver's. +// - A ScriptPromiseResolverWithContext retains a ScriptState. A caller +// can call resolve or reject from outside of a V8 context. +// - This class is an ActiveDOMObject and keeps track of the associated +// ExecutionContext state. When the ExecutionContext is suspended, +// resolve or reject will be delayed. When it is stopped, resolve or reject +// will be ignored. +class ScriptPromiseResolverWithContext : public ActiveDOMObject, public RefCounted<ScriptPromiseResolverWithContext> { + WTF_MAKE_NONCOPYABLE(ScriptPromiseResolverWithContext); + +public: + static PassRefPtr<ScriptPromiseResolverWithContext> create(ScriptState* scriptState) + { + RefPtr<ScriptPromiseResolverWithContext> resolver = adoptRef(new ScriptPromiseResolverWithContext(scriptState)); + resolver->suspendIfNeeded(); + return resolver.release(); + } + + virtual ~ScriptPromiseResolverWithContext() + { + // This assertion fails if: + // - promise() is called at least once and + // - this resolver is destructed before it is resolved, rejected or + // the associated ExecutionContext is stopped. + ASSERT(m_state == ResolvedOrRejected || !m_isPromiseCalled); + } + + // Anything that can be passed to toV8Value can be passed to this function. + template <typename T> + void resolve(T value) + { + resolveOrReject(value, Resolving); + } + + // Anything that can be passed to toV8Value can be passed to this function. + template <typename T> + void reject(T value) + { + resolveOrReject(value, Rejecting); + } + + ScriptState* scriptState() { return m_scriptState.get(); } + + // Note that an empty ScriptPromise will be returned after resolve or + // reject is called. + ScriptPromise promise() + { +#if ASSERT_ENABLED + m_isPromiseCalled = true; +#endif + return m_resolver ? m_resolver->promise() : ScriptPromise(); + } + + ScriptState* scriptState() const { return m_scriptState.get(); } + + // ActiveDOMObject implementation. + virtual void suspend() OVERRIDE; + virtual void resume() OVERRIDE; + virtual void stop() OVERRIDE; + + // Once this function is called this resolver stays alive while the + // promise is pending and the associated ExecutionContext isn't stopped. + void keepAliveWhilePending(); + +protected: + // You need to call suspendIfNeeded after the construction because + // this is an ActiveDOMObject. + explicit ScriptPromiseResolverWithContext(ScriptState*); + +private: + enum ResolutionState { + Pending, + Resolving, + Rejecting, + ResolvedOrRejected, + }; + enum LifetimeMode { + Default, + KeepAliveWhilePending, + }; + + template<typename T> + v8::Handle<v8::Value> toV8Value(const T& value) + { + return ToV8Value<ScriptPromiseResolverWithContext, v8::Handle<v8::Object> >::toV8Value(value, m_scriptState->context()->Global(), m_scriptState->isolate()); + } + + template <typename T> + void resolveOrReject(T value, ResolutionState newState) + { + if (m_state != Pending || !executionContext() || executionContext()->activeDOMObjectsAreStopped()) + return; + ASSERT(newState == Resolving || newState == Rejecting); + m_state = newState; + // Retain this object until it is actually resolved or rejected. + // |deref| will be called in |clear|. + ref(); + + ScriptState::Scope scope(m_scriptState.get()); + m_value.set(m_scriptState->isolate(), toV8Value(value)); + if (!executionContext()->activeDOMObjectsAreSuspended()) + resolveOrRejectImmediately(); + } + + void resolveOrRejectImmediately(); + void onTimerFired(Timer<ScriptPromiseResolverWithContext>*); + void clear(); + + ResolutionState m_state; + const RefPtr<ScriptState> m_scriptState; + LifetimeMode m_mode; + Timer<ScriptPromiseResolverWithContext> m_timer; + RefPtr<ScriptPromiseResolver> m_resolver; + ScopedPersistent<v8::Value> m_value; +#if ASSERT_ENABLED + // True if promise() is called. + bool m_isPromiseCalled; +#endif +}; + +} // namespace WebCore + +#endif // #ifndef ScriptPromiseResolverWithContext_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseTest.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseTest.cpp new file mode 100644 index 00000000000..618b38ea91b --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptPromiseTest.cpp @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2014 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 "bindings/v8/ScriptPromise.h" + +#include "bindings/v8/ScriptFunction.h" +#include "bindings/v8/ScriptPromiseResolver.h" +#include "bindings/v8/ScriptValue.h" +#include "bindings/v8/V8Binding.h" +#include "core/dom/DOMException.h" +#include "core/dom/ExceptionCode.h" + +#include <gtest/gtest.h> +#include <v8.h> + +namespace WebCore { + +namespace { + +void callback(const v8::FunctionCallbackInfo<v8::Value>& info) { } + +class Function : public ScriptFunction { +public: + static PassOwnPtr<Function> create(v8::Isolate* isolate, String* value) + { + return adoptPtr(new Function(isolate, value)); + } + + virtual ScriptValue call(ScriptValue value) OVERRIDE + { + ASSERT(!value.isEmpty()); + *m_value = toCoreString(value.v8Value()->ToString()); + return value; + } + +private: + Function(v8::Isolate* isolate, String* value) : ScriptFunction(isolate), m_value(value) { } + + String* m_value; +}; + +class ScriptPromiseTest : public testing::Test { +public: + ScriptPromiseTest() + : m_scope(v8::Isolate::GetCurrent()) + { + } + + ~ScriptPromiseTest() + { + // FIXME: We put this statement here to clear an exception from the isolate. + createClosure(callback, v8::Undefined(m_scope.isolate()), m_scope.isolate()); + + // Execute all pending microtasks + isolate()->RunMicrotasks(); + } + + ScriptState* scriptState() const { return m_scope.scriptState(); } + v8::Isolate* isolate() const { return m_scope.isolate(); } + +protected: + V8TestingScope m_scope; +}; + +TEST_F(ScriptPromiseTest, constructFromNonPromise) +{ + v8::TryCatch trycatch; + ScriptPromise promise(scriptState(), v8::Undefined(isolate())); + ASSERT_TRUE(trycatch.HasCaught()); + ASSERT_TRUE(promise.isEmpty()); +} + +TEST_F(ScriptPromiseTest, thenResolve) +{ + RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState()); + ScriptPromise promise = resolver->promise(); + String onFulfilled, onRejected; + promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); + + ASSERT_FALSE(promise.isEmpty()); + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); + + isolate()->RunMicrotasks(); + resolver->resolve("hello"); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); + + isolate()->RunMicrotasks(); + + EXPECT_EQ("hello", onFulfilled); + EXPECT_EQ(String(), onRejected); +} + +TEST_F(ScriptPromiseTest, resolveThen) +{ + RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState()); + ScriptPromise promise = resolver->promise(); + String onFulfilled, onRejected; + resolver->resolve("hello"); + promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); + + ASSERT_FALSE(promise.isEmpty()); + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); + + isolate()->RunMicrotasks(); + + EXPECT_EQ("hello", onFulfilled); + EXPECT_EQ(String(), onRejected); +} + +TEST_F(ScriptPromiseTest, thenReject) +{ + RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState()); + ScriptPromise promise = resolver->promise(); + String onFulfilled, onRejected; + promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); + + ASSERT_FALSE(promise.isEmpty()); + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); + + isolate()->RunMicrotasks(); + resolver->reject("hello"); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); + + isolate()->RunMicrotasks(); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ("hello", onRejected); +} + +TEST_F(ScriptPromiseTest, rejectThen) +{ + RefPtr<ScriptPromiseResolver> resolver = ScriptPromiseResolver::create(scriptState()); + ScriptPromise promise = resolver->promise(); + String onFulfilled, onRejected; + resolver->reject("hello"); + promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); + + ASSERT_FALSE(promise.isEmpty()); + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); + + isolate()->RunMicrotasks(); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ("hello", onRejected); +} + +TEST_F(ScriptPromiseTest, castPromise) +{ + ScriptPromise promise = ScriptPromiseResolver::create(scriptState())->promise(); + ScriptPromise newPromise = ScriptPromise::cast(scriptState(), promise.v8Value()); + + ASSERT_FALSE(promise.isEmpty()); + EXPECT_EQ(promise.v8Value(), newPromise.v8Value()); +} + +TEST_F(ScriptPromiseTest, castNonPromise) +{ + String onFulfilled1, onFulfilled2, onRejected1, onRejected2; + + ScriptValue value = ScriptValue(scriptState(), v8String(isolate(), "hello")); + ScriptPromise promise1 = ScriptPromise::cast(scriptState(), ScriptValue(value)); + ScriptPromise promise2 = ScriptPromise::cast(scriptState(), ScriptValue(value)); + promise1.then(Function::create(isolate(), &onFulfilled1), Function::create(isolate(), &onRejected1)); + promise2.then(Function::create(isolate(), &onFulfilled2), Function::create(isolate(), &onRejected2)); + + ASSERT_FALSE(promise1.isEmpty()); + ASSERT_FALSE(promise2.isEmpty()); + EXPECT_NE(promise1.v8Value(), promise2.v8Value()); + + ASSERT_TRUE(promise1.v8Value()->IsPromise()); + ASSERT_TRUE(promise2.v8Value()->IsPromise()); + + EXPECT_EQ(String(), onFulfilled1); + EXPECT_EQ(String(), onFulfilled2); + EXPECT_EQ(String(), onRejected1); + EXPECT_EQ(String(), onRejected2); + + isolate()->RunMicrotasks(); + + EXPECT_EQ("hello", onFulfilled1); + EXPECT_EQ("hello", onFulfilled2); + EXPECT_EQ(String(), onRejected1); + EXPECT_EQ(String(), onRejected2); +} + +TEST_F(ScriptPromiseTest, reject) +{ + String onFulfilled, onRejected; + + ScriptValue value = ScriptValue(scriptState(), v8String(isolate(), "hello")); + ScriptPromise promise = ScriptPromise::reject(scriptState(), ScriptValue(value)); + promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); + + ASSERT_FALSE(promise.isEmpty()); + ASSERT_TRUE(promise.v8Value()->IsPromise()); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); + + isolate()->RunMicrotasks(); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ("hello", onRejected); +} + +TEST_F(ScriptPromiseTest, rejectWithExceptionState) +{ + String onFulfilled, onRejected; + ScriptPromise promise = ScriptPromise::rejectWithDOMException(scriptState(), DOMException::create(SyntaxError, "some syntax error")); + promise.then(Function::create(isolate(), &onFulfilled), Function::create(isolate(), &onRejected)); + + ASSERT_FALSE(promise.isEmpty()); + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ(String(), onRejected); + + isolate()->RunMicrotasks(); + + EXPECT_EQ(String(), onFulfilled); + EXPECT_EQ("SyntaxError: some syntax error", onRejected); +} + +} // namespace + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptRegexp.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptRegexp.cpp index d0be2a1ec28..b4e25188288 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptRegexp.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptRegexp.cpp @@ -31,7 +31,8 @@ #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8PerIsolateData.h" -#include "bindings/v8/V8RecursionScope.h" +#include "bindings/v8/V8ScriptRunner.h" +#include "core/dom/ScriptForbiddenScope.h" namespace WebCore { @@ -39,8 +40,8 @@ ScriptRegexp::ScriptRegexp(const String& pattern, TextCaseSensitivity caseSensit { v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::HandleScope handleScope(isolate); - v8::Local<v8::Context> context = V8PerIsolateData::from(isolate)->ensureRegexContext(); - v8::Context::Scope scope(context); + v8::Context::Scope contextScope(V8PerIsolateData::from(isolate)->ensureScriptRegexpContext()); + v8::TryCatch tryCatch; unsigned flags = v8::RegExp::kNone; if (caseSensitivity == TextCaseInsensitive) @@ -48,8 +49,7 @@ ScriptRegexp::ScriptRegexp(const String& pattern, TextCaseSensitivity caseSensit if (multilineMode == MultilineEnabled) flags |= v8::RegExp::kMultiline; - v8::TryCatch tryCatch; - v8::Local<v8::RegExp> regex = v8::RegExp::New(v8String(context->GetIsolate(), pattern), static_cast<v8::RegExp::Flags>(flags)); + v8::Local<v8::RegExp> regex = v8::RegExp::New(v8String(isolate, pattern), static_cast<v8::RegExp::Flags>(flags)); // If the regex failed to compile we'll get an empty handle. if (!regex.IsEmpty()) @@ -68,19 +68,20 @@ int ScriptRegexp::match(const String& string, int startFrom, int* matchLength) c if (string.length() > INT_MAX) return -1; + ScriptForbiddenScope::AllowUserAgentScript allowScript; + v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::HandleScope handleScope(isolate); - v8::Local<v8::Context> context = V8PerIsolateData::current()->ensureRegexContext(); - v8::Context::Scope scope(context); + v8::Context::Scope contextScope(V8PerIsolateData::from(isolate)->ensureScriptRegexpContext()); v8::TryCatch tryCatch; - V8RecursionScope::MicrotaskSuppression microtaskScope; - v8::Local<v8::RegExp> regex = m_regex.newLocal(isolate); v8::Local<v8::Function> exec = regex->Get(v8AtomicString(isolate, "exec")).As<v8::Function>(); + v8::Handle<v8::Value> argv[] = { v8String(isolate, string.substring(startFrom)) }; + v8::Local<v8::Value> returnValue = V8ScriptRunner::callInternalFunction(exec, regex, WTF_ARRAY_LENGTH(argv), argv, isolate); - v8::Handle<v8::Value> argv[] = { v8String(context->GetIsolate(), string.substring(startFrom)) }; - v8::Local<v8::Value> returnValue = exec->Call(regex, 1, argv); + if (tryCatch.HasCaught()) + return -1; // RegExp#exec returns null if there's no match, otherwise it returns an // Array of strings with the first being the whole match string and others @@ -89,12 +90,12 @@ int ScriptRegexp::match(const String& string, int startFrom, int* matchLength) c // // https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/RegExp/exec + ASSERT(!returnValue.IsEmpty()); if (!returnValue->IsArray()) return -1; v8::Local<v8::Array> result = returnValue.As<v8::Array>(); int matchOffset = result->Get(v8AtomicString(isolate, "index"))->ToInt32()->Value(); - if (matchLength) { v8::Local<v8::String> match = result->Get(0).As<v8::String>(); *matchLength = match->Length(); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptScope.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptScope.cpp deleted file mode 100644 index 70815114cae..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptScope.cpp +++ /dev/null @@ -1,58 +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" -#include "bindings/v8/ScriptScope.h" - -#include "bindings/v8/ScriptState.h" -#include "wtf/Assertions.h" - -#include <v8.h> - -namespace WebCore { - -ScriptScope::ScriptScope(ScriptState* scriptState, bool reportExceptions) - : m_handleScope(scriptState->isolate()) - , m_context(scriptState->context()) - , m_scope(m_context) -{ - m_exceptionCatcher.SetVerbose(reportExceptions); - ASSERT(!m_context.IsEmpty()); -} - -bool ScriptScope::success() -{ - if (!m_exceptionCatcher.HasCaught()) - return true; - m_exceptionCatcher.Reset(); - return false; -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptScope.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptScope.h deleted file mode 100644 index ed2cf2f2e87..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptScope.h +++ /dev/null @@ -1,55 +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 ScriptScope_h -#define ScriptScope_h - -#include <v8.h> - -namespace WebCore { - class ScriptState; - - class ScriptScope { - public: - ScriptScope(ScriptState* scriptState, bool reportExceptions = true); - bool success(); - - v8::Local<v8::Object> global() const { return m_context->Global(); } - - private: - v8::HandleScope m_handleScope; - v8::Local<v8::Context> m_context; - v8::Context::Scope m_scope; - v8::TryCatch m_exceptionCatcher; - }; - -} - -#endif // ScriptScope_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptSourceCode.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptSourceCode.h index d5ddbccd082..92944bd9064 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptSourceCode.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptSourceCode.h @@ -38,8 +38,6 @@ #include "wtf/text/TextPosition.h" #include "wtf/text/WTFString.h" -#include <v8.h> - namespace WebCore { class ScriptSourceCode { diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptState.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptState.cpp index 0eda05f2ce6..5e17e4c6da8 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptState.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptState.cpp @@ -1,126 +1,114 @@ -/* - * 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. - */ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. #include "config.h" #include "bindings/v8/ScriptState.h" -#include "V8Window.h" -#include "V8WorkerGlobalScope.h" -#include "bindings/v8/ScriptController.h" -#include "bindings/v8/V8HiddenPropertyName.h" -#include "bindings/v8/WorkerScriptController.h" -#include "core/frame/Frame.h" -#include "core/workers/WorkerGlobalScope.h" -#include <v8.h> -#include "wtf/Assertions.h" +#include "bindings/v8/V8Binding.h" +#include "core/dom/ExecutionContext.h" +#include "core/frame/LocalFrame.h" namespace WebCore { -ScriptState::ScriptState(v8::Handle<v8::Context> context) - : m_context(context->GetIsolate(), context) - , m_isolate(context->GetIsolate()) +PassRefPtr<ScriptState> ScriptState::create(v8::Handle<v8::Context> context, PassRefPtr<DOMWrapperWorld> world) { - m_context.setWeak(this, &setWeakCallback); + RefPtr<ScriptState> scriptState = adoptRef(new ScriptState(context, world)); + // This ref() is for keeping this ScriptState alive as long as the v8::Context is alive. + // This is deref()ed in the weak callback of the v8::Context. + scriptState->ref(); + return scriptState; +} + +static void weakCallback(const v8::WeakCallbackData<v8::Context, ScriptState>& data) +{ + data.GetValue()->SetAlignedPointerInEmbedderData(v8ContextPerContextDataIndex, 0); + data.GetParameter()->clearContext(); + data.GetParameter()->deref(); +} + +ScriptState::ScriptState(v8::Handle<v8::Context> context, PassRefPtr<DOMWrapperWorld> world) + : m_isolate(context->GetIsolate()) + , m_context(m_isolate, context) + , m_world(world) + , m_perContextData(V8PerContextData::create(context)) +{ + ASSERT(m_world); + m_context.setWeak(this, &weakCallback); + context->SetAlignedPointerInEmbedderData(v8ContextPerContextDataIndex, this); } ScriptState::~ScriptState() { + ASSERT(!m_perContextData); + ASSERT(m_context.isEmpty()); } -DOMWindow* ScriptState::domWindow() const +bool ScriptState::evalEnabled() const { v8::HandleScope handleScope(m_isolate); - return toDOMWindow(m_context.newLocal(m_isolate)); + return context()->IsCodeGenerationFromStringsAllowed(); } -ExecutionContext* ScriptState::executionContext() const +void ScriptState::setEvalEnabled(bool enabled) { v8::HandleScope handleScope(m_isolate); - return toExecutionContext(m_context.newLocal(m_isolate)); + return context()->AllowCodeGenerationFromStrings(enabled); } -ScriptState* ScriptState::forContext(v8::Handle<v8::Context> context) +ScriptValue ScriptState::getFromGlobalObject(const char* name) { - v8::Context::Scope contextScope(context); - - v8::Local<v8::Object> innerGlobal = v8::Local<v8::Object>::Cast(context->Global()->GetPrototype()); - - v8::Local<v8::Value> scriptStateWrapper = innerGlobal->GetHiddenValue(V8HiddenPropertyName::scriptState(context->GetIsolate())); - if (!scriptStateWrapper.IsEmpty() && scriptStateWrapper->IsExternal()) - return static_cast<ScriptState*>(v8::External::Cast(*scriptStateWrapper)->Value()); + v8::HandleScope handleScope(m_isolate); + v8::Local<v8::Value> v8Value = context()->Global()->Get(v8AtomicString(isolate(), name)); + return ScriptValue(this, v8Value); +} - ScriptState* scriptState = new ScriptState(context); - innerGlobal->SetHiddenValue(V8HiddenPropertyName::scriptState(context->GetIsolate()), v8::External::New(context->GetIsolate(), scriptState)); - return scriptState; +ExecutionContext* ScriptState::executionContext() const +{ + v8::HandleScope scope(m_isolate); + return toExecutionContext(context()); } -ScriptState* ScriptState::current() +void ScriptState::setExecutionContext(ExecutionContext*) { - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::HandleScope handleScope(isolate); - v8::Local<v8::Context> context = isolate->GetCurrentContext(); - ASSERT(!context.IsEmpty()); - return ScriptState::forContext(context); + ASSERT_NOT_REACHED(); } -void ScriptState::setWeakCallback(const v8::WeakCallbackData<v8::Context, ScriptState>& data) +LocalDOMWindow* ScriptState::domWindow() const { - delete data.GetParameter(); + v8::HandleScope scope(m_isolate); + return toDOMWindow(context()); } -bool ScriptState::evalEnabled() const +ScriptState* ScriptState::forMainWorld(LocalFrame* frame) { - v8::HandleScope handleScope(m_isolate); - return context()->IsCodeGenerationFromStringsAllowed(); + v8::Isolate* isolate = toIsolate(frame); + v8::HandleScope handleScope(isolate); + return ScriptState::from(toV8Context(frame, DOMWrapperWorld::mainWorld())); } -void ScriptState::setEvalEnabled(bool enabled) +PassRefPtr<ScriptStateForTesting> ScriptStateForTesting::create(v8::Handle<v8::Context> context, PassRefPtr<DOMWrapperWorld> world) { - v8::HandleScope handleScope(m_isolate); - return context()->AllowCodeGenerationFromStrings(enabled); + RefPtr<ScriptStateForTesting> scriptState = adoptRef(new ScriptStateForTesting(context, world)); + // This ref() is for keeping this ScriptState alive as long as the v8::Context is alive. + // This is deref()ed in the weak callback of the v8::Context. + scriptState->ref(); + return scriptState; } -ScriptState* mainWorldScriptState(Frame* frame) +ScriptStateForTesting::ScriptStateForTesting(v8::Handle<v8::Context> context, PassRefPtr<DOMWrapperWorld> world) + : ScriptState(context, world) { - v8::HandleScope handleScope(toIsolate(frame)); - return ScriptState::forContext(frame->script().mainWorldContext()); } -ScriptState* scriptStateFromWorkerGlobalScope(WorkerGlobalScope* workerGlobalScope) +ExecutionContext* ScriptStateForTesting::executionContext() const { - WorkerScriptController* script = workerGlobalScope->script(); - if (!script) - return 0; + return m_executionContext; +} - v8::HandleScope handleScope(script->isolate()); - return ScriptState::forContext(script->context()); +void ScriptStateForTesting::setExecutionContext(ExecutionContext* executionContext) +{ + m_executionContext = executionContext; } } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptState.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptState.h index ac93b551167..81bc5840070 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptState.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptState.h @@ -1,130 +1,145 @@ -/* - * Copyright (C) 2008, 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. - */ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. #ifndef ScriptState_h #define ScriptState_h #include "bindings/v8/ScopedPersistent.h" -#include "bindings/v8/V8Utilities.h" +#include "bindings/v8/V8PerContextData.h" +#include "wtf/RefCounted.h" #include <v8.h> -#include "wtf/Noncopyable.h" namespace WebCore { -class DOMWindow; +class LocalDOMWindow; class DOMWrapperWorld; -class Frame; class ExecutionContext; -class WorkerGlobalScope; +class LocalFrame; +class ScriptValue; -class ScriptState { +// ScriptState is created when v8::Context is created. +// ScriptState is destroyed when v8::Context is garbage-collected and +// all V8 proxy objects that have references to the ScriptState are destructed. +class ScriptState : public RefCounted<ScriptState> { WTF_MAKE_NONCOPYABLE(ScriptState); public: - bool hadException() { return !m_exception.isEmpty(); } - void setException(v8::Local<v8::Value> exception) + class Scope { + public: + // You need to make sure that scriptState->context() is not empty before creating a Scope. + explicit Scope(ScriptState* scriptState) + : m_handleScope(scriptState->isolate()) + , m_context(scriptState->context()) + { + ASSERT(!m_context.IsEmpty()); + m_context->Enter(); + } + + ~Scope() + { + m_context->Exit(); + } + + private: + v8::HandleScope m_handleScope; + v8::Handle<v8::Context> m_context; + }; + + static PassRefPtr<ScriptState> create(v8::Handle<v8::Context>, PassRefPtr<DOMWrapperWorld>); + virtual ~ScriptState(); + + static ScriptState* current(v8::Isolate* isolate) { - m_exception.set(m_isolate, exception); + return from(isolate->GetCurrentContext()); } - v8::Local<v8::Value> exception() { return m_exception.newLocal(m_isolate); } - void clearException() { m_exception.clear(); } - v8::Local<v8::Context> context() const + static ScriptState* from(v8::Handle<v8::Context> context) { - return m_context.newLocal(m_isolate); + ASSERT(!context.IsEmpty()); + ScriptState* scriptState = static_cast<ScriptState*>(context->GetAlignedPointerFromEmbedderData(v8ContextPerContextDataIndex)); + // ScriptState::from() must not be called for a context that does not have + // valid embedder data in the embedder field. + RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(scriptState); + RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(scriptState->context() == context); + return scriptState; } - v8::Isolate* isolate() - { - return m_isolate; - } + static ScriptState* forMainWorld(LocalFrame*); + + v8::Isolate* isolate() const { return m_isolate; } + DOMWrapperWorld& world() const { return *m_world; } + LocalDOMWindow* domWindow() const; + virtual ExecutionContext* executionContext() const; + virtual void setExecutionContext(ExecutionContext*); + + // This can return an empty handle if the v8::Context is gone. + v8::Handle<v8::Context> context() const { return m_context.newLocal(m_isolate); } + bool contextIsEmpty() const { return m_context.isEmpty(); } + void clearContext() { return m_context.clear(); } + + V8PerContextData* perContextData() const { return m_perContextData.get(); } + void disposePerContextData() { m_perContextData = nullptr; } - DOMWindow* domWindow() const; - ExecutionContext* executionContext() const; bool evalEnabled() const; void setEvalEnabled(bool); - - static ScriptState* forContext(v8::Handle<v8::Context>); - static ScriptState* current(); + ScriptValue getFromGlobalObject(const char* name); protected: - ScriptState() - : m_isolate(v8::Isolate::GetCurrent()) - { - } - - ~ScriptState(); + ScriptState(v8::Handle<v8::Context>, PassRefPtr<DOMWrapperWorld>); private: - friend ScriptState* mainWorldScriptState(Frame*); - explicit ScriptState(v8::Handle<v8::Context>); + v8::Isolate* m_isolate; + // This persistent handle is weak. + ScopedPersistent<v8::Context> m_context; - static void setWeakCallback(const v8::WeakCallbackData<v8::Context, ScriptState>&); + // This RefPtr doesn't cause a cycle because all persistent handles that DOMWrapperWorld holds are weak. + RefPtr<DOMWrapperWorld> m_world; - ScopedPersistent<v8::Value> m_exception; - ScopedPersistent<v8::Context> m_context; - v8::Isolate* m_isolate; + // This OwnPtr causes a cycle: + // V8PerContextData --(Persistent)--> v8::Context --(RefPtr)--> ScriptState --(OwnPtr)--> V8PerContextData + // So you must explicitly clear the OwnPtr by calling disposePerContextData() + // once you no longer need V8PerContextData. Otherwise, the v8::Context will leak. + OwnPtr<V8PerContextData> m_perContextData; }; -class EmptyScriptState : public ScriptState { +class ScriptStateForTesting : public ScriptState { public: - EmptyScriptState() : ScriptState() { } - ~EmptyScriptState() { } + static PassRefPtr<ScriptStateForTesting> create(v8::Handle<v8::Context>, PassRefPtr<DOMWrapperWorld>); + + virtual ExecutionContext* executionContext() const OVERRIDE; + virtual void setExecutionContext(ExecutionContext*) OVERRIDE; + +private: + ScriptStateForTesting(v8::Handle<v8::Context>, PassRefPtr<DOMWrapperWorld>); + + ExecutionContext* m_executionContext; }; -class ScriptStateProtectedPtr { - WTF_MAKE_NONCOPYABLE(ScriptStateProtectedPtr); +// ScriptStateProtectingContext keeps the context associated with the ScriptState alive. +// You need to call clear() once you no longer need the context. Otherwise, the context will leak. +class ScriptStateProtectingContext { + WTF_MAKE_NONCOPYABLE(ScriptStateProtectingContext); public: - ScriptStateProtectedPtr() - : m_scriptState(0) + ScriptStateProtectingContext(ScriptState* scriptState) + : m_scriptState(scriptState) { + if (m_scriptState) + m_context.set(m_scriptState->isolate(), m_scriptState->context()); } - ScriptStateProtectedPtr(ScriptState* scriptState) - : m_scriptState(scriptState) + ScriptState* operator->() const { return m_scriptState.get(); } + ScriptState* get() const { return m_scriptState.get(); } + void clear() { - v8::HandleScope handleScope(scriptState->isolate()); - // Keep the context from being GC'ed. ScriptState is guaranteed to be live while the context is live. - m_context.set(scriptState->isolate(), scriptState->context()); + m_scriptState = nullptr; + m_context.clear(); } - ScriptState* get() const { return m_scriptState; } - private: - ScriptState* m_scriptState; + RefPtr<ScriptState> m_scriptState; ScopedPersistent<v8::Context> m_context; }; -ScriptState* mainWorldScriptState(Frame*); - -ScriptState* scriptStateFromWorkerGlobalScope(WorkerGlobalScope*); - } #endif // ScriptState_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptString.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptString.cpp index fe1ea3ecec2..aa75fde16ad 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptString.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptString.cpp @@ -31,26 +31,53 @@ #include "config.h" #include "bindings/v8/ScriptString.h" +#include "bindings/v8/V8Binding.h" + namespace WebCore { +ScriptString::ScriptString() + : m_isolate(0) +{ +} + +ScriptString::ScriptString(v8::Isolate* isolate, v8::Handle<v8::String> string) + : m_isolate(isolate) + , m_string(SharedPersistent<v8::String>::create(string, m_isolate)) +{ +} + +ScriptString& ScriptString::operator=(const ScriptString& string) +{ + if (this != &string) { + m_isolate = string.m_isolate; + m_string = string.m_string; + } + return *this; +} + +v8::Handle<v8::String> ScriptString::v8Value() +{ + if (isEmpty()) + return v8::Handle<v8::String>(); + return m_string->newLocal(isolate()); +} + ScriptString ScriptString::concatenateWith(const String& string) { v8::Isolate* nonNullIsolate = isolate(); v8::HandleScope handleScope(nonNullIsolate); - v8::Handle<v8::String> b = v8String(nonNullIsolate, string); - if (hasNoValue()) - return ScriptString(b, nonNullIsolate); - v8::Handle<v8::String> a = v8::Handle<v8::String>::Cast(v8Value()); - return ScriptString(v8::String::Concat(a, b), nonNullIsolate); + v8::Handle<v8::String> targetString = v8String(nonNullIsolate, string); + if (isEmpty()) + return ScriptString(nonNullIsolate, targetString); + return ScriptString(nonNullIsolate, v8::String::Concat(v8Value(), targetString)); } -String ScriptString::flattenToString() const +String ScriptString::flattenToString() { - if (hasNoValue()) + if (isEmpty()) return String(); v8::HandleScope handleScope(isolate()); - v8::Handle<v8::String> value = v8::Handle<v8::String>::Cast(v8Value()); - return v8StringToWebCoreString<String>(value, Externalize); + return v8StringToWebCoreString<String>(v8Value(), Externalize); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptString.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptString.h index ed493f8bf48..2638f44836d 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptString.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptString.h @@ -31,19 +31,34 @@ #ifndef ScriptString_h #define ScriptString_h -#include "bindings/v8/ScriptValue.h" -#include "bindings/v8/V8Binding.h" +#include "bindings/v8/SharedPersistent.h" +#include "wtf/RefPtr.h" #include "wtf/text/WTFString.h" +#include <v8.h> namespace WebCore { -class ScriptString : public ScriptValue { +class ScriptString FINAL { public: - ScriptString() { } - ScriptString(v8::Handle<v8::String> value, v8::Isolate* isolate) : ScriptValue(value, isolate) { } + ScriptString(); + ScriptString(v8::Isolate*, v8::Handle<v8::String>); + ScriptString& operator=(const ScriptString&); + v8::Isolate* isolate() + { + if (!m_isolate) + m_isolate = v8::Isolate::GetCurrent(); + return m_isolate; + } + bool isEmpty() const { return !m_string || m_string->isEmpty(); } + void clear() { m_string = nullptr; } + v8::Handle<v8::String> v8Value(); ScriptString concatenateWith(const String&); - String flattenToString() const; + String flattenToString(); + +private: + v8::Isolate* m_isolate; + RefPtr<SharedPersistent<v8::String> > m_string; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptValue.cpp b/chromium/third_party/WebKit/Source/bindings/v8/ScriptValue.cpp index 04b2287f9c2..bdfbe082258 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptValue.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptValue.cpp @@ -31,7 +31,6 @@ #include "config.h" #include "bindings/v8/ScriptValue.h" -#include "bindings/v8/ScriptScope.h" #include "bindings/v8/ScriptState.h" #include "bindings/v8/V8Binding.h" #include "platform/JSONValues.h" @@ -42,88 +41,41 @@ ScriptValue::~ScriptValue() { } -bool ScriptValue::getString(String& result) const +v8::Handle<v8::Value> ScriptValue::v8Value() const { - if (hasNoValue()) - return false; + if (isEmpty()) + return v8::Handle<v8::Value>(); - v8::HandleScope handleScope(m_isolate); - v8::Handle<v8::Value> string = v8Value(); - if (string.IsEmpty() || !string->IsString()) - return false; - result = toCoreString(string.As<v8::String>()); - return true; -} + ASSERT(isolate()->InContext()); -String ScriptValue::toString() const -{ - v8::TryCatch block; - v8::Handle<v8::String> string = v8Value()->ToString(); - if (block.HasCaught()) - return String(); - return v8StringToWebCoreString<String>(string, DoNotExternalize); + // This is a check to validate that you don't return a ScriptValue to a world different + // from the world that created the ScriptValue. + // Probably this could be: + // if (&m_scriptState->world() == &DOMWrapperWorld::current(isolate())) + // return v8::Handle<v8::Value>(); + // instead of triggering RELEASE_ASSERT. + RELEASE_ASSERT(&m_scriptState->world() == &DOMWrapperWorld::current(isolate())); + return m_value->newLocal(isolate()); } -static PassRefPtr<JSONValue> v8ToJSONValue(v8::Handle<v8::Value> value, int maxDepth, v8::Isolate* isolate) +bool ScriptValue::toString(String& result) const { - if (value.IsEmpty()) { - ASSERT_NOT_REACHED(); - return 0; - } - - if (!maxDepth) - return 0; - maxDepth--; + if (isEmpty()) + return false; - if (value->IsNull() || value->IsUndefined()) - return JSONValue::null(); - if (value->IsBoolean()) - return JSONBasicValue::create(value->BooleanValue()); - if (value->IsNumber()) - return JSONBasicValue::create(value->NumberValue()); - if (value->IsString()) - return JSONString::create(toCoreString(value.As<v8::String>())); - if (value->IsArray()) { - v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value); - RefPtr<JSONArray> inspectorArray = JSONArray::create(); - uint32_t length = array->Length(); - for (uint32_t i = 0; i < length; i++) { - v8::Local<v8::Value> value = array->Get(v8::Int32::New(i, isolate)); - RefPtr<JSONValue> element = v8ToJSONValue(value, maxDepth, isolate); - if (!element) - return 0; - inspectorArray->pushValue(element); - } - return inspectorArray; - } - if (value->IsObject()) { - RefPtr<JSONObject> jsonObject = JSONObject::create(); - v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); - v8::Local<v8::Array> propertyNames = object->GetPropertyNames(); - uint32_t length = propertyNames->Length(); - for (uint32_t i = 0; i < length; i++) { - v8::Local<v8::Value> name = propertyNames->Get(v8::Int32::New(i, isolate)); - // FIXME(yurys): v8::Object should support GetOwnPropertyNames - if (name->IsString() && !object->HasRealNamedProperty(v8::Handle<v8::String>::Cast(name))) - continue; - RefPtr<JSONValue> propertyValue = v8ToJSONValue(object->Get(name), maxDepth, isolate); - if (!propertyValue) - return 0; - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<WithNullCheck>, nameString, name, 0); - jsonObject->setValue(nameString, propertyValue); - } - return jsonObject; - } - ASSERT_NOT_REACHED(); - return 0; + ScriptState::Scope scope(m_scriptState.get()); + v8::Handle<v8::Value> string = v8Value(); + if (string.IsEmpty() || !string->IsString()) + return false; + result = toCoreString(v8::Handle<v8::String>::Cast(string)); + return true; } PassRefPtr<JSONValue> ScriptValue::toJSONValue(ScriptState* scriptState) const { - v8::HandleScope handleScope(scriptState->isolate()); - // v8::Object::GetPropertyNames() expects current context to be not null. - v8::Context::Scope contextScope(scriptState->context()); - return v8ToJSONValue(v8Value(), JSONValue::maxDepth, scriptState->isolate()); + ASSERT(!scriptState->contextIsEmpty()); + ScriptState::Scope scope(scriptState); + return v8ToJSONValue(scriptState->isolate(), v8Value(), JSONValue::maxDepth); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptValue.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptValue.h index 42b5fe7962b..41c76847987 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptValue.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptValue.h @@ -31,6 +31,7 @@ #ifndef ScriptValue_h #define ScriptValue_h +#include "bindings/v8/ScriptState.h" #include "bindings/v8/SharedPersistent.h" #include "wtf/PassRefPtr.h" #include "wtf/RefPtr.h" @@ -40,26 +41,36 @@ namespace WebCore { class JSONValue; -class ScriptState; class ScriptValue { public: ScriptValue() : m_isolate(0) - { } + , m_scriptState(nullptr) + { + } virtual ~ScriptValue(); - ScriptValue(v8::Handle<v8::Value> value, v8::Isolate* isolate) - : m_isolate(isolate) - , m_value(value.IsEmpty() ? 0 : SharedPersistent<v8::Value>::create(value, isolate)) + ScriptValue(ScriptState* scriptState, v8::Handle<v8::Value> value) + : m_isolate(scriptState->isolate()) + , m_scriptState(scriptState) + , m_value(value.IsEmpty() ? nullptr : SharedPersistent<v8::Value>::create(value, scriptState->isolate())) { + ASSERT(isEmpty() || m_scriptState); } ScriptValue(const ScriptValue& value) : m_isolate(value.m_isolate) + , m_scriptState(value.m_scriptState) , m_value(value.m_value) { + ASSERT(isEmpty() || m_scriptState); + } + + ScriptState* scriptState() const + { + return m_scriptState.get(); } v8::Isolate* isolate() const @@ -69,108 +80,80 @@ public: return m_isolate; } - static ScriptValue createUndefined(v8::Isolate* isolate) - { - return ScriptValue(v8::Undefined(isolate), isolate); - } - - static ScriptValue createNull() - { - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - return ScriptValue(v8::Null(isolate), isolate); - } - static ScriptValue createBoolean(bool b) - { - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - return ScriptValue(b ? v8::True(isolate) : v8::False(isolate), isolate); - } - ScriptValue& operator=(const ScriptValue& value) { if (this != &value) { - m_value = value.m_value; m_isolate = value.m_isolate; + m_scriptState = value.m_scriptState; + m_value = value.m_value; } return *this; } bool operator==(const ScriptValue& value) const { - if (hasNoValue()) - return value.hasNoValue(); - if (value.hasNoValue()) + if (isEmpty()) + return value.isEmpty(); + if (value.isEmpty()) return false; return *m_value == *value.m_value; } - bool isEqual(ScriptState*, const ScriptValue& value) const + bool operator!=(const ScriptValue& value) const { - return operator==(value); + return !operator==(value); } - // Note: This creates a new local Handle; not to be used in cases where is - // is an efficiency problem. + // This creates a new local Handle; Don't use this in performance-sensitive places. bool isFunction() const { - ASSERT(!hasNoValue()); + ASSERT(!isEmpty()); v8::Handle<v8::Value> value = v8Value(); return !value.IsEmpty() && value->IsFunction(); } - bool operator!=(const ScriptValue& value) const - { - return !operator==(value); - } - - // Note: This creates a new local Handle; not to be used in cases where is - // is an efficiency problem. + // This creates a new local Handle; Don't use this in performance-sensitive places. bool isNull() const { - ASSERT(!hasNoValue()); + ASSERT(!isEmpty()); v8::Handle<v8::Value> value = v8Value(); return !value.IsEmpty() && value->IsNull(); } - // Note: This creates a new local Handle; not to be used in cases where is - // is an efficiency problem. + // This creates a new local Handle; Don't use this in performance-sensitive places. bool isUndefined() const { - ASSERT(!hasNoValue()); + ASSERT(!isEmpty()); v8::Handle<v8::Value> value = v8Value(); return !value.IsEmpty() && value->IsUndefined(); } - // Note: This creates a new local Handle; not to be used in cases where is - // is an efficiency problem. + // This creates a new local Handle; Don't use this in performance-sensitive places. bool isObject() const { - ASSERT(!hasNoValue()); + ASSERT(!isEmpty()); v8::Handle<v8::Value> value = v8Value(); return !value.IsEmpty() && value->IsObject(); } - bool hasNoValue() const + bool isEmpty() const { return !m_value.get() || m_value->isEmpty(); } void clear() { - m_value = 0; - } - - v8::Handle<v8::Value> v8Value() const - { - return m_value.get() ? m_value->newLocal(m_isolate) : v8::Handle<v8::Value>(); + m_value = nullptr; } - bool getString(String& result) const; - String toString() const; + v8::Handle<v8::Value> v8Value() const; + bool toString(String&) const; PassRefPtr<JSONValue> toJSONValue(ScriptState*) const; private: mutable v8::Isolate* m_isolate; + mutable RefPtr<ScriptState> m_scriptState; RefPtr<SharedPersistent<v8::Value> > m_value; }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptWrappable.h b/chromium/third_party/WebKit/Source/bindings/v8/ScriptWrappable.h index 72ab761ee4f..c81fda0e6e1 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptWrappable.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/ScriptWrappable.h @@ -31,9 +31,8 @@ #ifndef ScriptWrappable_h #define ScriptWrappable_h -#include "bindings/v8/UnsafePersistent.h" -#include "bindings/v8/V8Utilities.h" #include "bindings/v8/WrapperTypeInfo.h" +#include "platform/heap/Handle.h" #include <v8.h> // Helper to call webCoreInitializeScriptWrappableForInterface in the global namespace. @@ -45,6 +44,35 @@ template <class C> inline void initializeScriptWrappableHelper(C* object) namespace WebCore { +/** + * ScriptWrappable wraps a V8 object and its WrapperTypeInfo. + * + * ScriptWrappable acts much like a v8::Persistent<> in that it keeps a + * V8 object alive. Under the hood, however, it keeps either a TypeInfo + * object or an actual v8 persistent (or is empty). + * + * The physical state space of ScriptWrappable is: + * - uintptr_t m_wrapperOrTypeInfo; + * - if 0: the ScriptWrappable is uninitialized/empty. + * - if even: a pointer to WebCore::TypeInfo + * - if odd: a pointer to v8::Persistent<v8::Object> + 1. + * + * In other words, one integer represents one of two object pointers, + * depending on its least signficiant bit, plus an uninitialized state. + * This class is meant to mask the logistics behind this. + * + * typeInfo() and newLocalWrapper will return appropriate values (possibly + * 0/empty) in all physical states. + * + * The state transitions are: + * - new: an empty and invalid ScriptWrappable. + * - init (to be called by all subclasses in their constructor): + * needs to call setTypeInfo + * - setTypeInfo: install a WrapperTypeInfo + * - setWrapper: install a v8::Persistent (or empty) + * - disposeWrapper (via setWeakCallback, triggered by V8 garbage collecter): + * remove v8::Persistent and install a TypeInfo of the previous value. + */ class ScriptWrappable { public: ScriptWrappable() : m_wrapperOrTypeInfo(0) { } @@ -77,7 +105,9 @@ public: v8::Local<v8::Object> newLocalWrapper(v8::Isolate* isolate) const { - return unsafePersistent().newLocal(isolate); + v8::Persistent<v8::Object> persistent; + getPersistent(&persistent); + return v8::Local<v8::Object>::New(isolate, persistent); } const WrapperTypeInfo* typeInfo() @@ -85,102 +115,134 @@ public: if (containsTypeInfo()) return reinterpret_cast<const WrapperTypeInfo*>(m_wrapperOrTypeInfo); - if (containsWrapper()) - return toWrapperTypeInfo(*(unsafePersistent().persistent())); + if (containsWrapper()) { + v8::Persistent<v8::Object> persistent; + getPersistent(&persistent); + return toWrapperTypeInfo(persistent); + } return 0; } - void setTypeInfo(const WrapperTypeInfo* info) + void setTypeInfo(const WrapperTypeInfo* typeInfo) { - m_wrapperOrTypeInfo = reinterpret_cast<uintptr_t>(info); + m_wrapperOrTypeInfo = reinterpret_cast<uintptr_t>(typeInfo); ASSERT(containsTypeInfo()); } + bool isEqualTo(const v8::Local<v8::Object>& other) const + { + v8::Persistent<v8::Object> persistent; + getPersistent(&persistent); + return persistent == other; + } + static bool wrapperCanBeStoredInObject(const void*) { return false; } static bool wrapperCanBeStoredInObject(const ScriptWrappable*) { return true; } - static void setWrapperInObject(void*, v8::Handle<v8::Object>, v8::Isolate*, const WrapperConfiguration&) + static ScriptWrappable* fromObject(const void*) { ASSERT_NOT_REACHED(); + return 0; } - static void setWrapperInObject(ScriptWrappable* object, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, const WrapperConfiguration& configuration) + static ScriptWrappable* fromObject(ScriptWrappable* object) { - object->setWrapper(wrapper, isolate, configuration); + return object; } - static const WrapperTypeInfo* getTypeInfoFromObject(void* object) + bool setReturnValue(v8::ReturnValue<v8::Value> returnValue) { - ASSERT_NOT_REACHED(); - return 0; + v8::Persistent<v8::Object> persistent; + getPersistent(&persistent); + returnValue.Set(persistent); + return containsWrapper(); } - static const WrapperTypeInfo* getTypeInfoFromObject(ScriptWrappable* object) + void markAsDependentGroup(ScriptWrappable* groupRoot, v8::Isolate* isolate) { - return object->typeInfo(); + ASSERT(containsWrapper()); + ASSERT(groupRoot && groupRoot->containsWrapper()); + + v8::UniqueId groupId(groupRoot->m_wrapperOrTypeInfo); + v8::Persistent<v8::Object> wrapper; + getPersistent(&wrapper); + wrapper.MarkPartiallyDependent(); + isolate->SetObjectGroupId(v8::Persistent<v8::Value>::Cast(wrapper), groupId); } - static void setTypeInfoInObject(void* object, const WrapperTypeInfo* info) + void setReference(const v8::Persistent<v8::Object>& parent, v8::Isolate* isolate) { - ASSERT_NOT_REACHED(); + v8::Persistent<v8::Object> persistent; + getPersistent(&persistent); + isolate->SetReference(parent, persistent); } - static void setTypeInfoInObject(ScriptWrappable* object, const WrapperTypeInfo* info) + template<typename V8T, typename T> + static void assertWrapperSanity(v8::Local<v8::Object> object, T* objectAsT) { - object->setTypeInfo(info); + ASSERT(objectAsT); + RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(object.IsEmpty() + || object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex) == V8T::toInternalPointer(objectAsT)); } template<typename V8T, typename T> - static bool setReturnValueWithSecurityCheck(v8::ReturnValue<v8::Value> returnValue, T* object) + static void assertWrapperSanity(void* object, T* objectAsT) { - return ScriptWrappable::getUnsafeWrapperFromObject(object).template setReturnValueWithSecurityCheck<V8T>(returnValue, object); + ASSERT_NOT_REACHED(); } - template<typename T> - static bool setReturnValue(v8::ReturnValue<v8::Value> returnValue, T* object) + template<typename V8T, typename T> + static void assertWrapperSanity(ScriptWrappable* object, T* objectAsT) { - return ScriptWrappable::getUnsafeWrapperFromObject(object).setReturnValue(returnValue); + ASSERT(object); + ASSERT(objectAsT); + v8::Object* value = object->getRawValue(); + RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(value == 0 + || value->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex) == V8T::toInternalPointer(objectAsT)); } + inline bool containsWrapper() const { return (m_wrapperOrTypeInfo & 1); } + inline bool containsTypeInfo() const { return m_wrapperOrTypeInfo && !(m_wrapperOrTypeInfo & 1); } + protected: ~ScriptWrappable() { - ASSERT(m_wrapperOrTypeInfo); // Assert initialization via init() even if not subsequently wrapped. - m_wrapperOrTypeInfo = 0; // Break UAF attempts to wrap. + // We must not get deleted as long as we contain a wrapper. If this happens, we screwed up ref + // counting somewhere. Crash here instead of crashing during a later gc cycle. + RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(!containsWrapper()); + ASSERT(m_wrapperOrTypeInfo); // Assert initialization via init() even if not subsequently wrapped. + m_wrapperOrTypeInfo = 0; // Break UAF attempts to wrap. } private: - // For calling unsafePersistent and getWrapperFromObject. - friend class MinorGCWrapperVisitor; - friend class DOMDataStore; - - UnsafePersistent<v8::Object> unsafePersistent() const + void getPersistent(v8::Persistent<v8::Object>* persistent) const { - v8::Object* object = containsWrapper() ? reinterpret_cast<v8::Object*>(m_wrapperOrTypeInfo & ~1) : 0; - return UnsafePersistent<v8::Object>(object); - } + ASSERT(persistent); - static UnsafePersistent<v8::Object> getUnsafeWrapperFromObject(void*) - { - ASSERT_NOT_REACHED(); - return UnsafePersistent<v8::Object>(); + // Horrible and super unsafe: Cast the Persistent to an Object*, so + // that we can inject the wrapped value. This only works because + // we previously 'stole' the object pointer from a Persistent in + // the setWrapper() method. + *reinterpret_cast<v8::Object**>(persistent) = getRawValue(); } - static UnsafePersistent<v8::Object> getUnsafeWrapperFromObject(ScriptWrappable* object) + inline v8::Object* getRawValue() const { - return object->unsafePersistent(); + v8::Object* object = containsWrapper() ? reinterpret_cast<v8::Object*>(m_wrapperOrTypeInfo & ~1) : 0; + return object; } - inline bool containsWrapper() const { return (m_wrapperOrTypeInfo & 1) == 1; } - inline bool containsTypeInfo() const { return m_wrapperOrTypeInfo && (m_wrapperOrTypeInfo & 1) == 0; } - - inline void disposeWrapper(v8::Local<v8::Object> value, const WrapperTypeInfo* info) + inline void disposeWrapper(v8::Local<v8::Object> wrapper) { ASSERT(containsWrapper()); - ASSERT(value == *unsafePersistent().persistent()); - unsafePersistent().dispose(); - setTypeInfo(info); + + v8::Persistent<v8::Object> persistent; + getPersistent(&persistent); + + ASSERT(wrapper == persistent); + persistent.Reset(); + setTypeInfo(toWrapperTypeInfo(wrapper)); } // If zero, then this contains nothing, otherwise: @@ -190,18 +252,15 @@ private: static void setWeakCallback(const v8::WeakCallbackData<v8::Object, ScriptWrappable>& data) { - ASSERT(*data.GetParameter()->unsafePersistent().persistent() == data.GetValue()); - - // Note: |object| might not be equal to |data|.GetParameter(), e.g., if ScriptWrappable isn't a left-most base class. - void* object = toNative(data.GetValue()); - const WrapperTypeInfo* info = toWrapperTypeInfo(data.GetValue()); - ASSERT(info->derefObjectFunction); + v8::Persistent<v8::Object> persistent; + data.GetParameter()->getPersistent(&persistent); + ASSERT(persistent == data.GetValue()); + data.GetParameter()->disposeWrapper(data.GetValue()); - data.GetParameter()->disposeWrapper(data.GetValue(), info); // FIXME: I noticed that 50%~ of minor GC cycle times can be consumed // inside data.GetParameter()->deref(), which causes Node destructions. We should // make Node destructions incremental. - info->derefObject(object); + releaseObject(data.GetValue()); } }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/SerializedScriptValue.cpp b/chromium/third_party/WebKit/Source/bindings/v8/SerializedScriptValue.cpp index 72f35602748..8da614f47cc 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/SerializedScriptValue.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/SerializedScriptValue.cpp @@ -31,16 +31,16 @@ #include "config.h" #include "bindings/v8/SerializedScriptValue.h" -#include "V8Blob.h" -#include "V8DOMFileSystem.h" -#include "V8File.h" -#include "V8FileList.h" -#include "V8ImageData.h" -#include "V8MessagePort.h" -#include "bindings/v8/ScriptScope.h" -#include "bindings/v8/ScriptState.h" +#include "bindings/core/v8/V8Blob.h" +#include "bindings/core/v8/V8File.h" +#include "bindings/core/v8/V8FileList.h" +#include "bindings/core/v8/V8ImageData.h" +#include "bindings/core/v8/V8MessagePort.h" +#include "bindings/modules/v8/V8DOMFileSystem.h" +#include "bindings/modules/v8/V8Key.h" +#include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" +#include "bindings/v8/WorkerScriptController.h" #include "bindings/v8/custom/V8ArrayBufferCustom.h" #include "bindings/v8/custom/V8ArrayBufferViewCustom.h" #include "bindings/v8/custom/V8DataViewCustom.h" @@ -61,6 +61,12 @@ #include "core/html/ImageData.h" #include "core/html/canvas/DataView.h" #include "platform/SharedBuffer.h" +#include "platform/heap/Handle.h" +#include "public/platform/Platform.h" +#include "public/platform/WebBlobInfo.h" +#include "public/platform/WebCrypto.h" +#include "public/platform/WebCryptoKey.h" +#include "public/platform/WebCryptoKeyAlgorithm.h" #include "wtf/ArrayBuffer.h" #include "wtf/ArrayBufferContents.h" #include "wtf/ArrayBufferView.h" @@ -133,6 +139,12 @@ private: // need to rehash after every garbage collection because a key object may have been moved. template<typename G> struct V8HandlePtrHash { + static v8::Handle<G> unsafeHandleFromRawValue(const G* value) + { + const v8::Handle<G>* handle = reinterpret_cast<const v8::Handle<G>*>(&value); + return *handle; + } + static unsigned hash(const G* key) { return static_cast<unsigned>(unsafeHandleFromRawValue(key)->GetIdentityHash()); @@ -186,10 +198,13 @@ enum SerializationTag { DateTag = 'D', // value:double -> Date (ref) MessagePortTag = 'M', // index:int -> MessagePort. Fills the result with transferred MessagePort. NumberTag = 'N', // value:double -> Number - BlobTag = 'b', // url:WebCoreString, type:WebCoreString, size:uint64_t -> Blob (ref) + BlobTag = 'b', // uuid:WebCoreString, type:WebCoreString, size:uint64_t -> Blob (ref) + BlobIndexTag = 'i', // index:int32_t -> Blob (ref) FileTag = 'f', // file:RawFile -> File (ref) - DOMFileSystemTag = 'd', // type:int32_t, name:WebCoreString, url:WebCoreString -> FileSystem (ref) + FileIndexTag = 'e', // index:int32_t -> File (ref) + DOMFileSystemTag = 'd', // type:int32_t, name:WebCoreString, uuid:WebCoreString -> FileSystem (ref) FileListTag = 'l', // length:uint32_t, files:RawFile[length] -> FileList (ref) + FileListIndexTag = 'L', // length:uint32_t, files:int32_t[length] -> FileList (ref) ImageDataTag = '#', // width:uint32_t, height:uint32_t, pixelDataLength:uint32_t, data:byte[pixelDataLength] -> ImageData (ref) ObjectTag = '{', // numProperties:uint32_t -> pops the last object from the open stack; // fills it with the last numProperties name,value pairs pushed onto the deserialization stack @@ -201,6 +216,13 @@ enum SerializationTag { ArrayBufferTag = 'B', // byteLength:uint32_t, data:byte[byteLength] -> ArrayBuffer (ref) ArrayBufferTransferTag = 't', // index:uint32_t -> ArrayBuffer. For ArrayBuffer transfer ArrayBufferViewTag = 'V', // subtag:byte, byteOffset:uint32_t, byteLength:uint32_t -> ArrayBufferView (ref). Consumes an ArrayBuffer from the top of the deserialization stack. + CryptoKeyTag = 'K', // subtag:byte, props, usages:uint32_t, keyDataLength:uint32_t, keyData:byte[keyDataLength] + // If subtag=AesKeyTag: + // props = keyLengthBytes:uint32_t, algorithmId:uint32_t + // If subtag=HmacKeyTag: + // props = keyLengthBytes:uint32_t, hashId:uint32_t + // If subtag=RsaHashedKeyTag: + // props = algorithmId:uint32_t, type:uint32_t, modulusLengthBits:uint32_t, publicExponentLength:uint32_t, publicExponent:byte[publicExponentLength], hashId:uint32_t ObjectReferenceTag = '^', // ref:uint32_t -> reference table[ref] GenerateFreshObjectTag = 'o', // -> empty object allocated an object ID and pushed onto the open stack (ref) GenerateFreshSparseArrayTag = 'a', // length:uint32_t -> empty array[length] allocated an object ID and pushed onto the open stack (ref) @@ -226,6 +248,52 @@ enum ArrayBufferViewSubTag { DataViewTag = '?' }; +enum CryptoKeySubTag { + AesKeyTag = 1, + HmacKeyTag = 2, + // ID 3 was used by RsaKeyTag, while still behind experimental flag. + RsaHashedKeyTag = 4, + // Maximum allowed value is 255 +}; + +enum AssymetricCryptoKeyType { + PublicKeyType = 1, + PrivateKeyType = 2, + // Maximum allowed value is 2^32-1 +}; + +enum CryptoKeyAlgorithmTag { + AesCbcTag = 1, + HmacTag = 2, + RsaSsaPkcs1v1_5Tag = 3, + // ID 4 was used by RsaEs, while still behind experimental flag. + Sha1Tag = 5, + Sha256Tag = 6, + Sha384Tag = 7, + Sha512Tag = 8, + AesGcmTag = 9, + RsaOaepTag = 10, + AesCtrTag = 11, + AesKwTag = 12, + // Maximum allowed value is 2^32-1 +}; + +enum CryptoKeyUsage { + // Extractability is not a "usage" in the WebCryptoKeyUsages sense, however + // it fits conveniently into this bitfield. + ExtractableUsage = 1 << 0, + + EncryptUsage = 1 << 1, + DecryptUsage = 1 << 2, + SignUsage = 1 << 3, + VerifyUsage = 1 << 4, + DeriveKeyUsage = 1 << 5, + WrapKeyUsage = 1 << 6, + UnwrapKeyUsage = 1 << 7, + DeriveBitsUsage = 1 << 8, + // Maximum allowed value is 1 << 31 +}; + static bool shouldCheckForCycles(int depth) { ASSERT(depth >= 0); @@ -272,9 +340,8 @@ private: class Writer { WTF_MAKE_NONCOPYABLE(Writer); public: - explicit Writer(v8::Isolate* isolate) + Writer() : m_position(0) - , m_isolate(isolate) { } @@ -392,6 +459,13 @@ public: doWriteUint64(size); } + void writeBlobIndex(int blobIndex) + { + ASSERT(blobIndex >= 0); + append(BlobIndexTag); + doWriteUint32(blobIndex); + } + void writeDOMFileSystem(int type, const String& name, const String& url) { append(DOMFileSystemTag); @@ -406,6 +480,12 @@ public: doWriteFile(file); } + void writeFileIndex(int blobIndex) + { + append(FileIndexTag); + doWriteUint32(blobIndex); + } + void writeFileList(const FileList& fileList) { append(FileListTag); @@ -415,6 +495,45 @@ public: doWriteFile(*fileList.item(i)); } + void writeFileListIndex(const Vector<int>& blobIndices) + { + append(FileListIndexTag); + uint32_t length = blobIndices.size(); + doWriteUint32(length); + for (unsigned i = 0; i < length; ++i) + doWriteUint32(blobIndices[i]); + } + + bool writeCryptoKey(const blink::WebCryptoKey& key) + { + append(static_cast<uint8_t>(CryptoKeyTag)); + + switch (key.algorithm().paramsType()) { + case blink::WebCryptoKeyAlgorithmParamsTypeAes: + doWriteAesKey(key); + break; + case blink::WebCryptoKeyAlgorithmParamsTypeHmac: + doWriteHmacKey(key); + break; + case blink::WebCryptoKeyAlgorithmParamsTypeRsaHashed: + doWriteRsaHashedKey(key); + break; + case blink::WebCryptoKeyAlgorithmParamsTypeNone: + ASSERT_NOT_REACHED(); + return false; + } + + doWriteKeyUsages(key.usages(), key.extractable()); + + blink::WebVector<uint8_t> keyData; + if (!blink::Platform::current()->crypto()->serializeKeyForClone(key, keyData)) + return false; + + doWriteUint32(keyData.size()); + append(keyData.data(), keyData.size()); + return true; + } + void writeArrayBuffer(const ArrayBuffer& arrayBuffer) { append(ArrayBufferTag); @@ -429,7 +548,7 @@ public: ASSERT(static_cast<const uint8_t*>(arrayBuffer.data()) + arrayBufferView.byteOffset() == static_cast<const uint8_t*>(arrayBufferView.baseAddress())); #endif - ArrayBufferView::ViewType type = arrayBufferView.getType(); + ArrayBufferView::ViewType type = arrayBufferView.type(); if (type == ArrayBufferView::TypeInt8) append(ByteArrayTag); @@ -544,8 +663,6 @@ public: doWriteUint32(length); } - v8::Isolate* getIsolate() { return m_isolate; } - private: void doWriteFile(const File& file) { @@ -588,6 +705,112 @@ private: doWriteString(stringUTF8.data(), stringUTF8.length()); } + void doWriteHmacKey(const blink::WebCryptoKey& key) + { + ASSERT(key.algorithm().paramsType() == blink::WebCryptoKeyAlgorithmParamsTypeHmac); + + append(static_cast<uint8_t>(HmacKeyTag)); + ASSERT(!(key.algorithm().hmacParams()->lengthBits() % 8)); + doWriteUint32(key.algorithm().hmacParams()->lengthBits() / 8); + doWriteAlgorithmId(key.algorithm().hmacParams()->hash().id()); + } + + void doWriteAesKey(const blink::WebCryptoKey& key) + { + ASSERT(key.algorithm().paramsType() == blink::WebCryptoKeyAlgorithmParamsTypeAes); + + append(static_cast<uint8_t>(AesKeyTag)); + doWriteAlgorithmId(key.algorithm().id()); + // Converting the key length from bits to bytes is lossless and makes + // it fit in 1 byte. + ASSERT(!(key.algorithm().aesParams()->lengthBits() % 8)); + doWriteUint32(key.algorithm().aesParams()->lengthBits() / 8); + } + + void doWriteRsaHashedKey(const blink::WebCryptoKey& key) + { + ASSERT(key.algorithm().rsaHashedParams()); + append(static_cast<uint8_t>(RsaHashedKeyTag)); + + doWriteAlgorithmId(key.algorithm().id()); + + switch (key.type()) { + case blink::WebCryptoKeyTypePublic: + doWriteUint32(PublicKeyType); + break; + case blink::WebCryptoKeyTypePrivate: + doWriteUint32(PrivateKeyType); + break; + case blink::WebCryptoKeyTypeSecret: + ASSERT_NOT_REACHED(); + } + + const blink::WebCryptoRsaHashedKeyAlgorithmParams* params = key.algorithm().rsaHashedParams(); + doWriteUint32(params->modulusLengthBits()); + doWriteUint32(params->publicExponent().size()); + append(params->publicExponent().data(), params->publicExponent().size()); + doWriteAlgorithmId(key.algorithm().rsaHashedParams()->hash().id()); + } + + void doWriteAlgorithmId(blink::WebCryptoAlgorithmId id) + { + switch (id) { + case blink::WebCryptoAlgorithmIdAesCbc: + return doWriteUint32(AesCbcTag); + case blink::WebCryptoAlgorithmIdHmac: + return doWriteUint32(HmacTag); + case blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5: + return doWriteUint32(RsaSsaPkcs1v1_5Tag); + case blink::WebCryptoAlgorithmIdSha1: + return doWriteUint32(Sha1Tag); + case blink::WebCryptoAlgorithmIdSha256: + return doWriteUint32(Sha256Tag); + case blink::WebCryptoAlgorithmIdSha384: + return doWriteUint32(Sha384Tag); + case blink::WebCryptoAlgorithmIdSha512: + return doWriteUint32(Sha512Tag); + case blink::WebCryptoAlgorithmIdAesGcm: + return doWriteUint32(AesGcmTag); + case blink::WebCryptoAlgorithmIdRsaOaep: + return doWriteUint32(RsaOaepTag); + case blink::WebCryptoAlgorithmIdAesCtr: + return doWriteUint32(AesCtrTag); + case blink::WebCryptoAlgorithmIdAesKw: + return doWriteUint32(AesKwTag); + } + ASSERT_NOT_REACHED(); + } + + void doWriteKeyUsages(const blink::WebCryptoKeyUsageMask usages, bool extractable) + { + // Reminder to update this when adding new key usages. + COMPILE_ASSERT(blink::EndOfWebCryptoKeyUsage == (1 << 7) + 1, UpdateMe); + + uint32_t value = 0; + + if (extractable) + value |= ExtractableUsage; + + if (usages & blink::WebCryptoKeyUsageEncrypt) + value |= EncryptUsage; + if (usages & blink::WebCryptoKeyUsageDecrypt) + value |= DecryptUsage; + if (usages & blink::WebCryptoKeyUsageSign) + value |= SignUsage; + if (usages & blink::WebCryptoKeyUsageVerify) + value |= VerifyUsage; + if (usages & blink::WebCryptoKeyUsageDeriveKey) + value |= DeriveKeyUsage; + if (usages & blink::WebCryptoKeyUsageWrapKey) + value |= WrapKeyUsage; + if (usages & blink::WebCryptoKeyUsageUnwrapKey) + value |= UnwrapKeyUsage; + if (usages & blink::WebCryptoKeyUsageDeriveBits) + value |= DeriveBitsUsage; + + doWriteUint32(value); + } + int bytesNeededToWireEncode(uint32_t value) { int bytes = 1; @@ -675,23 +898,22 @@ private: Vector<BufferValueType> m_buffer; unsigned m_position; - v8::Isolate* m_isolate; }; -static v8::Handle<v8::Object> toV8Object(MessagePort* impl, v8::Isolate* isolate) +static v8::Handle<v8::Object> toV8Object(MessagePort* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { if (!impl) return v8::Handle<v8::Object>(); - v8::Handle<v8::Value> wrapper = toV8(impl, v8::Handle<v8::Object>(), isolate); + v8::Handle<v8::Value> wrapper = toV8(impl, creationContext, isolate); ASSERT(wrapper->IsObject()); return wrapper.As<v8::Object>(); } -static v8::Handle<v8::ArrayBuffer> toV8Object(ArrayBuffer* impl, v8::Isolate* isolate) +static v8::Handle<v8::ArrayBuffer> toV8Object(ArrayBuffer* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { if (!impl) return v8::Handle<v8::ArrayBuffer>(); - v8::Handle<v8::Value> wrapper = toV8(impl, v8::Handle<v8::Object>(), isolate); + v8::Handle<v8::Value> wrapper = toV8(impl, creationContext, isolate); ASSERT(wrapper->IsArrayBuffer()); return wrapper.As<v8::ArrayBuffer>(); } @@ -703,28 +925,28 @@ public: Success, InputError, DataCloneError, - InvalidStateError, - JSException, - JSFailure + JSException }; - Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, v8::Isolate* isolate) - : m_writer(writer) + Serializer(Writer& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, ScriptState* scriptState) + : m_scriptState(scriptState) + , m_writer(writer) , m_tryCatch(tryCatch) , m_depth(0) , m_status(Success) , m_nextObjectReference(0) + , m_blobInfo(blobInfo) , m_blobDataHandles(blobDataHandles) - , m_isolate(isolate) { ASSERT(!tryCatch.HasCaught()); + v8::Handle<v8::Object> creationContext = m_scriptState->context()->Global(); if (messagePorts) { for (size_t i = 0; i < messagePorts->size(); i++) - m_transferredMessagePorts.set(toV8Object(messagePorts->at(i).get(), m_writer.getIsolate()), i); + m_transferredMessagePorts.set(toV8Object(messagePorts->at(i).get(), creationContext, isolate()), i); } if (arrayBuffers) { for (size_t i = 0; i < arrayBuffers->size(); i++) { - v8::Handle<v8::Object> v8ArrayBuffer = toV8Object(arrayBuffers->at(i).get(), m_writer.getIsolate()); + v8::Handle<v8::Object> v8ArrayBuffer = toV8Object(arrayBuffers->at(i).get(), creationContext, isolate()); // Coalesce multiple occurences of the same buffer to the first index. if (!m_transferredArrayBuffers.contains(v8ArrayBuffer)) m_transferredArrayBuffers.set(v8ArrayBuffer, i); @@ -732,9 +954,11 @@ public: } } + v8::Isolate* isolate() { return m_scriptState->isolate(); } + Status serialize(v8::Handle<v8::Value> value) { - v8::HandleScope scope(m_isolate); + v8::HandleScope scope(isolate()); m_writer.writeVersion(); StateBase* state = doSerialize(value, 0); while (state) @@ -742,6 +966,8 @@ public: return m_status; } + String errorMessage() { return m_errorMessage; } + // Functions used by serialization states. StateBase* doSerialize(v8::Handle<v8::Value>, StateBase* next); @@ -752,12 +978,7 @@ public: StateBase* checkException(StateBase* state) { - return m_tryCatch.HasCaught() ? handleError(JSException, state) : 0; - } - - StateBase* reportFailure(StateBase* state) - { - return handleError(JSFailure, state); + return m_tryCatch.HasCaught() ? handleError(JSException, "", state) : 0; } StateBase* writeObject(uint32_t numProperties, StateBase* state) @@ -796,10 +1017,6 @@ private: // state. virtual StateBase* advance(Serializer&) = 0; - // Returns 1 if this state is currently serializing a property - // via an accessor and 0 otherwise. - virtual uint32_t execDepth() const { return 0; } - protected: StateBase(v8::Handle<v8::Value> composite, StateBase* next) : m_composite(composite) @@ -813,14 +1030,14 @@ private: }; // Dummy state that is used to signal serialization errors. - class ErrorState : public StateBase { + class ErrorState FINAL : public StateBase { public: ErrorState() : StateBase(v8Undefined(), 0) { } - virtual StateBase* advance(Serializer&) + virtual StateBase* advance(Serializer&) OVERRIDE { delete this; return 0; @@ -860,7 +1077,7 @@ private: if (StateBase* newState = serializer.checkException(this)) return newState; if (propertyName.IsEmpty()) - return serializer.reportFailure(this); + return serializer.handleError(InputError, "Empty property names cannot be cloned.", this); bool hasStringProperty = propertyName->IsString() && composite()->HasRealNamedProperty(propertyName.As<v8::String>()); if (StateBase* newState = serializer.checkException(this)) return newState; @@ -905,33 +1122,33 @@ private: bool m_nameDone; }; - class ObjectState : public AbstractObjectState { + class ObjectState FINAL : public AbstractObjectState { public: ObjectState(v8::Handle<v8::Object> object, StateBase* next) : AbstractObjectState(object, next) { } - virtual StateBase* advance(Serializer& serializer) + virtual StateBase* advance(Serializer& serializer) OVERRIDE { if (m_propertyNames.IsEmpty()) { m_propertyNames = composite()->GetPropertyNames(); if (StateBase* newState = serializer.checkException(this)) return newState; if (m_propertyNames.IsEmpty()) - return serializer.reportFailure(this); + return serializer.handleError(InputError, "Empty property names cannot be cloned.", nextState()); } return serializeProperties(false, serializer); } protected: - virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) + virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) OVERRIDE { return serializer.writeObject(numProperties, this); } }; - class DenseArrayState : public AbstractObjectState { + class DenseArrayState FINAL : public AbstractObjectState { public: DenseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> propertyNames, StateBase* next, v8::Isolate* isolate) : AbstractObjectState(array, next) @@ -941,7 +1158,7 @@ private: m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames); } - virtual StateBase* advance(Serializer& serializer) + virtual StateBase* advance(Serializer& serializer) OVERRIDE { while (m_arrayIndex < m_arrayLength) { v8::Handle<v8::Value> value = composite().As<v8::Array>()->Get(m_arrayIndex); @@ -955,7 +1172,7 @@ private: } protected: - virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) + virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) OVERRIDE { return serializer.writeDenseArray(numProperties, m_arrayLength, this); } @@ -965,7 +1182,7 @@ private: uint32_t m_arrayLength; }; - class SparseArrayState : public AbstractObjectState { + class SparseArrayState FINAL : public AbstractObjectState { public: SparseArrayState(v8::Handle<v8::Array> array, v8::Handle<v8::Array> propertyNames, StateBase* next, v8::Isolate* isolate) : AbstractObjectState(array, next) @@ -973,13 +1190,13 @@ private: m_propertyNames = v8::Local<v8::Array>::New(isolate, propertyNames); } - virtual StateBase* advance(Serializer& serializer) + virtual StateBase* advance(Serializer& serializer) OVERRIDE { return serializeProperties(false, serializer); } protected: - virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) + virtual StateBase* objectDone(unsigned numProperties, Serializer& serializer) OVERRIDE { return serializer.writeSparseArray(numProperties, composite().As<v8::Array>()->Length(), this); } @@ -989,7 +1206,7 @@ private: { ASSERT(state); ++m_depth; - return checkComposite(state) ? state : handleError(InputError, state); + return checkComposite(state) ? state : handleError(InputError, "Value being cloned is either cyclic or too deeply nested.", state); } StateBase* pop(StateBase* state) @@ -1001,10 +1218,11 @@ private: return next; } - StateBase* handleError(Status errorStatus, StateBase* state) + StateBase* handleError(Status errorStatus, const String& message, StateBase* state) { ASSERT(errorStatus != Success); m_status = errorStatus; + m_errorMessage = message; while (state) { StateBase* tmp = state->nextState(); delete state; @@ -1056,13 +1274,20 @@ private: m_writer.writeBooleanObject(booleanObject->ValueOf()); } - void writeBlob(v8::Handle<v8::Value> value) + StateBase* writeBlob(v8::Handle<v8::Value> value, StateBase* next) { Blob* blob = V8Blob::toNative(value.As<v8::Object>()); if (!blob) - return; - m_writer.writeBlob(blob->uuid(), blob->type(), blob->size()); - m_blobDataHandles.add(blob->uuid(), blob->blobDataHandle()); + return 0; + if (blob->hasBeenClosed()) + return handleError(DataCloneError, "A Blob object has been closed, and could therefore not be cloned.", next); + int blobIndex = -1; + m_blobDataHandles.set(blob->uuid(), blob->blobDataHandle()); + if (appendBlobInfo(blob->uuid(), blob->type(), blob->size(), &blobIndex)) + m_writer.writeBlobIndex(blobIndex); + else + m_writer.writeBlob(blob->uuid(), blob->type(), blob->size()); + return 0; } StateBase* writeDOMFileSystem(v8::Handle<v8::Value> value, StateBase* next) @@ -1071,29 +1296,61 @@ private: if (!fs) return 0; if (!fs->clonable()) - return handleError(DataCloneError, next); + return handleError(DataCloneError, "A FileSystem object could not be cloned.", next); m_writer.writeDOMFileSystem(fs->type(), fs->name(), fs->rootURL().string()); return 0; } - void writeFile(v8::Handle<v8::Value> value) + StateBase* writeFile(v8::Handle<v8::Value> value, StateBase* next) { File* file = V8File::toNative(value.As<v8::Object>()); if (!file) - return; - m_writer.writeFile(*file); - m_blobDataHandles.add(file->uuid(), file->blobDataHandle()); + return 0; + if (file->hasBeenClosed()) + return handleError(DataCloneError, "A File object has been closed, and could therefore not be cloned.", next); + int blobIndex = -1; + m_blobDataHandles.set(file->uuid(), file->blobDataHandle()); + if (appendFileInfo(file, &blobIndex)) { + ASSERT(blobIndex >= 0); + m_writer.writeFileIndex(blobIndex); + } else { + m_writer.writeFile(*file); + } + return 0; } - void writeFileList(v8::Handle<v8::Value> value) + StateBase* writeFileList(v8::Handle<v8::Value> value, StateBase* next) { FileList* fileList = V8FileList::toNative(value.As<v8::Object>()); if (!fileList) - return; - m_writer.writeFileList(*fileList); + return 0; unsigned length = fileList->length(); - for (unsigned i = 0; i < length; ++i) - m_blobDataHandles.add(fileList->item(i)->uuid(), fileList->item(i)->blobDataHandle()); + Vector<int> blobIndices; + for (unsigned i = 0; i < length; ++i) { + int blobIndex = -1; + const File* file = fileList->item(i); + if (file->hasBeenClosed()) + return handleError(DataCloneError, "A File object has been closed, and could therefore not be cloned.", next); + m_blobDataHandles.set(file->uuid(), file->blobDataHandle()); + if (appendFileInfo(file, &blobIndex)) { + ASSERT(!i || blobIndex > 0); + ASSERT(blobIndex >= 0); + blobIndices.append(blobIndex); + } + } + if (!blobIndices.isEmpty()) + m_writer.writeFileListIndex(blobIndices); + else + m_writer.writeFileList(*fileList); + return 0; + } + + bool writeCryptoKey(v8::Handle<v8::Value> value) + { + Key* key = V8Key::toNative(value.As<v8::Object>()); + if (!key) + return false; + return m_writer.writeCryptoKey(key->key()); } void writeImageData(v8::Handle<v8::Value> value) @@ -1118,10 +1375,10 @@ private: if (!arrayBufferView) return 0; if (!arrayBufferView->buffer()) - return handleError(DataCloneError, next); - v8::Handle<v8::Value> underlyingBuffer = toV8(arrayBufferView->buffer(), v8::Handle<v8::Object>(), m_writer.getIsolate()); + return handleError(DataCloneError, "An ArrayBuffer could not be cloned.", next); + v8::Handle<v8::Value> underlyingBuffer = toV8(arrayBufferView->buffer(), m_scriptState->context()->Global(), isolate()); if (underlyingBuffer.IsEmpty()) - return handleError(DataCloneError, next); + return handleError(DataCloneError, "An ArrayBuffer could not be cloned.", next); StateBase* stateOut = doSerializeArrayBuffer(underlyingBuffer, next); if (stateOut) return stateOut; @@ -1146,7 +1403,7 @@ private: if (!arrayBuffer) return 0; if (arrayBuffer->isNeutered()) - return handleError(InvalidStateError, next); + return handleError(DataCloneError, "An ArrayBuffer is neutered and could not be cloned.", next); ASSERT(!m_transferredArrayBuffers.contains(value.As<v8::Object>())); m_writer.writeArrayBuffer(*arrayBuffer); return 0; @@ -1158,7 +1415,7 @@ private: if (!arrayBuffer) return 0; if (arrayBuffer->isNeutered()) - return handleError(DataCloneError, next); + return handleError(DataCloneError, "An ArrayBuffer is neutered and could not be cloned.", next); m_writer.writeTransferredArrayBuffer(index); return 0; } @@ -1181,11 +1438,11 @@ private: if (shouldSerializeDensely(length, propertyNames->Length())) { m_writer.writeGenerateFreshDenseArray(length); - return push(new DenseArrayState(array, propertyNames, next, m_isolate)); + return push(new DenseArrayState(array, propertyNames, next, isolate())); } m_writer.writeGenerateFreshSparseArray(length); - return push(new SparseArrayState(array, propertyNames, next, m_isolate)); + return push(new SparseArrayState(array, propertyNames, next, isolate())); } StateBase* startObjectState(v8::Handle<v8::Object> object, StateBase* next) @@ -1204,34 +1461,68 @@ private: m_objectPool.set(object, objectReference); } + bool appendBlobInfo(const String& uuid, const String& type, unsigned long long size, int* index) + { + if (!m_blobInfo) + return false; + *index = m_blobInfo->size(); + m_blobInfo->append(blink::WebBlobInfo(uuid, type, size)); + return true; + } + + bool appendFileInfo(const File* file, int* index) + { + if (!m_blobInfo) + return false; + + long long size = -1; + double lastModified = invalidFileTime(); + file->captureSnapshot(size, lastModified); + *index = m_blobInfo->size(); + m_blobInfo->append(blink::WebBlobInfo(file->uuid(), file->path(), file->name(), file->type(), lastModified, size)); + return true; + } + + RefPtr<ScriptState> m_scriptState; Writer& m_writer; v8::TryCatch& m_tryCatch; int m_depth; Status m_status; + String m_errorMessage; typedef V8ObjectMap<v8::Object, uint32_t> ObjectPool; ObjectPool m_objectPool; ObjectPool m_transferredMessagePorts; ObjectPool m_transferredArrayBuffers; uint32_t m_nextObjectReference; + WebBlobInfoArray* m_blobInfo; BlobDataHandleMap& m_blobDataHandles; - v8::Isolate* m_isolate; }; +// Returns true if the provided object is to be considered a 'host object', as used in the +// HTML5 structured clone algorithm. +static bool isHostObject(v8::Handle<v8::Object> object) +{ + // If the object has any internal fields, then we won't be able to serialize or deserialize + // them; conveniently, this is also a quick way to detect DOM wrapper objects, because + // the mechanism for these relies on data stored in these fields. We should + // catch external array data as a special case. + return object->InternalFieldCount() || object->HasIndexedPropertiesInExternalArrayData(); +} + Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, StateBase* next) { m_writer.writeReferenceCount(m_nextObjectReference); uint32_t objectReference; uint32_t arrayBufferIndex; - WrapperWorldType currentWorldType = worldType(m_isolate); if ((value->IsObject() || value->IsDate() || value->IsRegExp()) && m_objectPool.tryGet(value.As<v8::Object>(), &objectReference)) { // Note that IsObject() also detects wrappers (eg, it will catch the things // that we grey and write below). ASSERT(!value->IsString()); m_writer.writeObjectReference(objectReference); - } else if (value.IsEmpty()) - return reportFailure(next); - else if (value->IsUndefined()) + } else if (value.IsEmpty()) { + return handleError(InputError, "The empty property name cannot be cloned.", next); + } else if (value->IsUndefined()) m_writer.writeUndefined(); else if (value->IsNull()) m_writer.writeNull(); @@ -1245,22 +1536,22 @@ Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, Stat m_writer.writeUint32(value->Uint32Value()); else if (value->IsNumber()) m_writer.writeNumber(value.As<v8::Number>()->Value()); - else if (V8ArrayBufferView::hasInstance(value, m_isolate, currentWorldType)) + else if (V8ArrayBufferView::hasInstance(value, isolate())) return writeAndGreyArrayBufferView(value.As<v8::Object>(), next); else if (value->IsString()) writeString(value); - else if (V8MessagePort::hasInstance(value, m_isolate, currentWorldType)) { + else if (V8MessagePort::hasInstance(value, isolate())) { uint32_t messagePortIndex; if (m_transferredMessagePorts.tryGet(value.As<v8::Object>(), &messagePortIndex)) m_writer.writeTransferredMessagePort(messagePortIndex); else - return handleError(DataCloneError, next); - } else if (V8ArrayBuffer::hasInstance(value, m_isolate, currentWorldType) && m_transferredArrayBuffers.tryGet(value.As<v8::Object>(), &arrayBufferIndex)) + return handleError(DataCloneError, "A MessagePort could not be cloned.", next); + } else if (V8ArrayBuffer::hasInstance(value, isolate()) && m_transferredArrayBuffers.tryGet(value.As<v8::Object>(), &arrayBufferIndex)) return writeTransferredArrayBuffer(value, arrayBufferIndex, next); else { v8::Handle<v8::Object> jsObject = value.As<v8::Object>(); if (jsObject.IsEmpty()) - return handleError(DataCloneError, next); + return handleError(DataCloneError, "An object could not be cloned.", next); greyObject(jsObject); if (value->IsDate()) m_writer.writeDate(value->NumberValue()); @@ -1272,26 +1563,29 @@ Serializer::StateBase* Serializer::doSerialize(v8::Handle<v8::Value> value, Stat writeBooleanObject(value); else if (value->IsArray()) { return startArrayState(value.As<v8::Array>(), next); - } else if (V8File::hasInstance(value, m_isolate, currentWorldType)) - writeFile(value); - else if (V8Blob::hasInstance(value, m_isolate, currentWorldType)) - writeBlob(value); - else if (V8DOMFileSystem::hasInstance(value, m_isolate, currentWorldType)) + } else if (V8File::hasInstance(value, isolate())) + return writeFile(value, next); + else if (V8Blob::hasInstance(value, isolate())) + return writeBlob(value, next); + else if (V8DOMFileSystem::hasInstance(value, isolate())) return writeDOMFileSystem(value, next); - else if (V8FileList::hasInstance(value, m_isolate, currentWorldType)) - writeFileList(value); - else if (V8ImageData::hasInstance(value, m_isolate, currentWorldType)) + else if (V8FileList::hasInstance(value, isolate())) + return writeFileList(value, next); + else if (V8Key::hasInstance(value, isolate())) { + if (!writeCryptoKey(value)) + return handleError(DataCloneError, "Couldn't serialize key data", next); + } else if (V8ImageData::hasInstance(value, isolate())) writeImageData(value); else if (value->IsRegExp()) writeRegExp(value); - else if (V8ArrayBuffer::hasInstance(value, m_isolate, currentWorldType)) + else if (V8ArrayBuffer::hasInstance(value, isolate())) return writeArrayBuffer(value, next); else if (value->IsObject()) { if (isHostObject(jsObject) || jsObject->IsCallable() || value->IsNativeError()) - return handleError(DataCloneError, next); + return handleError(DataCloneError, "An object could not be cloned.", next); return startObjectState(jsObject, next); } else - return handleError(DataCloneError, next); + return handleError(DataCloneError, "A value could not be cloned.", next); } return 0; } @@ -1319,12 +1613,13 @@ public: // restoring information about saved objects of composite types. class Reader { public: - Reader(const uint8_t* buffer, int length, v8::Isolate* isolate, const BlobDataHandleMap& blobDataHandles) - : m_buffer(buffer) + Reader(const uint8_t* buffer, int length, const WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles, ScriptState* scriptState) + : m_scriptState(scriptState) + , m_buffer(buffer) , m_length(length) , m_position(0) , m_version(0) - , m_isolate(isolate) + , m_blobInfo(blobInfo) , m_blobDataHandles(blobDataHandles) { ASSERT(!(reinterpret_cast<size_t>(buffer) & 1)); @@ -1333,8 +1628,12 @@ public: bool isEof() const { return m_position >= m_length; } - v8::Isolate* isolate() const { return m_isolate; } + ScriptState* scriptState() const { return m_scriptState.get(); } + +private: + v8::Isolate* isolate() const { return m_scriptState->isolate(); } +public: bool read(v8::Handle<v8::Value>* value, CompositeCreator& creator) { SerializationTag tag; @@ -1342,7 +1641,7 @@ public: return false; switch (tag) { case ReferenceCountTag: { - if (m_version <= 0) + if (!m_version) return false; uint32_t referenceTableSize; if (!doReadUint32(&referenceTableSize)) @@ -1359,16 +1658,16 @@ public: case PaddingTag: return true; case UndefinedTag: - *value = v8::Undefined(m_isolate); + *value = v8::Undefined(isolate()); break; case NullTag: - *value = v8::Null(m_isolate); + *value = v8::Null(isolate()); break; case TrueTag: - *value = v8BooleanWithCheck(true, m_isolate); + *value = v8Boolean(true, isolate()); break; case FalseTag: - *value = v8BooleanWithCheck(false, m_isolate); + *value = v8Boolean(false, isolate()); break; case TrueObjectTag: *value = v8::BooleanObject::New(true); @@ -1414,12 +1713,14 @@ public: creator.pushObjectReference(*value); break; case BlobTag: - if (!readBlob(value)) + case BlobIndexTag: + if (!readBlob(value, tag == BlobIndexTag)) return false; creator.pushObjectReference(*value); break; case FileTag: - if (!readFile(value)) + case FileIndexTag: + if (!readFile(value, tag == FileIndexTag)) return false; creator.pushObjectReference(*value); break; @@ -1429,7 +1730,13 @@ public: creator.pushObjectReference(*value); break; case FileListTag: - if (!readFileList(value)) + case FileListIndexTag: + if (!readFileList(value, tag == FileListIndexTag)) + return false; + creator.pushObjectReference(*value); + break; + case CryptoKeyTag: + if (!readCryptoKey(value)) return false; creator.pushObjectReference(*value); break; @@ -1475,7 +1782,7 @@ public: break; } case ArrayBufferViewTag: { - if (m_version <= 0) + if (!m_version) return false; if (!readArrayBufferView(value, creator)) return false; @@ -1483,7 +1790,7 @@ public: break; } case ArrayBufferTag: { - if (m_version <= 0) + if (!m_version) return false; if (!readArrayBuffer(value)) return false; @@ -1491,14 +1798,14 @@ public: break; } case GenerateFreshObjectTag: { - if (m_version <= 0) + if (!m_version) return false; if (!creator.newObject()) return false; return true; } case GenerateFreshSparseArrayTag: { - if (m_version <= 0) + if (!m_version) return false; uint32_t length; if (!doReadUint32(&length)) @@ -1508,7 +1815,7 @@ public: return true; } case GenerateFreshDenseArrayTag: { - if (m_version <= 0) + if (!m_version) return false; uint32_t length; if (!doReadUint32(&length)) @@ -1518,7 +1825,7 @@ public: return true; } case MessagePortTag: { - if (m_version <= 0) + if (!m_version) return false; uint32_t index; if (!doReadUint32(&index)) @@ -1528,7 +1835,7 @@ public: break; } case ArrayBufferTransferTag: { - if (m_version <= 0) + if (!m_version) return false; uint32_t index; if (!doReadUint32(&index)) @@ -1538,7 +1845,7 @@ public: break; } case ObjectReferenceTag: { - if (m_version <= 0) + if (!m_version) return false; uint32_t reference; if (!doReadUint32(&reference)) @@ -1577,8 +1884,6 @@ public: m_version = version; } - v8::Isolate* getIsolate() { return m_isolate; } - private: bool readTag(SerializationTag* tag) { @@ -1609,7 +1914,7 @@ private: return false; if (m_position + length > m_length) return false; - *value = v8::String::NewFromUtf8(m_isolate, reinterpret_cast<const char*>(m_buffer + m_position), v8::String::kNormalString, length); + *value = v8::String::NewFromUtf8(isolate(), reinterpret_cast<const char*>(m_buffer + m_position), v8::String::kNormalString, length); m_position += length; return true; } @@ -1622,7 +1927,7 @@ private: if (m_position + length > m_length) return false; ASSERT(!(m_position & 1)); - *value = v8::String::NewFromTwoByte(m_isolate, reinterpret_cast<const uint16_t*>(m_buffer + m_position), v8::String::kNormalString, length / sizeof(UChar)); + *value = v8::String::NewFromTwoByte(isolate(), reinterpret_cast<const uint16_t*>(m_buffer + m_position), v8::String::kNormalString, length / sizeof(UChar)); m_position += length; return true; } @@ -1653,7 +1958,7 @@ private: uint32_t rawValue; if (!doReadUint32(&rawValue)) return false; - *value = v8::Integer::New(static_cast<int32_t>(ZigZag::decode(rawValue)), m_isolate); + *value = v8::Integer::New(isolate(), static_cast<int32_t>(ZigZag::decode(rawValue))); return true; } @@ -1662,7 +1967,7 @@ private: uint32_t rawValue; if (!doReadUint32(&rawValue)) return false; - *value = v8::Integer::NewFromUnsigned(rawValue, m_isolate); + *value = v8::Integer::NewFromUnsigned(isolate(), rawValue); return true; } @@ -1671,7 +1976,7 @@ private: double numberValue; if (!doReadNumber(&numberValue)) return false; - *value = v8DateOrNull(numberValue, m_isolate); + *value = v8DateOrNaN(numberValue, isolate()); return true; } @@ -1680,7 +1985,7 @@ private: double number; if (!doReadNumber(&number)) return false; - *value = v8::Number::New(m_isolate, number); + *value = v8::Number::New(isolate(), number); return true; } @@ -1689,7 +1994,7 @@ private: double number; if (!doReadNumber(&number)) return false; - *value = v8::NumberObject::New(m_isolate, number); + *value = v8::NumberObject::New(isolate(), number); return true; } @@ -1706,13 +2011,13 @@ private: return false; if (m_position + pixelDataLength > m_length) return false; - RefPtr<ImageData> imageData = ImageData::create(IntSize(width, height)); + RefPtrWillBeRawPtr<ImageData> imageData = ImageData::create(IntSize(width, height)); Uint8ClampedArray* pixelArray = imageData->data(); ASSERT(pixelArray); ASSERT(pixelArray->length() >= pixelDataLength); memcpy(pixelArray->data(), m_buffer + m_position, pixelDataLength); m_position += pixelDataLength; - *value = toV8(imageData.release(), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(imageData.release(), m_scriptState->context()->Global(), isolate()); return true; } @@ -1720,9 +2025,9 @@ private: { uint32_t byteLength; if (!doReadUint32(&byteLength)) - return 0; + return nullptr; if (m_position + byteLength > m_length) - return 0; + return nullptr; const void* bufferStart = m_buffer + m_position; RefPtr<ArrayBuffer> arrayBuffer = ArrayBuffer::create(bufferStart, byteLength); arrayBuffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instanceTemplate()); @@ -1735,7 +2040,7 @@ private: RefPtr<ArrayBuffer> arrayBuffer = doReadArrayBuffer(); if (!arrayBuffer) return false; - *value = toV8(arrayBuffer.release(), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(arrayBuffer.release(), m_scriptState->context()->Global(), isolate()); return true; } @@ -1759,60 +2064,62 @@ private: arrayBuffer = V8ArrayBuffer::toNative(arrayBufferV8Value.As<v8::Object>()); if (!arrayBuffer) return false; + + v8::Handle<v8::Object> creationContext = m_scriptState->context()->Global(); switch (subTag) { case ByteArrayTag: - *value = toV8(Int8Array::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(Int8Array::create(arrayBuffer.release(), byteOffset, byteLength), creationContext, isolate()); break; case UnsignedByteArrayTag: - *value = toV8(Uint8Array::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(Uint8Array::create(arrayBuffer.release(), byteOffset, byteLength), creationContext, isolate()); break; case UnsignedByteClampedArrayTag: - *value = toV8(Uint8ClampedArray::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(Uint8ClampedArray::create(arrayBuffer.release(), byteOffset, byteLength), creationContext, isolate()); break; case ShortArrayTag: { uint32_t shortLength = byteLength / sizeof(int16_t); if (shortLength * sizeof(int16_t) != byteLength) return false; - *value = toV8(Int16Array::create(arrayBuffer.release(), byteOffset, shortLength), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(Int16Array::create(arrayBuffer.release(), byteOffset, shortLength), creationContext, isolate()); break; } case UnsignedShortArrayTag: { uint32_t shortLength = byteLength / sizeof(uint16_t); if (shortLength * sizeof(uint16_t) != byteLength) return false; - *value = toV8(Uint16Array::create(arrayBuffer.release(), byteOffset, shortLength), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(Uint16Array::create(arrayBuffer.release(), byteOffset, shortLength), creationContext, isolate()); break; } case IntArrayTag: { uint32_t intLength = byteLength / sizeof(int32_t); if (intLength * sizeof(int32_t) != byteLength) return false; - *value = toV8(Int32Array::create(arrayBuffer.release(), byteOffset, intLength), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(Int32Array::create(arrayBuffer.release(), byteOffset, intLength), creationContext, isolate()); break; } case UnsignedIntArrayTag: { uint32_t intLength = byteLength / sizeof(uint32_t); if (intLength * sizeof(uint32_t) != byteLength) return false; - *value = toV8(Uint32Array::create(arrayBuffer.release(), byteOffset, intLength), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(Uint32Array::create(arrayBuffer.release(), byteOffset, intLength), creationContext, isolate()); break; } case FloatArrayTag: { uint32_t floatLength = byteLength / sizeof(float); if (floatLength * sizeof(float) != byteLength) return false; - *value = toV8(Float32Array::create(arrayBuffer.release(), byteOffset, floatLength), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(Float32Array::create(arrayBuffer.release(), byteOffset, floatLength), creationContext, isolate()); break; } case DoubleArrayTag: { uint32_t floatLength = byteLength / sizeof(double); if (floatLength * sizeof(double) != byteLength) return false; - *value = toV8(Float64Array::create(arrayBuffer.release(), byteOffset, floatLength), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(Float64Array::create(arrayBuffer.release(), byteOffset, floatLength), creationContext, isolate()); break; } case DataViewTag: - *value = toV8(DataView::create(arrayBuffer.release(), byteOffset, byteLength), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(DataView::create(arrayBuffer.release(), byteOffset, byteLength), creationContext, isolate()); break; default: return false; @@ -1835,21 +2142,35 @@ private: return true; } - bool readBlob(v8::Handle<v8::Value>* value) + bool readBlob(v8::Handle<v8::Value>* value, bool isIndexed) { if (m_version < 3) return false; - String uuid; - String type; - uint64_t size; - if (!readWebCoreString(&uuid)) - return false; - if (!readWebCoreString(&type)) - return false; - if (!doReadUint64(&size)) - return false; - RefPtr<Blob> blob = Blob::create(getOrCreateBlobDataHandle(uuid, type, size)); - *value = toV8(blob.release(), v8::Handle<v8::Object>(), m_isolate); + RefPtrWillBeRawPtr<Blob> blob; + if (isIndexed) { + if (m_version < 6) + return false; + ASSERT(m_blobInfo); + uint32_t index; + if (!doReadUint32(&index) || index >= m_blobInfo->size()) + return false; + const blink::WebBlobInfo& info = (*m_blobInfo)[index]; + blob = Blob::create(getOrCreateBlobDataHandle(info.uuid(), info.type(), info.size())); + } else { + ASSERT(!m_blobInfo); + String uuid; + String type; + uint64_t size; + ASSERT(!m_blobInfo); + if (!readWebCoreString(&uuid)) + return false; + if (!readWebCoreString(&type)) + return false; + if (!doReadUint64(&size)) + return false; + blob = Blob::create(getOrCreateBlobDataHandle(uuid, type, size)); + } + *value = toV8(blob.release(), m_scriptState->context()->Global(), isolate()); return true; } @@ -1864,42 +2185,108 @@ private: return false; if (!readWebCoreString(&url)) return false; - RefPtr<DOMFileSystem> fs = DOMFileSystem::create(getExecutionContext(), name, static_cast<WebCore::FileSystemType>(type), KURL(ParsedURLString, url)); - *value = toV8(fs.release(), v8::Handle<v8::Object>(), m_isolate); + DOMFileSystem* fs = DOMFileSystem::create(m_scriptState->executionContext(), name, static_cast<WebCore::FileSystemType>(type), KURL(ParsedURLString, url)); + *value = toV8(fs, m_scriptState->context()->Global(), isolate()); return true; } - bool readFile(v8::Handle<v8::Value>* value) + bool readFile(v8::Handle<v8::Value>* value, bool isIndexed) { - RefPtr<File> file = doReadFileHelper(); + RefPtrWillBeRawPtr<File> file; + if (isIndexed) { + if (m_version < 6) + return false; + file = readFileIndexHelper(); + } else { + file = readFileHelper(); + } if (!file) return false; - *value = toV8(file.release(), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(file.release(), m_scriptState->context()->Global(), isolate()); return true; } - bool readFileList(v8::Handle<v8::Value>* value) + bool readFileList(v8::Handle<v8::Value>* value, bool isIndexed) { if (m_version < 3) return false; uint32_t length; if (!doReadUint32(&length)) return false; - RefPtr<FileList> fileList = FileList::create(); + RefPtrWillBeRawPtr<FileList> fileList = FileList::create(); for (unsigned i = 0; i < length; ++i) { - RefPtr<File> file = doReadFileHelper(); + RefPtrWillBeRawPtr<File> file; + if (isIndexed) { + if (m_version < 6) + return false; + file = readFileIndexHelper(); + } else { + file = readFileHelper(); + } if (!file) return false; fileList->append(file.release()); } - *value = toV8(fileList.release(), v8::Handle<v8::Object>(), m_isolate); + *value = toV8(fileList.release(), m_scriptState->context()->Global(), isolate()); return true; } - PassRefPtr<File> doReadFileHelper() + bool readCryptoKey(v8::Handle<v8::Value>* value) + { + uint32_t rawKeyType; + if (!doReadUint32(&rawKeyType)) + return false; + + blink::WebCryptoKeyAlgorithm algorithm; + blink::WebCryptoKeyType type = blink::WebCryptoKeyTypeSecret; + + switch (static_cast<CryptoKeySubTag>(rawKeyType)) { + case AesKeyTag: + if (!doReadAesKey(algorithm, type)) + return false; + break; + case HmacKeyTag: + if (!doReadHmacKey(algorithm, type)) + return false; + break; + case RsaHashedKeyTag: + if (!doReadRsaHashedKey(algorithm, type)) + return false; + break; + default: + return false; + } + + blink::WebCryptoKeyUsageMask usages; + bool extractable; + if (!doReadKeyUsages(usages, extractable)) + return false; + + uint32_t keyDataLength; + if (!doReadUint32(&keyDataLength)) + return false; + + if (m_position + keyDataLength > m_length) + return false; + + const uint8_t* keyData = m_buffer + m_position; + m_position += keyDataLength; + + blink::WebCryptoKey key = blink::WebCryptoKey::createNull(); + if (!blink::Platform::current()->crypto()->deserializeKeyForClone( + algorithm, type, extractable, usages, keyData, keyDataLength, key)) { + return false; + } + + *value = toV8(Key::create(key), m_scriptState->context()->Global(), isolate()); + return true; + } + + PassRefPtrWillBeRawPtr<File> readFileHelper() { if (m_version < 3) - return 0; + return nullptr; + ASSERT(!m_blobInfo); String path; String name; String relativePath; @@ -1909,26 +2296,38 @@ private: uint64_t size = 0; double lastModified = 0; if (!readWebCoreString(&path)) - return 0; + return nullptr; if (m_version >= 4 && !readWebCoreString(&name)) - return 0; + return nullptr; if (m_version >= 4 && !readWebCoreString(&relativePath)) - return 0; + return nullptr; if (!readWebCoreString(&uuid)) - return 0; + return nullptr; if (!readWebCoreString(&type)) - return 0; + return nullptr; if (m_version >= 4 && !doReadUint32(&hasSnapshot)) - return 0; + return nullptr; if (hasSnapshot) { if (!doReadUint64(&size)) - return 0; + return nullptr; if (!doReadNumber(&lastModified)) - return 0; + return nullptr; } return File::create(path, name, relativePath, hasSnapshot > 0, size, lastModified, getOrCreateBlobDataHandle(uuid, type)); } + PassRefPtrWillBeRawPtr<File> readFileIndexHelper() + { + if (m_version < 3) + return nullptr; + ASSERT(m_blobInfo); + uint32_t index; + if (!doReadUint32(&index) || index >= m_blobInfo->size()) + return nullptr; + const blink::WebBlobInfo& info = (*m_blobInfo)[index]; + return File::create(info.filePath(), info.fileName(), info.size(), info.lastModified(), getOrCreateBlobDataHandle(info.uuid(), info.type(), info.size())); + } + template<class T> bool doReadUintHelper(T* value) { @@ -1976,7 +2375,7 @@ private: // the collection of BDH's for blobs to work, which would encourage lifetimes to be considered // when passing ssv's around cross process. At present, we get 'lucky' in some cases because // the blob in the src process happens to still exist at the time the dest process is deserializing. - // For example in sharedWorker.postMesssage(...). + // For example in sharedWorker.postMessage(...). BlobDataHandleMap::const_iterator it = m_blobDataHandles.find(uuid); if (it != m_blobDataHandles.end()) { // make assertions about type and size? @@ -1985,18 +2384,171 @@ private: return BlobDataHandle::create(uuid, type, size); } + bool doReadHmacKey(blink::WebCryptoKeyAlgorithm& algorithm, blink::WebCryptoKeyType& type) + { + uint32_t lengthBytes; + if (!doReadUint32(&lengthBytes)) + return false; + blink::WebCryptoAlgorithmId hash; + if (!doReadAlgorithmId(hash)) + return false; + algorithm = blink::WebCryptoKeyAlgorithm::createHmac(hash, lengthBytes * 8); + type = blink::WebCryptoKeyTypeSecret; + return !algorithm.isNull(); + } + + bool doReadAesKey(blink::WebCryptoKeyAlgorithm& algorithm, blink::WebCryptoKeyType& type) + { + blink::WebCryptoAlgorithmId id; + if (!doReadAlgorithmId(id)) + return false; + uint32_t lengthBytes; + if (!doReadUint32(&lengthBytes)) + return false; + algorithm = blink::WebCryptoKeyAlgorithm::createAes(id, lengthBytes * 8); + type = blink::WebCryptoKeyTypeSecret; + return !algorithm.isNull(); + } + + bool doReadRsaHashedKey(blink::WebCryptoKeyAlgorithm& algorithm, blink::WebCryptoKeyType& type) + { + blink::WebCryptoAlgorithmId id; + if (!doReadAlgorithmId(id)) + return false; + + uint32_t rawType; + if (!doReadUint32(&rawType)) + return false; + + switch (static_cast<AssymetricCryptoKeyType>(rawType)) { + case PublicKeyType: + type = blink::WebCryptoKeyTypePublic; + break; + case PrivateKeyType: + type = blink::WebCryptoKeyTypePrivate; + break; + default: + return false; + } + + uint32_t modulusLengthBits; + if (!doReadUint32(&modulusLengthBits)) + return false; + + uint32_t publicExponentSize; + if (!doReadUint32(&publicExponentSize)) + return false; + + if (m_position + publicExponentSize > m_length) + return false; + + const uint8_t* publicExponent = m_buffer + m_position; + m_position += publicExponentSize; + + blink::WebCryptoAlgorithmId hash; + if (!doReadAlgorithmId(hash)) + return false; + algorithm = blink::WebCryptoKeyAlgorithm::createRsaHashed(id, modulusLengthBits, publicExponent, publicExponentSize, hash); + + return !algorithm.isNull(); + } + + bool doReadAlgorithmId(blink::WebCryptoAlgorithmId& id) + { + uint32_t rawId; + if (!doReadUint32(&rawId)) + return false; + + switch (static_cast<CryptoKeyAlgorithmTag>(rawId)) { + case AesCbcTag: + id = blink::WebCryptoAlgorithmIdAesCbc; + return true; + case HmacTag: + id = blink::WebCryptoAlgorithmIdHmac; + return true; + case RsaSsaPkcs1v1_5Tag: + id = blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5; + return true; + case Sha1Tag: + id = blink::WebCryptoAlgorithmIdSha1; + return true; + case Sha256Tag: + id = blink::WebCryptoAlgorithmIdSha256; + return true; + case Sha384Tag: + id = blink::WebCryptoAlgorithmIdSha384; + return true; + case Sha512Tag: + id = blink::WebCryptoAlgorithmIdSha512; + return true; + case AesGcmTag: + id = blink::WebCryptoAlgorithmIdAesGcm; + return true; + case RsaOaepTag: + id = blink::WebCryptoAlgorithmIdRsaOaep; + return true; + case AesCtrTag: + id = blink::WebCryptoAlgorithmIdAesCtr; + return true; + case AesKwTag: + id = blink::WebCryptoAlgorithmIdAesKw; + return true; + } + + return false; + } + + bool doReadKeyUsages(blink::WebCryptoKeyUsageMask& usages, bool& extractable) + { + // Reminder to update this when adding new key usages. + COMPILE_ASSERT(blink::EndOfWebCryptoKeyUsage == (1 << 7) + 1, UpdateMe); + const uint32_t allPossibleUsages = ExtractableUsage | EncryptUsage | DecryptUsage | SignUsage | VerifyUsage | DeriveKeyUsage | WrapKeyUsage | UnwrapKeyUsage | DeriveBitsUsage; + + uint32_t rawUsages; + if (!doReadUint32(&rawUsages)) + return false; + + // Make sure it doesn't contain an unrecognized usage value. + if (rawUsages & ~allPossibleUsages) + return false; + + usages = 0; + + extractable = rawUsages & ExtractableUsage; + + if (rawUsages & EncryptUsage) + usages |= blink::WebCryptoKeyUsageEncrypt; + if (rawUsages & DecryptUsage) + usages |= blink::WebCryptoKeyUsageDecrypt; + if (rawUsages & SignUsage) + usages |= blink::WebCryptoKeyUsageSign; + if (rawUsages & VerifyUsage) + usages |= blink::WebCryptoKeyUsageVerify; + if (rawUsages & DeriveKeyUsage) + usages |= blink::WebCryptoKeyUsageDeriveKey; + if (rawUsages & WrapKeyUsage) + usages |= blink::WebCryptoKeyUsageWrapKey; + if (rawUsages & UnwrapKeyUsage) + usages |= blink::WebCryptoKeyUsageUnwrapKey; + if (rawUsages & DeriveBitsUsage) + usages |= blink::WebCryptoKeyUsageDeriveBits; + + return true; + } + + RefPtr<ScriptState> m_scriptState; const uint8_t* m_buffer; const unsigned m_length; unsigned m_position; uint32_t m_version; - v8::Isolate* m_isolate; + const WebBlobInfoArray* m_blobInfo; const BlobDataHandleMap& m_blobDataHandles; }; typedef Vector<WTF::ArrayBufferContents, 1> ArrayBufferContentsArray; -class Deserializer : public CompositeCreator { +class Deserializer FINAL : public CompositeCreator { public: Deserializer(Reader& reader, MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContents) : m_reader(reader) @@ -2009,35 +2561,36 @@ public: v8::Handle<v8::Value> deserialize() { + v8::Isolate* isolate = m_reader.scriptState()->isolate(); if (!m_reader.readVersion(m_version) || m_version > SerializedScriptValue::wireFormatVersion) - return v8::Null(m_reader.getIsolate()); + return v8::Null(isolate); m_reader.setVersion(m_version); - v8::EscapableHandleScope scope(m_reader.getIsolate()); + v8::EscapableHandleScope scope(isolate); while (!m_reader.isEof()) { if (!doDeserialize()) - return v8::Null(m_reader.getIsolate()); + return v8::Null(isolate); } if (stackDepth() != 1 || m_openCompositeReferenceStack.size()) - return v8::Null(m_reader.getIsolate()); + return v8::Null(isolate); v8::Handle<v8::Value> result = scope.Escape(element(0)); return result; } - virtual bool newSparseArray(uint32_t) + virtual bool newSparseArray(uint32_t) OVERRIDE { - v8::Local<v8::Array> array = v8::Array::New(m_reader.isolate(), 0); + v8::Local<v8::Array> array = v8::Array::New(m_reader.scriptState()->isolate(), 0); openComposite(array); return true; } - virtual bool newDenseArray(uint32_t length) + virtual bool newDenseArray(uint32_t length) OVERRIDE { - v8::Local<v8::Array> array = v8::Array::New(m_reader.isolate(), length); + v8::Local<v8::Array> array = v8::Array::New(m_reader.scriptState()->isolate(), length); openComposite(array); return true; } - virtual bool consumeTopOfStack(v8::Handle<v8::Value>* object) + virtual bool consumeTopOfStack(v8::Handle<v8::Value>* object) OVERRIDE { if (stackDepth() < 1) return false; @@ -2046,40 +2599,16 @@ public: return true; } - virtual bool completeArray(uint32_t length, v8::Handle<v8::Value>* value) - { - if (length > stackDepth()) - return false; - v8::Local<v8::Array> array; - if (m_version > 0) { - v8::Local<v8::Value> composite; - if (!closeComposite(&composite)) - return false; - array = composite.As<v8::Array>(); - } else { - array = v8::Array::New(m_reader.isolate(), length); - } - if (array.IsEmpty()) - return false; - const int depth = stackDepth() - length; - // The V8 API ensures space exists for any index argument to Set; it will (eg) resize arrays as necessary. - for (unsigned i = 0; i < length; ++i) - array->Set(i, element(depth + i)); - pop(length); - *value = array; - return true; - } - - virtual bool newObject() + virtual bool newObject() OVERRIDE { - v8::Local<v8::Object> object = v8::Object::New(); + v8::Local<v8::Object> object = v8::Object::New(m_reader.scriptState()->isolate()); if (object.IsEmpty()) return false; openComposite(object); return true; } - virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>* value) + virtual bool completeObject(uint32_t numProperties, v8::Handle<v8::Value>* value) OVERRIDE { v8::Local<v8::Object> object; if (m_version > 0) { @@ -2087,14 +2616,15 @@ public: if (!closeComposite(&composite)) return false; object = composite.As<v8::Object>(); - } else - object = v8::Object::New(); + } else { + object = v8::Object::New(m_reader.scriptState()->isolate()); + } if (object.IsEmpty()) return false; return initializeObject(object, numProperties, value); } - virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) + virtual bool completeSparseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) OVERRIDE { v8::Local<v8::Array> array; if (m_version > 0) { @@ -2103,14 +2633,14 @@ public: return false; array = composite.As<v8::Array>(); } else { - array = v8::Array::New(m_reader.isolate()); + array = v8::Array::New(m_reader.scriptState()->isolate()); } if (array.IsEmpty()) return false; return initializeObject(array, numProperties, value); } - virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) + virtual bool completeDenseArray(uint32_t numProperties, uint32_t length, v8::Handle<v8::Value>* value) OVERRIDE { v8::Local<v8::Array> array; if (m_version > 0) { @@ -2134,22 +2664,23 @@ public: return true; } - virtual void pushObjectReference(const v8::Handle<v8::Value>& object) + virtual void pushObjectReference(const v8::Handle<v8::Value>& object) OVERRIDE { m_objectPool.append(object); } - virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>* object) + virtual bool tryGetTransferredMessagePort(uint32_t index, v8::Handle<v8::Value>* object) OVERRIDE { if (!m_transferredMessagePorts) return false; if (index >= m_transferredMessagePorts->size()) return false; - *object = toV8(m_transferredMessagePorts->at(index).get(), v8::Handle<v8::Object>(), m_reader.getIsolate()); + v8::Handle<v8::Object> creationContext = m_reader.scriptState()->context()->Global(); + *object = toV8(m_transferredMessagePorts->at(index).get(), creationContext, m_reader.scriptState()->isolate()); return true; } - virtual bool tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::Value>* object) + virtual bool tryGetTransferredArrayBuffer(uint32_t index, v8::Handle<v8::Value>* object) OVERRIDE { if (!m_arrayBufferContents) return false; @@ -2159,15 +2690,17 @@ public: if (result.IsEmpty()) { RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(m_arrayBufferContents->at(index)); buffer->setDeallocationObserver(V8ArrayBufferDeallocationObserver::instanceTemplate()); - m_reader.isolate()->AdjustAmountOfExternalAllocatedMemory(buffer->byteLength()); - result = toV8Object(buffer.get(), m_reader.getIsolate()); + v8::Isolate* isolate = m_reader.scriptState()->isolate(); + v8::Handle<v8::Object> creationContext = m_reader.scriptState()->context()->Global(); + isolate->AdjustAmountOfExternalAllocatedMemory(buffer->byteLength()); + result = toV8Object(buffer.get(), creationContext, isolate); m_arrayBuffers[index] = result; } *object = result; return true; } - virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<v8::Value>* object) + virtual bool tryGetObjectFromObjectReference(uint32_t reference, v8::Handle<v8::Value>* object) OVERRIDE { if (reference >= m_objectPool.size()) return false; @@ -2175,7 +2708,7 @@ public: return object; } - virtual uint32_t objectReferenceCount() + virtual uint32_t objectReferenceCount() OVERRIDE { return m_objectPool.size(); } @@ -2253,21 +2786,21 @@ private: } // namespace -PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, bool& didThrow, v8::Isolate* isolate) +PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate) { - return adoptRef(new SerializedScriptValue(value, messagePorts, arrayBuffers, didThrow, isolate)); + return adoptRef(new SerializedScriptValue(value, messagePorts, arrayBuffers, 0, exceptionState, isolate)); } PassRefPtr<SerializedScriptValue> SerializedScriptValue::createAndSwallowExceptions(v8::Handle<v8::Value> value, v8::Isolate* isolate) { - bool didThrow; - return adoptRef(new SerializedScriptValue(value, 0, 0, didThrow, isolate, DoNotThrowExceptions)); + TrackExceptionState exceptionState; + return adoptRef(new SerializedScriptValue(value, 0, 0, 0, exceptionState, isolate)); } -PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const ScriptValue& value, bool& didThrow, ScriptState* state) +PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const ScriptValue& value, WebBlobInfoArray* blobInfo, ExceptionState& exceptionState, v8::Isolate* isolate) { - ScriptScope scope(state); - return adoptRef(new SerializedScriptValue(value.v8Value(), 0, 0, didThrow, state->isolate())); + ASSERT(isolate->InContext()); + return adoptRef(new SerializedScriptValue(value.v8Value(), 0, 0, blobInfo, exceptionState, isolate)); } PassRefPtr<SerializedScriptValue> SerializedScriptValue::createFromWire(const String& data) @@ -2296,7 +2829,7 @@ PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& da PassRefPtr<SerializedScriptValue> SerializedScriptValue::create(const String& data, v8::Isolate* isolate) { - Writer writer(isolate); + Writer writer; writer.writeWebCoreString(data); String wireData = writer.takeWireString(); return adoptRef(new SerializedScriptValue(wireData)); @@ -2309,12 +2842,7 @@ PassRefPtr<SerializedScriptValue> SerializedScriptValue::create() PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue() { - return nullValue(v8::Isolate::GetCurrent()); -} - -PassRefPtr<SerializedScriptValue> SerializedScriptValue::nullValue(v8::Isolate* isolate) -{ - Writer writer(isolate); + Writer writer; writer.writeNull(); String wireData = writer.takeWireString(); return adoptRef(new SerializedScriptValue(wireData)); @@ -2344,12 +2872,21 @@ SerializedScriptValue::SerializedScriptValue() { } -inline void neuterBinding(ArrayBuffer* object) +static void neuterArrayBufferInAllWorlds(ArrayBuffer* object) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); - Vector<DOMDataStore*>& allStores = V8PerIsolateData::from(isolate)->allStores(); - for (size_t i = 0; i < allStores.size(); i++) { - v8::Handle<v8::Object> wrapper = allStores[i]->get<V8ArrayBuffer>(object, isolate); + if (isMainThread()) { + Vector<RefPtr<DOMWrapperWorld> > worlds; + DOMWrapperWorld::allWorldsInMainThread(worlds); + for (size_t i = 0; i < worlds.size(); i++) { + v8::Handle<v8::Object> wrapper = worlds[i]->domDataStore().get<V8ArrayBuffer>(object, isolate); + if (!wrapper.IsEmpty()) { + ASSERT(wrapper->IsArrayBuffer()); + v8::Handle<v8::ArrayBuffer>::Cast(wrapper)->Neuter(); + } + } + } else { + v8::Handle<v8::Object> wrapper = DOMWrapperWorld::current(isolate).domDataStore().get<V8ArrayBuffer>(object, isolate); if (!wrapper.IsEmpty()) { ASSERT(wrapper->IsArrayBuffer()); v8::Handle<v8::ArrayBuffer>::Cast(wrapper)->Neuter(); @@ -2357,25 +2894,13 @@ inline void neuterBinding(ArrayBuffer* object) } } -inline void neuterBinding(ArrayBufferView* object) -{ - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - Vector<DOMDataStore*>& allStores = V8PerIsolateData::from(isolate)->allStores(); - for (size_t i = 0; i < allStores.size(); i++) { - v8::Handle<v8::Object> wrapper = allStores[i]->get<V8ArrayBufferView>(object, isolate); - if (!wrapper.IsEmpty()) - wrapper->SetIndexedPropertiesToExternalArrayData(0, v8::kExternalByteArray, 0); - } -} - -PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::transferArrayBuffers(ArrayBufferArray& arrayBuffers, bool& didThrow, v8::Isolate* isolate) +PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValue::transferArrayBuffers(ArrayBufferArray& arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate) { ASSERT(arrayBuffers.size()); for (size_t i = 0; i < arrayBuffers.size(); i++) { if (arrayBuffers[i]->isNeutered()) { - setDOMException(InvalidStateError, isolate); - didThrow = true; + exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " is already neutered."); return nullptr; } } @@ -2384,72 +2909,51 @@ PassOwnPtr<SerializedScriptValue::ArrayBufferContentsArray> SerializedScriptValu HashSet<ArrayBuffer*> visited; for (size_t i = 0; i < arrayBuffers.size(); i++) { - Vector<RefPtr<ArrayBufferView> > neuteredViews; - if (visited.contains(arrayBuffers[i].get())) continue; visited.add(arrayBuffers[i].get()); - bool result = arrayBuffers[i]->transfer(contents->at(i), neuteredViews); + bool result = arrayBuffers[i]->transfer(contents->at(i)); if (!result) { - setDOMException(InvalidStateError, isolate); - didThrow = true; + exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " could not be transferred."); return nullptr; } - neuterBinding(arrayBuffers[i].get()); - for (size_t j = 0; j < neuteredViews.size(); j++) - neuterBinding(neuteredViews[j].get()); + neuterArrayBufferInAllWorlds(arrayBuffers[i].get()); } return contents.release(); } -SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, bool& didThrow, v8::Isolate* isolate, ExceptionPolicy policy) +SerializedScriptValue::SerializedScriptValue(v8::Handle<v8::Value> value, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, WebBlobInfoArray* blobInfo, ExceptionState& exceptionState, v8::Isolate* isolate) : m_externallyAllocatedMemory(0) { - didThrow = false; - Writer writer(isolate); + Writer writer; Serializer::Status status; + String errorMessage; { v8::TryCatch tryCatch; - Serializer serializer(writer, messagePorts, arrayBuffers, m_blobDataHandles, tryCatch, isolate); + Serializer serializer(writer, messagePorts, arrayBuffers, blobInfo, m_blobDataHandles, tryCatch, ScriptState::current(isolate)); status = serializer.serialize(value); if (status == Serializer::JSException) { - didThrow = true; // If there was a JS exception thrown, re-throw it. - if (policy == ThrowExceptions) - tryCatch.ReThrow(); + exceptionState.rethrowV8Exception(tryCatch.Exception()); return; } + errorMessage = serializer.errorMessage(); } switch (status) { case Serializer::InputError: case Serializer::DataCloneError: - // If there was an input error, throw a new exception outside - // of the TryCatch scope. - didThrow = true; - if (policy == ThrowExceptions) - setDOMException(DataCloneError, isolate); - return; - case Serializer::InvalidStateError: - didThrow = true; - if (policy == ThrowExceptions) - setDOMException(InvalidStateError, isolate); - return; - case Serializer::JSFailure: - // If there was a JS failure (but no exception), there's not - // much we can do except for unwinding the C++ stack by - // pretending there was a JS exception. - didThrow = true; + exceptionState.throwDOMException(DataCloneError, errorMessage); return; case Serializer::Success: m_data = writer.takeWireString(); ASSERT(m_data.impl()->hasOneRef()); if (arrayBuffers && arrayBuffers->size()) - m_arrayBufferContentsArray = transferArrayBuffers(*arrayBuffers, didThrow, isolate); + m_arrayBufferContentsArray = transferArrayBuffers(*arrayBuffers, exceptionState, isolate); return; case Serializer::JSException: - // We should never get here because this case was handled above. + ASSERT_NOT_REACHED(); break; } ASSERT_NOT_REACHED(); @@ -2463,10 +2967,10 @@ SerializedScriptValue::SerializedScriptValue(const String& wireData) v8::Handle<v8::Value> SerializedScriptValue::deserialize(MessagePortArray* messagePorts) { - return deserialize(v8::Isolate::GetCurrent(), messagePorts); + return deserialize(v8::Isolate::GetCurrent(), messagePorts, 0); } -v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, MessagePortArray* messagePorts) +v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, MessagePortArray* messagePorts, const WebBlobInfoArray* blobInfo) { if (!m_data.impl()) return v8::Null(isolate); @@ -2476,7 +2980,7 @@ v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, M // storage. Instead, it should use SharedBuffer or Vector<uint8_t>. The // information stored in m_data isn't even encoded in UTF-16. Instead, // unicode characters are encoded as UTF-8 with two code units per UChar. - Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters16()), 2 * m_data.length(), isolate, m_blobDataHandles); + Reader reader(reinterpret_cast<const uint8_t*>(m_data.impl()->characters16()), 2 * m_data.length(), blobInfo, m_blobDataHandles, ScriptState::current(isolate)); Deserializer deserializer(reader, messagePorts, m_arrayBufferContentsArray.get()); // deserialize() can run arbitrary script (e.g., setters), which could result in |this| being destroyed. @@ -2485,6 +2989,57 @@ v8::Handle<v8::Value> SerializedScriptValue::deserialize(v8::Isolate* isolate, M return deserializer.deserialize(); } +bool SerializedScriptValue::extractTransferables(v8::Local<v8::Value> value, int argumentIndex, MessagePortArray& ports, ArrayBufferArray& arrayBuffers, ExceptionState& exceptionState, v8::Isolate* isolate) +{ + if (isUndefinedOrNull(value)) { + ports.resize(0); + arrayBuffers.resize(0); + return true; + } + + uint32_t length = 0; + if (value->IsArray()) { + v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(value); + length = array->Length(); + } else if (toV8Sequence(value, length, isolate).IsEmpty()) { + exceptionState.throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex + 1)); + return false; + } + + v8::Local<v8::Object> transferrables = v8::Local<v8::Object>::Cast(value); + + // Validate the passed array of transferrables. + for (unsigned i = 0; i < length; ++i) { + v8::Local<v8::Value> transferrable = transferrables->Get(i); + // Validation of non-null objects, per HTML5 spec 10.3.3. + if (isUndefinedOrNull(transferrable)) { + exceptionState.throwDOMException(DataCloneError, "Value at index " + String::number(i) + " is an untransferable " + (transferrable->IsUndefined() ? "'undefined'" : "'null'") + " value."); + return false; + } + // Validation of Objects implementing an interface, per WebIDL spec 4.1.15. + if (V8MessagePort::hasInstance(transferrable, isolate)) { + RefPtr<MessagePort> port = V8MessagePort::toNative(v8::Handle<v8::Object>::Cast(transferrable)); + // Check for duplicate MessagePorts. + if (ports.contains(port)) { + exceptionState.throwDOMException(DataCloneError, "Message port at index " + String::number(i) + " is a duplicate of an earlier port."); + return false; + } + ports.append(port.release()); + } else if (V8ArrayBuffer::hasInstance(transferrable, isolate)) { + RefPtr<ArrayBuffer> arrayBuffer = V8ArrayBuffer::toNative(v8::Handle<v8::Object>::Cast(transferrable)); + if (arrayBuffers.contains(arrayBuffer)) { + exceptionState.throwDOMException(DataCloneError, "ArrayBuffer at index " + String::number(i) + " is a duplicate of an earlier ArrayBuffer."); + return false; + } + arrayBuffers.append(arrayBuffer.release()); + } else { + exceptionState.throwDOMException(DataCloneError, "Value at index " + String::number(i) + " does not have a transferable type."); + return false; + } + } + return true; +} + void SerializedScriptValue::registerMemoryAllocatedWithCurrentScriptContext() { if (m_externallyAllocatedMemory) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/SerializedScriptValue.h b/chromium/third_party/WebKit/Source/bindings/v8/SerializedScriptValue.h index 97a73aa04ab..b1064206698 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/SerializedScriptValue.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/SerializedScriptValue.h @@ -32,11 +32,16 @@ #define SerializedScriptValue_h #include "bindings/v8/ScriptValue.h" - #include "wtf/HashMap.h" #include "wtf/ThreadSafeRefCounted.h" #include <v8.h> +namespace blink { + +class WebBlobInfo; + +} + namespace WTF { class ArrayBuffer; @@ -47,11 +52,13 @@ class ArrayBufferContents; namespace WebCore { class BlobDataHandle; +class ExceptionState; class MessagePort; typedef Vector<RefPtr<MessagePort>, 1> MessagePortArray; typedef Vector<RefPtr<WTF::ArrayBuffer>, 1> ArrayBufferArray; typedef HashMap<String, RefPtr<BlobDataHandle> > BlobDataHandleMap; +typedef Vector<blink::WebBlobInfo> WebBlobInfoArray; class SerializedScriptValue FINAL : public ThreadSafeRefCounted<SerializedScriptValue> { public: @@ -59,7 +66,9 @@ public: // Version 2: Added StringUCharTag for UChar v8 strings. // Version 3: Switched to using uuids as blob data identifiers. // Version 4: Extended File serialization to be complete. - static const uint32_t wireFormatVersion = 4; + // Version 5: Added CryptoKeyTag for Key objects. + // Version 6: Added indexed serialization for File, Blob, and FileList. + static const uint32_t wireFormatVersion = 6; ~SerializedScriptValue(); @@ -68,20 +77,18 @@ public: // be thrown using v8::ThrowException(), and sets |didThrow|. In this case // the caller must not invoke any V8 operations until control returns to // V8. When serialization is successful, |didThrow| is false. - static PassRefPtr<SerializedScriptValue> create(v8::Handle<v8::Value>, MessagePortArray*, ArrayBufferArray*, bool& didThrow, v8::Isolate*); + static PassRefPtr<SerializedScriptValue> create(v8::Handle<v8::Value>, MessagePortArray*, ArrayBufferArray*, ExceptionState&, v8::Isolate*); static PassRefPtr<SerializedScriptValue> createFromWire(const String&); static PassRefPtr<SerializedScriptValue> createFromWireBytes(const Vector<uint8_t>&); static PassRefPtr<SerializedScriptValue> create(const String&); static PassRefPtr<SerializedScriptValue> create(const String&, v8::Isolate*); static PassRefPtr<SerializedScriptValue> create(); - - static PassRefPtr<SerializedScriptValue> create(const ScriptValue&, bool& didThrow, ScriptState*); + static PassRefPtr<SerializedScriptValue> create(const ScriptValue&, WebBlobInfoArray*, ExceptionState&, v8::Isolate*); // Never throws exceptions. static PassRefPtr<SerializedScriptValue> createAndSwallowExceptions(v8::Handle<v8::Value>, v8::Isolate*); static PassRefPtr<SerializedScriptValue> nullValue(); - static PassRefPtr<SerializedScriptValue> nullValue(v8::Isolate*); String toWireString() const { return m_data; } void toWireBytes(Vector<char>&) const; @@ -89,11 +96,13 @@ public: // Deserializes the value (in the current context). Returns a null value in // case of failure. v8::Handle<v8::Value> deserialize(MessagePortArray* = 0); - v8::Handle<v8::Value> deserialize(v8::Isolate*, MessagePortArray* = 0); + v8::Handle<v8::Value> deserialize(v8::Isolate*, MessagePortArray* = 0, const WebBlobInfoArray* = 0); - // Only reflects the truth if the SSV was created by walking a v8 value, not reliable - // if the SSV was created createdFromWire(data). - bool containsBlobs() const { return !m_blobDataHandles.isEmpty(); } + // 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 and generates exceptions as appropriate. + // Returns true if the array was filled, or false if the passed value was not of an appropriate type. + static bool extractTransferables(v8::Local<v8::Value>, int, MessagePortArray&, ArrayBufferArray&, ExceptionState&, v8::Isolate*); // Informs the V8 about external memory allocated and owned by this object. Large values should contribute // to GC counters to eventually trigger a GC, otherwise flood of postMessage() can cause OOM. @@ -106,17 +115,13 @@ private: StringValue, WireData }; - enum ExceptionPolicy { - ThrowExceptions, - DoNotThrowExceptions - }; typedef Vector<WTF::ArrayBufferContents, 1> ArrayBufferContentsArray; SerializedScriptValue(); - SerializedScriptValue(v8::Handle<v8::Value>, MessagePortArray*, ArrayBufferArray*, bool& didThrow, v8::Isolate*, ExceptionPolicy = ThrowExceptions); + SerializedScriptValue(v8::Handle<v8::Value>, MessagePortArray*, ArrayBufferArray*, WebBlobInfoArray*, ExceptionState&, v8::Isolate*); explicit SerializedScriptValue(const String& wireData); - static PassOwnPtr<ArrayBufferContentsArray> transferArrayBuffers(ArrayBufferArray&, bool& didThrow, v8::Isolate*); + static PassOwnPtr<ArrayBufferContentsArray> transferArrayBuffers(ArrayBufferArray&, ExceptionState&, v8::Isolate*); String m_data; OwnPtr<ArrayBufferContentsArray> m_arrayBufferContentsArray; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/UnsafePersistent.h b/chromium/third_party/WebKit/Source/bindings/v8/UnsafePersistent.h deleted file mode 100644 index 4a889c27430..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/UnsafePersistent.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2013 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 UnsafePersistent_h -#define UnsafePersistent_h - -#include "bindings/v8/WrapperTypeInfo.h" - -#include <v8.h> - -namespace WebCore { - -template<class KeyType> class DOMWrapperMap; - -// An unsafe way to pass Persistent handles around. Do not use unless you know -// what you're doing. UnsafePersistent is only safe to use when we know that the -// memory pointed by the it is not going away: 1) When GC cannot happen while -// the UnsafePersistent is alive or 2) when there is a strong Persistent keeping -// the memory alive while the UnsafePersistent is alive. -template<typename T> class UnsafePersistent { -public: - UnsafePersistent() : m_value(0) { } - explicit UnsafePersistent(T* value) : m_value(value) { } - explicit UnsafePersistent(v8::Persistent<T>& handle) - { - m_value = handle.ClearAndLeak(); - } - - UnsafePersistent(v8::Isolate* isolate, v8::Handle<T>& handle) - { - v8::Persistent<T> persistent(isolate, handle); - m_value = persistent.ClearAndLeak(); - } - - T* value() const - { - return m_value; - } - - template<typename V8T, typename U> - inline bool setReturnValueWithSecurityCheck(v8::ReturnValue<v8::Value> returnValue, U* object) - { - v8::Handle<v8::Object> result = deprecatedHandle(); - // Security: always guard against malicious tampering. - RELEASE_ASSERT_WITH_SECURITY_IMPLICATION(result.IsEmpty() || result->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex) == V8T::toInternalPointer(object)); - returnValue.Set(result); - return !result.IsEmpty(); - } - - inline bool setReturnValue(v8::ReturnValue<v8::Value> returnValue) - { - returnValue.Set(deprecatedHandle()); - return !isEmpty(); - } - - // This is incredibly unsafe: the handle is valid only when this - // UnsafePersistent is alive and valid (see class level comment). - v8::Persistent<T>* persistent() - { - v8::Persistent<T>* handle = reinterpret_cast<v8::Persistent<T>*>(&m_value); - return handle; - } - - void setReferenceFrom(const v8::Persistent<v8::Object>& parent, v8::Isolate* isolate) - { - isolate->SetReference(parent, *persistent()); - } - - void dispose() - { - persistent()->Reset(); - m_value = 0; - } - - void clear() - { - m_value = 0; - } - - v8::Local<T> newLocal(v8::Isolate* isolate) - { - return v8::Local<T>::New(isolate, *persistent()); - } - - bool isEmpty() const - { - return !m_value; - } - -private: - v8::Handle<T> deprecatedHandle() - { - v8::Handle<T>* handle = reinterpret_cast<v8::Handle<T>*>(&m_value); - return *handle; - } - - T* m_value; -}; - -} // namespace WebCore - -#endif // UnsafePersistent_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8AbstractEventListener.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8AbstractEventListener.cpp index 5324a0d59c2..12f78db5563 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8AbstractEventListener.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8AbstractEventListener.cpp @@ -31,23 +31,32 @@ #include "config.h" #include "bindings/v8/V8AbstractEventListener.h" -#include "V8Event.h" -#include "V8EventTarget.h" +#include "bindings/core/v8/V8Event.h" +#include "bindings/core/v8/V8EventTarget.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8EventListenerList.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "core/events/BeforeUnloadEvent.h" #include "core/events/Event.h" -#include "core/events/ThreadLocalEventNames.h" #include "core/inspector/InspectorCounters.h" #include "core/workers/WorkerGlobalScope.h" namespace WebCore { -V8AbstractEventListener::V8AbstractEventListener(bool isAttribute, PassRefPtr<DOMWrapperWorld> world, v8::Isolate* isolate) +V8AbstractEventListener::V8AbstractEventListener(bool isAttribute, ScriptState* scriptState) : EventListener(JSEventListenerType) , m_isAttribute(isAttribute) - , m_world(world) + , m_scriptState(scriptState) + , m_isolate(scriptState->isolate()) +{ + if (isMainThread()) + InspectorCounters::incrementCounter(InspectorCounters::JSEventListenerCounter); +} + +V8AbstractEventListener::V8AbstractEventListener(bool isAttribute, v8::Isolate* isolate) + : EventListener(JSEventListenerType) + , m_isAttribute(isAttribute) + , m_scriptState(nullptr) , m_isolate(isolate) { if (isMainThread()) @@ -58,16 +67,16 @@ V8AbstractEventListener::~V8AbstractEventListener() { if (!m_listener.isEmpty()) { v8::HandleScope scope(m_isolate); - V8EventListenerList::clearWrapper(m_listener.newLocal(m_isolate), m_isAttribute, m_isolate); + V8EventListenerList::clearWrapper(m_listener.newLocal(isolate()), m_isAttribute, isolate()); } if (isMainThread()) InspectorCounters::decrementCounter(InspectorCounters::JSEventListenerCounter); } -void V8AbstractEventListener::handleEvent(ExecutionContext* context, Event* event) +void V8AbstractEventListener::handleEvent(ExecutionContext*, Event* event) { // Don't reenter V8 if execution was terminated in this instance of V8. - if (context->isJSExecutionForbidden()) + if (scriptState()->executionContext()->isJSExecutionForbidden()) return; ASSERT(event); @@ -76,82 +85,68 @@ void V8AbstractEventListener::handleEvent(ExecutionContext* context, Event* even // See issue 889829. RefPtr<V8AbstractEventListener> protect(this); - v8::HandleScope handleScope(m_isolate); - - v8::Local<v8::Context> v8Context = toV8Context(context, world()); - if (v8Context.IsEmpty()) + if (scriptState()->contextIsEmpty()) return; - - // Enter the V8 context in which to perform the event handling. - v8::Context::Scope scope(v8Context); + ScriptState::Scope scope(scriptState()); // Get the V8 wrapper for the event object. - v8::Isolate* isolate = v8Context->GetIsolate(); - v8::Handle<v8::Value> jsEvent = toV8(event, v8::Handle<v8::Object>(), isolate); + v8::Handle<v8::Value> jsEvent = toV8(event, scriptState()->context()->Global(), isolate()); if (jsEvent.IsEmpty()) return; - invokeEventHandler(context, event, v8::Local<v8::Value>::New(isolate, jsEvent)); + invokeEventHandler(event, v8::Local<v8::Value>::New(isolate(), jsEvent)); } void V8AbstractEventListener::setListenerObject(v8::Handle<v8::Object> listener) { - m_listener.set(m_isolate, listener); + m_listener.set(isolate(), listener); m_listener.setWeak(this, &setWeakCallback); } -void V8AbstractEventListener::invokeEventHandler(ExecutionContext* context, Event* event, v8::Local<v8::Value> jsEvent) +void V8AbstractEventListener::invokeEventHandler(Event* event, v8::Local<v8::Value> jsEvent) { // If jsEvent is empty, attempt to set it as a hidden value would crash v8. if (jsEvent.IsEmpty()) return; - v8::Local<v8::Context> v8Context = toV8Context(context, world()); - if (v8Context.IsEmpty()) - return; - - // We push the event being processed into the global object, so that it can be exposed by DOMWindow's bindings. - v8::Handle<v8::String> eventSymbol = V8HiddenPropertyName::event(v8Context->GetIsolate()); + ASSERT(!scriptState()->contextIsEmpty()); v8::Local<v8::Value> returnValue; - { // Catch exceptions thrown in the event handler so they do not propagate to javascript code that caused the event to fire. v8::TryCatch tryCatch; tryCatch.SetVerbose(true); // Save the old 'event' property so we can restore it later. - v8::Local<v8::Value> savedEvent = v8Context->Global()->GetHiddenValue(eventSymbol); + v8::Local<v8::Value> savedEvent = V8HiddenValue::getHiddenValue(isolate(), scriptState()->context()->Global(), V8HiddenValue::event(isolate())); tryCatch.Reset(); - // Make the event available in the global object, so DOMWindow can expose it. - v8Context->Global()->SetHiddenValue(eventSymbol, jsEvent); + // Make the event available in the global object, so LocalDOMWindow can expose it. + V8HiddenValue::setHiddenValue(isolate(), scriptState()->context()->Global(), V8HiddenValue::event(isolate()), jsEvent); tryCatch.Reset(); - returnValue = callListenerFunction(context, jsEvent, event); + returnValue = callListenerFunction(jsEvent, event); if (tryCatch.HasCaught()) event->target()->uncaughtExceptionInEventHandler(); if (!tryCatch.CanContinue()) { // Result of TerminateExecution(). - if (context->isWorkerGlobalScope()) - toWorkerGlobalScope(context)->script()->forbidExecution(); + if (scriptState()->executionContext()->isWorkerGlobalScope()) + toWorkerGlobalScope(scriptState()->executionContext())->script()->forbidExecution(); return; } tryCatch.Reset(); // Restore the old event. This must be done for all exit paths through this method. if (savedEvent.IsEmpty()) - v8Context->Global()->SetHiddenValue(eventSymbol, v8::Undefined(v8Context->GetIsolate())); + V8HiddenValue::setHiddenValue(isolate(), scriptState()->context()->Global(), V8HiddenValue::event(isolate()), v8::Undefined(isolate())); else - v8Context->Global()->SetHiddenValue(eventSymbol, savedEvent); + V8HiddenValue::setHiddenValue(isolate(), scriptState()->context()->Global(), V8HiddenValue::event(isolate()), savedEvent); tryCatch.Reset(); } - ASSERT(!handleOutOfMemory() || returnValue.IsEmpty()); - if (returnValue.IsEmpty()) return; - if (!returnValue->IsNull() && !returnValue->IsUndefined() && event->isBeforeUnloadEvent()) { - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, stringReturnValue, returnValue); + if (m_isAttribute && !returnValue->IsNull() && !returnValue->IsUndefined() && event->isBeforeUnloadEvent()) { + TOSTRING_VOID(V8StringResource<>, stringReturnValue, returnValue); toBeforeUnloadEvent(event)->setReturnValue(stringReturnValue); } @@ -166,18 +161,22 @@ bool V8AbstractEventListener::shouldPreventDefault(v8::Local<v8::Value> returnVa return returnValue->IsBoolean() && !returnValue->BooleanValue(); } -v8::Local<v8::Object> V8AbstractEventListener::getReceiverObject(ExecutionContext* context, Event* event) +v8::Local<v8::Object> V8AbstractEventListener::getReceiverObject(Event* event) { - v8::Isolate* isolate = toV8Context(context, world())->GetIsolate(); - v8::Local<v8::Object> listener = m_listener.newLocal(isolate); + v8::Local<v8::Object> listener = m_listener.newLocal(isolate()); if (!m_listener.isEmpty() && !listener->IsFunction()) return listener; EventTarget* target = event->currentTarget(); - v8::Handle<v8::Value> value = toV8(target, v8::Handle<v8::Object>(), isolate); + v8::Handle<v8::Value> value = toV8(target, scriptState()->context()->Global(), isolate()); if (value.IsEmpty()) return v8::Local<v8::Object>(); - return v8::Local<v8::Object>::New(isolate, v8::Handle<v8::Object>::Cast(value)); + return v8::Local<v8::Object>::New(isolate(), v8::Handle<v8::Object>::Cast(value)); +} + +bool V8AbstractEventListener::belongsToTheCurrentWorld() const +{ + return isolate()->InContext() && &world() == &DOMWrapperWorld::current(isolate()); } void V8AbstractEventListener::setWeakCallback(const v8::WeakCallbackData<v8::Object, V8AbstractEventListener> &data) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8AbstractEventListener.h b/chromium/third_party/WebKit/Source/bindings/v8/V8AbstractEventListener.h index c605821ea67..469050c4207 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8AbstractEventListener.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8AbstractEventListener.h @@ -33,7 +33,6 @@ #include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/ScopedPersistent.h" -#include "bindings/v8/V8Utilities.h" #include "core/events/EventListener.h" #include <v8.h> #include "wtf/PassRefPtr.h" @@ -69,9 +68,9 @@ namespace WebCore { // Implementation of EventListener interface. - virtual bool operator==(const EventListener& other) { return this == &other; } + virtual bool operator==(const EventListener& other) OVERRIDE { return this == &other; } - virtual void handleEvent(ExecutionContext*, Event*); + virtual void handleEvent(ExecutionContext*, Event*) OVERRIDE; virtual bool isLazy() const { return false; } @@ -109,26 +108,34 @@ namespace WebCore { m_listener.clear(); } - virtual DOMWrapperWorld* world() const OVERRIDE FINAL { return m_world.get(); } + virtual bool belongsToTheCurrentWorld() const OVERRIDE FINAL; v8::Isolate* isolate() const { return m_isolate; } + virtual DOMWrapperWorld& world() const { return scriptState()->world(); } + ScriptState* scriptState() const + { + ASSERT(m_scriptState); + return m_scriptState.get(); + } + void setScriptState(ScriptState* scriptState) { m_scriptState = scriptState; } protected: - V8AbstractEventListener(bool isAttribute, PassRefPtr<DOMWrapperWorld>, v8::Isolate*); + V8AbstractEventListener(bool isAttribute, ScriptState*); + V8AbstractEventListener(bool isAttribute, v8::Isolate*); virtual void prepareListenerObject(ExecutionContext*) { } void setListenerObject(v8::Handle<v8::Object> listener); - void invokeEventHandler(ExecutionContext*, Event*, v8::Local<v8::Value> jsEvent); + void invokeEventHandler(Event*, v8::Local<v8::Value> jsEvent); // Get the receiver object to use for event listener call. - v8::Local<v8::Object> getReceiverObject(ExecutionContext*, Event*); + v8::Local<v8::Object> getReceiverObject(Event*); private: // Implementation of EventListener function. - virtual bool virtualisAttribute() const { return m_isAttribute; } + virtual bool virtualisAttribute() const OVERRIDE { return m_isAttribute; } - virtual v8::Local<v8::Value> callListenerFunction(ExecutionContext*, v8::Handle<v8::Value> jsevent, Event*) = 0; + virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsevent, Event*) = 0; virtual bool shouldPreventDefault(v8::Local<v8::Value> returnValue); @@ -139,7 +146,10 @@ namespace WebCore { // Indicates if this is an HTML type listener. bool m_isAttribute; - RefPtr<DOMWrapperWorld> m_world; + // For V8LazyEventListener, m_scriptState can be 0 until V8LazyEventListener is actually used. + // m_scriptState is set lazily because V8LazyEventListener doesn't know the associated frame + // until the listener is actually used. + RefPtr<ScriptState> m_scriptState; v8::Isolate* m_isolate; }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8Binding.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8Binding.cpp index 2d8da03d149..639784e3f56 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8Binding.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8Binding.cpp @@ -31,12 +31,14 @@ #include "config.h" #include "bindings/v8/V8Binding.h" -#include "V8Element.h" -#include "V8NodeFilter.h" -#include "V8Window.h" -#include "V8WorkerGlobalScope.h" -#include "V8XPathNSResolver.h" +#include "bindings/core/v8/V8Element.h" +#include "bindings/core/v8/V8NodeFilter.h" +#include "bindings/core/v8/V8Window.h" +#include "bindings/core/v8/V8WorkerGlobalScope.h" +#include "bindings/core/v8/V8XPathNSResolver.h" #include "bindings/v8/ScriptController.h" +#include "bindings/v8/V8AbstractEventListener.h" +#include "bindings/v8/V8BindingMacros.h" #include "bindings/v8/V8NodeFilterCondition.h" #include "bindings/v8/V8ObjectConstructor.h" #include "bindings/v8/V8WindowShell.h" @@ -45,14 +47,16 @@ #include "core/dom/Element.h" #include "core/dom/NodeFilter.h" #include "core/dom/QualifiedName.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/Settings.h" #include "core/inspector/BindingVisitors.h" +#include "core/inspector/InspectorTraceEvents.h" #include "core/loader/FrameLoader.h" #include "core/loader/FrameLoaderClient.h" -#include "core/frame/Frame.h" -#include "core/frame/Settings.h" #include "core/workers/WorkerGlobalScope.h" #include "core/xml/XPathNSResolver.h" -#include "gin/public/isolate_holder.h" +#include "platform/EventTracer.h" +#include "platform/JSONValues.h" #include "wtf/ArrayBufferContents.h" #include "wtf/MainThread.h" #include "wtf/MathExtras.h" @@ -63,38 +67,56 @@ #include "wtf/text/StringBuffer.h" #include "wtf/text/StringHash.h" #include "wtf/text/WTFString.h" +#include "wtf/unicode/CharacterNames.h" +#include "wtf/unicode/Unicode.h" namespace WebCore { -v8::Handle<v8::Value> setDOMException(int exceptionCode, v8::Isolate* isolate) +v8::Handle<v8::Value> throwError(V8ErrorType errorType, const String& message, v8::Isolate* isolate) { - // FIXME: pass in an ExceptionState instead for better creationContext. - return V8ThrowException::throwDOMException(exceptionCode, v8::Handle<v8::Object>(), isolate); + return V8ThrowException::throwError(errorType, message, isolate); } -v8::Handle<v8::Value> setDOMException(int exceptionCode, const String& message, v8::Isolate* isolate) +v8::Handle<v8::Value> throwError(v8::Handle<v8::Value> exception, v8::Isolate* isolate) { - return V8ThrowException::throwDOMException(exceptionCode, message, v8::Handle<v8::Object>(), isolate); + return V8ThrowException::throwError(exception, isolate); } -v8::Handle<v8::Value> throwError(V8ErrorType errorType, const String& message, v8::Isolate* isolate) +v8::Handle<v8::Value> throwTypeError(const String& message, v8::Isolate* isolate) { - return V8ThrowException::throwError(errorType, message, isolate); + return V8ThrowException::throwTypeError(message, isolate); } -v8::Handle<v8::Value> throwError(v8::Handle<v8::Value> exception, v8::Isolate* isolate) +void throwArityTypeErrorForMethod(const char* method, const char* type, const char* valid, unsigned provided, v8::Isolate* isolate) { - return V8ThrowException::throwError(exception, isolate); + throwTypeError(ExceptionMessages::failedToExecute(method, type, ExceptionMessages::invalidArity(valid, provided)), isolate); } -v8::Handle<v8::Value> throwUninformativeAndGenericTypeError(v8::Isolate* isolate) +void throwArityTypeErrorForConstructor(const char* type, const char* valid, unsigned provided, v8::Isolate* isolate) { - return V8ThrowException::throwTypeError(String(), isolate); + throwTypeError(ExceptionMessages::failedToConstruct(type, ExceptionMessages::invalidArity(valid, provided)), isolate); } -v8::Handle<v8::Value> throwTypeError(const String& message, v8::Isolate* isolate) +void throwArityTypeError(ExceptionState& exceptionState, const char* valid, unsigned provided) { - return V8ThrowException::throwTypeError(message, isolate); + exceptionState.throwTypeError(ExceptionMessages::invalidArity(valid, provided)); + exceptionState.throwIfNeeded(); +} + +void throwMinimumArityTypeErrorForMethod(const char* method, const char* type, unsigned expected, unsigned providedLeastNumMandatoryParams, v8::Isolate* isolate) +{ + throwTypeError(ExceptionMessages::failedToExecute(method, type, ExceptionMessages::notEnoughArguments(expected, providedLeastNumMandatoryParams)), isolate); +} + +void throwMinimumArityTypeErrorForConstructor(const char* type, unsigned expected, unsigned providedLeastNumMandatoryParams, v8::Isolate* isolate) +{ + throwTypeError(ExceptionMessages::failedToConstruct(type, ExceptionMessages::notEnoughArguments(expected, providedLeastNumMandatoryParams)), isolate); +} + +void throwMinimumArityTypeError(ExceptionState& exceptionState, unsigned expected, unsigned providedLeastNumMandatoryParams) +{ + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(expected, providedLeastNumMandatoryParams)); + exceptionState.throwIfNeeded(); } class ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { @@ -124,14 +146,13 @@ v8::ArrayBuffer::Allocator* v8ArrayBufferAllocator() return &arrayBufferAllocator; } -PassRefPtr<NodeFilter> toNodeFilter(v8::Handle<v8::Value> callback, v8::Isolate* isolate) +PassRefPtrWillBeRawPtr<NodeFilter> toNodeFilter(v8::Handle<v8::Value> callback, v8::Handle<v8::Object> creationContext, ScriptState* scriptState) { - RefPtr<NodeFilter> filter = NodeFilter::create(); + RefPtrWillBeRawPtr<NodeFilter> filter = NodeFilter::create(); - // FIXME: Should pass in appropriate creationContext - v8::Handle<v8::Object> filterWrapper = toV8(filter, v8::Handle<v8::Object>(), isolate).As<v8::Object>(); + v8::Handle<v8::Object> filterWrapper = toV8(filter, creationContext, scriptState->isolate()).As<v8::Object>(); - RefPtr<NodeFilterCondition> condition = V8NodeFilterCondition::create(callback, filterWrapper, isolate); + RefPtrWillBeRawPtr<NodeFilterCondition> condition = V8NodeFilterCondition::create(callback, filterWrapper, scriptState); filter->setCondition(condition.release()); return filter.release(); @@ -140,17 +161,17 @@ PassRefPtr<NodeFilter> toNodeFilter(v8::Handle<v8::Value> callback, v8::Isolate* const int32_t kMaxInt32 = 0x7fffffff; const int32_t kMinInt32 = -kMaxInt32 - 1; const uint32_t kMaxUInt32 = 0xffffffff; -const int64_t kJSMaxInteger = 0x20000000000000LL - 1; // 2^53 - 1, maximum integer exactly representable in ECMAScript. +const int64_t kJSMaxInteger = 0x20000000000000LL - 1; // 2^53 - 1, maximum uniquely representable integer in ECMAScript. -static double enforceRange(double x, double minimum, double maximum, bool& ok) +static double enforceRange(double x, double minimum, double maximum, const char* typeName, ExceptionState& exceptionState) { if (std::isnan(x) || std::isinf(x)) { - ok = false; + exceptionState.throwTypeError("Value is" + String(std::isinf(x) ? " infinite and" : "") + " not of type '" + String(typeName) + "'."); return 0; } x = trunc(x); if (x < minimum || x > maximum) { - ok = false; + exceptionState.throwTypeError("Value is outside the '" + String(typeName) + "' value range."); return 0; } return x; @@ -187,10 +208,9 @@ struct IntTypeLimits<uint16_t> { }; template <typename T> -static inline T toSmallerInt(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) +static inline T toSmallerInt(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, const char* typeName, ExceptionState& exceptionState) { typedef IntTypeLimits<T> LimitsTrait; - ok = true; // Fast case. The value is already a 32-bit integer in the right range. if (value->IsInt32()) { @@ -198,7 +218,7 @@ static inline T toSmallerInt(v8::Handle<v8::Value> value, IntegerConversionConfi if (result >= LimitsTrait::minValue && result <= LimitsTrait::maxValue) return static_cast<T>(result); if (configuration == EnforceRange) { - ok = false; + exceptionState.throwTypeError("Value is outside the '" + String(typeName) + "' value range."); return 0; } result %= LimitsTrait::numberOfValues; @@ -206,14 +226,14 @@ static inline T toSmallerInt(v8::Handle<v8::Value> value, IntegerConversionConfi } // Can the value be converted to a number? - v8::Local<v8::Number> numberObject = value->ToNumber(); + TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0); if (numberObject.IsEmpty()) { - ok = false; + exceptionState.throwTypeError("Not convertible to a number value (of type '" + String(typeName) + "'."); return 0; } if (configuration == EnforceRange) - return enforceRange(numberObject->Value(), LimitsTrait::minValue, LimitsTrait::maxValue, ok); + return enforceRange(numberObject->Value(), LimitsTrait::minValue, LimitsTrait::maxValue, typeName, exceptionState); double numberValue = numberObject->Value(); if (std::isnan(numberValue) || std::isinf(numberValue) || !numberValue) @@ -226,10 +246,9 @@ static inline T toSmallerInt(v8::Handle<v8::Value> value, IntegerConversionConfi } template <typename T> -static inline T toSmallerUInt(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) +static inline T toSmallerUInt(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, const char* typeName, ExceptionState& exceptionState) { typedef IntTypeLimits<T> LimitsTrait; - ok = true; // Fast case. The value is a 32-bit signed integer - possibly positive? if (value->IsInt32()) { @@ -237,21 +256,21 @@ static inline T toSmallerUInt(v8::Handle<v8::Value> value, IntegerConversionConf if (result >= 0 && result <= LimitsTrait::maxValue) return static_cast<T>(result); if (configuration == EnforceRange) { - ok = false; + exceptionState.throwTypeError("Value is outside the '" + String(typeName) + "' value range."); return 0; } return static_cast<T>(result); } // Can the value be converted to a number? - v8::Local<v8::Number> numberObject = value->ToNumber(); + TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0); if (numberObject.IsEmpty()) { - ok = false; + exceptionState.throwTypeError("Not convertible to a number value (of type '" + String(typeName) + "'."); return 0; } if (configuration == EnforceRange) - return enforceRange(numberObject->Value(), 0, LimitsTrait::maxValue, ok); + return enforceRange(numberObject->Value(), 0, LimitsTrait::maxValue, typeName, exceptionState); // Does the value convert to nan or to an infinity? double numberValue = numberObject->Value(); @@ -265,44 +284,65 @@ static inline T toSmallerUInt(v8::Handle<v8::Value> value, IntegerConversionConf return static_cast<T>(fmod(numberValue, LimitsTrait::numberOfValues)); } -int8_t toInt8(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) +int8_t toInt8(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) +{ + return toSmallerInt<int8_t>(value, configuration, "byte", exceptionState); +} + +int8_t toInt8(v8::Handle<v8::Value> value) +{ + NonThrowableExceptionState exceptionState; + return toInt8(value, NormalConversion, exceptionState); +} + +uint8_t toUInt8(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toSmallerInt<int8_t>(value, configuration, ok); + return toSmallerUInt<uint8_t>(value, configuration, "octet", exceptionState); } -uint8_t toUInt8(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) +uint8_t toUInt8(v8::Handle<v8::Value> value) { - return toSmallerUInt<uint8_t>(value, configuration, ok); + NonThrowableExceptionState exceptionState; + return toUInt8(value, NormalConversion, exceptionState); } -int16_t toInt16(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) +int16_t toInt16(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - return toSmallerInt<int16_t>(value, configuration, ok); + return toSmallerInt<int16_t>(value, configuration, "short", exceptionState); } -uint16_t toUInt16(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) +int16_t toInt16(v8::Handle<v8::Value> value) { - return toSmallerUInt<uint16_t>(value, configuration, ok); + NonThrowableExceptionState exceptionState; + return toInt16(value, NormalConversion, exceptionState); } -int32_t toInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) +uint16_t toUInt16(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) { - ok = true; + return toSmallerUInt<uint16_t>(value, configuration, "unsigned short", exceptionState); +} +uint16_t toUInt16(v8::Handle<v8::Value> value) +{ + NonThrowableExceptionState exceptionState; + return toUInt16(value, NormalConversion, exceptionState); +} + +int32_t toInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) +{ // Fast case. The value is already a 32-bit integer. if (value->IsInt32()) return value->Int32Value(); // Can the value be converted to a number? - ok = false; - V8TRYCATCH_RETURN(v8::Local<v8::Number>, numberObject, value->ToNumber(), 0); + TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0); if (numberObject.IsEmpty()) { + exceptionState.throwTypeError("Not convertible to a number value (of type 'long'.)"); return 0; } - ok = true; if (configuration == EnforceRange) - return enforceRange(numberObject->Value(), kMinInt32, kMaxInt32, ok); + return enforceRange(numberObject->Value(), kMinInt32, kMaxInt32, "long", exceptionState); // Does the value convert to nan or to an infinity? double numberValue = numberObject->Value(); @@ -312,14 +352,18 @@ int32_t toInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration conf if (configuration == Clamp) return clampTo<int32_t>(numberObject->Value()); - V8TRYCATCH_RETURN(int32_t, result, numberObject->Int32Value(), 0); + TONATIVE_DEFAULT_EXCEPTIONSTATE(int32_t, result, numberObject->Int32Value(), exceptionState, 0); return result; } -uint32_t toUInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) +int32_t toInt32(v8::Handle<v8::Value> value) { - ok = true; + NonThrowableExceptionState exceptionState; + return toInt32(value, NormalConversion, exceptionState); +} +uint32_t toUInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) +{ // Fast case. The value is already a 32-bit unsigned integer. if (value->IsUint32()) return value->Uint32Value(); @@ -330,22 +374,21 @@ uint32_t toUInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration co if (result >= 0) return result; if (configuration == EnforceRange) { - ok = false; + exceptionState.throwTypeError("Value is outside the 'unsigned long' value range."); return 0; } return result; } // Can the value be converted to a number? - ok = false; - V8TRYCATCH_RETURN(v8::Local<v8::Number>, numberObject, value->ToNumber(), 0); + TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0); if (numberObject.IsEmpty()) { + exceptionState.throwTypeError("Not convertible to a number value (of type 'unsigned long'.)"); return 0; } - ok = true; if (configuration == EnforceRange) - return enforceRange(numberObject->Value(), 0, kMaxUInt32, ok); + return enforceRange(numberObject->Value(), 0, kMaxUInt32, "unsigned long", exceptionState); // Does the value convert to nan or to an infinity? double numberValue = numberObject->Value(); @@ -355,29 +398,33 @@ uint32_t toUInt32(v8::Handle<v8::Value> value, IntegerConversionConfiguration co if (configuration == Clamp) return clampTo<uint32_t>(numberObject->Value()); - V8TRYCATCH_RETURN(uint32_t, result, numberObject->Uint32Value(), 0); + TONATIVE_DEFAULT(uint32_t, result, numberObject->Uint32Value(), 0); return result; } -int64_t toInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) +uint32_t toUInt32(v8::Handle<v8::Value> value) { - ok = true; + NonThrowableExceptionState exceptionState; + return toUInt32(value, NormalConversion, exceptionState); +} +int64_t toInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) +{ // Fast case. The value is a 32-bit integer. if (value->IsInt32()) return value->Int32Value(); // Can the value be converted to a number? - v8::Local<v8::Number> numberObject = value->ToNumber(); + TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0); if (numberObject.IsEmpty()) { - ok = false; + exceptionState.throwTypeError("Not convertible to a number value (of type 'long long'.)"); return 0; } double x = numberObject->Value(); if (configuration == EnforceRange) - return enforceRange(x, -kJSMaxInteger, kJSMaxInteger, ok); + return enforceRange(x, -kJSMaxInteger, kJSMaxInteger, "long long", exceptionState); // Does the value convert to nan or to an infinity? if (std::isnan(x) || std::isinf(x)) @@ -389,10 +436,14 @@ int64_t toInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration conf return integer; } -uint64_t toUInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, bool& ok) +int64_t toInt64(v8::Handle<v8::Value> value) { - ok = true; + NonThrowableExceptionState exceptionState; + return toInt64(value, NormalConversion, exceptionState); +} +uint64_t toUInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration configuration, ExceptionState& exceptionState) +{ // Fast case. The value is a 32-bit unsigned integer. if (value->IsUint32()) return value->Uint32Value(); @@ -403,23 +454,23 @@ uint64_t toUInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration co if (result >= 0) return result; if (configuration == EnforceRange) { - ok = false; + exceptionState.throwTypeError("Value is outside the 'unsigned long long' value range."); return 0; } return result; } // Can the value be converted to a number? - v8::Local<v8::Number> numberObject = value->ToNumber(); + TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0); if (numberObject.IsEmpty()) { - ok = false; + exceptionState.throwTypeError("Not convertible to a number value (of type 'unsigned long long'.)"); return 0; } double x = numberObject->Value(); if (configuration == EnforceRange) - return enforceRange(x, 0, kJSMaxInteger, ok); + return enforceRange(x, 0, kJSMaxInteger, "unsigned long long", exceptionState); // Does the value convert to nan or to an infinity? if (std::isnan(x) || std::isinf(x)) @@ -431,134 +482,283 @@ uint64_t toUInt64(v8::Handle<v8::Value> value, IntegerConversionConfiguration co return integer; } -v8::Handle<v8::FunctionTemplate> createRawTemplate(v8::Isolate* isolate) +uint64_t toUInt64(v8::Handle<v8::Value> value) +{ + NonThrowableExceptionState exceptionState; + return toUInt64(value, NormalConversion, exceptionState); +} + +float toFloat(v8::Handle<v8::Value> value, ExceptionState& exceptionState) +{ + TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::Number>, numberObject, value->ToNumber(), exceptionState, 0); + return numberObject->NumberValue(); +} + +String toByteString(v8::Handle<v8::Value> value, ExceptionState& exceptionState) +{ + // Handle null default value. + if (value.IsEmpty()) + return String(); + + // From the Web IDL spec: http://heycam.github.io/webidl/#es-ByteString + if (value.IsEmpty()) + return String(); + + // 1. Let x be ToString(v) + TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::String>, stringObject, value->ToString(), exceptionState, String()); + String x = toCoreString(stringObject); + + // 2. If the value of any element of x is greater than 255, then throw a TypeError. + if (!x.containsOnlyLatin1()) { + exceptionState.throwTypeError("Value is not a valid ByteString."); + return String(); + } + + // 3. Return an IDL ByteString value whose length is the length of x, and where the + // value of each element is the value of the corresponding element of x. + // Blink: A ByteString is simply a String with a range constrained per the above, so + // this is the identity operation. + return x; +} + +static bool hasUnmatchedSurrogates(const String& string) +{ + // By definition, 8-bit strings are confined to the Latin-1 code page and + // have no surrogates, matched or otherwise. + if (string.is8Bit()) + return false; + + const UChar* characters = string.characters16(); + const unsigned length = string.length(); + + for (unsigned i = 0; i < length; ++i) { + UChar c = characters[i]; + if (U16_IS_SINGLE(c)) + continue; + if (U16_IS_TRAIL(c)) + return true; + ASSERT(U16_IS_LEAD(c)); + if (i == length - 1) + return true; + UChar d = characters[i + 1]; + if (!U16_IS_TRAIL(d)) + return true; + ++i; + } + return false; +} + +// Replace unmatched surrogates with REPLACEMENT CHARACTER U+FFFD. +static String replaceUnmatchedSurrogates(const String& string) +{ + // This roughly implements http://heycam.github.io/webidl/#dfn-obtain-unicode + // but since Blink strings are 16-bits internally, the output is simply + // re-encoded to UTF-16. + + // The concept of surrogate pairs is explained at: + // http://www.unicode.org/versions/Unicode6.2.0/ch03.pdf#G2630 + + // Blink-specific optimization to avoid making an unnecessary copy. + if (!hasUnmatchedSurrogates(string)) + return string; + ASSERT(!string.is8Bit()); + + // 1. Let S be the DOMString value. + const UChar* s = string.characters16(); + + // 2. Let n be the length of S. + const unsigned n = string.length(); + + // 3. Initialize i to 0. + unsigned i = 0; + + // 4. Initialize U to be an empty sequence of Unicode characters. + StringBuilder u; + u.reserveCapacity(n); + + // 5. While i < n: + while (i < n) { + // 1. Let c be the code unit in S at index i. + UChar c = s[i]; + // 2. Depending on the value of c: + if (U16_IS_SINGLE(c)) { + // c < 0xD800 or c > 0xDFFF + // Append to U the Unicode character with code point c. + u.append(c); + } else if (U16_IS_TRAIL(c)) { + // 0xDC00 <= c <= 0xDFFF + // Append to U a U+FFFD REPLACEMENT CHARACTER. + u.append(WTF::Unicode::replacementCharacter); + } else { + // 0xD800 <= c <= 0xDBFF + ASSERT(U16_IS_LEAD(c)); + if (i == n - 1) { + // 1. If i = n−1, then append to U a U+FFFD REPLACEMENT CHARACTER. + u.append(WTF::Unicode::replacementCharacter); + } else { + // 2. Otherwise, i < n−1: + ASSERT(i < n - 1); + // ....1. Let d be the code unit in S at index i+1. + UChar d = s[i + 1]; + if (U16_IS_TRAIL(d)) { + // 2. If 0xDC00 <= d <= 0xDFFF, then: + // ..1. Let a be c & 0x3FF. + // ..2. Let b be d & 0x3FF. + // ..3. Append to U the Unicode character with code point 2^16+2^10*a+b. + u.append(U16_GET_SUPPLEMENTARY(c, d)); + // Blink: This is equivalent to u.append(c); u.append(d); + ++i; + } else { + // 3. Otherwise, d < 0xDC00 or d > 0xDFFF. Append to U a U+FFFD REPLACEMENT CHARACTER. + u.append(WTF::Unicode::replacementCharacter); + } + } + } + // 3. Set i to i+1. + ++i; + } + + // 6. Return U. + ASSERT(u.length() == string.length()); + return u.toString(); +} + +String toScalarValueString(v8::Handle<v8::Value> value, ExceptionState& exceptionState) { - v8::EscapableHandleScope scope(isolate); - v8::Local<v8::FunctionTemplate> result = v8::FunctionTemplate::New(isolate, V8ObjectConstructor::isValidConstructorMode); - return scope.Escape(result); + // From the Encoding standard (with a TODO to move to Web IDL): + // http://encoding.spec.whatwg.org/#type-scalarvaluestring + if (value.IsEmpty()) + return String(); + TONATIVE_DEFAULT_EXCEPTIONSTATE(v8::Local<v8::String>, stringObject, value->ToString(), exceptionState, String()); + + // ScalarValueString is identical to DOMString except that "convert a + // DOMString to a sequence of Unicode characters" is used subsequently + // when converting to an IDL value + String x = toCoreString(stringObject); + return replaceUnmatchedSurrogates(x); } -PassRefPtr<XPathNSResolver> toXPathNSResolver(v8::Handle<v8::Value> value, v8::Isolate* isolate) +PassRefPtrWillBeRawPtr<XPathNSResolver> toXPathNSResolver(v8::Handle<v8::Value> value, v8::Isolate* isolate) { - RefPtr<XPathNSResolver> resolver; - if (V8XPathNSResolver::hasInstance(value, isolate, worldType(isolate))) + RefPtrWillBeRawPtr<XPathNSResolver> resolver = nullptr; + if (V8XPathNSResolver::hasInstance(value, isolate)) resolver = V8XPathNSResolver::toNative(v8::Handle<v8::Object>::Cast(value)); else if (value->IsObject()) resolver = V8CustomXPathNSResolver::create(value->ToObject(), isolate); return resolver; } -v8::Handle<v8::Object> toInnerGlobalObject(v8::Handle<v8::Context> context) +LocalDOMWindow* toDOMWindow(v8::Handle<v8::Value> value, v8::Isolate* isolate) { - return v8::Handle<v8::Object>::Cast(context->Global()->GetPrototype()); + if (value.IsEmpty() || !value->IsObject()) + return 0; + + v8::Handle<v8::Object> windowWrapper = V8Window::findInstanceInPrototypeChain(v8::Handle<v8::Object>::Cast(value), isolate); + if (!windowWrapper.IsEmpty()) + return V8Window::toNative(windowWrapper); + return 0; } -DOMWindow* toDOMWindow(v8::Handle<v8::Context> context) +LocalDOMWindow* toDOMWindow(v8::Handle<v8::Context> context) { - v8::Handle<v8::Object> global = context->Global(); - ASSERT(!global.IsEmpty()); - v8::Handle<v8::Object> window = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), MainWorld)); - if (!window.IsEmpty()) - return V8Window::toNative(window); - window = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), IsolatedWorld)); - ASSERT(!window.IsEmpty()); - return V8Window::toNative(window); + if (context.IsEmpty()) + return 0; + return toDOMWindow(context->Global(), context->GetIsolate()); +} + +LocalDOMWindow* enteredDOMWindow(v8::Isolate* isolate) +{ + LocalDOMWindow* window = toDOMWindow(isolate->GetEnteredContext()); + if (!window) { + // We don't always have an entered DOM window, for example during microtask callbacks from V8 + // (where the entered context may be the DOM-in-JS context). In that case, we fall back + // to the current context. + window = currentDOMWindow(isolate); + ASSERT(window); + } + return window; +} + +LocalDOMWindow* currentDOMWindow(v8::Isolate* isolate) +{ + return toDOMWindow(isolate->GetCurrentContext()); +} + +LocalDOMWindow* callingDOMWindow(v8::Isolate* isolate) +{ + v8::Handle<v8::Context> context = isolate->GetCallingContext(); + if (context.IsEmpty()) { + // Unfortunately, when processing script from a plug-in, we might not + // have a calling context. In those cases, we fall back to the + // entered context. + context = isolate->GetEnteredContext(); + } + return toDOMWindow(context); } ExecutionContext* toExecutionContext(v8::Handle<v8::Context> context) { v8::Handle<v8::Object> global = context->Global(); - v8::Handle<v8::Object> windowWrapper = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), MainWorld)); - if (!windowWrapper.IsEmpty()) - return V8Window::toNative(windowWrapper)->executionContext(); - windowWrapper = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), IsolatedWorld)); + v8::Handle<v8::Object> windowWrapper = V8Window::findInstanceInPrototypeChain(global, context->GetIsolate()); if (!windowWrapper.IsEmpty()) return V8Window::toNative(windowWrapper)->executionContext(); - v8::Handle<v8::Object> workerWrapper = global->FindInstanceInPrototypeChain(V8WorkerGlobalScope::domTemplate(context->GetIsolate(), WorkerWorld)); + v8::Handle<v8::Object> workerWrapper = V8WorkerGlobalScope::findInstanceInPrototypeChain(global, context->GetIsolate()); if (!workerWrapper.IsEmpty()) return V8WorkerGlobalScope::toNative(workerWrapper)->executionContext(); // FIXME: Is this line of code reachable? return 0; } -DOMWindow* activeDOMWindow() +ExecutionContext* currentExecutionContext(v8::Isolate* isolate) { - v8::Handle<v8::Context> context = v8::Isolate::GetCurrent()->GetCallingContext(); - if (context.IsEmpty()) { - // Unfortunately, when processing script from a plug-in, we might not - // have a calling context. In those cases, we fall back to the - // entered context. - context = v8::Isolate::GetCurrent()->GetEnteredContext(); - } - return toDOMWindow(context); + return toExecutionContext(isolate->GetCurrentContext()); } -ExecutionContext* activeExecutionContext() +ExecutionContext* callingExecutionContext(v8::Isolate* isolate) { - v8::Handle<v8::Context> context = v8::Isolate::GetCurrent()->GetCallingContext(); + v8::Handle<v8::Context> context = isolate->GetCallingContext(); if (context.IsEmpty()) { // Unfortunately, when processing script from a plug-in, we might not // have a calling context. In those cases, we fall back to the // entered context. - context = v8::Isolate::GetCurrent()->GetEnteredContext(); + context = isolate->GetEnteredContext(); } return toExecutionContext(context); } -DOMWindow* firstDOMWindow() -{ - return toDOMWindow(v8::Isolate::GetCurrent()->GetEnteredContext()); -} - -Document* currentDocument() -{ - return toDOMWindow(v8::Isolate::GetCurrent()->GetCurrentContext())->document(); -} - -Frame* toFrameIfNotDetached(v8::Handle<v8::Context> context) +LocalFrame* toFrameIfNotDetached(v8::Handle<v8::Context> context) { - DOMWindow* window = toDOMWindow(context); - if (window->isCurrentlyDisplayedInFrame()) + LocalDOMWindow* window = toDOMWindow(context); + if (window && window->isCurrentlyDisplayedInFrame()) return window->frame(); - // We return 0 here because |context| is detached from the Frame. If we + // We return 0 here because |context| is detached from the LocalFrame. If we // did return |frame| we could get in trouble because the frame could be // navigated to another security origin. return 0; } -v8::Local<v8::Context> toV8Context(ExecutionContext* context, DOMWrapperWorld* world) +v8::Local<v8::Context> toV8Context(ExecutionContext* context, DOMWrapperWorld& world) { + ASSERT(context); if (context->isDocument()) { - ASSERT(world); - if (Frame* frame = toDocument(context)->frame()) + if (LocalFrame* frame = toDocument(context)->frame()) return frame->script().windowShell(world)->context(); } else if (context->isWorkerGlobalScope()) { - ASSERT(!world); if (WorkerScriptController* script = toWorkerGlobalScope(context)->script()) return script->context(); } return v8::Local<v8::Context>(); } -bool handleOutOfMemory() +v8::Local<v8::Context> toV8Context(LocalFrame* frame, DOMWrapperWorld& world) { - v8::Local<v8::Context> context = v8::Isolate::GetCurrent()->GetCurrentContext(); - - if (!context->HasOutOfMemoryException()) - return false; - - // Warning, error, disable JS for this frame? - Frame* frame = toFrameIfNotDetached(context); if (!frame) - return true; - - frame->script().clearForOutOfMemory(); - frame->loader().client()->didExhaustMemoryAvailableForScript(); - - if (Settings* settings = frame->settings()) - settings->setScriptEnabled(false); - - return true; + return v8::Local<v8::Context>(); + v8::Local<v8::Context> context = frame->script().windowShell(world)->context(); + if (context.IsEmpty()) + return v8::Local<v8::Context>(); + LocalFrame* attachedFrame= toFrameIfNotDetached(context); + return frame == attachedFrame ? context : v8::Local<v8::Context>(); } v8::Local<v8::Value> handleMaxRecursionDepthExceeded(v8::Isolate* isolate) @@ -576,73 +776,165 @@ void crashIfV8IsDead() } } -WrapperWorldType worldType(v8::Isolate* isolate) +v8::Handle<v8::Function> getBoundFunction(v8::Handle<v8::Function> function) { - V8PerIsolateData* data = V8PerIsolateData::from(isolate); - if (!data->workerDOMDataStore()) - return worldTypeInMainThread(isolate); - return WorkerWorld; + v8::Handle<v8::Value> boundFunction = function->GetBoundFunction(); + return boundFunction->IsFunction() ? v8::Handle<v8::Function>::Cast(boundFunction) : function; } -WrapperWorldType worldTypeInMainThread(v8::Isolate* isolate) +void addHiddenValueToArray(v8::Handle<v8::Object> object, v8::Local<v8::Value> value, int arrayIndex, v8::Isolate* isolate) { - if (!DOMWrapperWorld::isolatedWorldsExist()) - return MainWorld; - ASSERT(!isolate->GetEnteredContext().IsEmpty()); - DOMWrapperWorld* isolatedWorld = DOMWrapperWorld::isolatedWorld(isolate->GetEnteredContext()); - if (isolatedWorld) - return IsolatedWorld; - return MainWorld; + v8::Local<v8::Value> arrayValue = object->GetInternalField(arrayIndex); + if (arrayValue->IsNull() || arrayValue->IsUndefined()) { + arrayValue = v8::Array::New(isolate); + object->SetInternalField(arrayIndex, arrayValue); + } + + v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(arrayValue); + array->Set(v8::Integer::New(isolate, array->Length()), value); } -DOMWrapperWorld* isolatedWorldForIsolate(v8::Isolate* isolate) +void removeHiddenValueFromArray(v8::Handle<v8::Object> object, v8::Local<v8::Value> value, int arrayIndex, v8::Isolate* isolate) { - V8PerIsolateData* data = V8PerIsolateData::from(isolate); - if (data->workerDOMDataStore()) - return 0; - if (!DOMWrapperWorld::isolatedWorldsExist()) - return 0; - ASSERT(isolate->InContext()); - return DOMWrapperWorld::isolatedWorld(isolate->GetCurrentContext()); + v8::Local<v8::Value> arrayValue = object->GetInternalField(arrayIndex); + if (!arrayValue->IsArray()) + return; + v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(arrayValue); + for (int i = array->Length() - 1; i >= 0; --i) { + v8::Local<v8::Value> item = array->Get(v8::Integer::New(isolate, i)); + if (item->StrictEquals(value)) { + array->Delete(i); + return; + } + } } -v8::Local<v8::Value> getHiddenValueFromMainWorldWrapper(v8::Isolate* isolate, ScriptWrappable* wrappable, v8::Handle<v8::String> key) +void moveEventListenerToNewWrapper(v8::Handle<v8::Object> object, EventListener* oldValue, v8::Local<v8::Value> newValue, int arrayIndex, v8::Isolate* isolate) { - v8::Local<v8::Object> wrapper = wrappable->newLocalWrapper(isolate); - return wrapper.IsEmpty() ? v8::Local<v8::Value>() : wrapper->GetHiddenValue(key); + if (oldValue) { + V8AbstractEventListener* oldListener = V8AbstractEventListener::cast(oldValue); + if (oldListener) { + v8::Local<v8::Object> oldListenerObject = oldListener->getExistingListenerObject(); + if (!oldListenerObject.IsEmpty()) + removeHiddenValueFromArray(object, oldListenerObject, arrayIndex, isolate); + } + } + // Non-callable input is treated as null and ignored + if (newValue->IsFunction()) + addHiddenValueToArray(object, newValue, arrayIndex, isolate); } -static gin::IsolateHolder* mainIsolateHolder = 0; +v8::Isolate* toIsolate(ExecutionContext* context) +{ + if (context && context->isDocument()) + return V8PerIsolateData::mainThreadIsolate(); + return v8::Isolate::GetCurrent(); +} -v8::Isolate* mainThreadIsolate() +v8::Isolate* toIsolate(LocalFrame* frame) { - ASSERT(mainIsolateHolder); - ASSERT(isMainThread()); - return mainIsolateHolder->isolate(); + ASSERT(frame); + return frame->script().isolate(); } -void setMainThreadIsolate(v8::Isolate* isolate) +PassRefPtr<JSONValue> v8ToJSONValue(v8::Isolate* isolate, v8::Handle<v8::Value> value, int maxDepth) { - ASSERT(!mainIsolateHolder || !isolate); - ASSERT(isMainThread()); - if (isolate) { - mainIsolateHolder = new gin::IsolateHolder(isolate); - } else { - delete mainIsolateHolder; - mainIsolateHolder = 0; + if (value.IsEmpty()) { + ASSERT_NOT_REACHED(); + return nullptr; + } + + if (!maxDepth) + return nullptr; + maxDepth--; + + if (value->IsNull() || value->IsUndefined()) + return JSONValue::null(); + if (value->IsBoolean()) + return JSONBasicValue::create(value->BooleanValue()); + if (value->IsNumber()) + return JSONBasicValue::create(value->NumberValue()); + if (value->IsString()) + return JSONString::create(toCoreString(value.As<v8::String>())); + if (value->IsArray()) { + v8::Handle<v8::Array> array = v8::Handle<v8::Array>::Cast(value); + RefPtr<JSONArray> inspectorArray = JSONArray::create(); + uint32_t length = array->Length(); + for (uint32_t i = 0; i < length; i++) { + v8::Local<v8::Value> value = array->Get(v8::Int32::New(isolate, i)); + RefPtr<JSONValue> element = v8ToJSONValue(isolate, value, maxDepth); + if (!element) + return nullptr; + inspectorArray->pushValue(element); + } + return inspectorArray; + } + if (value->IsObject()) { + RefPtr<JSONObject> jsonObject = JSONObject::create(); + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); + v8::Local<v8::Array> propertyNames = object->GetPropertyNames(); + uint32_t length = propertyNames->Length(); + for (uint32_t i = 0; i < length; i++) { + v8::Local<v8::Value> name = propertyNames->Get(v8::Int32::New(isolate, i)); + // FIXME(yurys): v8::Object should support GetOwnPropertyNames + if (name->IsString() && !object->HasRealNamedProperty(v8::Handle<v8::String>::Cast(name))) + continue; + RefPtr<JSONValue> propertyValue = v8ToJSONValue(isolate, object->Get(name), maxDepth); + if (!propertyValue) + return nullptr; + TOSTRING_DEFAULT(V8StringResource<WithNullCheck>, nameString, name, nullptr); + jsonObject->setValue(nameString, propertyValue); + } + return jsonObject; } + ASSERT_NOT_REACHED(); + return nullptr; } -v8::Isolate* toIsolate(ExecutionContext* context) +V8TestingScope::V8TestingScope(v8::Isolate* isolate) + : m_handleScope(isolate) + , m_contextScope(v8::Context::New(isolate)) + , m_scriptState(ScriptStateForTesting::create(isolate->GetCurrentContext(), DOMWrapperWorld::create())) { - if (context && context->isDocument()) - return mainThreadIsolate(); - return v8::Isolate::GetCurrent(); } -v8::Isolate* toIsolate(Frame* frame) +V8TestingScope::~V8TestingScope() { - return frame->script().isolate(); + m_scriptState->disposePerContextData(); +} + +ScriptState* V8TestingScope::scriptState() const +{ + return m_scriptState.get(); +} + +v8::Isolate* V8TestingScope::isolate() const +{ + return m_scriptState->isolate(); +} + +void GetDevToolsFunctionInfo(v8::Handle<v8::Function> function, v8::Isolate* isolate, int& scriptId, String& resourceName, int& lineNumber) +{ + v8::Handle<v8::Function> originalFunction = getBoundFunction(function); + scriptId = originalFunction->ScriptId(); + v8::ScriptOrigin origin = originalFunction->GetScriptOrigin(); + if (!origin.ResourceName().IsEmpty()) { + resourceName = NativeValueTraits<String>::nativeValue(origin.ResourceName(), isolate); + lineNumber = originalFunction->GetScriptLineNumber() + 1; + } + if (resourceName.isEmpty()) { + resourceName = "undefined"; + lineNumber = 1; + } +} + +PassRefPtr<TraceEvent::ConvertableToTraceFormat> devToolsTraceEventData(ExecutionContext* context, v8::Handle<v8::Function> function, v8::Isolate* isolate) +{ + int scriptId = 0; + String resourceName; + int lineNumber = 1; + GetDevToolsFunctionInfo(function, isolate, scriptId, resourceName, lineNumber); + return InspectorFunctionCallEvent::data(context, scriptId, resourceName, lineNumber); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8Binding.h b/chromium/third_party/WebKit/Source/bindings/v8/V8Binding.h index 48200a2fdd0..7fb8e727b57 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8Binding.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8Binding.h @@ -34,668 +34,942 @@ #include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/ExceptionMessages.h" +#include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8BindingMacros.h" #include "bindings/v8/V8PerIsolateData.h" #include "bindings/v8/V8StringResource.h" #include "bindings/v8/V8ThrowException.h" #include "bindings/v8/V8ValueCache.h" +#include "platform/heap/Heap.h" #include "wtf/MathExtras.h" #include "wtf/text/AtomicString.h" #include <v8.h> namespace WebCore { - class DOMWindow; - class Document; - class Frame; - class NodeFilter; - class ExecutionContext; - class ScriptWrappable; - class XPathNSResolver; +class LocalDOMWindow; +class Document; +class EventListener; +class ExecutionContext; +class ExceptionState; +class LocalFrame; +class NodeFilter; +class ScriptWrappable; +class XPathNSResolver; + +namespace TraceEvent { +class ConvertableToTraceFormat; +} + +const int kMaxRecursionDepth = 22; + +// Schedule a JavaScript error to be thrown. +v8::Handle<v8::Value> throwError(V8ErrorType, const String&, v8::Isolate*); + +// Schedule a JavaScript error to be thrown. +v8::Handle<v8::Value> throwError(v8::Handle<v8::Value>, v8::Isolate*); + +// A helper for throwing JavaScript TypeError. +v8::Handle<v8::Value> throwTypeError(const String&, v8::Isolate*); + +// Helpers for throwing JavaScript TypeErrors for arity mismatches. +void throwArityTypeErrorForMethod(const char* method, const char* type, const char* valid, unsigned provided, v8::Isolate*); +void throwArityTypeErrorForConstructor(const char* type, const char* valid, unsigned provided, v8::Isolate*); +void throwArityTypeError(ExceptionState&, const char* valid, unsigned provided); +void throwMinimumArityTypeErrorForMethod(const char* method, const char* type, unsigned expected, unsigned providedLeastNumMandatoryParams, v8::Isolate*); +void throwMinimumArityTypeErrorForConstructor(const char* type, unsigned expected, unsigned providedLeastNumMandatoryParams, v8::Isolate*); +void throwMinimumArityTypeError(ExceptionState&, unsigned expected, unsigned providedLeastNumMandatoryParams); + +v8::ArrayBuffer::Allocator* v8ArrayBufferAllocator(); + +inline v8::Handle<v8::Value> argumentOrNull(const v8::FunctionCallbackInfo<v8::Value>& info, int index) +{ + return index >= info.Length() ? v8::Local<v8::Value>() : info[index]; +} + +template<typename CallbackInfo, typename V> +inline void v8SetReturnValue(const CallbackInfo& info, V v) +{ + info.GetReturnValue().Set(v); +} + +template<typename CallbackInfo> +inline void v8SetReturnValueBool(const CallbackInfo& info, bool v) +{ + info.GetReturnValue().Set(v); +} + +template<typename CallbackInfo> +inline void v8SetReturnValueInt(const CallbackInfo& info, int v) +{ + info.GetReturnValue().Set(v); +} + +template<typename CallbackInfo> +inline void v8SetReturnValueUnsigned(const CallbackInfo& info, unsigned v) +{ + info.GetReturnValue().Set(v); +} + +template<typename CallbackInfo> +inline void v8SetReturnValueNull(const CallbackInfo& info) +{ + info.GetReturnValue().SetNull(); +} + +template<typename CallbackInfo> +inline void v8SetReturnValueUndefined(const CallbackInfo& info) +{ + info.GetReturnValue().SetUndefined(); +} + +template<typename CallbackInfo> +inline void v8SetReturnValueEmptyString(const CallbackInfo& info) +{ + info.GetReturnValue().SetEmptyString(); +} + +template <class CallbackInfo> +inline void v8SetReturnValueString(const CallbackInfo& info, const String& string, v8::Isolate* isolate) +{ + if (string.isNull()) { + v8SetReturnValueEmptyString(info); + return; + } + V8PerIsolateData::from(isolate)->stringCache()->setReturnValueFromString(info.GetReturnValue(), string.impl()); +} + +template <class CallbackInfo> +inline void v8SetReturnValueStringOrNull(const CallbackInfo& info, const String& string, v8::Isolate* isolate) +{ + if (string.isNull()) { + v8SetReturnValueNull(info); + return; + } + V8PerIsolateData::from(isolate)->stringCache()->setReturnValueFromString(info.GetReturnValue(), string.impl()); +} + +template <class CallbackInfo> +inline void v8SetReturnValueStringOrUndefined(const CallbackInfo& info, const String& string, v8::Isolate* isolate) +{ + if (string.isNull()) { + v8SetReturnValueUndefined(info); + return; + } + V8PerIsolateData::from(isolate)->stringCache()->setReturnValueFromString(info.GetReturnValue(), string.impl()); +} + +// Convert v8::String to a WTF::String. If the V8 string is not already +// an external string then it is transformed into an external string at this +// point to avoid repeated conversions. +inline String toCoreString(v8::Handle<v8::String> value) +{ + return v8StringToWebCoreString<String>(value, Externalize); +} + +inline String toCoreStringWithNullCheck(v8::Handle<v8::String> value) +{ + if (value.IsEmpty() || value->IsNull()) + return String(); + return toCoreString(value); +} + +inline String toCoreStringWithUndefinedOrNullCheck(v8::Handle<v8::String> value) +{ + if (value.IsEmpty() || value->IsNull() || value->IsUndefined()) + return String(); + return toCoreString(value); +} + +inline AtomicString toCoreAtomicString(v8::Handle<v8::String> value) +{ + return v8StringToWebCoreString<AtomicString>(value, Externalize); +} + +// This method will return a null String if the v8::Value does not contain a v8::String. +// It will not call ToString() on the v8::Value. If you want ToString() to be called, +// please use the TONATIVE_FOR_V8STRINGRESOURCE_*() macros instead. +inline String toCoreStringWithUndefinedOrNullCheck(v8::Handle<v8::Value> value) +{ + if (value.IsEmpty() || !value->IsString()) + return String(); + return toCoreString(value.As<v8::String>()); +} + +// Convert a string to a V8 string. +// Return a V8 external string that shares the underlying buffer with the given +// WebCore string. The reference counting mechanism is used to keep the +// underlying buffer alive while the string is still live in the V8 engine. +inline v8::Handle<v8::String> v8String(v8::Isolate* isolate, const String& string) +{ + if (string.isNull()) + return v8::String::Empty(isolate); + return V8PerIsolateData::from(isolate)->stringCache()->v8ExternalString(string.impl(), isolate); +} + +inline v8::Handle<v8::String> v8AtomicString(v8::Isolate* isolate, const char* str) +{ + ASSERT(isolate); + return v8::String::NewFromUtf8(isolate, str, v8::String::kInternalizedString, strlen(str)); +} - const int kMaxRecursionDepth = 22; +inline v8::Handle<v8::String> v8AtomicString(v8::Isolate* isolate, const char* str, size_t length) +{ + ASSERT(isolate); + return v8::String::NewFromUtf8(isolate, str, v8::String::kInternalizedString, length); +} - // Schedule a DOM exception to be thrown, if the exception code is different - // from zero. - v8::Handle<v8::Value> setDOMException(int, v8::Isolate*); - v8::Handle<v8::Value> setDOMException(int, const String&, v8::Isolate*); +inline v8::Handle<v8::Value> v8Undefined() +{ + return v8::Handle<v8::Value>(); +} - // Schedule a JavaScript error to be thrown. - v8::Handle<v8::Value> throwError(V8ErrorType, const String&, v8::Isolate*); - - // Schedule a JavaScript error to be thrown. - v8::Handle<v8::Value> throwError(v8::Handle<v8::Value>, v8::Isolate*); - - // A helper for throwing JavaScript TypeError. - v8::Handle<v8::Value> throwTypeError(const String&, v8::Isolate*); - - // FIXME: Remove this once we kill its callers. - v8::Handle<v8::Value> throwUninformativeAndGenericTypeError(v8::Isolate*); - - v8::ArrayBuffer::Allocator* v8ArrayBufferAllocator(); - - v8::Handle<v8::Value> toV8Sequence(v8::Handle<v8::Value>, uint32_t& length, v8::Isolate*); - - inline v8::Handle<v8::Value> argumentOrNull(const v8::FunctionCallbackInfo<v8::Value>& info, int index) +template <class T> +struct V8ValueTraits { + // FIXME: This function requires the associated generated header to be + // included. Also, this function does not match with other V8ValueTraits + // classes. Remove this V8ValueTraits if possible. + static inline v8::Handle<v8::Value> toV8Value(const T& value, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { - return index >= info.Length() ? v8::Local<v8::Value>() : info[index]; + return toV8(WTF::getPtr(value), creationContext, isolate); } +}; - template<typename CallbackInfo, typename V> - inline void v8SetReturnValue(const CallbackInfo& info, V v) +template<> +struct V8ValueTraits<String> { + static inline v8::Handle<v8::Value> toV8Value(const String& value, v8::Handle<v8::Object>, v8::Isolate* isolate) { - info.GetReturnValue().Set(v); + return v8String(isolate, value); } +}; - template<typename CallbackInfo> - inline void v8SetReturnValueBool(const CallbackInfo& info, bool v) +template<> +struct V8ValueTraits<AtomicString> { + static inline v8::Handle<v8::Value> toV8Value(const AtomicString& value, v8::Handle<v8::Object>, v8::Isolate* isolate) { - info.GetReturnValue().Set(v); + return v8String(isolate, value); } +}; - template<typename CallbackInfo> - inline void v8SetReturnValueInt(const CallbackInfo& info, int v) +template<size_t n> +struct V8ValueTraits<char[n]> { + static inline v8::Handle<v8::Value> toV8Value(char const (&value)[n], v8::Handle<v8::Object>, v8::Isolate* isolate) { - info.GetReturnValue().Set(v); + return v8String(isolate, value); } +}; - template<typename CallbackInfo> - inline void v8SetReturnValueUnsigned(const CallbackInfo& info, unsigned v) +template<> +struct V8ValueTraits<const char*> { + static inline v8::Handle<v8::Value> toV8Value(const char* const& value, v8::Handle<v8::Object>, v8::Isolate* isolate) { - info.GetReturnValue().Set(v); + return v8String(isolate, value); } +}; - template<typename CallbackInfo> - inline void v8SetReturnValueNull(const CallbackInfo& info) +template<> +struct V8ValueTraits<int> { + static inline v8::Handle<v8::Value> toV8Value(const int& value, v8::Handle<v8::Object>, v8::Isolate* isolate) { - info.GetReturnValue().SetNull(); + return v8::Integer::New(isolate, value); } +}; - template<typename CallbackInfo> - inline void v8SetReturnValueUndefined(const CallbackInfo& info) +template<> +struct V8ValueTraits<long> { + static inline v8::Handle<v8::Value> toV8Value(const long& value, v8::Handle<v8::Object>, v8::Isolate* isolate) { - info.GetReturnValue().SetUndefined(); + return v8::Integer::New(isolate, value); } +}; - template<typename CallbackInfo> - inline void v8SetReturnValueEmptyString(const CallbackInfo& info) +template<> +struct V8ValueTraits<unsigned> { + static inline v8::Handle<v8::Value> toV8Value(const unsigned& value, v8::Handle<v8::Object>, v8::Isolate* isolate) { - info.GetReturnValue().SetEmptyString(); + return v8::Integer::NewFromUnsigned(isolate, value); } +}; - template <class CallbackInfo> - inline void v8SetReturnValueString(const CallbackInfo& info, const String& string, v8::Isolate* isolate) +template<> +struct V8ValueTraits<unsigned long> { + static inline v8::Handle<v8::Value> toV8Value(const unsigned long& value, v8::Handle<v8::Object>, v8::Isolate* isolate) { - if (string.isNull()) { - v8SetReturnValueEmptyString(info); - return; - } - V8PerIsolateData::from(isolate)->stringCache()->setReturnValueFromString(info.GetReturnValue(), string.impl()); + return v8::Integer::NewFromUnsigned(isolate, value); } +}; - template <class CallbackInfo> - inline void v8SetReturnValueStringOrNull(const CallbackInfo& info, const String& string, v8::Isolate* isolate) +template<> +struct V8ValueTraits<float> { + static inline v8::Handle<v8::Value> toV8Value(const float& value, v8::Handle<v8::Object>, v8::Isolate* isolate) { - if (string.isNull()) { - v8SetReturnValueNull(info); - return; - } - V8PerIsolateData::from(isolate)->stringCache()->setReturnValueFromString(info.GetReturnValue(), string.impl()); + return v8::Number::New(isolate, value); } +}; - template <class CallbackInfo> - inline void v8SetReturnValueStringOrUndefined(const CallbackInfo& info, const String& string, v8::Isolate* isolate) +template<> +struct V8ValueTraits<double> { + static inline v8::Handle<v8::Value> toV8Value(const double& value, v8::Handle<v8::Object>, v8::Isolate* isolate) { - if (string.isNull()) { - v8SetReturnValueUndefined(info); - return; - } - V8PerIsolateData::from(isolate)->stringCache()->setReturnValueFromString(info.GetReturnValue(), string.impl()); + return v8::Number::New(isolate, value); } +}; - // Convert v8::String to a WTF::String. If the V8 string is not already - // an external string then it is transformed into an external string at this - // point to avoid repeated conversions. - inline String toCoreString(v8::Handle<v8::String> value) +template<> +struct V8ValueTraits<bool> { + static inline v8::Handle<v8::Value> toV8Value(const bool& value, v8::Handle<v8::Object>, v8::Isolate* isolate) { - return v8StringToWebCoreString<String>(value, Externalize); + return v8::Boolean::New(isolate, value); } +}; - inline String toCoreStringWithNullCheck(v8::Handle<v8::String> value) - { - if (value.IsEmpty() || value->IsNull()) - return String(); - return toCoreString(value); - } +// V8NullType and V8UndefinedType are used only for the value conversion. +class V8NullType { }; +class V8UndefinedType { }; - inline String toCoreStringWithUndefinedOrNullCheck(v8::Handle<v8::String> value) +template<> +struct V8ValueTraits<V8NullType> { + static inline v8::Handle<v8::Value> toV8Value(const V8NullType&, v8::Handle<v8::Object>, v8::Isolate* isolate) { - if (value.IsEmpty() || value->IsNull() || value->IsUndefined()) - return String(); - return toCoreString(value); + return v8::Null(isolate); } +}; - inline AtomicString toCoreAtomicString(v8::Handle<v8::String> value) +template<> +struct V8ValueTraits<V8UndefinedType> { + static inline v8::Handle<v8::Value> toV8Value(const V8UndefinedType&, v8::Handle<v8::Object>, v8::Isolate* isolate) { - return v8StringToWebCoreString<AtomicString>(value, Externalize); + return v8::Undefined(isolate); } +}; - // This method will return a null String if the v8::Value does not contain a v8::String. - // It will not call ToString() on the v8::Value. If you want ToString() to be called, - // please use the V8TRYCATCH_FOR_V8STRINGRESOURCE_*() macros instead. - inline String toCoreStringWithUndefinedOrNullCheck(v8::Handle<v8::Value> value) +template<> +struct V8ValueTraits<ScriptValue> { + static inline v8::Handle<v8::Value> toV8Value(const ScriptValue& value, v8::Handle<v8::Object>, v8::Isolate*) { - if (value.IsEmpty() || !value->IsString()) - return String(); - - return toCoreString(value.As<v8::String>()); + return value.v8Value(); } +}; - // Convert a string to a V8 string. - // Return a V8 external string that shares the underlying buffer with the given - // WebCore string. The reference counting mechanism is used to keep the - // underlying buffer alive while the string is still live in the V8 engine. - inline v8::Handle<v8::String> v8String(v8::Isolate* isolate, const String& string) +template<> +struct V8ValueTraits<v8::Handle<v8::Value> > { + static inline v8::Handle<v8::Value> toV8Value(const v8::Handle<v8::Value>& value, v8::Handle<v8::Object>, v8::Isolate*) { - if (string.isNull()) - return v8::String::Empty(isolate); - return V8PerIsolateData::from(isolate)->stringCache()->v8ExternalString(string.impl(), isolate); + return value; } +}; - inline v8::Handle<v8::Value> v8Undefined() +template<> +struct V8ValueTraits<v8::Local<v8::Value> > { + static inline v8::Handle<v8::Value> toV8Value(const v8::Local<v8::Value>& value, v8::Handle<v8::Object>, v8::Isolate*) { - return v8::Handle<v8::Value>(); + return value; } +}; - template <class T> - struct V8ValueTraits { - static inline v8::Handle<v8::Value> arrayV8Value(const T& value, v8::Isolate* isolate) - { - return toV8(WTF::getPtr(value), v8::Handle<v8::Object>(), isolate); - } - }; - - template<> - struct V8ValueTraits<String> { - static inline v8::Handle<v8::Value> arrayV8Value(const String& value, v8::Isolate* isolate) - { - return v8String(isolate, value); - } - }; - - template<> - struct V8ValueTraits<unsigned> { - static inline v8::Handle<v8::Value> arrayV8Value(const unsigned& value, v8::Isolate* isolate) - { - return v8::Integer::NewFromUnsigned(value, isolate); - } - }; - - template<> - struct V8ValueTraits<unsigned long> { - static inline v8::Handle<v8::Value> arrayV8Value(const unsigned long& value, v8::Isolate* isolate) - { - return v8::Integer::NewFromUnsigned(value, isolate); - } - }; - - template<> - struct V8ValueTraits<float> { - static inline v8::Handle<v8::Value> arrayV8Value(const float& value, v8::Isolate* isolate) - { - return v8::Number::New(isolate, value); - } - }; - - template<> - struct V8ValueTraits<double> { - static inline v8::Handle<v8::Value> arrayV8Value(const double& value, v8::Isolate* isolate) - { - return v8::Number::New(isolate, value); - } - }; - - template<typename T, size_t inlineCapacity> - v8::Handle<v8::Value> v8Array(const Vector<T, inlineCapacity>& iterator, v8::Isolate* isolate) +template<typename T, size_t inlineCapacity> +v8::Handle<v8::Value> v8Array(const Vector<T, inlineCapacity>& iterator, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) +{ + v8::Local<v8::Array> result = v8::Array::New(isolate, iterator.size()); + int index = 0; + typename Vector<T, inlineCapacity>::const_iterator end = iterator.end(); + typedef V8ValueTraits<T> TraitsType; + for (typename Vector<T, inlineCapacity>::const_iterator iter = iterator.begin(); iter != end; ++iter) + result->Set(v8::Integer::New(isolate, index++), TraitsType::toV8Value(*iter, creationContext, isolate)); + return result; +} + +template<typename T, size_t inlineCapacity> +v8::Handle<v8::Value> v8Array(const HeapVector<T, inlineCapacity>& iterator, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) +{ + v8::Local<v8::Array> result = v8::Array::New(isolate, iterator.size()); + int index = 0; + typename HeapVector<T, inlineCapacity>::const_iterator end = iterator.end(); + typedef V8ValueTraits<T> TraitsType; + for (typename HeapVector<T, inlineCapacity>::const_iterator iter = iterator.begin(); iter != end; ++iter) + result->Set(v8::Integer::New(isolate, index++), TraitsType::toV8Value(*iter, creationContext, isolate)); + return result; +} + +template<typename T, size_t inlineCapacity> +v8::Handle<v8::Value> v8ArrayNoInline(const Vector<T, inlineCapacity>& iterator, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) +{ + v8::Local<v8::Array> result = v8::Array::New(isolate, iterator.size()); + int index = 0; + typename Vector<T, inlineCapacity>::const_iterator end = iterator.end(); + for (typename Vector<T, inlineCapacity>::const_iterator iter = iterator.begin(); iter != end; ++iter) + result->Set(v8::Integer::New(isolate, index++), toV8NoInline(WTF::getPtr(*iter), creationContext, isolate)); + return result; +} + +template<typename T, size_t inlineCapacity> +v8::Handle<v8::Value> v8ArrayNoInline(const HeapVector<T, inlineCapacity>& iterator, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) +{ + v8::Local<v8::Array> result = v8::Array::New(isolate, iterator.size()); + int index = 0; + typename HeapVector<T, inlineCapacity>::const_iterator end = iterator.end(); + for (typename HeapVector<T, inlineCapacity>::const_iterator iter = iterator.begin(); iter != end; ++iter) + result->Set(v8::Integer::New(isolate, index++), toV8NoInline(WTF::getPtr(*iter), creationContext, isolate)); + return result; +} + +// Conversion flags, used in toIntXX/toUIntXX. +enum IntegerConversionConfiguration { + NormalConversion, + EnforceRange, + Clamp +}; + +// Convert a value to a 8-bit signed integer. The conversion fails if the +// value cannot be converted to a number or the range violated per WebIDL: +// http://www.w3.org/TR/WebIDL/#es-byte +int8_t toInt8(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&); +inline int8_t toInt8(v8::Handle<v8::Value> value, ExceptionState& exceptionState) +{ + return toInt8(value, NormalConversion, exceptionState); +} + +// Convert a value to a 8-bit integer assuming the conversion cannot fail. +int8_t toInt8(v8::Handle<v8::Value>); + +// Convert a value to a 8-bit unsigned integer. The conversion fails if the +// value cannot be converted to a number or the range violated per WebIDL: +// http://www.w3.org/TR/WebIDL/#es-octet +uint8_t toUInt8(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&); +inline uint8_t toUInt8(v8::Handle<v8::Value> value, ExceptionState& exceptionState) +{ + return toUInt8(value, NormalConversion, exceptionState); +} + +// Convert a value to a 8-bit unsigned integer assuming the conversion cannot fail. +uint8_t toUInt8(v8::Handle<v8::Value>); + +// Convert a value to a 16-bit signed integer. The conversion fails if the +// value cannot be converted to a number or the range violated per WebIDL: +// http://www.w3.org/TR/WebIDL/#es-short +int16_t toInt16(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&); +inline int16_t toInt16(v8::Handle<v8::Value> value, ExceptionState& exceptionState) +{ + return toInt16(value, NormalConversion, exceptionState); +} + +// Convert a value to a 16-bit integer assuming the conversion cannot fail. +int16_t toInt16(v8::Handle<v8::Value>); + +// Convert a value to a 16-bit unsigned integer. The conversion fails if the +// value cannot be converted to a number or the range violated per WebIDL: +// http://www.w3.org/TR/WebIDL/#es-unsigned-short +uint16_t toUInt16(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&); +inline uint16_t toUInt16(v8::Handle<v8::Value> value, ExceptionState& exceptionState) +{ + return toUInt16(value, NormalConversion, exceptionState); +} + +// Convert a value to a 16-bit unsigned integer assuming the conversion cannot fail. +uint16_t toUInt16(v8::Handle<v8::Value>); + +// Convert a value to a 32-bit signed integer. The conversion fails if the +// value cannot be converted to a number or the range violated per WebIDL: +// http://www.w3.org/TR/WebIDL/#es-long +int32_t toInt32(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&); +inline int32_t toInt32(v8::Handle<v8::Value> value, ExceptionState& exceptionState) +{ + return toInt32(value, NormalConversion, exceptionState); +} + +// Convert a value to a 32-bit integer assuming the conversion cannot fail. +int32_t toInt32(v8::Handle<v8::Value>); + +// Convert a value to a 32-bit unsigned integer. The conversion fails if the +// value cannot be converted to a number or the range violated per WebIDL: +// http://www.w3.org/TR/WebIDL/#es-unsigned-long +uint32_t toUInt32(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&); +inline uint32_t toUInt32(v8::Handle<v8::Value> value, ExceptionState& exceptionState) +{ + return toUInt32(value, NormalConversion, exceptionState); +} + +// Convert a value to a 32-bit unsigned integer assuming the conversion cannot fail. +uint32_t toUInt32(v8::Handle<v8::Value>); + +// Convert a value to a 64-bit signed integer. The conversion fails if the +// value cannot be converted to a number or the range violated per WebIDL: +// http://www.w3.org/TR/WebIDL/#es-long-long +int64_t toInt64(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&); +inline int64_t toInt64(v8::Handle<v8::Value> value, ExceptionState& exceptionState) +{ + return toInt64(value, NormalConversion, exceptionState); +} + +// Convert a value to a 64-bit integer assuming the conversion cannot fail. +int64_t toInt64(v8::Handle<v8::Value>); + +// Convert a value to a 64-bit unsigned integer. The conversion fails if the +// value cannot be converted to a number or the range violated per WebIDL: +// http://www.w3.org/TR/WebIDL/#es-unsigned-long-long +uint64_t toUInt64(v8::Handle<v8::Value>, IntegerConversionConfiguration, ExceptionState&); +inline uint64_t toUInt64(v8::Handle<v8::Value> value, ExceptionState& exceptionState) +{ + return toUInt64(value, NormalConversion, exceptionState); +} + +// Convert a value to a 64-bit unsigned integer assuming the conversion cannot fail. +uint64_t toUInt64(v8::Handle<v8::Value>); + +// Convert a value to a single precision float, which might fail. +float toFloat(v8::Handle<v8::Value>, ExceptionState&); + +// Convert a value to a single precision float assuming the conversion cannot fail. +inline float toFloat(v8::Local<v8::Value> value) +{ + return static_cast<float>(value->NumberValue()); +} + +// Converts a value to a String, throwing if any code unit is outside 0-255. +String toByteString(v8::Handle<v8::Value>, ExceptionState&); + +// Converts a value to a String, replacing unmatched UTF-16 surrogates with replacement characters. +String toScalarValueString(v8::Handle<v8::Value>, ExceptionState&); + +inline v8::Handle<v8::Boolean> v8Boolean(bool value, v8::Isolate* isolate) +{ + return value ? v8::True(isolate) : v8::False(isolate); +} + +inline double toCoreDate(v8::Handle<v8::Value> object) +{ + if (object->IsDate()) + return v8::Handle<v8::Date>::Cast(object)->ValueOf(); + if (object->IsNumber()) + return object->NumberValue(); + return std::numeric_limits<double>::quiet_NaN(); +} + +inline v8::Handle<v8::Value> v8DateOrNaN(double value, v8::Isolate* isolate) +{ + ASSERT(isolate); + return v8::Date::New(isolate, std::isfinite(value) ? value : std::numeric_limits<double>::quiet_NaN()); +} + +// FIXME: Remove the special casing for NodeFilter and XPathNSResolver. +PassRefPtrWillBeRawPtr<NodeFilter> toNodeFilter(v8::Handle<v8::Value>, v8::Handle<v8::Object>, ScriptState*); +PassRefPtrWillBeRawPtr<XPathNSResolver> toXPathNSResolver(v8::Handle<v8::Value>, v8::Isolate*); + +template<class T> struct NativeValueTraits; + +template<> +struct NativeValueTraits<String> { + static inline String nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) + { + TOSTRING_DEFAULT(V8StringResource<>, stringValue, value, String()); + return stringValue; + } +}; + +template<> +struct NativeValueTraits<unsigned> { + static inline unsigned nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) + { + return toUInt32(value); + } +}; + +template<> +struct NativeValueTraits<float> { + static inline float nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) { - v8::Local<v8::Array> result = v8::Array::New(isolate, iterator.size()); - int index = 0; - typename Vector<T, inlineCapacity>::const_iterator end = iterator.end(); - typedef V8ValueTraits<T> TraitsType; - for (typename Vector<T, inlineCapacity>::const_iterator iter = iterator.begin(); iter != end; ++iter) - result->Set(v8::Integer::New(index++, isolate), TraitsType::arrayV8Value(*iter, isolate)); - return result; + return static_cast<float>(value->NumberValue()); } +}; - // Conversion flags, used in toIntXX/toUIntXX. - enum IntegerConversionConfiguration { - NormalConversion, - EnforceRange, - Clamp - }; - - // Convert a value to a 8-bit signed integer. The conversion fails if the - // value cannot be converted to a number or the range violated per WebIDL: - // http://www.w3.org/TR/WebIDL/#es-byte - int8_t toInt8(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); - inline int8_t toInt8(v8::Handle<v8::Value> value, bool& ok) { return toInt8(value, NormalConversion, ok); } - - // Convert a value to a 8-bit integer assuming the conversion cannot fail. - inline int8_t toInt8(v8::Handle<v8::Value> value) +template<> +struct NativeValueTraits<double> { + static inline double nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) { - bool ok; - return toInt8(value, NormalConversion, ok); + return static_cast<double>(value->NumberValue()); } +}; - // Convert a value to a 8-bit unsigned integer. The conversion fails if the - // value cannot be converted to a number or the range violated per WebIDL: - // http://www.w3.org/TR/WebIDL/#es-octet - uint8_t toUInt8(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); - inline uint8_t toUInt8(v8::Handle<v8::Value> value, bool& ok) { return toUInt8(value, NormalConversion, ok); } - - // Convert a value to a 8-bit unsigned integer assuming the conversion cannot fail. - inline uint8_t toUInt8(v8::Handle<v8::Value> value) +template<> +struct NativeValueTraits<v8::Handle<v8::Value> > { + static inline v8::Handle<v8::Value> nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) { - bool ok; - return toUInt8(value, NormalConversion, ok); + return value; } +}; - // Convert a value to a 16-bit signed integer. The conversion fails if the - // value cannot be converted to a number or the range violated per WebIDL: - // http://www.w3.org/TR/WebIDL/#es-short - int16_t toInt16(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); - inline int16_t toInt16(v8::Handle<v8::Value> value, bool& ok) { return toInt16(value, NormalConversion, ok); } +v8::Handle<v8::Value> toV8Sequence(v8::Handle<v8::Value>, uint32_t& length, v8::Isolate*); - // Convert a value to a 16-bit integer assuming the conversion cannot fail. - inline int16_t toInt16(v8::Handle<v8::Value> value) - { - bool ok; - return toInt16(value, NormalConversion, ok); +// Converts a JavaScript value to an array as per the Web IDL specification: +// http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-array +template <class T, class V8T> +Vector<RefPtr<T> > toRefPtrNativeArrayUnchecked(v8::Local<v8::Value> v8Value, uint32_t length, v8::Isolate* isolate, bool* success = 0) +{ + Vector<RefPtr<T> > result; + result.reserveInitialCapacity(length); + v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value); + for (uint32_t i = 0; i < length; ++i) { + v8::Handle<v8::Value> element = object->Get(i); + if (V8T::hasInstance(element, isolate)) { + v8::Handle<v8::Object> elementObject = v8::Handle<v8::Object>::Cast(element); + result.uncheckedAppend(V8T::toNative(elementObject)); + } else { + if (success) + *success = false; + throwTypeError("Invalid Array element type", isolate); + return Vector<RefPtr<T> >(); + } } - - // Convert a value to a 16-bit unsigned integer. The conversion fails if the - // value cannot be converted to a number or the range violated per WebIDL: - // http://www.w3.org/TR/WebIDL/#es-unsigned-short - uint16_t toUInt16(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); - inline uint16_t toUInt16(v8::Handle<v8::Value> value, bool& ok) { return toUInt16(value, NormalConversion, ok); } - - // Convert a value to a 16-bit unsigned integer assuming the conversion cannot fail. - inline uint16_t toUInt16(v8::Handle<v8::Value> value) - { - bool ok; - return toUInt16(value, NormalConversion, ok); + return result; +} + +template <class T, class V8T> +Vector<RefPtr<T> > toRefPtrNativeArray(v8::Handle<v8::Value> value, int argumentIndex, v8::Isolate* isolate, bool* success = 0) +{ + if (success) + *success = true; + + v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value)); + uint32_t length = 0; + if (value->IsArray()) { + length = v8::Local<v8::Array>::Cast(v8Value)->Length(); + } else if (toV8Sequence(value, length, isolate).IsEmpty()) { + throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex), isolate); + return Vector<RefPtr<T> >(); + } + return toRefPtrNativeArrayUnchecked<T, V8T>(v8Value, length, isolate, success); +} + +template <class T, class V8T> +Vector<RefPtr<T> > toRefPtrNativeArray(v8::Handle<v8::Value> value, const String& propertyName, v8::Isolate* isolate, bool* success = 0) +{ + if (success) + *success = true; + + v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value)); + uint32_t length = 0; + if (value->IsArray()) { + length = v8::Local<v8::Array>::Cast(v8Value)->Length(); + } else if (toV8Sequence(value, length, isolate).IsEmpty()) { + throwTypeError(ExceptionMessages::notASequenceTypeProperty(propertyName), isolate); + return Vector<RefPtr<T> >(); + } + return toRefPtrNativeArrayUnchecked<T, V8T>(v8Value, length, isolate, success); +} + +template <class T, class V8T> +WillBeHeapVector<RefPtrWillBeMember<T> > toRefPtrWillBeMemberNativeArray(v8::Handle<v8::Value> value, int argumentIndex, v8::Isolate* isolate, bool* success = 0) +{ + if (success) + *success = true; + + v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value)); + uint32_t length = 0; + if (value->IsArray()) { + length = v8::Local<v8::Array>::Cast(v8Value)->Length(); + } else if (toV8Sequence(value, length, isolate).IsEmpty()) { + throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex), isolate); + return WillBeHeapVector<RefPtrWillBeMember<T> >(); + } + + WillBeHeapVector<RefPtrWillBeMember<T> > result; + result.reserveInitialCapacity(length); + v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value); + for (uint32_t i = 0; i < length; ++i) { + v8::Handle<v8::Value> element = object->Get(i); + if (V8T::hasInstance(element, isolate)) { + v8::Handle<v8::Object> elementObject = v8::Handle<v8::Object>::Cast(element); + result.uncheckedAppend(V8T::toNative(elementObject)); + } else { + if (success) + *success = false; + throwTypeError("Invalid Array element type", isolate); + return WillBeHeapVector<RefPtrWillBeMember<T> >(); + } } - - // Convert a value to a 32-bit signed integer. The conversion fails if the - // value cannot be converted to a number or the range violated per WebIDL: - // http://www.w3.org/TR/WebIDL/#es-long - int32_t toInt32(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); - inline int32_t toInt32(v8::Handle<v8::Value> value, bool& ok) { return toInt32(value, NormalConversion, ok); } - - // Convert a value to a 32-bit integer assuming the conversion cannot fail. - inline int32_t toInt32(v8::Handle<v8::Value> value) + return result; +} + +// Converts a JavaScript value to an array as per the Web IDL specification: +// http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-array +template <class T> +Vector<T> toNativeArray(v8::Handle<v8::Value> value, int argumentIndex, v8::Isolate* isolate) +{ + v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value)); + uint32_t length = 0; + if (value->IsArray()) { + length = v8::Local<v8::Array>::Cast(v8Value)->Length(); + } else if (toV8Sequence(value, length, isolate).IsEmpty()) { + throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex), isolate); + return Vector<T>(); + } + + Vector<T> result; + result.reserveInitialCapacity(length); + typedef NativeValueTraits<T> TraitsType; + v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value); + for (uint32_t i = 0; i < length; ++i) + result.uncheckedAppend(TraitsType::nativeValue(object->Get(i), isolate)); + return result; +} + +template <class T> +Vector<T> toNativeArguments(const v8::FunctionCallbackInfo<v8::Value>& info, int startIndex) +{ + ASSERT(startIndex <= info.Length()); + Vector<T> result; + typedef NativeValueTraits<T> TraitsType; + int length = info.Length(); + result.reserveInitialCapacity(length); + for (int i = startIndex; i < length; ++i) + result.uncheckedAppend(TraitsType::nativeValue(info[i], info.GetIsolate())); + return result; +} + +// Validates that the passed object is a sequence type per WebIDL spec +// http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-sequence +inline v8::Handle<v8::Value> toV8Sequence(v8::Handle<v8::Value> value, uint32_t& length, v8::Isolate* isolate) +{ + // Attempt converting to a sequence if the value is not already an array but is + // any kind of object except for a native Date object or a native RegExp object. + ASSERT(!value->IsArray()); + // FIXME: Do we really need to special case Date and RegExp object? + // https://www.w3.org/Bugs/Public/show_bug.cgi?id=22806 + if (!value->IsObject() || value->IsDate() || value->IsRegExp()) { + // The caller is responsible for reporting a TypeError. + return v8Undefined(); + } + + v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value)); + v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value); + v8::Local<v8::String> lengthSymbol = v8AtomicString(isolate, "length"); + + // FIXME: The specification states that the length property should be used as fallback, if value + // is not a platform object that supports indexed properties. If it supports indexed properties, + // length should actually be one greater than value’s maximum indexed property index. + TONATIVE_EXCEPTION(v8::Local<v8::Value>, lengthValue, object->Get(lengthSymbol)); + + if (lengthValue->IsUndefined() || lengthValue->IsNull()) { + // The caller is responsible for reporting a TypeError. + return v8Undefined(); + } + + TONATIVE_EXCEPTION(uint32_t, sequenceLength, lengthValue->Int32Value()); + length = sequenceLength; + return v8Value; +} + +v8::Isolate* toIsolate(ExecutionContext*); +v8::Isolate* toIsolate(LocalFrame*); + +LocalDOMWindow* toDOMWindow(v8::Handle<v8::Value>, v8::Isolate*); +LocalDOMWindow* toDOMWindow(v8::Handle<v8::Context>); +LocalDOMWindow* enteredDOMWindow(v8::Isolate*); +LocalDOMWindow* currentDOMWindow(v8::Isolate*); +LocalDOMWindow* callingDOMWindow(v8::Isolate*); +ExecutionContext* toExecutionContext(v8::Handle<v8::Context>); +ExecutionContext* currentExecutionContext(v8::Isolate*); +ExecutionContext* callingExecutionContext(v8::Isolate*); + +// Returns a V8 context associated with a ExecutionContext and a DOMWrapperWorld. +// This method returns an empty context if there is no frame or the frame is already detached. +v8::Local<v8::Context> toV8Context(ExecutionContext*, DOMWrapperWorld&); +// Returns a V8 context associated with a LocalFrame and a DOMWrapperWorld. +// This method returns an empty context if the frame is already detached. +v8::Local<v8::Context> toV8Context(LocalFrame*, DOMWrapperWorld&); + +// Returns the frame object of the window object associated with +// a context, if the window is currently being displayed in the LocalFrame. +LocalFrame* toFrameIfNotDetached(v8::Handle<v8::Context>); + +// If the current context causes out of memory, JavaScript setting +// is disabled and it returns true. +bool handleOutOfMemory(); +v8::Local<v8::Value> handleMaxRecursionDepthExceeded(v8::Isolate*); +void crashIfV8IsDead(); + +inline bool isUndefinedOrNull(v8::Handle<v8::Value> value) +{ + return value->IsNull() || value->IsUndefined(); +} +v8::Handle<v8::Function> getBoundFunction(v8::Handle<v8::Function>); + +// Attaches |environment| to |function| and returns it. +inline v8::Local<v8::Function> createClosure(v8::FunctionCallback function, v8::Handle<v8::Value> environment, v8::Isolate* isolate) +{ + return v8::Function::New(isolate, function, environment); +} + +// FIXME: This will be soon embedded in the generated code. +template<class Collection> static void indexedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) +{ + Collection* collection = reinterpret_cast<Collection*>(info.Holder()->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex)); + int length = collection->length(); + v8::Handle<v8::Array> properties = v8::Array::New(info.GetIsolate(), length); + for (int i = 0; i < length; ++i) { + // FIXME: Do we need to check that the item function returns a non-null value for this index? + v8::Handle<v8::Integer> integer = v8::Integer::New(info.GetIsolate(), i); + properties->Set(integer, integer); + } + v8SetReturnValue(info, properties); +} + +// These methods store hidden values into an array that is stored in the internal field of a DOM wrapper. +void addHiddenValueToArray(v8::Handle<v8::Object>, v8::Local<v8::Value>, int cacheIndex, v8::Isolate*); +void removeHiddenValueFromArray(v8::Handle<v8::Object>, v8::Local<v8::Value>, int cacheIndex, v8::Isolate*); +void moveEventListenerToNewWrapper(v8::Handle<v8::Object>, EventListener* oldValue, v8::Local<v8::Value> newValue, int cacheIndex, v8::Isolate*); + +PassRefPtr<JSONValue> v8ToJSONValue(v8::Isolate*, v8::Handle<v8::Value>, int); + +// Converts a DOM object to a v8 value. +// This is a no-inline version of toV8(). If you want to call toV8() +// without creating #include cycles, you can use this function instead. +// Each specialized implementation will be generated. +template<typename T> +v8::Handle<v8::Value> toV8NoInline(T* impl, v8::Handle<v8::Object> creationContext, v8::Isolate*); + +// ToV8Value<U, Context> is a class that converts a C++ object to a +// v8 value. U has to be a class having a static method getCreationContext +// which returns an object created from a target context. +template<typename U, typename Context> +class ToV8Value { +public: + template<typename T> + static v8::Handle<v8::Value> toV8Value(const T& value, Context context, v8::Isolate* isolate) { - bool ok; - return toInt32(value, NormalConversion, ok); + // Default implementaion: for types that don't need the context. + return V8ValueTraits<T>::toV8Value(value, context, isolate); } - // Convert a value to a 32-bit unsigned integer. The conversion fails if the - // value cannot be converted to a number or the range violated per WebIDL: - // http://www.w3.org/TR/WebIDL/#es-unsigned-long - uint32_t toUInt32(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); - inline uint32_t toUInt32(v8::Handle<v8::Value> value, bool& ok) { return toUInt32(value, NormalConversion, ok); } - - // Convert a value to a 32-bit unsigned integer assuming the conversion cannot fail. - inline uint32_t toUInt32(v8::Handle<v8::Value> value) + // Pointer specializations. + template<typename T> + static v8::Handle<v8::Value> toV8Value(T* const& value, Context context, v8::Isolate* isolate) { - bool ok; - return toUInt32(value, NormalConversion, ok); + return toV8NoInline(value, context, isolate); } - - // Convert a value to a 64-bit signed integer. The conversion fails if the - // value cannot be converted to a number or the range violated per WebIDL: - // http://www.w3.org/TR/WebIDL/#es-long-long - int64_t toInt64(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); - - // Convert a value to a 64-bit integer assuming the conversion cannot fail. - inline int64_t toInt64(v8::Handle<v8::Value> value) + template<typename T> + static v8::Handle<v8::Value> toV8Value(const RefPtr<T>& value, Context context, v8::Isolate* isolate) { - bool ok; - return toInt64(value, NormalConversion, ok); + return toV8Value(value.get(), context, isolate); } - - // Convert a value to a 64-bit unsigned integer. The conversion fails if the - // value cannot be converted to a number or the range violated per WebIDL: - // http://www.w3.org/TR/WebIDL/#es-unsigned-long-long - uint64_t toUInt64(v8::Handle<v8::Value>, IntegerConversionConfiguration, bool& ok); - - // Convert a value to a 64-bit unsigned integer assuming the conversion cannot fail. - inline uint64_t toUInt64(v8::Handle<v8::Value> value) + template<typename T> + static v8::Handle<v8::Value> toV8Value(const PassRefPtr<T>& value, Context context, v8::Isolate* isolate) { - bool ok; - return toUInt64(value, NormalConversion, ok); + return toV8Value(value.get(), context, isolate); } - - inline float toFloat(v8::Local<v8::Value> value) + template<typename T> + static v8::Handle<v8::Value> toV8Value(const OwnPtr<T>& value, Context context, v8::Isolate* isolate) { - return static_cast<float>(value->NumberValue()); - } - - WrapperWorldType worldType(v8::Isolate*); - WrapperWorldType worldTypeInMainThread(v8::Isolate*); - - DOMWrapperWorld* isolatedWorldForIsolate(v8::Isolate*); - - template<class T> struct NativeValueTraits; - - template<> - struct NativeValueTraits<String> { - static inline String nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) - { - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, value, String()); - return stringValue; - } - }; - - template<> - struct NativeValueTraits<unsigned> { - static inline unsigned nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) - { - return toUInt32(value); - } - }; - - template<> - struct NativeValueTraits<float> { - static inline float nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) - { - return static_cast<float>(value->NumberValue()); - } - }; - - template<> - struct NativeValueTraits<double> { - static inline double nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) - { - return static_cast<double>(value->NumberValue()); - } - }; - - template<> - struct NativeValueTraits<v8::Handle<v8::Value> > { - static inline v8::Handle<v8::Value> nativeValue(const v8::Handle<v8::Value>& value, v8::Isolate* isolate) - { - return value; - } - }; - - // Converts a JavaScript value to an array as per the Web IDL specification: - // http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-array - template <class T, class V8T> - Vector<RefPtr<T> > toRefPtrNativeArrayUnchecked(v8::Local<v8::Value> v8Value, uint32_t length, v8::Isolate* isolate, bool* success = 0) - { - Vector<RefPtr<T> > result; - result.reserveInitialCapacity(length); - v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value); - for (uint32_t i = 0; i < length; ++i) { - v8::Handle<v8::Value> element = object->Get(i); - - if (V8T::hasInstance(element, isolate, worldType(isolate))) { - v8::Handle<v8::Object> elementObject = v8::Handle<v8::Object>::Cast(element); - result.uncheckedAppend(V8T::toNative(elementObject)); - } else { - if (success) - *success = false; - throwTypeError("Invalid Array element type", isolate); - return Vector<RefPtr<T> >(); - } - } - return result; + return toV8Value(value.get(), context, isolate); } - - template <class T, class V8T> - Vector<RefPtr<T> > toRefPtrNativeArray(v8::Handle<v8::Value> value, int argumentIndex, v8::Isolate* isolate, bool* success = 0) + template<typename T> + static v8::Handle<v8::Value> toV8Value(const PassOwnPtr<T>& value, Context context, v8::Isolate* isolate) { - if (success) - *success = true; - - v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value)); - uint32_t length = 0; - if (value->IsArray()) { - length = v8::Local<v8::Array>::Cast(v8Value)->Length(); - } else if (toV8Sequence(value, length, isolate).IsEmpty()) { - throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex), isolate); - return Vector<RefPtr<T> >(); - } - - return toRefPtrNativeArrayUnchecked<T, V8T>(v8Value, length, isolate, success); + return toV8Value(value.get(), context, isolate); } - - template <class T, class V8T> - Vector<RefPtr<T> > toRefPtrNativeArray(v8::Handle<v8::Value> value, const String& propertyName, v8::Isolate* isolate, bool* success = 0) + template<typename T> + static v8::Handle<v8::Value> toV8Value(const RawPtr<T>& value, Context context, v8::Isolate* isolate) { - if (success) - *success = true; - - v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value)); - uint32_t length = 0; - if (value->IsArray()) { - length = v8::Local<v8::Array>::Cast(v8Value)->Length(); - } else if (toV8Sequence(value, length, isolate).IsEmpty()) { - throwTypeError(ExceptionMessages::notASequenceTypeProperty(propertyName), isolate); - return Vector<RefPtr<T> >(); - } - - return toRefPtrNativeArrayUnchecked<T, V8T>(v8Value, length, isolate, success); + return toV8Value(value.get(), context, isolate); } - // Converts a JavaScript value to an array as per the Web IDL specification: - // http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-array - template <class T> - Vector<T> toNativeArray(v8::Handle<v8::Value> value, int argumentIndex, v8::Isolate* isolate) + // const char* should use V8ValueTraits. + static v8::Handle<v8::Value> toV8Value(const char* const& value, Context context, v8::Isolate* isolate) { - v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value)); - uint32_t length = 0; - if (value->IsArray()) { - length = v8::Local<v8::Array>::Cast(v8Value)->Length(); - } else if (toV8Sequence(value, length, isolate).IsEmpty()) { - throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex), isolate); - return Vector<T>(); - } - - Vector<T> result; - result.reserveInitialCapacity(length); - typedef NativeValueTraits<T> TraitsType; - v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value); - for (uint32_t i = 0; i < length; ++i) - result.uncheckedAppend(TraitsType::nativeValue(object->Get(i), isolate)); - return result; - } - - template <class T> - Vector<T> toNativeArguments(const v8::FunctionCallbackInfo<v8::Value>& info, int startIndex) - { - ASSERT(startIndex <= info.Length()); - Vector<T> result; - typedef NativeValueTraits<T> TraitsType; - int length = info.Length(); - result.reserveInitialCapacity(length); - for (int i = startIndex; i < length; ++i) - result.uncheckedAppend(TraitsType::nativeValue(info[i], info.GetIsolate())); - return result; - } - - // Validates that the passed object is a sequence type per WebIDL spec - // http://www.w3.org/TR/2012/CR-WebIDL-20120419/#es-sequence - inline v8::Handle<v8::Value> toV8Sequence(v8::Handle<v8::Value> value, uint32_t& length, v8::Isolate* isolate) - { - // Attempt converting to a sequence if the value is not already an array but is - // any kind of object except for a native Date object or a native RegExp object. - ASSERT(!value->IsArray()); - // FIXME: Do we really need to special case Date and RegExp object? - // https://www.w3.org/Bugs/Public/show_bug.cgi?id=22806 - if (!value->IsObject() || value->IsDate() || value->IsRegExp()) { - // The caller is responsible for reporting a TypeError. - return v8Undefined(); - } - - v8::Local<v8::Value> v8Value(v8::Local<v8::Value>::New(isolate, value)); - v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(v8Value); - v8::Local<v8::String> lengthSymbol = v8::String::NewFromUtf8(isolate, "length", v8::String::kInternalizedString, 6); - - // FIXME: The specification states that the length property should be used as fallback, if value - // is not a platform object that supports indexed properties. If it supports indexed properties, - // length should actually be one greater than value’s maximum indexed property index. - V8TRYCATCH(v8::Local<v8::Value>, lengthValue, object->Get(lengthSymbol)); - - if (lengthValue->IsUndefined() || lengthValue->IsNull()) { - // The caller is responsible for reporting a TypeError. - return v8Undefined(); - } - - V8TRYCATCH(uint32_t, sequenceLength, lengthValue->Int32Value()); - length = sequenceLength; - - return v8Value; + return V8ValueTraits<const char*>::toV8Value(value, context, isolate); } - PassRefPtr<NodeFilter> toNodeFilter(v8::Handle<v8::Value>, v8::Isolate*); - - inline bool isUndefinedOrNull(v8::Handle<v8::Value> value) + template<typename T, size_t inlineCapacity> + static v8::Handle<v8::Value> toV8Value(const Vector<T, inlineCapacity>& value, Context context, v8::Isolate* isolate) { - return value->IsNull() || value->IsUndefined(); + return v8ArrayNoInline(value, context, isolate); } - // Returns true if the provided object is to be considered a 'host object', as used in the - // HTML5 structured clone algorithm. - inline bool isHostObject(v8::Handle<v8::Object> object) + template<typename T, size_t inlineCapacity> + static v8::Handle<v8::Value> toV8Value(const HeapVector<T, inlineCapacity>& value, Context context, v8::Isolate* isolate) { - // If the object has any internal fields, then we won't be able to serialize or deserialize - // them; conveniently, this is also a quick way to detect DOM wrapper objects, because - // the mechanism for these relies on data stored in these fields. We should - // catch external array data as a special case. - return object->InternalFieldCount() || object->HasIndexedPropertiesInExternalArrayData(); + return v8ArrayNoInline(value, context, isolate); } - inline v8::Handle<v8::Boolean> v8Boolean(bool value, v8::Isolate* isolate) + template<typename T, size_t inlineCapacity> + static v8::Handle<v8::Value> toV8Value(const PersistentHeapVector<T, inlineCapacity>& value, Context context, v8::Isolate* isolate) { - return value ? v8::True(isolate) : v8::False(isolate); + return v8ArrayNoInline(static_cast<HeapVector<T, inlineCapacity> >(value), context, isolate); } +}; - // Since v8Boolean(value, isolate) crashes if we pass a null isolate, - // we need to use v8BooleanWithCheck(value, isolate) if an isolate can be null. - // - // FIXME: Remove all null isolates from V8 bindings, and remove v8BooleanWithCheck(value, isolate). - inline v8::Handle<v8::Boolean> v8BooleanWithCheck(bool value, v8::Isolate* isolate) - { - return isolate ? v8Boolean(value, isolate) : v8Boolean(value, v8::Isolate::GetCurrent()); - } +// Result values for platform object 'deleter' methods, +// http://www.w3.org/TR/WebIDL/#delete +enum DeleteResult { + DeleteSuccess, + DeleteReject, + DeleteUnknownProperty +}; - inline double toWebCoreDate(v8::Handle<v8::Value> object) - { - if (object->IsDate()) - return v8::Handle<v8::Date>::Cast(object)->ValueOf(); - if (object->IsNumber()) - return object->NumberValue(); - return std::numeric_limits<double>::quiet_NaN(); - } +class V8IsolateInterruptor : public ThreadState::Interruptor { +public: + explicit V8IsolateInterruptor(v8::Isolate* isolate) : m_isolate(isolate) { } - inline v8::Handle<v8::Value> v8DateOrNull(double value, v8::Isolate* isolate) + static void onInterruptCallback(v8::Isolate* isolate, void* data) { - ASSERT(isolate); - return std::isfinite(value) ? v8::Date::New(isolate, value) : v8::Handle<v8::Value>::Cast(v8::Null(isolate)); + reinterpret_cast<V8IsolateInterruptor*>(data)->onInterrupted(); } - inline v8::Handle<v8::String> v8AtomicString(v8::Isolate* isolate, const char* str) + virtual void requestInterrupt() OVERRIDE { - ASSERT(isolate); - return v8::String::NewFromUtf8(isolate, str, v8::String::kInternalizedString, strlen(str)); + m_isolate->RequestInterrupt(&onInterruptCallback, this); } - inline v8::Handle<v8::String> v8AtomicString(v8::Isolate* isolate, const char* str, size_t length) + virtual void clearInterrupt() OVERRIDE { - ASSERT(isolate); - return v8::String::NewFromUtf8(isolate, str, v8::String::kInternalizedString, length); + m_isolate->ClearInterrupt(); } +private: + v8::Isolate* m_isolate; +}; - v8::Handle<v8::FunctionTemplate> createRawTemplate(v8::Isolate*); - - PassRefPtr<XPathNSResolver> toXPathNSResolver(v8::Handle<v8::Value>, v8::Isolate*); +class V8TestingScope { +public: + explicit V8TestingScope(v8::Isolate*); + ScriptState* scriptState() const; + v8::Isolate* isolate() const; + ~V8TestingScope(); - v8::Handle<v8::Object> toInnerGlobalObject(v8::Handle<v8::Context>); - DOMWindow* toDOMWindow(v8::Handle<v8::Context>); - ExecutionContext* toExecutionContext(v8::Handle<v8::Context>); +private: + v8::HandleScope m_handleScope; + v8::Context::Scope m_contextScope; + RefPtr<ScriptState> m_scriptState; +}; - DOMWindow* activeDOMWindow(); - ExecutionContext* activeExecutionContext(); - DOMWindow* firstDOMWindow(); - Document* currentDocument(); +void GetDevToolsFunctionInfo(v8::Handle<v8::Function>, v8::Isolate*, int& scriptId, String& resourceName, int& lineNumber); +PassRefPtr<TraceEvent::ConvertableToTraceFormat> devToolsTraceEventData(ExecutionContext*, v8::Handle<v8::Function>, v8::Isolate*); - // Returns the context associated with a ExecutionContext. - v8::Local<v8::Context> toV8Context(ExecutionContext*, DOMWrapperWorld*); - - // Returns the frame object of the window object associated with - // a context, if the window is currently being displayed in the Frame. - Frame* toFrameIfNotDetached(v8::Handle<v8::Context>); - - inline DOMWrapperWorld* isolatedWorldForEnteredContext(v8::Isolate* isolate) +class V8RethrowTryCatchScope FINAL { +public: + explicit V8RethrowTryCatchScope(v8::TryCatch& block) : m_block(block) { } + ~V8RethrowTryCatchScope() { - v8::Handle<v8::Context> context = isolate->GetEnteredContext(); - if (context.IsEmpty()) - return 0; - return DOMWrapperWorld::isolatedWorld(context); + // ReThrow() is a no-op if no exception has been caught, so always call. + m_block.ReThrow(); } - // FIXME: This will be soon embedded in the generated code. - template<class Collection> static void indexedPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info) - { - Collection* collection = reinterpret_cast<Collection*>(info.Holder()->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex)); - int length = collection->length(); - v8::Handle<v8::Array> properties = v8::Array::New(info.GetIsolate(), length); - for (int i = 0; i < length; ++i) { - // FIXME: Do we need to check that the item function returns a non-null value for this index? - v8::Handle<v8::Integer> integer = v8::Integer::New(i, info.GetIsolate()); - properties->Set(integer, integer); - } - v8SetReturnValue(info, properties); - } - - // If the current context causes out of memory, JavaScript setting - // is disabled and it returns true. - bool handleOutOfMemory(); - v8::Local<v8::Value> handleMaxRecursionDepthExceeded(v8::Isolate*); - - void crashIfV8IsDead(); +private: + v8::TryCatch& m_block; +}; - template <class T> - v8::Handle<T> unsafeHandleFromRawValue(const T* value) +class V8ResetTryCatchScope FINAL { +public: + explicit V8ResetTryCatchScope(v8::TryCatch& block) : m_block(block) { } + ~V8ResetTryCatchScope() { - const v8::Handle<T>* handle = reinterpret_cast<const v8::Handle<T>*>(&value); - return *handle; + m_block.Reset(); } - // Attaches |environment| to |function| and returns it. - inline v8::Local<v8::Function> createClosure(v8::FunctionCallback function, v8::Handle<v8::Value> environment, v8::Isolate* isolate) - { - return v8::Function::New(isolate, function, environment); - } - - v8::Local<v8::Value> getHiddenValueFromMainWorldWrapper(v8::Isolate*, ScriptWrappable*, v8::Handle<v8::String> key); +private: + v8::TryCatch& m_block; +}; - v8::Isolate* mainThreadIsolate(); - v8::Isolate* toIsolate(ExecutionContext*); - v8::Isolate* toIsolate(Frame*); - - // Can only be called by blink::initialize - void setMainThreadIsolate(v8::Isolate*); - - // Converts a DOM object to a v8 value. - // This is a no-inline version of toV8(). If you want to call toV8() - // without creating #include cycles, you can use this function instead. - // Each specialized implementation will be generated. - template<typename T> - v8::Handle<v8::Value> toV8NoInline(T* impl, v8::Handle<v8::Object> creationContext, v8::Isolate*); } // namespace WebCore #endif // V8Binding_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8BindingMacros.h b/chromium/third_party/WebKit/Source/bindings/v8/V8BindingMacros.h index 8098652e209..1abb3233b80 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8BindingMacros.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8BindingMacros.h @@ -33,65 +33,84 @@ namespace WebCore { -#define V8TRYCATCH(type, var, value) \ - type var; \ - { \ - v8::TryCatch block; \ - var = (value); \ - if (block.HasCaught()) \ - return block.ReThrow(); \ +// Naming scheme: +// TO*_RETURNTYPE[_ARGTYPE]... +// ...using _DEFAULT instead of _ANY..._ANY when returing a default value. + +#define TONATIVE_EXCEPTION(type, var, value) \ + type var; \ + { \ + v8::TryCatch block; \ + var = (value); \ + if (UNLIKELY(block.HasCaught())) \ + return block.ReThrow(); \ } -#define V8TRYCATCH_RETURN(type, var, value, retVal) \ - type var; \ - { \ - v8::TryCatch block; \ - var = (value); \ - if (block.HasCaught()) { \ - block.ReThrow(); \ - return retVal; \ - } \ +#define TONATIVE_VOID_INTERNAL(var, value) \ + var = (value); \ + if (UNLIKELY(block.HasCaught())) \ + return; + +#define TONATIVE_VOID(type, var, value) \ + type var; \ + { \ + v8::TryCatch block; \ + V8RethrowTryCatchScope rethrow(block); \ + TONATIVE_VOID_INTERNAL(var, value); \ } -#define V8TRYCATCH_VOID(type, var, value) \ - type var; \ - { \ - v8::TryCatch block; \ - var = (value); \ - if (block.HasCaught()) { \ - block.ReThrow(); \ - return; \ - } \ +#define TONATIVE_DEFAULT(type, var, value, retVal) \ + type var; \ + { \ + v8::TryCatch block; \ + var = (value); \ + if (UNLIKELY(block.HasCaught())) { \ + block.ReThrow(); \ + return retVal; \ + } \ } -#define V8TRYCATCH_WITH_TYPECHECK_VOID(type, var, value, isolate) \ - type var; \ - { \ - bool ok = true; \ - { \ - v8::TryCatch block; \ - var = (value); \ - if (block.HasCaught()) { \ - block.ReThrow(); \ - return; \ - } \ - } \ - if (UNLIKELY(!ok)) { \ - throwUninformativeAndGenericTypeError(isolate); \ - return; \ - } \ +#define TONATIVE_VOID_EXCEPTIONSTATE_INTERNAL(var, value, exceptionState) \ + var = (value); \ + if (UNLIKELY(block.HasCaught() || exceptionState.throwIfNeeded())) \ + return; \ + +#define TONATIVE_VOID_EXCEPTIONSTATE(type, var, value, exceptionState) \ + type var; \ + { \ + v8::TryCatch block; \ + V8RethrowTryCatchScope rethrow(block); \ + TONATIVE_VOID_EXCEPTIONSTATE_INTERNAL(var, value, exceptionState); \ } -#define V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(type, var, value, retVal) \ - type var(value); \ - if (!var.prepare()) \ - return retVal; +#define TONATIVE_DEFAULT_EXCEPTIONSTATE(type, var, value, exceptionState, retVal) \ + type var; \ + { \ + v8::TryCatch block; \ + V8RethrowTryCatchScope rethrow(block); \ + var = (value); \ + if (UNLIKELY(block.HasCaught() || exceptionState.throwIfNeeded())) \ + return retVal; \ + } + +// type is an instance of class template V8StringResource<>, +// but Mode argument varies; using type (not Mode) for consistency +// with other macros and ease of code generation +#define TOSTRING_VOID(type, var, value) \ + type var(value); \ + if (UNLIKELY(!var.prepare())) \ + return; -#define V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(type, var, value) \ - type var(value); \ - if (!var.prepare()) \ +#define TOSTRING_VOID_INTERNAL(var, value) \ + var = (value); \ + if (UNLIKELY(!var.prepare())) \ return; +#define TOSTRING_DEFAULT(type, var, value, retVal) \ + type var(value); \ + if (UNLIKELY(!var.prepare())) \ + return retVal; + } // namespace WebCore #endif // V8BindingMacros_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8Callback.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8Callback.cpp index ef56f45fcbc..b47b3daf58a 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8Callback.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8Callback.cpp @@ -36,16 +36,16 @@ namespace WebCore { -bool invokeCallback(v8::Local<v8::Function> callback, int argc, v8::Handle<v8::Value> argv[], ExecutionContext* executionContext, v8::Isolate* isolate) +bool invokeCallback(ScriptState* scriptState, v8::Local<v8::Function> callback, int argc, v8::Handle<v8::Value> argv[]) { - return invokeCallback(callback, isolate->GetCurrentContext()->Global(), argc, argv, executionContext, isolate); + return invokeCallback(scriptState, callback, scriptState->context()->Global(), argc, argv); } -bool invokeCallback(v8::Local<v8::Function> callback, v8::Handle<v8::Object> thisObject, int argc, v8::Handle<v8::Value> argv[], ExecutionContext* executionContext, v8::Isolate* isolate) +bool invokeCallback(ScriptState* scriptState, v8::Local<v8::Function> callback, v8::Handle<v8::Value> thisValue, int argc, v8::Handle<v8::Value> argv[]) { v8::TryCatch exceptionCatcher; exceptionCatcher.SetVerbose(true); - ScriptController::callFunction(executionContext, callback, thisObject, argc, argv, isolate); + ScriptController::callFunction(scriptState->executionContext(), callback, thisValue, argc, argv, scriptState->isolate()); return !exceptionCatcher.HasCaught(); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8Callback.h b/chromium/third_party/WebKit/Source/bindings/v8/V8Callback.h index 6fad1b5c503..f6126243f27 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8Callback.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8Callback.h @@ -31,8 +31,8 @@ #ifndef V8Callback_h #define V8Callback_h +#include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "core/dom/ExceptionCode.h" #include <v8.h> @@ -41,9 +41,10 @@ namespace WebCore { class ExecutionContext; // Returns false if the callback threw an exception, true otherwise. -bool invokeCallback(v8::Local<v8::Function> callback, int argc, v8::Handle<v8::Value> argv[], ExecutionContext*, v8::Isolate*); -bool invokeCallback(v8::Local<v8::Function> callback, v8::Handle<v8::Object> thisObject, int argc, v8::Handle<v8::Value> argv[], ExecutionContext*, v8::Isolate*); +bool invokeCallback(ScriptState*, v8::Local<v8::Function> callback, int argc, v8::Handle<v8::Value> argv[]); +bool invokeCallback(ScriptState*, v8::Local<v8::Function> callback, v8::Handle<v8::Value> thisValue, int argc, v8::Handle<v8::Value> argv[]); +// FIXME: This file is used only by V8GeolocationCustom.cpp. Remove the custom binding and this file. enum CallbackAllowedValueFlag { CallbackAllowUndefined = 1, CallbackAllowNull = 1 << 1 @@ -53,7 +54,7 @@ typedef unsigned CallbackAllowedValueFlags; // 'FunctionOnly' is assumed for the created callback. template <typename V8CallbackType> -PassOwnPtr<V8CallbackType> createFunctionOnlyCallback(v8::Local<v8::Value> value, bool& succeeded, v8::Isolate* isolate, CallbackAllowedValueFlags acceptedValues = 0) +PassOwnPtr<V8CallbackType> createFunctionOnlyCallback(v8::Local<v8::Value> value, unsigned index, bool& succeeded, v8::Isolate* isolate, ExceptionState& exceptionState, CallbackAllowedValueFlags acceptedValues = 0) { succeeded = true; @@ -65,11 +66,12 @@ PassOwnPtr<V8CallbackType> createFunctionOnlyCallback(v8::Local<v8::Value> value if (!value->IsFunction()) { succeeded = false; - setDOMException(TypeMismatchError, isolate); + exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::argumentNullOrIncorrectType(index, "Function")); + exceptionState.throwIfNeeded(); return nullptr; } - return V8CallbackType::create(v8::Handle<v8::Function>::Cast(value), getExecutionContext()); + return V8CallbackType::create(v8::Handle<v8::Function>::Cast(value), ScriptState::current(isolate)); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8CustomElementLifecycleCallbacks.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8CustomElementLifecycleCallbacks.cpp index 29e1bc093de..aa03363d7d9 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8CustomElementLifecycleCallbacks.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8CustomElementLifecycleCallbacks.cpp @@ -31,14 +31,15 @@ #include "config.h" #include "bindings/v8/V8CustomElementLifecycleCallbacks.h" -#include "V8Element.h" +#include "bindings/core/v8/V8Element.h" #include "bindings/v8/CustomElementBinding.h" #include "bindings/v8/DOMDataStore.h" #include "bindings/v8/ScriptController.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "bindings/v8/V8PerContextData.h" #include "core/dom/ExecutionContext.h" +#include "core/inspector/InspectorInstrumentation.h" #include "wtf/PassOwnPtr.h" namespace WebCore { @@ -49,20 +50,20 @@ namespace WebCore { V(detached, Detached) \ V(attributeChanged, AttributeChanged) -PassRefPtr<V8CustomElementLifecycleCallbacks> V8CustomElementLifecycleCallbacks::create(ExecutionContext* executionContext, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> attached, v8::Handle<v8::Function> detached, v8::Handle<v8::Function> attributeChanged) +PassRefPtr<V8CustomElementLifecycleCallbacks> V8CustomElementLifecycleCallbacks::create(ScriptState* scriptState, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> attached, v8::Handle<v8::Function> detached, v8::Handle<v8::Function> attributeChanged) { - v8::Isolate* isolate = toIsolate(executionContext); + v8::Isolate* isolate = scriptState->isolate(); // A given object can only be used as a Custom Element prototype // once; see customElementIsInterfacePrototypeObject -#define SET_HIDDEN_PROPERTY(Value, Name) \ - ASSERT(prototype->GetHiddenValue(V8HiddenPropertyName::customElement##Name(isolate)).IsEmpty()); \ +#define SET_HIDDEN_VALUE(Value, Name) \ + ASSERT(V8HiddenValue::getHiddenValue(isolate, prototype, V8HiddenValue::customElement##Name(isolate)).IsEmpty()); \ if (!Value.IsEmpty()) \ - prototype->SetHiddenValue(V8HiddenPropertyName::customElement##Name(isolate), Value); + V8HiddenValue::setHiddenValue(isolate, prototype, V8HiddenValue::customElement##Name(isolate), Value); - CALLBACK_LIST(SET_HIDDEN_PROPERTY) -#undef SET_HIDDEN_PROPERTY + CALLBACK_LIST(SET_HIDDEN_VALUE) +#undef SET_HIDDEN_VALUE - return adoptRef(new V8CustomElementLifecycleCallbacks(executionContext, prototype, created, attached, detached, attributeChanged)); + return adoptRef(new V8CustomElementLifecycleCallbacks(scriptState, prototype, created, attached, detached, attributeChanged)); } static CustomElementLifecycleCallbacks::CallbackType flagSet(v8::Handle<v8::Function> attached, v8::Handle<v8::Function> detached, v8::Handle<v8::Function> attributeChanged) @@ -88,16 +89,16 @@ static void weakCallback(const v8::WeakCallbackData<T, ScopedPersistent<T> >& da data.GetParameter()->clear(); } -V8CustomElementLifecycleCallbacks::V8CustomElementLifecycleCallbacks(ExecutionContext* executionContext, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> attached, v8::Handle<v8::Function> detached, v8::Handle<v8::Function> attributeChanged) +V8CustomElementLifecycleCallbacks::V8CustomElementLifecycleCallbacks(ScriptState* scriptState, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> attached, v8::Handle<v8::Function> detached, v8::Handle<v8::Function> attributeChanged) : CustomElementLifecycleCallbacks(flagSet(attached, detached, attributeChanged)) - , ActiveDOMCallback(executionContext) + , ContextLifecycleObserver(scriptState->executionContext()) , m_owner(0) - , m_world(DOMWrapperWorld::current()) - , m_prototype(toIsolate(executionContext), prototype) - , m_created(toIsolate(executionContext), created) - , m_attached(toIsolate(executionContext), attached) - , m_detached(toIsolate(executionContext), detached) - , m_attributeChanged(toIsolate(executionContext), attributeChanged) + , m_scriptState(scriptState) + , m_prototype(scriptState->isolate(), prototype) + , m_created(scriptState->isolate(), created) + , m_attached(scriptState->isolate(), attached) + , m_detached(scriptState->isolate(), detached) + , m_attributeChanged(scriptState->isolate(), attributeChanged) { m_prototype.setWeak(&m_prototype, weakCallback<v8::Object>); @@ -114,7 +115,7 @@ V8PerContextData* V8CustomElementLifecycleCallbacks::creationContextData() if (!executionContext()) return 0; - v8::Handle<v8::Context> context = toV8Context(executionContext(), m_world.get()); + v8::Handle<v8::Context> context = m_scriptState->context(); if (context.IsEmpty()) return 0; @@ -126,7 +127,7 @@ V8CustomElementLifecycleCallbacks::~V8CustomElementLifecycleCallbacks() if (!m_owner) return; - v8::HandleScope handleScope(toIsolate(executionContext())); + v8::HandleScope handleScope(m_scriptState->isolate()); if (V8PerContextData* perContextData = creationContextData()) perContextData->clearCustomElementBinding(m_owner); } @@ -149,20 +150,20 @@ bool V8CustomElementLifecycleCallbacks::setBinding(CustomElementDefinition* owne void V8CustomElementLifecycleCallbacks::created(Element* element) { - if (!canInvokeCallback()) + // FIXME: callbacks while paused should be queued up for execution to + // continue then be delivered in order rather than delivered immediately. + // Bug 329665 tracks similar behavior for other synchronous events. + if (!executionContext() || executionContext()->activeDOMObjectsAreStopped()) return; element->setCustomElementState(Element::Upgraded); - v8::Isolate* isolate = toIsolate(executionContext()); - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> context = toV8Context(executionContext(), m_world.get()); - if (context.IsEmpty()) + if (m_scriptState->contextIsEmpty()) return; - - v8::Context::Scope scope(context); - - v8::Handle<v8::Object> receiver = DOMDataStore::current(isolate).get<V8Element>(element, isolate); + ScriptState::Scope scope(m_scriptState.get()); + v8::Isolate* isolate = m_scriptState->isolate(); + v8::Handle<v8::Context> context = m_scriptState->context(); + v8::Handle<v8::Object> receiver = m_scriptState->world().domDataStore().get<V8Element>(element, isolate); if (!receiver.IsEmpty()) { // Swizzle the prototype of the existing wrapper. We don't need to // worry about non-existent wrappers; they will get the right @@ -182,6 +183,8 @@ void V8CustomElementLifecycleCallbacks::created(Element* element) ASSERT(!receiver.IsEmpty()); + InspectorInstrumentation::willExecuteCustomElementCallback(element); + v8::TryCatch exceptionCatcher; exceptionCatcher.SetVerbose(true); ScriptController::callFunction(executionContext(), callback, receiver, 0, 0, isolate); @@ -199,17 +202,17 @@ void V8CustomElementLifecycleCallbacks::detached(Element* element) void V8CustomElementLifecycleCallbacks::attributeChanged(Element* element, const AtomicString& name, const AtomicString& oldValue, const AtomicString& newValue) { - if (!canInvokeCallback()) + // FIXME: callbacks while paused should be queued up for execution to + // continue then be delivered in order rather than delivered immediately. + // Bug 329665 tracks similar behavior for other synchronous events. + if (!executionContext() || executionContext()->activeDOMObjectsAreStopped()) return; - v8::Isolate* isolate = toIsolate(executionContext()); - v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> context = toV8Context(executionContext(), m_world.get()); - if (context.IsEmpty()) + if (m_scriptState->contextIsEmpty()) return; - - v8::Context::Scope scope(context); - + ScriptState::Scope scope(m_scriptState.get()); + v8::Isolate* isolate = m_scriptState->isolate(); + v8::Handle<v8::Context> context = m_scriptState->context(); v8::Handle<v8::Object> receiver = toV8(element, context->Global(), isolate).As<v8::Object>(); ASSERT(!receiver.IsEmpty()); @@ -223,6 +226,8 @@ void V8CustomElementLifecycleCallbacks::attributeChanged(Element* element, const newValue.isNull() ? v8::Handle<v8::Value>(v8::Null(isolate)) : v8::Handle<v8::Value>(v8String(isolate, newValue)) }; + InspectorInstrumentation::willExecuteCustomElementCallback(element); + v8::TryCatch exceptionCatcher; exceptionCatcher.SetVerbose(true); ScriptController::callFunction(executionContext(), callback, receiver, WTF_ARRAY_LENGTH(argv), argv, isolate); @@ -230,17 +235,17 @@ void V8CustomElementLifecycleCallbacks::attributeChanged(Element* element, const void V8CustomElementLifecycleCallbacks::call(const ScopedPersistent<v8::Function>& weakCallback, Element* element) { - if (!canInvokeCallback()) + // FIXME: callbacks while paused should be queued up for execution to + // continue then be delivered in order rather than delivered immediately. + // Bug 329665 tracks similar behavior for other synchronous events. + if (!executionContext() || executionContext()->activeDOMObjectsAreStopped()) return; - v8::HandleScope handleScope(toIsolate(executionContext())); - v8::Handle<v8::Context> context = toV8Context(executionContext(), m_world.get()); - if (context.IsEmpty()) + if (m_scriptState->contextIsEmpty()) return; - - v8::Context::Scope scope(context); - v8::Isolate* isolate = context->GetIsolate(); - + ScriptState::Scope scope(m_scriptState.get()); + v8::Isolate* isolate = m_scriptState->isolate(); + v8::Handle<v8::Context> context = m_scriptState->context(); v8::Handle<v8::Function> callback = weakCallback.newLocal(isolate); if (callback.IsEmpty()) return; @@ -248,6 +253,8 @@ void V8CustomElementLifecycleCallbacks::call(const ScopedPersistent<v8::Function v8::Handle<v8::Object> receiver = toV8(element, context->Global(), isolate).As<v8::Object>(); ASSERT(!receiver.IsEmpty()); + InspectorInstrumentation::willExecuteCustomElementCallback(element); + v8::TryCatch exceptionCatcher; exceptionCatcher.SetVerbose(true); ScriptController::callFunction(executionContext(), callback, receiver, 0, 0, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8CustomElementLifecycleCallbacks.h b/chromium/third_party/WebKit/Source/bindings/v8/V8CustomElementLifecycleCallbacks.h index e911e2899cc..fe32ad90ef4 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8CustomElementLifecycleCallbacks.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8CustomElementLifecycleCallbacks.h @@ -31,9 +31,9 @@ #ifndef V8CustomElementLifecycleCallbacks_h #define V8CustomElementLifecycleCallbacks_h -#include "bindings/v8/ActiveDOMCallback.h" -#include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/ScopedPersistent.h" +#include "bindings/v8/ScriptState.h" +#include "core/dom/ContextLifecycleObserver.h" #include "core/dom/custom/CustomElementLifecycleCallbacks.h" #include "wtf/PassOwnPtr.h" #include "wtf/PassRefPtr.h" @@ -46,16 +46,16 @@ class Element; class ExecutionContext; class V8PerContextData; -class V8CustomElementLifecycleCallbacks : public CustomElementLifecycleCallbacks, ActiveDOMCallback { +class V8CustomElementLifecycleCallbacks FINAL : public CustomElementLifecycleCallbacks, ContextLifecycleObserver { public: - static PassRefPtr<V8CustomElementLifecycleCallbacks> create(ExecutionContext*, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> attached, v8::Handle<v8::Function> detached, v8::Handle<v8::Function> attributeChanged); + static PassRefPtr<V8CustomElementLifecycleCallbacks> create(ScriptState*, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> attached, v8::Handle<v8::Function> detached, v8::Handle<v8::Function> attributeChanged); virtual ~V8CustomElementLifecycleCallbacks(); bool setBinding(CustomElementDefinition* owner, PassOwnPtr<CustomElementBinding>); private: - V8CustomElementLifecycleCallbacks(ExecutionContext*, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> attached, v8::Handle<v8::Function> detached, v8::Handle<v8::Function> attributeChanged); + V8CustomElementLifecycleCallbacks(ScriptState*, v8::Handle<v8::Object> prototype, v8::Handle<v8::Function> created, v8::Handle<v8::Function> attached, v8::Handle<v8::Function> detached, v8::Handle<v8::Function> attributeChanged); virtual void created(Element*) OVERRIDE; virtual void attached(Element*) OVERRIDE; @@ -67,7 +67,7 @@ private: V8PerContextData* creationContextData(); CustomElementDefinition* m_owner; - RefPtr<DOMWrapperWorld> m_world; + RefPtr<ScriptState> m_scriptState; ScopedPersistent<v8::Object> m_prototype; ScopedPersistent<v8::Function> m_created; ScopedPersistent<v8::Function> m_attached; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8DOMActivityLogger.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMActivityLogger.cpp new file mode 100644 index 00000000000..20ead4f4ce0 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMActivityLogger.cpp @@ -0,0 +1,72 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "bindings/v8/V8DOMActivityLogger.h" + +#include "bindings/v8/V8Binding.h" +#include "platform/weborigin/KURL.h" +#include "wtf/HashMap.h" +#include "wtf/MainThread.h" +#include "wtf/text/StringHash.h" + +namespace WebCore { + +typedef HashMap<String, OwnPtr<V8DOMActivityLogger> > DOMActivityLoggerMapForMainWorld; +typedef HashMap<int, OwnPtr<V8DOMActivityLogger>, WTF::IntHash<int>, WTF::UnsignedWithZeroKeyHashTraits<int> > DOMActivityLoggerMapForIsolatedWorld; + +static DOMActivityLoggerMapForMainWorld& domActivityLoggersForMainWorld() +{ + ASSERT(isMainThread()); + DEFINE_STATIC_LOCAL(DOMActivityLoggerMapForMainWorld, map, ()); + return map; +} + +static DOMActivityLoggerMapForIsolatedWorld& domActivityLoggersForIsolatedWorld() +{ + ASSERT(isMainThread()); + DEFINE_STATIC_LOCAL(DOMActivityLoggerMapForIsolatedWorld, map, ()); + return map; +} + +void V8DOMActivityLogger::setActivityLogger(int worldId, const String& extensionId, PassOwnPtr<V8DOMActivityLogger> logger) +{ + if (worldId) + domActivityLoggersForIsolatedWorld().set(worldId, logger); + else + domActivityLoggersForMainWorld().set(extensionId, logger); +} + +V8DOMActivityLogger* V8DOMActivityLogger::activityLogger(int worldId, const String& extensionId) +{ + if (worldId) { + DOMActivityLoggerMapForIsolatedWorld& loggers = domActivityLoggersForIsolatedWorld(); + DOMActivityLoggerMapForIsolatedWorld::iterator it = loggers.find(worldId); + return it == loggers.end() ? 0 : it->value.get(); + } + + if (extensionId.isEmpty()) + return 0; + + DOMActivityLoggerMapForMainWorld& loggers = domActivityLoggersForMainWorld(); + DOMActivityLoggerMapForMainWorld::iterator it = loggers.find(extensionId); + return it == loggers.end() ? 0 : it->value.get(); +} + +V8DOMActivityLogger* V8DOMActivityLogger::activityLogger(int worldId, const KURL& url) +{ + // extension ID is ignored for worldId != 0. + if (worldId) + return activityLogger(worldId, String()); + + // To find an activity logger that corresponds to the main world of an + // extension, we need to obtain the extension ID. Extension ID is a hostname + // of a background page's URL. + if (!url.protocolIs("chrome-extension")) + return 0; + + return activityLogger(worldId, url.host()); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8DOMActivityLogger.h b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMActivityLogger.h index 93915a65f2c..0f6b05c8e3c 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8DOMActivityLogger.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMActivityLogger.h @@ -31,16 +31,38 @@ #ifndef V8DOMActivityLogger_h #define V8DOMActivityLogger_h -#include <v8.h> +#include "wtf/PassOwnPtr.h" #include "wtf/text/WTFString.h" +#include <v8.h> namespace WebCore { +class KURL; + class V8DOMActivityLogger { public: virtual ~V8DOMActivityLogger() { } - virtual void log(const String& apiName, int argc, const v8::Handle<v8::Value>* argv, const String& extraInfo) { } + virtual void logGetter(const String& apiName) { } + virtual void logSetter(const String& apiName, const v8::Handle<v8::Value>& newValue) { } + virtual void logSetter(const String& apiName, const v8::Handle<v8::Value>& newValue, const v8::Handle<v8::Value>& oldValue) { } + virtual void logMethod(const String& apiName, int argc, const v8::Handle<v8::Value>* argv) { } + + // Associates a logger with the world identified by worldId (worlId may be 0 + // identifying the main world) and extension ID. Extension ID is used to + // identify a logger for main world only (worldId == 0). If the world is not + // a main world, an extension ID is ignored. + // + // A renderer process may host multiple extensions when the browser hits the + // renderer process limit. In such case, we assign multiple extensions to + // the same main world of a renderer process. In order to distinguish the + // extensions and their activity loggers in the main world, we require an + // extension ID. Otherwise, extension activities may be logged under + // a wrong extension ID. + static void setActivityLogger(int worldId, const String&, PassOwnPtr<V8DOMActivityLogger>); + static V8DOMActivityLogger* activityLogger(int worldId, const String& extensionId); + static V8DOMActivityLogger* activityLogger(int worldId, const KURL&); + }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8DOMConfiguration.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMConfiguration.cpp index f92f9f0736e..13f2bf3659b 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8DOMConfiguration.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMConfiguration.cpp @@ -30,21 +30,24 @@ #include "bindings/v8/V8DOMConfiguration.h" #include "bindings/v8/V8Binding.h" +#include "bindings/v8/V8ObjectConstructor.h" +#include "platform/TraceEvent.h" namespace WebCore { -void V8DOMConfiguration::installAttributes(v8::Handle<v8::ObjectTemplate> instanceTemplate, v8::Handle<v8::ObjectTemplate> prototype, const AttributeConfiguration* attributes, size_t attributeCount, v8::Isolate* isolate, WrapperWorldType currentWorldType) +void V8DOMConfiguration::installAttributes(v8::Handle<v8::ObjectTemplate> instanceTemplate, v8::Handle<v8::ObjectTemplate> prototype, const AttributeConfiguration* attributes, size_t attributeCount, v8::Isolate* isolate) { for (size_t i = 0; i < attributeCount; ++i) - installAttribute(instanceTemplate, prototype, attributes[i], isolate, currentWorldType); + installAttribute(instanceTemplate, prototype, attributes[i], isolate); } -void V8DOMConfiguration::installAccessors(v8::Handle<v8::ObjectTemplate> prototype, v8::Handle<v8::Signature> signature, const AccessorConfiguration* accessors, size_t accessorCount, v8::Isolate* isolate, WrapperWorldType currentWorldType) +void V8DOMConfiguration::installAccessors(v8::Handle<v8::ObjectTemplate> prototype, v8::Handle<v8::Signature> signature, const AccessorConfiguration* accessors, size_t accessorCount, v8::Isolate* isolate) { + bool isMainWorld = DOMWrapperWorld::current(isolate).isMainWorld(); for (size_t i = 0; i < accessorCount; ++i) { v8::FunctionCallback getterCallback = accessors[i].getter; v8::FunctionCallback setterCallback = accessors[i].setter; - if (currentWorldType == MainWorld) { + if (isMainWorld) { if (accessors[i].getterForMainWorld) getterCallback = accessors[i].getterForMainWorld; if (accessors[i].setterForMainWorld) @@ -61,7 +64,7 @@ void V8DOMConfiguration::installAccessors(v8::Handle<v8::ObjectTemplate> prototy setter = v8::FunctionTemplate::New(isolate, setterCallback, v8::External::New(isolate, const_cast<WrapperTypeInfo*>(accessors[i].data)), signature, 1); setter->RemovePrototype(); } - prototype->SetAccessorProperty(v8::String::NewFromUtf8(isolate, accessors[i].name, v8::String::kInternalizedString), getter, setter, accessors[i].attribute, accessors[i].settings); + prototype->SetAccessorProperty(v8AtomicString(isolate, accessors[i].name), getter, setter, accessors[i].attribute, accessors[i].settings); } } @@ -69,20 +72,22 @@ void V8DOMConfiguration::installConstants(v8::Handle<v8::FunctionTemplate> funct { for (size_t i = 0; i < constantCount; ++i) { const ConstantConfiguration* constant = &constants[i]; - functionDescriptor->Set(v8::String::NewFromUtf8(isolate, constant->name, v8::String::kInternalizedString), v8::Integer::New(isolate, constant->value), static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete)); - prototype->Set(v8::String::NewFromUtf8(isolate, constant->name, v8::String::kInternalizedString), v8::Integer::New(isolate, constant->value), static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete)); + v8::Handle<v8::String> constantName = v8AtomicString(isolate, constant->name); + functionDescriptor->Set(constantName, v8::Integer::New(isolate, constant->value), static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete)); + prototype->Set(constantName, v8::Integer::New(isolate, constant->value), static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete)); } } -void V8DOMConfiguration::installCallbacks(v8::Handle<v8::ObjectTemplate> prototype, v8::Handle<v8::Signature> signature, v8::PropertyAttribute attributes, const MethodConfiguration* callbacks, size_t callbackCount, v8::Isolate* isolate, WrapperWorldType currentWorldType) +void V8DOMConfiguration::installCallbacks(v8::Handle<v8::ObjectTemplate> prototype, v8::Handle<v8::Signature> signature, v8::PropertyAttribute attributes, const MethodConfiguration* callbacks, size_t callbackCount, v8::Isolate* isolate) { + bool isMainWorld = DOMWrapperWorld::current(isolate).isMainWorld(); for (size_t i = 0; i < callbackCount; ++i) { v8::FunctionCallback callback = callbacks[i].callback; - if (currentWorldType == MainWorld && callbacks[i].callbackForMainWorld) + if (isMainWorld && callbacks[i].callbackForMainWorld) callback = callbacks[i].callbackForMainWorld; v8::Local<v8::FunctionTemplate> functionTemplate = v8::FunctionTemplate::New(isolate, callback, v8Undefined(), signature, callbacks[i].length); functionTemplate->RemovePrototype(); - prototype->Set(v8::String::NewFromUtf8(isolate, callbacks[i].name, v8::String::kInternalizedString), functionTemplate, attributes); + prototype->Set(v8AtomicString(isolate, callbacks[i].name), functionTemplate, attributes); } } @@ -90,9 +95,9 @@ v8::Local<v8::Signature> V8DOMConfiguration::installDOMClassTemplate(v8::Handle< const AttributeConfiguration* attributes, size_t attributeCount, const AccessorConfiguration* accessors, size_t accessorCount, const MethodConfiguration* callbacks, size_t callbackCount, - v8::Isolate* isolate, WrapperWorldType currentWorldType) + v8::Isolate* isolate) { - functionDescriptor->SetClassName(v8::String::NewFromUtf8(isolate, interfaceName, v8::String::kInternalizedString)); + functionDescriptor->SetClassName(v8AtomicString(isolate, interfaceName)); v8::Local<v8::ObjectTemplate> instanceTemplate = functionDescriptor->InstanceTemplate(); instanceTemplate->SetInternalFieldCount(fieldCount); if (!parentClass.IsEmpty()) { @@ -106,12 +111,26 @@ v8::Local<v8::Signature> V8DOMConfiguration::installDOMClassTemplate(v8::Handle< v8::Local<v8::Signature> defaultSignature = v8::Signature::New(isolate, functionDescriptor); if (attributeCount) - installAttributes(instanceTemplate, functionDescriptor->PrototypeTemplate(), attributes, attributeCount, isolate, currentWorldType); + installAttributes(instanceTemplate, functionDescriptor->PrototypeTemplate(), attributes, attributeCount, isolate); if (accessorCount) - installAccessors(functionDescriptor->PrototypeTemplate(), defaultSignature, accessors, accessorCount, isolate, currentWorldType); + installAccessors(functionDescriptor->PrototypeTemplate(), defaultSignature, accessors, accessorCount, isolate); if (callbackCount) - installCallbacks(functionDescriptor->PrototypeTemplate(), defaultSignature, static_cast<v8::PropertyAttribute>(v8::DontDelete), callbacks, callbackCount, isolate, currentWorldType); + installCallbacks(functionDescriptor->PrototypeTemplate(), defaultSignature, static_cast<v8::PropertyAttribute>(v8::DontDelete), callbacks, callbackCount, isolate); return defaultSignature; } +v8::Handle<v8::FunctionTemplate> V8DOMConfiguration::domClassTemplate(v8::Isolate* isolate, WrapperTypeInfo* wrapperTypeInfo, void (*configureDOMClassTemplate)(v8::Handle<v8::FunctionTemplate>, v8::Isolate*)) +{ + V8PerIsolateData* data = V8PerIsolateData::from(isolate); + v8::Local<v8::FunctionTemplate> result = data->existingDOMTemplate(wrapperTypeInfo); + if (!result.IsEmpty()) + return result; + + TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "BuildDOMTemplate"); + result = v8::FunctionTemplate::New(isolate, V8ObjectConstructor::isValidConstructorMode); + configureDOMClassTemplate(result, isolate); + data->setDOMTemplate(wrapperTypeInfo, result); + return result; +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8DOMConfiguration.h b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMConfiguration.h index 18a2e3bf0d5..28b1e504aef 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8DOMConfiguration.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMConfiguration.h @@ -69,25 +69,14 @@ public: v8::PropertyAttribute attribute; }; - static void installAttributes(v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::ObjectTemplate>, const AttributeConfiguration*, size_t attributeCount, v8::Isolate*, WrapperWorldType currentWorldType); + static void installAttributes(v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::ObjectTemplate>, const AttributeConfiguration*, size_t attributeCount, v8::Isolate*); template<class ObjectOrTemplate> static inline void installAttribute(v8::Handle<ObjectOrTemplate> instanceTemplate, v8::Handle<ObjectOrTemplate> prototype, const AttributeConfiguration& attribute, v8::Isolate* isolate) { - (attribute.onPrototype ? prototype : instanceTemplate)->SetAccessor(v8::String::NewFromUtf8(isolate, attribute.name, v8::String::kInternalizedString), - attribute.getter, - attribute.setter, - v8::External::New(isolate, const_cast<WrapperTypeInfo*>(attribute.data)), - attribute.settings, - attribute.attribute); - } - - template<class ObjectOrTemplate> - static inline void installAttribute(v8::Handle<ObjectOrTemplate> instanceTemplate, v8::Handle<ObjectOrTemplate> prototype, const AttributeConfiguration& attribute, v8::Isolate* isolate, WrapperWorldType currentWorldType) - { v8::AccessorGetterCallback getter = attribute.getter; v8::AccessorSetterCallback setter = attribute.setter; - if (currentWorldType == MainWorld) { + if (DOMWrapperWorld::current(isolate).isMainWorld()) { if (attribute.getterForMainWorld) getter = attribute.getterForMainWorld; if (attribute.setterForMainWorld) @@ -120,15 +109,17 @@ public: int length; }; - static void installCallbacks(v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::Signature>, v8::PropertyAttribute, const MethodConfiguration*, size_t callbackCount, v8::Isolate*, WrapperWorldType); + static void installCallbacks(v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::Signature>, v8::PropertyAttribute, const MethodConfiguration*, size_t callbackCount, v8::Isolate*); - static void installAccessors(v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::Signature>, const AccessorConfiguration*, size_t accessorCount, v8::Isolate*, WrapperWorldType); + static void installAccessors(v8::Handle<v8::ObjectTemplate>, v8::Handle<v8::Signature>, const AccessorConfiguration*, size_t accessorCount, v8::Isolate*); static v8::Local<v8::Signature> installDOMClassTemplate(v8::Handle<v8::FunctionTemplate>, const char* interfaceName, v8::Handle<v8::FunctionTemplate> parentClass, size_t fieldCount, const AttributeConfiguration*, size_t attributeCount, const AccessorConfiguration*, size_t accessorCount, const MethodConfiguration*, size_t callbackCount, - v8::Isolate*, WrapperWorldType); + v8::Isolate*); + + static v8::Handle<v8::FunctionTemplate> domClassTemplate(v8::Isolate*, WrapperTypeInfo*, void (*)(v8::Handle<v8::FunctionTemplate>, v8::Isolate*)); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8DOMWrapper.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMWrapper.cpp index 41dca146507..8a52d8c4296 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8DOMWrapper.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMWrapper.cpp @@ -31,11 +31,10 @@ #include "config.h" #include "bindings/v8/V8DOMWrapper.h" -#include "V8HTMLCollection.h" -#include "V8HTMLDocument.h" -#include "V8Window.h" +#include "bindings/core/v8/V8HTMLCollection.h" +#include "bindings/core/v8/V8HTMLDocument.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" #include "bindings/v8/V8ObjectConstructor.h" #include "bindings/v8/V8PerContextData.h" #include "bindings/v8/V8ScriptRunner.h" @@ -44,30 +43,28 @@ namespace WebCore { static v8::Local<v8::Object> wrapInShadowTemplate(v8::Local<v8::Object> wrapper, Node* impl, v8::Isolate* isolate) { - // This is only for getting a unique pointer which we can pass to privateTemplate. - static int shadowTemplateUniqueKey; - WrapperWorldType currentWorldType = worldType(isolate); + static int shadowTemplateKey; // This address is used for a key to look up the dom template. V8PerIsolateData* data = V8PerIsolateData::from(isolate); - v8::Handle<v8::FunctionTemplate> shadowTemplate = data->privateTemplateIfExists(currentWorldType, &shadowTemplateUniqueKey); + v8::Handle<v8::FunctionTemplate> shadowTemplate = data->existingDOMTemplate(&shadowTemplateKey); if (shadowTemplate.IsEmpty()) { shadowTemplate = v8::FunctionTemplate::New(isolate); if (shadowTemplate.IsEmpty()) return v8::Local<v8::Object>(); shadowTemplate->SetClassName(v8AtomicString(isolate, "HTMLDocument")); - shadowTemplate->Inherit(V8HTMLDocument::domTemplate(isolate, currentWorldType)); + shadowTemplate->Inherit(V8HTMLDocument::domTemplate(isolate)); shadowTemplate->InstanceTemplate()->SetInternalFieldCount(V8HTMLDocument::internalFieldCount); - data->setPrivateTemplate(currentWorldType, &shadowTemplateUniqueKey, shadowTemplate); + data->setDOMTemplate(&shadowTemplateKey, shadowTemplate); } v8::Local<v8::Function> shadowConstructor = shadowTemplate->GetFunction(); if (shadowConstructor.IsEmpty()) return v8::Local<v8::Object>(); - v8::Local<v8::Object> shadow = V8ScriptRunner::instantiateObject(shadowConstructor); + v8::Local<v8::Object> shadow = V8ScriptRunner::instantiateObject(isolate, shadowConstructor); if (shadow.IsEmpty()) return v8::Local<v8::Object>(); shadow->SetPrototype(wrapper); - V8DOMWrapper::setNativeInfo(wrapper, &V8HTMLDocument::wrapperTypeInfo, impl); + V8DOMWrapper::setNativeInfoForHiddenWrapper(wrapper, &V8HTMLDocument::wrapperTypeInfo, impl); return shadow; } @@ -76,7 +73,7 @@ v8::Local<v8::Object> V8DOMWrapper::createWrapper(v8::Handle<v8::Object> creatio V8WrapperInstantiationScope scope(creationContext, isolate); V8PerContextData* perContextData = V8PerContextData::from(scope.context()); - v8::Local<v8::Object> wrapper = perContextData ? perContextData->createWrapperFromCache(type) : V8ObjectConstructor::newInstance(type->domTemplate(isolate, worldTypeInMainThread(isolate))->GetFunction()); + v8::Local<v8::Object> wrapper = perContextData ? perContextData->createWrapperFromCache(type) : V8ObjectConstructor::newInstance(isolate, type->domTemplate(isolate)->GetFunction()); if (type == &V8HTMLDocument::wrapperTypeInfo && !wrapper.IsEmpty()) wrapper = wrapInShadowTemplate(wrapper, static_cast<Node*>(impl), isolate); @@ -84,59 +81,22 @@ v8::Local<v8::Object> V8DOMWrapper::createWrapper(v8::Handle<v8::Object> creatio return wrapper; } -static bool hasInternalField(v8::Handle<v8::Value> value) +bool V8DOMWrapper::isDOMWrapper(v8::Handle<v8::Value> value) { if (value.IsEmpty() || !value->IsObject()) return false; - return v8::Handle<v8::Object>::Cast(value)->InternalFieldCount(); -} -#ifndef NDEBUG -bool V8DOMWrapper::maybeDOMWrapper(v8::Handle<v8::Value> value) -{ - if (!hasInternalField(value)) - return false; - - v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(value); - ASSERT(object->InternalFieldCount() >= v8DefaultWrapperInternalFieldCount); - - v8::HandleScope scope(v8::Isolate::GetCurrent()); - ASSERT(object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex)); - - const WrapperTypeInfo* typeInfo = static_cast<const WrapperTypeInfo*>(object->GetAlignedPointerFromInternalField(v8DOMWrapperTypeIndex)); - - return typeInfo->ginEmbedder == gin::kEmbedderBlink; -} -#endif - -bool V8DOMWrapper::isDOMWrapper(v8::Handle<v8::Value> value) -{ - if (value.IsEmpty() || !value->IsObject()) + if (v8::Handle<v8::Object>::Cast(value)->InternalFieldCount() < v8DefaultWrapperInternalFieldCount) return false; v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(value); - if (wrapper->InternalFieldCount() < v8DefaultWrapperInternalFieldCount) - return false; ASSERT(wrapper->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex)); ASSERT(wrapper->GetAlignedPointerFromInternalField(v8DOMWrapperTypeIndex)); const WrapperTypeInfo* typeInfo = static_cast<const WrapperTypeInfo*>(wrapper->GetAlignedPointerFromInternalField(v8DOMWrapperTypeIndex)); - - // FIXME: Add class id checks. + // FIXME: We should add a more strict way to check if the typeInfo is a typeInfo of some DOM wrapper. + // Even if it's a typeInfo of Blink, it's not guaranteed that it's a typeInfo of a DOM wrapper. return typeInfo->ginEmbedder == gin::kEmbedderBlink; } -bool V8DOMWrapper::isWrapperOfType(v8::Handle<v8::Value> value, const WrapperTypeInfo* type) -{ - if (!hasInternalField(value)) - return false; - - v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(value); - ASSERT(wrapper->InternalFieldCount() >= v8DefaultWrapperInternalFieldCount); - ASSERT(wrapper->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex)); - - const WrapperTypeInfo* typeInfo = static_cast<const WrapperTypeInfo*>(wrapper->GetAlignedPointerFromInternalField(v8DOMWrapperTypeIndex)); - return typeInfo->ginEmbedder == gin::kEmbedderBlink && typeInfo == type; -} - } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8DOMWrapper.h b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMWrapper.h index 4bda879805b..db41c8f9034 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8DOMWrapper.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8DOMWrapper.h @@ -34,6 +34,7 @@ #include "bindings/v8/DOMDataStore.h" #include <v8.h> #include "wtf/PassRefPtr.h" +#include "wtf/RawPtr.h" #include "wtf/text/AtomicString.h" namespace WebCore { @@ -42,60 +43,115 @@ struct WrapperTypeInfo; class V8DOMWrapper { public: -#ifndef NDEBUG - // Checks if a v8 value can be a DOM wrapper - static bool maybeDOMWrapper(v8::Handle<v8::Value>); -#endif - static v8::Local<v8::Object> createWrapper(v8::Handle<v8::Object> creationContext, const WrapperTypeInfo*, void*, v8::Isolate*); template<typename V8T, typename T> static inline v8::Handle<v8::Object> associateObjectWithWrapper(PassRefPtr<T>, const WrapperTypeInfo*, v8::Handle<v8::Object>, v8::Isolate*, WrapperConfiguration::Lifetime); + template<typename V8T, typename T> + static inline v8::Handle<v8::Object> associateObjectWithWrapper(RawPtr<T> object, const WrapperTypeInfo* wrapperTypeInfo, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, WrapperConfiguration::Lifetime lifetime) + { + return associateObjectWithWrapper<V8T, T>(object.get(), wrapperTypeInfo, wrapper, isolate, lifetime); + } + template<typename V8T, typename T> + static inline v8::Handle<v8::Object> associateObjectWithWrapper(T*, const WrapperTypeInfo*, v8::Handle<v8::Object>, v8::Isolate*, WrapperConfiguration::Lifetime); static inline void setNativeInfo(v8::Handle<v8::Object>, const WrapperTypeInfo*, void*); + static inline void setNativeInfoForHiddenWrapper(v8::Handle<v8::Object>, const WrapperTypeInfo*, void*); + static inline void setNativeInfoWithPersistentHandle(v8::Handle<v8::Object>, const WrapperTypeInfo*, void*, PersistentNode*); static inline void clearNativeInfo(v8::Handle<v8::Object>, const WrapperTypeInfo*); static bool isDOMWrapper(v8::Handle<v8::Value>); - static bool isWrapperOfType(v8::Handle<v8::Value>, const WrapperTypeInfo*); }; - inline void V8DOMWrapper::setNativeInfo(v8::Handle<v8::Object> wrapper, const WrapperTypeInfo* type, void* object) + inline void V8DOMWrapper::setNativeInfo(v8::Handle<v8::Object> wrapper, const WrapperTypeInfo* wrapperTypeInfo, void* object) + { + ASSERT(wrapper->InternalFieldCount() >= 2); + ASSERT(object); + ASSERT(wrapperTypeInfo); +#if ENABLE(OILPAN) + ASSERT(wrapperTypeInfo->gcType == RefCountedObject); +#else + ASSERT(wrapperTypeInfo->gcType == RefCountedObject || wrapperTypeInfo->gcType == WillBeGarbageCollectedObject); +#endif + wrapper->SetAlignedPointerInInternalField(v8DOMWrapperObjectIndex, object); + wrapper->SetAlignedPointerInInternalField(v8DOMWrapperTypeIndex, const_cast<WrapperTypeInfo*>(wrapperTypeInfo)); + } + + inline void V8DOMWrapper::setNativeInfoForHiddenWrapper(v8::Handle<v8::Object> wrapper, const WrapperTypeInfo* wrapperTypeInfo, void* object) { + // see V8WindowShell::installDOMWindow() comment for why this version is needed and safe. ASSERT(wrapper->InternalFieldCount() >= 2); ASSERT(object); - ASSERT(type); + ASSERT(wrapperTypeInfo); +#if ENABLE(OILPAN) + ASSERT(wrapperTypeInfo->gcType != RefCountedObject); +#else + ASSERT(wrapperTypeInfo->gcType == RefCountedObject || wrapperTypeInfo->gcType == WillBeGarbageCollectedObject); +#endif + + // Clear out the last internal field, which is assumed to contain a valid persistent pointer value. + if (wrapperTypeInfo->gcType == GarbageCollectedObject) { + wrapper->SetAlignedPointerInInternalField(wrapper->InternalFieldCount() - 1, 0); + } else if (wrapperTypeInfo->gcType == WillBeGarbageCollectedObject) { +#if ENABLE(OILPAN) + wrapper->SetAlignedPointerInInternalField(wrapper->InternalFieldCount() - 1, 0); +#endif + } + wrapper->SetAlignedPointerInInternalField(v8DOMWrapperObjectIndex, object); + wrapper->SetAlignedPointerInInternalField(v8DOMWrapperTypeIndex, const_cast<WrapperTypeInfo*>(wrapperTypeInfo)); + } + + inline void V8DOMWrapper::setNativeInfoWithPersistentHandle(v8::Handle<v8::Object> wrapper, const WrapperTypeInfo* wrapperTypeInfo, void* object, PersistentNode* handle) + { + ASSERT(wrapper->InternalFieldCount() >= 3); + ASSERT(object); + ASSERT(wrapperTypeInfo); + ASSERT(wrapperTypeInfo->gcType != RefCountedObject); wrapper->SetAlignedPointerInInternalField(v8DOMWrapperObjectIndex, object); - wrapper->SetAlignedPointerInInternalField(v8DOMWrapperTypeIndex, const_cast<WrapperTypeInfo*>(type)); + wrapper->SetAlignedPointerInInternalField(v8DOMWrapperTypeIndex, const_cast<WrapperTypeInfo*>(wrapperTypeInfo)); + // Persistent handle is stored in the last internal field. + wrapper->SetAlignedPointerInInternalField(wrapper->InternalFieldCount() - 1, handle); } - inline void V8DOMWrapper::clearNativeInfo(v8::Handle<v8::Object> wrapper, const WrapperTypeInfo* type) + inline void V8DOMWrapper::clearNativeInfo(v8::Handle<v8::Object> wrapper, const WrapperTypeInfo* wrapperTypeInfo) { ASSERT(wrapper->InternalFieldCount() >= 2); - ASSERT(type); - wrapper->SetAlignedPointerInInternalField(v8DOMWrapperTypeIndex, const_cast<WrapperTypeInfo*>(type)); + ASSERT(wrapperTypeInfo); + // clearNativeInfo() is used only by NP objects, which are not garbage collected. + ASSERT(wrapperTypeInfo->gcType == RefCountedObject); + wrapper->SetAlignedPointerInInternalField(v8DOMWrapperTypeIndex, const_cast<WrapperTypeInfo*>(wrapperTypeInfo)); wrapper->SetAlignedPointerInInternalField(v8DOMWrapperObjectIndex, 0); } template<typename V8T, typename T> - inline v8::Handle<v8::Object> V8DOMWrapper::associateObjectWithWrapper(PassRefPtr<T> object, const WrapperTypeInfo* type, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, WrapperConfiguration::Lifetime lifetime) + inline v8::Handle<v8::Object> V8DOMWrapper::associateObjectWithWrapper(PassRefPtr<T> object, const WrapperTypeInfo* wrapperTypeInfo, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, WrapperConfiguration::Lifetime lifetime) { - setNativeInfo(wrapper, type, V8T::toInternalPointer(object.get())); - ASSERT(maybeDOMWrapper(wrapper)); + setNativeInfo(wrapper, wrapperTypeInfo, V8T::toInternalPointer(object.get())); + ASSERT(isDOMWrapper(wrapper)); WrapperConfiguration configuration = buildWrapperConfiguration(object.get(), lifetime); DOMDataStore::setWrapper<V8T>(object.leakRef(), wrapper, isolate, configuration); return wrapper; } + template<typename V8T, typename T> + inline v8::Handle<v8::Object> V8DOMWrapper::associateObjectWithWrapper(T* object, const WrapperTypeInfo* wrapperTypeInfo, v8::Handle<v8::Object> wrapper, v8::Isolate* isolate, WrapperConfiguration::Lifetime lifetime) + { + setNativeInfoWithPersistentHandle(wrapper, wrapperTypeInfo, V8T::toInternalPointer(object), new Persistent<T>(object)); + ASSERT(isDOMWrapper(wrapper)); + WrapperConfiguration configuration = buildWrapperConfiguration(object, lifetime); + DOMDataStore::setWrapper<V8T>(object, wrapper, isolate, configuration); + return wrapper; + } + class V8WrapperInstantiationScope { public: V8WrapperInstantiationScope(v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) : m_didEnterContext(false) , m_context(isolate->GetCurrentContext()) { - // FIXME: Remove all empty creationContexts from caller sites. - // If a creationContext is empty, we will end up creating a new object - // in the context currently entered. This is wrong. - if (creationContext.IsEmpty()) - return; + // creationContext should not be empty. Because if we have an + // empty creationContext, we will end up creating + // a new object in the context currently entered. This is wrong. + RELEASE_ASSERT(!creationContext.IsEmpty()); v8::Handle<v8::Context> contextForWrapper = creationContext->CreationContext(); // For performance, we enter the context only if the currently running context // is different from the context that we are about to enter. diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8ErrorHandler.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8ErrorHandler.cpp index 758eb47fedf..c72ac25806b 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8ErrorHandler.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8ErrorHandler.cpp @@ -31,63 +31,61 @@ #include "config.h" #include "bindings/v8/V8ErrorHandler.h" -#include "V8ErrorEvent.h" +#include "bindings/core/v8/V8ErrorEvent.h" #include "bindings/v8/ScriptController.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "bindings/v8/V8ScriptRunner.h" #include "core/dom/Document.h" #include "core/dom/ExecutionContext.h" #include "core/events/ErrorEvent.h" -#include "core/events/ThreadLocalEventNames.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" namespace WebCore { -V8ErrorHandler::V8ErrorHandler(v8::Local<v8::Object> listener, bool isInline, v8::Isolate* isolate) - : V8EventListener(listener, isInline, isolate) +V8ErrorHandler::V8ErrorHandler(v8::Local<v8::Object> listener, bool isInline, ScriptState* scriptState) + : V8EventListener(listener, isInline, scriptState) { } -v8::Local<v8::Value> V8ErrorHandler::callListenerFunction(ExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event) +v8::Local<v8::Value> V8ErrorHandler::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event) { if (!event->hasInterface(EventNames::ErrorEvent)) - return V8EventListener::callListenerFunction(context, jsEvent, event); + return V8EventListener::callListenerFunction(jsEvent, event); ErrorEvent* errorEvent = static_cast<ErrorEvent*>(event); - v8::Isolate* isolate = toV8Context(context, world())->GetIsolate(); - if (errorEvent->world() && errorEvent->world() != world()) - return v8::Null(isolate); + if (errorEvent->world() && errorEvent->world() != &world()) + return v8::Null(isolate()); - v8::Local<v8::Object> listener = getListenerObject(context); + v8::Local<v8::Object> listener = getListenerObject(scriptState()->executionContext()); v8::Local<v8::Value> returnValue; if (!listener.IsEmpty() && listener->IsFunction()) { v8::Local<v8::Function> callFunction = v8::Local<v8::Function>::Cast(listener); - v8::Local<v8::Object> thisValue = isolate->GetCurrentContext()->Global(); + v8::Local<v8::Object> thisValue = scriptState()->context()->Global(); - v8::Local<v8::Value> error = jsEvent->ToObject()->GetHiddenValue(V8HiddenPropertyName::error(isolate)); + v8::Local<v8::Value> error = V8HiddenValue::getHiddenValue(isolate(), jsEvent->ToObject(), V8HiddenValue::error(isolate())); if (error.IsEmpty()) - error = v8::Null(isolate); + error = v8::Null(isolate()); - v8::Handle<v8::Value> parameters[5] = { v8String(isolate, errorEvent->message()), v8String(isolate, errorEvent->filename()), v8::Integer::New(errorEvent->lineno(), isolate), v8::Integer::New(errorEvent->colno(), isolate), error }; + v8::Handle<v8::Value> parameters[5] = { v8String(isolate(), errorEvent->message()), v8String(isolate(), errorEvent->filename()), v8::Integer::New(isolate(), errorEvent->lineno()), v8::Integer::New(isolate(), errorEvent->colno()), error }; v8::TryCatch tryCatch; tryCatch.SetVerbose(true); - if (worldType(isolate) == WorkerWorld) - returnValue = V8ScriptRunner::callFunction(callFunction, context, thisValue, WTF_ARRAY_LENGTH(parameters), parameters, isolate); + if (scriptState()->executionContext()->isWorkerGlobalScope()) + returnValue = V8ScriptRunner::callFunction(callFunction, scriptState()->executionContext(), thisValue, WTF_ARRAY_LENGTH(parameters), parameters, isolate()); else - returnValue = ScriptController::callFunction(context, callFunction, thisValue, WTF_ARRAY_LENGTH(parameters), parameters, isolate); + returnValue = ScriptController::callFunction(scriptState()->executionContext(), callFunction, thisValue, WTF_ARRAY_LENGTH(parameters), parameters, isolate()); } return returnValue; } // static -void V8ErrorHandler::storeExceptionOnErrorEventWrapper(ErrorEvent* event, v8::Handle<v8::Value> data, v8::Isolate* isolate) +void V8ErrorHandler::storeExceptionOnErrorEventWrapper(ErrorEvent* event, v8::Handle<v8::Value> data, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { - v8::Local<v8::Value> wrappedEvent = toV8(event, v8::Handle<v8::Object>(), isolate); + v8::Local<v8::Value> wrappedEvent = toV8(event, creationContext, isolate); if (!wrappedEvent.IsEmpty()) { ASSERT(wrappedEvent->IsObject()); - v8::Local<v8::Object>::Cast(wrappedEvent)->SetHiddenValue(V8HiddenPropertyName::error(isolate), data); + V8HiddenValue::setHiddenValue(isolate, v8::Local<v8::Object>::Cast(wrappedEvent), V8HiddenValue::error(isolate), data); } } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8ErrorHandler.h b/chromium/third_party/WebKit/Source/bindings/v8/V8ErrorHandler.h index cfaa69de587..8e1d5f22489 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8ErrorHandler.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8ErrorHandler.h @@ -38,22 +38,22 @@ namespace WebCore { class ErrorEvent; -class Frame; +class LocalFrame; -class V8ErrorHandler : public V8EventListener { +class V8ErrorHandler FINAL : public V8EventListener { public: - static PassRefPtr<V8ErrorHandler> create(v8::Local<v8::Object> listener, bool isInline, v8::Isolate* isolate) + static PassRefPtr<V8ErrorHandler> create(v8::Local<v8::Object> listener, bool isInline, ScriptState* scriptState) { - return adoptRef(new V8ErrorHandler(listener, isInline, isolate)); + return adoptRef(new V8ErrorHandler(listener, isInline, scriptState)); } - static void storeExceptionOnErrorEventWrapper(ErrorEvent*, v8::Handle<v8::Value>, v8::Isolate*); + static void storeExceptionOnErrorEventWrapper(ErrorEvent*, v8::Handle<v8::Value>, v8::Handle<v8::Object> creationContext, v8::Isolate*); private: - V8ErrorHandler(v8::Local<v8::Object> listener, bool isInline, v8::Isolate*); + V8ErrorHandler(v8::Local<v8::Object> listener, bool isInline, ScriptState*); - virtual v8::Local<v8::Value> callListenerFunction(ExecutionContext*, v8::Handle<v8::Value> jsEvent, Event*); - virtual bool shouldPreventDefault(v8::Local<v8::Value> returnValue); + virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsEvent, Event*) OVERRIDE; + virtual bool shouldPreventDefault(v8::Local<v8::Value> returnValue) OVERRIDE; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8EventListener.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8EventListener.cpp index 13144b96e9d..fc204607cee 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8EventListener.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8EventListener.cpp @@ -34,19 +34,19 @@ #include "bindings/v8/ScriptController.h" #include "bindings/v8/V8Binding.h" #include "core/dom/Document.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" namespace WebCore { -V8EventListener::V8EventListener(v8::Local<v8::Object> listener, bool isAttribute, v8::Isolate* isolate) - : V8AbstractEventListener(isAttribute, DOMWrapperWorld::current(), isolate) +V8EventListener::V8EventListener(v8::Local<v8::Object> listener, bool isAttribute, ScriptState* scriptState) + : V8AbstractEventListener(isAttribute, scriptState) { setListenerObject(listener); } -v8::Local<v8::Function> V8EventListener::getListenerFunction(ExecutionContext* context) +v8::Local<v8::Function> V8EventListener::getListenerFunction(ExecutionContext*) { - v8::Local<v8::Object> listener = getListenerObject(context); + v8::Local<v8::Object> listener = getListenerObject(scriptState()->executionContext()); // Has the listener been disposed? if (listener.IsEmpty()) @@ -67,22 +67,18 @@ v8::Local<v8::Function> V8EventListener::getListenerFunction(ExecutionContext* c return v8::Local<v8::Function>(); } -v8::Local<v8::Value> V8EventListener::callListenerFunction(ExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event) +v8::Local<v8::Value> V8EventListener::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event) { - v8::Local<v8::Function> handlerFunction = getListenerFunction(context); - v8::Local<v8::Object> receiver = getReceiverObject(context, event); + v8::Local<v8::Function> handlerFunction = getListenerFunction(scriptState()->executionContext()); + v8::Local<v8::Object> receiver = getReceiverObject(event); if (handlerFunction.IsEmpty() || receiver.IsEmpty()) return v8::Local<v8::Value>(); - // FIXME: Can |context| be 0 here? - if (!context) + if (!scriptState()->executionContext()->isDocument()) return v8::Local<v8::Value>(); - if (!context->isDocument()) - return v8::Local<v8::Value>(); - - Frame* frame = toDocument(context)->frame(); + LocalFrame* frame = toDocument(scriptState()->executionContext())->frame(); if (!frame) return v8::Local<v8::Value>(); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8EventListener.h b/chromium/third_party/WebKit/Source/bindings/v8/V8EventListener.h index 1358848a5f1..93296ae659e 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8EventListener.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8EventListener.h @@ -31,7 +31,6 @@ #ifndef V8EventListener_h #define V8EventListener_h -#include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/V8AbstractEventListener.h" #include <v8.h> #include "wtf/PassRefPtr.h" @@ -39,23 +38,23 @@ namespace WebCore { class Event; - class Frame; + class LocalFrame; // V8EventListener is a wrapper of a JS object implements EventListener interface (has handleEvent(event) method), or a JS function // that can handle the event. class V8EventListener : public V8AbstractEventListener { public: - static PassRefPtr<V8EventListener> create(v8::Local<v8::Object> listener, bool isAttribute, v8::Isolate* isolate) + static PassRefPtr<V8EventListener> create(v8::Local<v8::Object> listener, bool isAttribute, ScriptState* scriptState) { - return adoptRef(new V8EventListener(listener, isAttribute, isolate)); + return adoptRef(new V8EventListener(listener, isAttribute, scriptState)); } protected: - V8EventListener(v8::Local<v8::Object> listener, bool isAttribute, v8::Isolate*); + V8EventListener(v8::Local<v8::Object> listener, bool isAttribute, ScriptState*); v8::Local<v8::Function> getListenerFunction(ExecutionContext*); - virtual v8::Local<v8::Value> callListenerFunction(ExecutionContext*, v8::Handle<v8::Value> jsEvent, Event*); + virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsEvent, Event*) OVERRIDE; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8EventListenerList.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8EventListenerList.cpp index 0606fb69fa6..ad44ef8bd1f 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8EventListenerList.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8EventListenerList.cpp @@ -31,27 +31,24 @@ #include "config.h" #include "bindings/v8/V8EventListenerList.h" -#include "V8Window.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8WorkerGlobalScopeEventListener.h" namespace WebCore { -PassRefPtr<EventListener> V8EventListenerList::getEventListener(v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) +PassRefPtr<EventListener> V8EventListenerList::getEventListener(ScriptState* scriptState, v8::Local<v8::Value> value, bool isAttribute, ListenerLookupType lookup) { - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::Handle<v8::Context> context = isolate->GetCurrentContext(); - if (context.IsEmpty()) - return 0; + ASSERT(!scriptState->contextIsEmpty()); if (lookup == ListenerFindOnly) { // Used by EventTarget::removeEventListener, specifically // EventTargetV8Internal::removeEventListenerMethod ASSERT(!isAttribute); - return V8EventListenerList::findWrapper(value, isolate); + return V8EventListenerList::findWrapper(value, scriptState); } - if (V8DOMWrapper::isWrapperOfType(toInnerGlobalObject(context), &V8Window::wrapperTypeInfo)) - return V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute, isolate); - return V8EventListenerList::findOrCreateWrapper<V8WorkerGlobalScopeEventListener>(value, isAttribute, isolate); + if (toDOMWindow(scriptState->context())) + return V8EventListenerList::findOrCreateWrapper<V8EventListener>(value, isAttribute, scriptState); + return V8EventListenerList::findOrCreateWrapper<V8WorkerGlobalScopeEventListener>(value, isAttribute, scriptState); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8EventListenerList.h b/chromium/third_party/WebKit/Source/bindings/v8/V8EventListenerList.h index 3be3bb9f34f..34ee4106e01 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8EventListenerList.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8EventListenerList.h @@ -31,15 +31,13 @@ #ifndef V8EventListenerList_h #define V8EventListenerList_h +#include "bindings/v8/V8Binding.h" #include "bindings/v8/V8EventListener.h" -#include "bindings/v8/V8HiddenPropertyName.h" - #include <v8.h> -#include "wtf/PassRefPtr.h" namespace WebCore { -class Frame; +class LocalFrame; enum ListenerLookupType { ListenerFindOnly, @@ -49,18 +47,18 @@ enum ListenerLookupType { // This is a container for V8EventListener objects that uses hidden properties of v8::Object to speed up lookups. class V8EventListenerList { public: - static PassRefPtr<V8EventListener> findWrapper(v8::Local<v8::Value> value, v8::Isolate* isolate) + static PassRefPtr<V8EventListener> findWrapper(v8::Local<v8::Value> value, ScriptState* scriptState) { - ASSERT(isolate->InContext()); + ASSERT(scriptState->isolate()->InContext()); if (!value->IsObject()) - return 0; + return nullptr; - v8::Handle<v8::String> wrapperProperty = getHiddenProperty(false, isolate); - return doFindWrapper(v8::Local<v8::Object>::Cast(value), wrapperProperty, isolate); + v8::Handle<v8::String> wrapperProperty = getHiddenProperty(false, scriptState->isolate()); + return doFindWrapper(v8::Local<v8::Object>::Cast(value), wrapperProperty, scriptState); } template<typename WrapperType> - static PassRefPtr<V8EventListener> findOrCreateWrapper(v8::Local<v8::Value>, bool isAttribute, v8::Isolate*); + static PassRefPtr<V8EventListener> findOrCreateWrapper(v8::Local<v8::Value>, bool isAttribute, ScriptState*); static void clearWrapper(v8::Handle<v8::Object> listenerObject, bool isAttribute, v8::Isolate* isolate) { @@ -68,13 +66,13 @@ public: listenerObject->DeleteHiddenValue(wrapperProperty); } - static PassRefPtr<EventListener> getEventListener(v8::Local<v8::Value>, bool isAttribute, ListenerLookupType); + static PassRefPtr<EventListener> getEventListener(ScriptState*, v8::Local<v8::Value>, bool isAttribute, ListenerLookupType); private: - static V8EventListener* doFindWrapper(v8::Local<v8::Object> object, v8::Handle<v8::String> wrapperProperty, v8::Isolate* isolate) + static V8EventListener* doFindWrapper(v8::Local<v8::Object> object, v8::Handle<v8::String> wrapperProperty, ScriptState* scriptState) { - ASSERT(isolate->InContext()); - v8::HandleScope scope(isolate); + v8::HandleScope scope(scriptState->isolate()); + ASSERT(scriptState->isolate()->InContext()); v8::Local<v8::Value> listener = object->GetHiddenValue(wrapperProperty); if (listener.IsEmpty()) return 0; @@ -83,27 +81,28 @@ private: static inline v8::Handle<v8::String> getHiddenProperty(bool isAttribute, v8::Isolate* isolate) { - return isAttribute ? V8HiddenPropertyName::attributeListener(isolate) : V8HiddenPropertyName::listener(isolate); + return isAttribute ? v8AtomicString(isolate, "attributeListener") : v8AtomicString(isolate, "listener"); } }; template<typename WrapperType> -PassRefPtr<V8EventListener> V8EventListenerList::findOrCreateWrapper(v8::Local<v8::Value> value, bool isAttribute, v8::Isolate* isolate) +PassRefPtr<V8EventListener> V8EventListenerList::findOrCreateWrapper(v8::Local<v8::Value> value, bool isAttribute, ScriptState* scriptState) { + v8::Isolate* isolate = scriptState->isolate(); ASSERT(isolate->InContext()); if (!value->IsObject() // Non-callable attribute setter input is treated as null (no wrapper) || (isAttribute && !value->IsFunction())) - return 0; + return nullptr; v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(value); v8::Handle<v8::String> wrapperProperty = getHiddenProperty(isAttribute, isolate); - V8EventListener* wrapper = doFindWrapper(object, wrapperProperty, isolate); + V8EventListener* wrapper = doFindWrapper(object, wrapperProperty, scriptState); if (wrapper) return wrapper; - RefPtr<V8EventListener> wrapperPtr = WrapperType::create(object, isAttribute, isolate); + RefPtr<V8EventListener> wrapperPtr = WrapperType::create(object, isAttribute, scriptState); if (wrapperPtr) object->SetHiddenValue(wrapperProperty, v8::External::New(isolate, wrapperPtr.get())); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8GCController.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8GCController.cpp index 133914ad9c4..b09bfe742a3 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8GCController.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8GCController.cpp @@ -31,13 +31,12 @@ #include "config.h" #include "bindings/v8/V8GCController.h" -#include <algorithm> -#include "V8MutationObserver.h" -#include "V8Node.h" -#include "V8ScriptRunner.h" +#include "bindings/core/v8/V8MutationObserver.h" +#include "bindings/core/v8/V8Node.h" #include "bindings/v8/RetainedDOMInfo.h" #include "bindings/v8/V8AbstractEventListener.h" #include "bindings/v8/V8Binding.h" +#include "bindings/v8/V8ScriptRunner.h" #include "bindings/v8/WrapperTypeInfo.h" #include "core/dom/Attr.h" #include "core/dom/NodeTraversal.h" @@ -46,8 +45,12 @@ #include "core/dom/shadow/ShadowRoot.h" #include "core/html/HTMLImageElement.h" #include "core/html/HTMLTemplateElement.h" +#include "core/html/imports/HTMLImportsController.h" +#include "core/inspector/InspectorTraceEvents.h" #include "core/svg/SVGElement.h" +#include "platform/Partitions.h" #include "platform/TraceEvent.h" +#include <algorithm> namespace WebCore { @@ -64,20 +67,23 @@ static void addReferencesForNodeWithEventListeners(v8::Isolate* isolate, Node* n if (!v8listener->hasExistingListenerObject()) continue; - // FIXME: update this to use the upcasting function which v8 will provide. - v8::Persistent<v8::Value>* value = reinterpret_cast<v8::Persistent<v8::Value>*>(&(v8listener->existingListenerObjectPersistentHandle())); - isolate->SetReference(wrapper, *value); + isolate->SetReference(wrapper, v8::Persistent<v8::Value>::Cast(v8listener->existingListenerObjectPersistentHandle())); } } Node* V8GCController::opaqueRootForGC(Node* node, v8::Isolate*) { + ASSERT(node); // FIXME: Remove the special handling for image elements. // The same special handling is in V8GCController::gcTree(). // Maybe should image elements be active DOM nodes? // See https://code.google.com/p/chromium/issues/detail?id=164882 - if (node->inDocument() || (node->hasTagName(HTMLNames::imgTag) && toHTMLImageElement(node)->hasPendingActivity())) - return &node->document(); + if (node->inDocument() || (isHTMLImageElement(*node) && toHTMLImageElement(*node).hasPendingActivity())) { + Document& document = node->document(); + if (HTMLImportsController* controller = document.importsController()) + return controller->master(); + return &document; + } if (node->isAttributeNode()) { Node* ownerElement = toAttr(node)->ownerElement(); @@ -117,12 +123,12 @@ public: if (m_nodesInNewSpace.size() >= wrappersHandledByEachMinorGC) return; - // Casting to a Handle is safe here, since the Persistent cannot get GCd + // Casting to a Handle is safe here, since the Persistent doesn't get GCd // during the GC prologue. ASSERT((*reinterpret_cast<v8::Handle<v8::Value>*>(value))->IsObject()); v8::Handle<v8::Object>* wrapper = reinterpret_cast<v8::Handle<v8::Object>*>(value); - ASSERT(V8DOMWrapper::maybeDOMWrapper(*wrapper)); - ASSERT(V8Node::hasInstanceInAnyWorld(*wrapper, m_isolate)); + ASSERT(V8DOMWrapper::isDOMWrapper(*wrapper)); + ASSERT(V8Node::hasInstance(*wrapper, m_isolate)); Node* node = V8Node::toNative(*wrapper); // A minor DOM GC can handle only node wrappers in the main world. // Note that node->wrapper().IsEmpty() returns true for nodes that @@ -132,8 +138,18 @@ public: ActiveDOMObject* activeDOMObject = type->toActiveDOMObject(*wrapper); if (activeDOMObject && activeDOMObject->hasPendingActivity()) return; + // FIXME: Remove the special handling for image elements. + // The same special handling is in V8GCController::opaqueRootForGC(). + // Maybe should image elements be active DOM nodes? + // See https://code.google.com/p/chromium/issues/detail?id=164882 + if (isHTMLImageElement(*node) && toHTMLImageElement(*node).hasPendingActivity()) + return; + // FIXME: Remove the special handling for SVG context elements. + if (node->isSVGElement() && toSVGElement(node)->isContextElement()) + return; + m_nodesInNewSpace.append(node); - node->setV8CollectableDuringMinorGC(true); + node->markV8CollectableDuringMinorGC(); } } @@ -144,82 +160,83 @@ public: for (; nodeIterator < nodeIteratorEnd; ++nodeIterator) { Node* node = *nodeIterator; ASSERT(node->containsWrapper()); - if (node->isV8CollectableDuringMinorGC()) // This branch is just for performance. + if (node->isV8CollectableDuringMinorGC()) { // This branch is just for performance. gcTree(m_isolate, node); + node->clearV8CollectableDuringMinorGC(); + } } } private: - bool traverseTree(Node* rootNode, Vector<Node*, initialNodeVectorSize>* newSpaceNodes) + bool traverseTree(Node* rootNode, Vector<Node*, initialNodeVectorSize>* partiallyDependentNodes) { // To make each minor GC time bounded, we might need to give up // traversing at some point for a large DOM tree. That being said, // I could not observe the need even in pathological test cases. for (Node* node = rootNode; node; node = NodeTraversal::next(*node)) { if (node->containsWrapper()) { - // FIXME: Remove the special handling for image elements. - // FIXME: Remove the special handling for SVG context elements. - // The same special handling is in V8GCController::opaqueRootForGC(). - // Maybe should image elements be active DOM nodes? - // See https://code.google.com/p/chromium/issues/detail?id=164882 - if (!node->isV8CollectableDuringMinorGC() || (node->hasTagName(HTMLNames::imgTag) && toHTMLImageElement(node)->hasPendingActivity()) || (node->isSVGElement() && toSVGElement(node)->isContextElement())) { + if (!node->isV8CollectableDuringMinorGC()) { // This node is not in the new space of V8. This indicates that // the minor GC cannot anyway judge reachability of this DOM tree. // Thus we give up traversing the DOM tree. return false; } - node->setV8CollectableDuringMinorGC(false); - newSpaceNodes->append(node); + node->clearV8CollectableDuringMinorGC(); + partiallyDependentNodes->append(node); } if (ShadowRoot* shadowRoot = node->youngestShadowRoot()) { - if (!traverseTree(shadowRoot, newSpaceNodes)) + if (!traverseTree(shadowRoot, partiallyDependentNodes)) return false; } else if (node->isShadowRoot()) { if (ShadowRoot* shadowRoot = toShadowRoot(node)->olderShadowRoot()) { - if (!traverseTree(shadowRoot, newSpaceNodes)) + if (!traverseTree(shadowRoot, partiallyDependentNodes)) return false; } } // <template> has a |content| property holding a DOM fragment which we must traverse, // just like we do for the shadow trees above. - if (node->hasTagName(HTMLNames::templateTag)) { - if (!traverseTree(toHTMLTemplateElement(node)->content(), newSpaceNodes)) + if (isHTMLTemplateElement(*node)) { + if (!traverseTree(toHTMLTemplateElement(*node).content(), partiallyDependentNodes)) return false; } + + // Document maintains the list of imported documents through HTMLImportsController. + if (node->isDocumentNode()) { + Document* document = toDocument(node); + HTMLImportsController* controller = document->importsController(); + if (controller && document == controller->master()) { + for (unsigned i = 0; i < controller->loaderCount(); ++i) { + if (!traverseTree(controller->loaderDocumentAt(i), partiallyDependentNodes)) + return false; + } + } + } } return true; } void gcTree(v8::Isolate* isolate, Node* startNode) { - Vector<Node*, initialNodeVectorSize> newSpaceNodes; + Vector<Node*, initialNodeVectorSize> partiallyDependentNodes; Node* node = startNode; while (Node* parent = node->parentOrShadowHostOrTemplateHostNode()) node = parent; - if (!traverseTree(node, &newSpaceNodes)) + if (!traverseTree(node, &partiallyDependentNodes)) return; // We completed the DOM tree traversal. All wrappers in the DOM tree are - // stored in newSpaceNodes and are expected to exist in the new space of V8. + // stored in partiallyDependentNodes and are expected to exist in the new space of V8. // We report those wrappers to V8 as an object group. - Node** nodeIterator = newSpaceNodes.begin(); - Node** const nodeIteratorEnd = newSpaceNodes.end(); + Node** nodeIterator = partiallyDependentNodes.begin(); + Node** const nodeIteratorEnd = partiallyDependentNodes.end(); if (nodeIterator == nodeIteratorEnd) return; - v8::UniqueId id(reinterpret_cast<intptr_t>((*nodeIterator)->unsafePersistent().value())); + + Node* groupRoot = *nodeIterator; for (; nodeIterator != nodeIteratorEnd; ++nodeIterator) { - // This is safe because we know that GC won't happen before we - // dispose the UnsafePersistent (we're just preparing a GC). Though, - // we need to keep the UnsafePersistent alive until we're done with - // v8::Persistent. - UnsafePersistent<v8::Object> unsafeWrapper = (*nodeIterator)->unsafePersistent(); - v8::Persistent<v8::Object>* wrapper = unsafeWrapper.persistent(); - wrapper->MarkPartiallyDependent(); - // FIXME: update this to use the upcasting function which v8 will provide - v8::Persistent<v8::Value>* value = reinterpret_cast<v8::Persistent<v8::Value>*>(wrapper); - isolate->SetObjectGroupId(*value, id); + (*nodeIterator)->markAsDependentGroup(groupRoot, isolate); } } @@ -238,16 +255,14 @@ public: virtual void VisitPersistentHandle(v8::Persistent<v8::Value>* value, uint16_t classId) OVERRIDE { - // Casting to a Handle is safe here, since the Persistent cannot get GCd - // during the GC prologue. - ASSERT((*reinterpret_cast<v8::Handle<v8::Value>*>(value))->IsObject()); - if (classId != v8DOMNodeClassId && classId != v8DOMObjectClassId) return; + // Casting to a Handle is safe here, since the Persistent doesn't get GCd + // during the GC prologue. + ASSERT((*reinterpret_cast<v8::Handle<v8::Value>*>(value))->IsObject()); v8::Handle<v8::Object>* wrapper = reinterpret_cast<v8::Handle<v8::Object>*>(value); - - ASSERT(V8DOMWrapper::maybeDOMWrapper(*wrapper)); + ASSERT(V8DOMWrapper::isDOMWrapper(*wrapper)); if (value->IsIndependent()) return; @@ -255,26 +270,13 @@ public: const WrapperTypeInfo* type = toWrapperTypeInfo(*wrapper); void* object = toNative(*wrapper); - if (V8MutationObserver::wrapperTypeInfo.equals(type)) { - // FIXME: Allow opaqueRootForGC to operate on multiple roots and move this logic into V8MutationObserverCustom. - MutationObserver* observer = static_cast<MutationObserver*>(object); - HashSet<Node*> observedNodes = observer->getObservedNodes(); - for (HashSet<Node*>::iterator it = observedNodes.begin(); it != observedNodes.end(); ++it) { - v8::UniqueId id(reinterpret_cast<intptr_t>(V8GCController::opaqueRootForGC(*it, m_isolate))); - m_isolate->SetReferenceFromGroup(id, *value); - } - } else { - ActiveDOMObject* activeDOMObject = type->toActiveDOMObject(*wrapper); - if (activeDOMObject && activeDOMObject->hasPendingActivity()) - m_isolate->SetObjectGroupId(*value, liveRootId()); - } + ActiveDOMObject* activeDOMObject = type->toActiveDOMObject(*wrapper); + if (activeDOMObject && activeDOMObject->hasPendingActivity()) + m_isolate->SetObjectGroupId(*value, liveRootId()); if (classId == v8DOMNodeClassId) { - ASSERT(V8Node::hasInstanceInAnyWorld(*wrapper, m_isolate)); - ASSERT(!value->IsIndependent()); - + ASSERT(V8Node::hasInstance(*wrapper, m_isolate)); Node* node = static_cast<Node*>(object); - if (node->hasEventListeners()) addReferencesForNodeWithEventListeners(m_isolate, node, v8::Persistent<v8::Object>::Cast(*value)); Node* root = V8GCController::opaqueRootForGC(node, m_isolate); @@ -282,9 +284,7 @@ public: if (m_constructRetainedObjectInfos) m_groupsWhichNeedRetainerInfo.append(root); } else if (classId == v8DOMObjectClassId) { - ASSERT(!value->IsIndependent()); - v8::Persistent<v8::Object>* wrapperPersistent = reinterpret_cast<v8::Persistent<v8::Object>*>(value); - type->visitDOMWrapper(object, *wrapperPersistent, m_isolate); + type->visitDOMWrapper(object, v8::Persistent<v8::Object>::Cast(*value), m_isolate); } else { ASSERT_NOT_REACHED(); } @@ -325,10 +325,18 @@ private: bool m_constructRetainedObjectInfos; }; +static unsigned long long usedHeapSize(v8::Isolate* isolate) +{ + v8::HeapStatistics heapStatistics; + isolate->GetHeapStatistics(&heapStatistics); + return heapStatistics.used_heap_size(); +} + void V8GCController::gcPrologue(v8::GCType type, v8::GCCallbackFlags flags) { // FIXME: It would be nice if the GC callbacks passed the Isolate directly.... v8::Isolate* isolate = v8::Isolate::GetCurrent(); + TRACE_EVENT_BEGIN1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "GCEvent", "usedHeapSizeBefore", usedHeapSize(isolate)); if (type == v8::kGCTypeScavenge) minorGCPrologue(isolate); else if (type == v8::kGCTypeMarkSweepCompact) @@ -340,14 +348,14 @@ void V8GCController::minorGCPrologue(v8::Isolate* isolate) TRACE_EVENT_BEGIN0("v8", "minorGC"); if (isMainThread()) { { - TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "MinorGC"); + TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMMinorGC"); v8::HandleScope scope(isolate); MinorGCWrapperVisitor visitor(isolate); v8::V8::VisitHandlesForPartialDependence(isolate, &visitor); visitor.notifyFinished(); } V8PerIsolateData::from(isolate)->setPreviousSamplingState(TRACE_EVENT_GET_SAMPLING_STATE()); - TRACE_EVENT_SET_SAMPLING_STATE("V8", "MinorGC"); + TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8MinorGC"); } } @@ -358,13 +366,13 @@ void V8GCController::majorGCPrologue(bool constructRetainedObjectInfos, v8::Isol TRACE_EVENT_BEGIN0("v8", "majorGC"); if (isMainThread()) { { - TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "MajorGC"); + TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "DOMMajorGC"); MajorGCWrapperVisitor visitor(isolate, constructRetainedObjectInfos); v8::V8::VisitHandlesWithClassIds(&visitor); visitor.notifyFinished(); } V8PerIsolateData::from(isolate)->setPreviousSamplingState(TRACE_EVENT_GET_SAMPLING_STATE()); - TRACE_EVENT_SET_SAMPLING_STATE("V8", "MajorGC"); + TRACE_EVENT_SET_SAMPLING_STATE("V8", "V8MajorGC"); } else { MajorGCWrapperVisitor visitor(isolate, constructRetainedObjectInfos); v8::V8::VisitHandlesWithClassIds(&visitor); @@ -380,6 +388,29 @@ void V8GCController::gcEpilogue(v8::GCType type, v8::GCCallbackFlags flags) minorGCEpilogue(isolate); else if (type == v8::kGCTypeMarkSweepCompact) majorGCEpilogue(isolate); + + // Forces a Blink heap garbage collection when a garbage collection + // was forced from V8. This is used for tests that force GCs from + // JavaScript to verify that objects die when expected. + if (flags & v8::kGCCallbackFlagForced) { + // This single GC is not enough for two reasons: + // (1) The GC is not precise because the GC scans on-stack pointers conservatively. + // (2) One GC is not enough to break a chain of persistent handles. It's possible that + // some heap allocated objects own objects that contain persistent handles + // pointing to other heap allocated objects. To break the chain, we need multiple GCs. + // + // Regarding (1), we force a precise GC at the end of the current event loop. So if you want + // to collect all garbage, you need to wait until the next event loop. + // Regarding (2), it would be OK in practice to trigger only one GC per gcEpilogue, because + // GCController.collectAll() forces 7 V8's GC. + Heap::collectGarbage(ThreadState::HeapPointersOnStack); + + // Forces a precise GC at the end of the current event loop. + Heap::setForcePreciseGCForTesting(); + } + + TRACE_EVENT_END1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "GCEvent", "usedHeapSizeAfter", usedHeapSize(isolate)); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data()); } void V8GCController::minorGCEpilogue(v8::Isolate* isolate) @@ -398,25 +429,27 @@ void V8GCController::majorGCEpilogue(v8::Isolate* isolate) TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(V8PerIsolateData::from(isolate)->previousSamplingState()); } -void V8GCController::hintForCollectGarbage() +void V8GCController::collectGarbage(v8::Isolate* isolate) { - V8PerIsolateData* data = V8PerIsolateData::current(); - if (!data->shouldCollectGarbageSoon()) - return; - const int longIdlePauseInMS = 1000; - data->clearShouldCollectGarbageSoon(); - v8::V8::ContextDisposedNotification(); - v8::V8::IdleNotification(longIdlePauseInMS); + v8::HandleScope handleScope(isolate); + RefPtr<ScriptState> scriptState = ScriptState::create(v8::Context::New(isolate), DOMWrapperWorld::create()); + ScriptState::Scope scope(scriptState.get()); + V8ScriptRunner::compileAndRunInternalScript(v8String(isolate, "if (gc) gc();"), isolate); + scriptState->disposePerContextData(); } -void V8GCController::collectGarbage(v8::Isolate* isolate) +void V8GCController::reportDOMMemoryUsageToV8(v8::Isolate* isolate) { - v8::HandleScope handleScope(isolate); - v8::Local<v8::Context> context = v8::Context::New(isolate); - if (context.IsEmpty()) + if (!isMainThread()) return; - v8::Context::Scope contextScope(context); - V8ScriptRunner::compileAndRunInternalScript(v8String(isolate, "if (gc) gc();"), isolate); + + static size_t lastUsageReportedToV8 = 0; + + size_t currentUsage = Partitions::currentDOMMemoryUsage(); + int64_t diff = static_cast<int64_t>(currentUsage) - static_cast<int64_t>(lastUsageReportedToV8); + isolate->AdjustAmountOfExternalAllocatedMemory(diff); + + lastUsageReportedToV8 = currentUsage; } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8GCController.h b/chromium/third_party/WebKit/Source/bindings/v8/V8GCController.h index b0aa80227d5..b0c541a84b5 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8GCController.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8GCController.h @@ -47,10 +47,11 @@ public: static void majorGCPrologue(bool constructRetainedObjectInfos, v8::Isolate*); static void majorGCEpilogue(v8::Isolate*); - static void hintForCollectGarbage(); static void collectGarbage(v8::Isolate*); static Node* opaqueRootForGC(Node*, v8::Isolate*); + + static void reportDOMMemoryUsageToV8(v8::Isolate*); }; } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8GCForContextDispose.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8GCForContextDispose.cpp index e7d40bd129e..688a212a30c 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8GCForContextDispose.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8GCForContextDispose.cpp @@ -32,6 +32,7 @@ #include "bindings/v8/V8GCForContextDispose.h" #include "wtf/StdLibExtras.h" +#include <v8.h> namespace WebCore { @@ -46,7 +47,7 @@ void V8GCForContextDispose::notifyContextDisposed(bool isMainFrame) m_didDisposeContextForMainFrame = m_didDisposeContextForMainFrame || isMainFrame; v8::V8::ContextDisposedNotification(); if (!m_pseudoIdleTimer.isActive()) - m_pseudoIdleTimer.startOneShot(0.8); + m_pseudoIdleTimer.startOneShot(0.8, FROM_HERE); } void V8GCForContextDispose::notifyIdleSooner(double maximumFireInterval) @@ -55,7 +56,7 @@ void V8GCForContextDispose::notifyIdleSooner(double maximumFireInterval) double nextFireInterval = m_pseudoIdleTimer.nextFireInterval(); if (nextFireInterval > maximumFireInterval) { m_pseudoIdleTimer.stop(); - m_pseudoIdleTimer.startOneShot(maximumFireInterval); + m_pseudoIdleTimer.startOneShot(maximumFireInterval, FROM_HERE); } } } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8GCForContextDispose.h b/chromium/third_party/WebKit/Source/bindings/v8/V8GCForContextDispose.h index 3d16be47de2..53fbbfd53e3 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8GCForContextDispose.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8GCForContextDispose.h @@ -31,7 +31,6 @@ #ifndef V8GCForContextDispose_h #define V8GCForContextDispose_h -#include <v8.h> #include "platform/Timer.h" namespace WebCore { diff --git a/chromium/third_party/WebKit/Source/bindings/v8/ScriptObject.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8GarbageCollected.h index 36b1a54451a..697974839d9 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/ScriptObject.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8GarbageCollected.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 Google Inc. All rights reserved. + * Copyright (C) 2014 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 @@ -28,55 +28,62 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "bindings/v8/ScriptObject.h" - -#include "bindings/v8/ScriptScope.h" -#include "bindings/v8/ScriptState.h" - -#include "V8InspectorFrontendHost.h" +#ifndef V8GarbageCollected_h +#define V8GarbageCollected_h #include <v8.h> namespace WebCore { -ScriptObject::ScriptObject(ScriptState* scriptState, v8::Handle<v8::Object> v8Object) - : ScriptValue(v8Object, scriptState->isolate()) - , m_scriptState(scriptState) -{ -} +template<typename T> +class V8GarbageCollected { + WTF_MAKE_NONCOPYABLE(V8GarbageCollected); +public: + static T* Cast(v8::Handle<v8::Value> value) + { + ASSERT(value->IsExternal()); + T* result = static_cast<T*>(value.As<v8::External>()->Value()); + RELEASE_ASSERT(result->m_handle == value); + return result; + } -ScriptObject::ScriptObject(ScriptState* scriptState, const ScriptValue& scriptValue) - : ScriptValue(scriptValue) - , m_scriptState(scriptState) -{ -} +protected: + V8GarbageCollected(v8::Isolate* isolate) + : m_isolate(isolate) + , m_handle(isolate, v8::External::New(isolate, static_cast<T*>(this))) + , m_releasedToV8GarbageCollector(false) + { + } -v8::Handle<v8::Object> ScriptObject::v8Object() const -{ - ASSERT(v8Value()->IsObject()); - return v8::Handle<v8::Object>::Cast(v8Value()); -} + v8::Handle<v8::External> releaseToV8GarbageCollector() + { + ASSERT(!m_handle.isWeak()); // Call this exactly once. + m_releasedToV8GarbageCollector = true; + v8::Handle<v8::External> result = m_handle.newLocal(m_isolate); + m_handle.setWeak(static_cast<T*>(this), &weakCallback); + return result; + } -bool ScriptGlobalObject::set(ScriptState* scriptState, const char* name, InspectorFrontendHost* value) -{ - ScriptScope scope(scriptState); - scope.global()->Set(v8AtomicString(scriptState->isolate(), name), toV8(value, v8::Handle<v8::Object>(), scriptState->isolate())); - return scope.success(); -} + ~V8GarbageCollected() + { + ASSERT(!m_releasedToV8GarbageCollector || m_handle.isEmpty()); + } -bool ScriptGlobalObject::get(ScriptState* scriptState, const char* name, ScriptObject& value) -{ - ScriptScope scope(scriptState); - v8::Local<v8::Value> v8Value = scope.global()->Get(v8AtomicString(scriptState->isolate(), name)); - if (v8Value.IsEmpty()) - return false; + v8::Isolate* isolate() { return m_isolate; } - if (!v8Value->IsObject()) - return false; +private: + static void weakCallback(const v8::WeakCallbackData<v8::External, T>& data) + { + T* self = data.GetParameter(); + self->m_handle.clear(); + delete self; + } - value = ScriptObject(scriptState, v8::Handle<v8::Object>::Cast(v8Value)); - return true; -} + v8::Isolate* m_isolate; + ScopedPersistent<v8::External> m_handle; + bool m_releasedToV8GarbageCollector; +}; } // namespace WebCore + +#endif // V8GarbageCollected_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenPropertyName.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenPropertyName.cpp deleted file mode 100644 index 1108e9e7aa0..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenPropertyName.cpp +++ /dev/null @@ -1,79 +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" -#include "bindings/v8/V8HiddenPropertyName.h" - -#include "bindings/v8/V8Binding.h" -#include <string.h> -#include "wtf/StdLibExtras.h" -#include "wtf/Vector.h" - -namespace WebCore { - -#define V8_AS_STRING(x) V8_AS_STRING_IMPL(x) -#define V8_AS_STRING_IMPL(x) #x - -#define V8_HIDDEN_PROPERTY_PREFIX "WebCore::HiddenProperty::" - -#define V8_DEFINE_HIDDEN_PROPERTY(name) \ -v8::Handle<v8::String> V8HiddenPropertyName::name(v8::Isolate* isolate) \ -{ \ - V8HiddenPropertyName* hiddenPropertyName = V8PerIsolateData::from(isolate)->hiddenPropertyName(); \ - if (hiddenPropertyName->m_##name.IsEmpty()) { \ - createString(V8_HIDDEN_PROPERTY_PREFIX V8_AS_STRING(name), &(hiddenPropertyName->m_##name), isolate); \ - } \ - return v8::Local<v8::String>::New(isolate, hiddenPropertyName->m_##name); \ -} - -V8_HIDDEN_PROPERTIES(V8_DEFINE_HIDDEN_PROPERTY); - -static v8::Handle<v8::String> hiddenReferenceName(const char* name, unsigned length) -{ - ASSERT(length); - Vector<char, 64> prefixedName; - prefixedName.append(V8_HIDDEN_PROPERTY_PREFIX, sizeof(V8_HIDDEN_PROPERTY_PREFIX) - 1); - prefixedName.append(name, length); - return v8AtomicString(v8::Isolate::GetCurrent(), prefixedName.data(), static_cast<int>(prefixedName.size())); -} - -void V8HiddenPropertyName::setNamedHiddenReference(v8::Handle<v8::Object> parent, const char* name, v8::Handle<v8::Value> child) -{ - ASSERT(name); - parent->SetHiddenValue(hiddenReferenceName(name, strlen(name)), child); -} - -void V8HiddenPropertyName::createString(const char* key, v8::Persistent<v8::String>* handle, v8::Isolate* isolate) -{ - v8::HandleScope scope(isolate); - handle->Reset(isolate, v8AtomicString(isolate, key)); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenPropertyName.h b/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenPropertyName.h deleted file mode 100644 index 76dc17ca1ae..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenPropertyName.h +++ /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: - * - * * 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 V8HiddenPropertyName_h -#define V8HiddenPropertyName_h - -#include <v8.h> - -namespace WebCore { - -#define V8_HIDDEN_PROPERTIES(V) \ - V(adaptorFunctionPeer) \ - V(attributeListener) \ - V(callback) \ - V(condition) \ - V(customElementAttached) \ - V(customElementAttributeChanged) \ - V(customElementCreated) \ - V(customElementDetached) \ - V(customElementDocument) \ - V(customElementIsInterfacePrototypeObject) \ - V(customElementNamespaceURI) \ - V(customElementTagName) \ - V(customElementType) \ - V(data) \ - V(detail) \ - V(document) \ - V(event) \ - V(error) \ - V(listener) \ - V(scriptState) \ - V(sleepFunction) \ - V(state) \ - V(toStringString) \ - V(typedArrayHiddenCopyMethod) \ - V(thenableHiddenPromise) - -class V8HiddenPropertyName { -public: - V8HiddenPropertyName() { } -#define V8_DECLARE_PROPERTY(name) static v8::Handle<v8::String> name(v8::Isolate*); - V8_HIDDEN_PROPERTIES(V8_DECLARE_PROPERTY); -#undef V8_DECLARE_PROPERTY - - static void setNamedHiddenReference(v8::Handle<v8::Object> parent, const char* name, v8::Handle<v8::Value> child); - -private: - static void createString(const char* key, v8::Persistent<v8::String>* handle, v8::Isolate*); -#define V8_DECLARE_FIELD(name) v8::Persistent<v8::String> m_##name; - V8_HIDDEN_PROPERTIES(V8_DECLARE_FIELD); -#undef V8_DECLARE_FIELD -}; - -} - -#endif // V8HiddenPropertyName_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenValue.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenValue.cpp new file mode 100644 index 00000000000..ab6e97d147c --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenValue.cpp @@ -0,0 +1,46 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "bindings/v8/V8HiddenValue.h" + +#include "bindings/v8/ScriptWrappable.h" +#include "bindings/v8/V8Binding.h" + +namespace WebCore { + +#define V8_DEFINE_METHOD(name) \ +v8::Handle<v8::String> V8HiddenValue::name(v8::Isolate* isolate) \ +{ \ + V8HiddenValue* hiddenValue = V8PerIsolateData::from(isolate)->hiddenValue(); \ + if (hiddenValue->m_##name.isEmpty()) { \ + hiddenValue->m_##name.set(isolate, v8AtomicString(isolate, #name)); \ + } \ + return hiddenValue->m_##name.newLocal(isolate); \ +} + +V8_HIDDEN_VALUES(V8_DEFINE_METHOD); + +v8::Local<v8::Value> V8HiddenValue::getHiddenValue(v8::Isolate* isolate, v8::Handle<v8::Object> object, v8::Handle<v8::String> key) +{ + return object->GetHiddenValue(key); +} + +bool V8HiddenValue::setHiddenValue(v8::Isolate* isolate, v8::Handle<v8::Object> object, v8::Handle<v8::String> key, v8::Handle<v8::Value> value) +{ + return object->SetHiddenValue(key, value); +} + +bool V8HiddenValue::deleteHiddenValue(v8::Isolate* isolate, v8::Handle<v8::Object> object, v8::Handle<v8::String> key) +{ + return object->DeleteHiddenValue(key); +} + +v8::Local<v8::Value> V8HiddenValue::getHiddenValueFromMainWorldWrapper(v8::Isolate* isolate, ScriptWrappable* wrappable, v8::Handle<v8::String> key) +{ + v8::Local<v8::Object> wrapper = wrappable->newLocalWrapper(isolate); + return wrapper.IsEmpty() ? v8::Local<v8::Value>() : getHiddenValue(isolate, wrapper, key); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenValue.h b/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenValue.h new file mode 100644 index 00000000000..75da4efe761 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8HiddenValue.h @@ -0,0 +1,61 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef V8HiddenValue_h +#define V8HiddenValue_h + +#include "bindings/v8/ScopedPersistent.h" +#include <v8.h> + +namespace WebCore { + +class ScriptWrappable; + +#define V8_HIDDEN_VALUES(V) \ + V(arrayBufferData) \ + V(customElementAttached) \ + V(customElementAttributeChanged) \ + V(customElementCreated) \ + V(customElementDetached) \ + V(customElementDocument) \ + V(customElementIsInterfacePrototypeObject) \ + V(customElementNamespaceURI) \ + V(customElementTagName) \ + V(customElementType) \ + V(callback) \ + V(condition) \ + V(data) \ + V(detail) \ + V(document) \ + V(error) \ + V(event) \ + V(idbCursorRequest) \ + V(port1) \ + V(port2) \ + V(state) \ + V(stringData) \ + V(scriptState) \ + V(thenableHiddenPromise) \ + V(toStringString) + +class V8HiddenValue { +public: +#define V8_DECLARE_METHOD(name) static v8::Handle<v8::String> name(v8::Isolate* isolate); + V8_HIDDEN_VALUES(V8_DECLARE_METHOD); +#undef V8_DECLARE_METHOD + + static v8::Local<v8::Value> getHiddenValue(v8::Isolate*, v8::Handle<v8::Object>, v8::Handle<v8::String>); + static bool setHiddenValue(v8::Isolate*, v8::Handle<v8::Object>, v8::Handle<v8::String>, v8::Handle<v8::Value>); + static bool deleteHiddenValue(v8::Isolate*, v8::Handle<v8::Object>, v8::Handle<v8::String>); + static v8::Local<v8::Value> getHiddenValueFromMainWorldWrapper(v8::Isolate*, ScriptWrappable*, v8::Handle<v8::String>); + +private: +#define V8_DECLARE_FIELD(name) ScopedPersistent<v8::String> m_##name; + V8_HIDDEN_VALUES(V8_DECLARE_FIELD); +#undef V8_DECLARE_FIELD +}; + +} // namespace WebCore + +#endif // V8HiddenValue_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8Initializer.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8Initializer.cpp index 9646ae76204..0f2f1f13261 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8Initializer.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8Initializer.cpp @@ -26,11 +26,11 @@ #include "config.h" #include "bindings/v8/V8Initializer.h" -#include "V8DOMException.h" -#include "V8ErrorEvent.h" -#include "V8History.h" -#include "V8Location.h" -#include "V8Window.h" +#include "bindings/core/v8/V8DOMException.h" +#include "bindings/core/v8/V8ErrorEvent.h" +#include "bindings/core/v8/V8History.h" +#include "bindings/core/v8/V8Location.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/ScriptCallStackFactory.h" #include "bindings/v8/ScriptController.h" @@ -38,15 +38,15 @@ #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8ErrorHandler.h" #include "bindings/v8/V8GCController.h" -#include "bindings/v8/V8HiddenPropertyName.h" #include "bindings/v8/V8PerContextData.h" #include "core/dom/Document.h" #include "core/dom/ExceptionCode.h" -#include "core/inspector/ScriptCallStack.h" #include "core/frame/ConsoleTypes.h" -#include "core/frame/ContentSecurityPolicy.h" -#include "core/frame/DOMWindow.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/csp/ContentSecurityPolicy.h" +#include "core/inspector/ScriptCallStack.h" +#include "platform/TraceEvent.h" #include "public/platform/Platform.h" #include "wtf/RefPtr.h" #include "wtf/text/WTFString.h" @@ -54,12 +54,12 @@ namespace WebCore { -static Frame* findFrame(v8::Local<v8::Object> host, v8::Local<v8::Value> data, v8::Isolate* isolate) +static LocalFrame* findFrame(v8::Local<v8::Object> host, v8::Local<v8::Value> data, v8::Isolate* isolate) { const WrapperTypeInfo* type = WrapperTypeInfo::unwrap(data); if (V8Window::wrapperTypeInfo.equals(type)) { - v8::Handle<v8::Object> windowWrapper = host->FindInstanceInPrototypeChain(V8Window::domTemplate(isolate, worldTypeInMainThread(isolate))); + v8::Handle<v8::Object> windowWrapper = V8Window::findInstanceInPrototypeChain(host, isolate); if (windowWrapper.IsEmpty()) return 0; return V8Window::toNative(windowWrapper)->frame(); @@ -85,30 +85,34 @@ static void reportFatalErrorInMainThread(const char* location, const char* messa static void messageHandlerInMainThread(v8::Handle<v8::Message> message, v8::Handle<v8::Value> data) { - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - // If called during context initialization, there will be no entered context. - v8::Handle<v8::Context> enteredContext = isolate->GetEnteredContext(); - if (enteredContext.IsEmpty()) + ASSERT(isMainThread()); + // It's possible that messageHandlerInMainThread() is invoked while we're initializing a window. + // In that half-baked situation, we don't have a valid context nor a valid world, + // so just return immediately. + if (DOMWrapperWorld::windowIsBeingInitialized()) return; - DOMWindow* firstWindow = toDOMWindow(enteredContext); - if (!firstWindow->isCurrentlyDisplayedInFrame()) + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + // If called during context initialization, there will be no entered window. + LocalDOMWindow* enteredWindow = enteredDOMWindow(isolate); + if (!enteredWindow || !enteredWindow->isCurrentlyDisplayedInFrame()) return; String errorMessage = toCoreString(message->Get()); v8::Handle<v8::StackTrace> stackTrace = message->GetStackTrace(); - RefPtr<ScriptCallStack> callStack; + RefPtrWillBeRawPtr<ScriptCallStack> callStack = nullptr; // Currently stack trace is only collected when inspector is open. if (!stackTrace.IsEmpty() && stackTrace->GetFrameCount() > 0) callStack = createScriptCallStack(stackTrace, ScriptCallStack::maxCallStackSizeToCapture, isolate); v8::Handle<v8::Value> resourceName = message->GetScriptResourceName(); bool shouldUseDocumentURL = resourceName.IsEmpty() || !resourceName->IsString(); - String resource = shouldUseDocumentURL ? firstWindow->document()->url() : toCoreString(resourceName.As<v8::String>()); + String resource = shouldUseDocumentURL ? enteredWindow->document()->url() : toCoreString(resourceName.As<v8::String>()); AccessControlStatus corsStatus = message->IsSharedCrossOrigin() ? SharableCrossOrigin : NotSharableCrossOrigin; - RefPtr<ErrorEvent> event = ErrorEvent::create(errorMessage, resource, message->GetLineNumber(), message->GetStartColumn() + 1, DOMWrapperWorld::current()); + ScriptState* scriptState = ScriptState::current(isolate); + RefPtrWillBeRawPtr<ErrorEvent> event = ErrorEvent::create(errorMessage, resource, message->GetLineNumber(), message->GetStartColumn() + 1, &scriptState->world()); if (V8DOMWrapper::isDOMWrapper(data)) { v8::Handle<v8::Object> obj = v8::Handle<v8::Object>::Cast(data); const WrapperTypeInfo* type = toWrapperTypeInfo(obj); @@ -122,22 +126,24 @@ static void messageHandlerInMainThread(v8::Handle<v8::Message> message, v8::Hand // This method might be called while we're creating a new context. In this case, we // avoid storing the exception object, as we can't create a wrapper during context creation. // FIXME: Can we even get here during initialization now that we bail out when GetEntered returns an empty handle? - DOMWrapperWorld* world = DOMWrapperWorld::current(); - Frame* frame = firstWindow->document()->frame(); - if (world && frame && frame->script().existingWindowShell(world)) - V8ErrorHandler::storeExceptionOnErrorEventWrapper(event.get(), data, v8::Isolate::GetCurrent()); - firstWindow->document()->reportException(event.release(), callStack, corsStatus); + LocalFrame* frame = enteredWindow->document()->frame(); + if (frame && frame->script().existingWindowShell(scriptState->world())) { + V8ErrorHandler::storeExceptionOnErrorEventWrapper(event.get(), data, scriptState->context()->Global(), isolate); + } + enteredWindow->document()->reportException(event.release(), callStack, corsStatus); } static void failedAccessCheckCallbackInMainThread(v8::Local<v8::Object> host, v8::AccessType type, v8::Local<v8::Value> data) { - Frame* target = findFrame(host, data, v8::Isolate::GetCurrent()); + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + LocalFrame* target = findFrame(host, data, isolate); if (!target) return; - DOMWindow* targetWindow = target->domWindow(); + LocalDOMWindow* targetWindow = target->domWindow(); - ExceptionState exceptionState(v8::Handle<v8::Object>(), v8::Isolate::GetCurrent()); - exceptionState.throwSecurityError(targetWindow->sanitizedCrossDomainAccessErrorMessage(activeDOMWindow()), targetWindow->crossDomainAccessErrorMessage(activeDOMWindow())); + // FIXME: We should modify V8 to pass in more contextual information (context, property, and object). + ExceptionState exceptionState(ExceptionState::UnknownContext, 0, 0, isolate->GetCurrentContext()->Global(), isolate); + exceptionState.throwSecurityError(targetWindow->sanitizedCrossDomainAccessErrorMessage(callingDOMWindow(isolate)), targetWindow->crossDomainAccessErrorMessage(callingDOMWindow(isolate))); exceptionState.throwIfNeeded(); } @@ -145,22 +151,32 @@ static bool codeGenerationCheckCallbackInMainThread(v8::Local<v8::Context> conte { if (ExecutionContext* executionContext = toExecutionContext(context)) { if (ContentSecurityPolicy* policy = toDocument(executionContext)->contentSecurityPolicy()) - return policy->allowEval(ScriptState::forContext(context)); + return policy->allowEval(ScriptState::from(context)); } return false; } +static void timerTraceProfilerInMainThread(const char* name, int status) +{ + if (!status) { + TRACE_EVENT_BEGIN0("V8", name); + } else { + TRACE_EVENT_END0("V8", name); + } +} + static void initializeV8Common(v8::Isolate* isolate) { v8::ResourceConstraints constraints; - constraints.ConfigureDefaults(static_cast<uint64_t>(blink::Platform::current()->physicalMemoryMB()) << 20, static_cast<uint32_t>(blink::Platform::current()->numberOfProcessors())); + constraints.ConfigureDefaults(static_cast<uint64_t>(blink::Platform::current()->physicalMemoryMB()) << 20, static_cast<uint32_t>(blink::Platform::current()->virtualMemoryLimitMB()) << 20, static_cast<uint32_t>(blink::Platform::current()->numberOfProcessors())); v8::SetResourceConstraints(isolate, &constraints); v8::V8::AddGCPrologueCallback(V8GCController::gcPrologue); v8::V8::AddGCEpilogueCallback(V8GCController::gcEpilogue); - v8::V8::IgnoreOutOfMemoryException(); - v8::Debug::SetLiveEditEnabled(false); + v8::Debug::SetLiveEditEnabled(isolate, false); + + isolate->SetAutorunMicrotasks(false); } void V8Initializer::initializeMainThreadIfNeeded(v8::Isolate* isolate) @@ -175,11 +191,14 @@ void V8Initializer::initializeMainThreadIfNeeded(v8::Isolate* isolate) initializeV8Common(isolate); v8::V8::SetFatalErrorHandler(reportFatalErrorInMainThread); + V8PerIsolateData::ensureInitialized(isolate); v8::V8::AddMessageListener(messageHandlerInMainThread); v8::V8::SetFailedAccessCheckCallbackFunction(failedAccessCheckCallbackInMainThread); v8::V8::SetAllowCodeGenerationFromStringsCallback(codeGenerationCheckCallbackInMainThread); + + isolate->SetEventLogger(timerTraceProfilerInMainThread); + ScriptProfiler::initialize(); - V8PerIsolateData::ensureInitialized(isolate); } static void reportFatalErrorInWorker(const char* location, const char* message) @@ -197,16 +216,18 @@ static void messageHandlerInWorker(v8::Handle<v8::Message> message, v8::Handle<v return; isReportingException = true; + v8::Isolate* isolate = v8::Isolate::GetCurrent(); + ScriptState* scriptState = ScriptState::current(isolate); // During the frame teardown, there may not be a valid context. - if (ExecutionContext* context = getExecutionContext()) { + if (ExecutionContext* context = scriptState->executionContext()) { String errorMessage = toCoreString(message->Get()); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, sourceURL, message->GetScriptResourceName()); + TOSTRING_VOID(V8StringResource<>, sourceURL, message->GetScriptResourceName()); - RefPtr<ErrorEvent> event = ErrorEvent::create(errorMessage, sourceURL, message->GetLineNumber(), message->GetStartColumn() + 1, DOMWrapperWorld::current()); + RefPtrWillBeRawPtr<ErrorEvent> event = ErrorEvent::create(errorMessage, sourceURL, message->GetLineNumber(), message->GetStartColumn() + 1, &DOMWrapperWorld::current(isolate)); AccessControlStatus corsStatus = message->IsSharedCrossOrigin() ? SharableCrossOrigin : NotSharableCrossOrigin; - V8ErrorHandler::storeExceptionOnErrorEventWrapper(event.get(), data, v8::Isolate::GetCurrent()); - context->reportException(event.release(), 0, corsStatus); + V8ErrorHandler::storeExceptionOnErrorEventWrapper(event.get(), data, scriptState->context()->Global(), isolate); + context->reportException(event.release(), nullptr, corsStatus); } isReportingException = false; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8LazyEventListener.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8LazyEventListener.cpp index 1d80ffd89bf..23b8fcf52f8 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8LazyEventListener.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8LazyEventListener.cpp @@ -31,29 +31,29 @@ #include "config.h" #include "bindings/v8/V8LazyEventListener.h" -#include "V8Document.h" -#include "V8HTMLFormElement.h" -#include "V8Node.h" +#include "bindings/core/v8/V8Document.h" +#include "bindings/core/v8/V8HTMLFormElement.h" +#include "bindings/core/v8/V8Node.h" #include "bindings/v8/ScriptController.h" #include "bindings/v8/ScriptSourceCode.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8DOMWrapper.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "bindings/v8/V8ScriptRunner.h" #include "core/dom/Document.h" #include "core/dom/Node.h" #include "core/html/HTMLElement.h" #include "core/html/HTMLFormElement.h" #include "core/inspector/InspectorInstrumentation.h" -#include "core/frame/ContentSecurityPolicy.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/csp/ContentSecurityPolicy.h" #include "wtf/StdLibExtras.h" namespace WebCore { V8LazyEventListener::V8LazyEventListener(const AtomicString& functionName, const AtomicString& eventParameterName, const String& code, const String sourceURL, const TextPosition& position, Node* node, v8::Isolate* isolate) - : V8AbstractEventListener(true, mainThreadNormalWorld(), isolate) + : V8AbstractEventListener(true, isolate) , m_functionName(functionName) , m_eventParameterName(eventParameterName) , m_code(code) @@ -64,35 +64,31 @@ V8LazyEventListener::V8LazyEventListener(const AtomicString& functionName, const } template<typename T> -v8::Handle<v8::Object> toObjectWrapper(T* domObject, v8::Isolate* isolate) +v8::Handle<v8::Object> toObjectWrapper(T* domObject, ScriptState* scriptState) { if (!domObject) - return v8::Object::New(); - v8::Handle<v8::Value> value = toV8(domObject, v8::Handle<v8::Object>(), isolate); + return v8::Object::New(scriptState->isolate()); + v8::Handle<v8::Value> value = toV8(domObject, scriptState->context()->Global(), scriptState->isolate()); if (value.IsEmpty()) - return v8::Object::New(); - return v8::Local<v8::Object>::New(isolate, value.As<v8::Object>()); + return v8::Object::New(scriptState->isolate()); + return v8::Local<v8::Object>::New(scriptState->isolate(), value.As<v8::Object>()); } -v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(ExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event) +v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event) { - v8::Local<v8::Object> listenerObject = getListenerObject(context); + v8::Local<v8::Object> listenerObject = getListenerObject(scriptState()->executionContext()); if (listenerObject.IsEmpty()) return v8::Local<v8::Value>(); v8::Local<v8::Function> handlerFunction = listenerObject.As<v8::Function>(); - v8::Local<v8::Object> receiver = getReceiverObject(context, event); + v8::Local<v8::Object> receiver = getReceiverObject(event); if (handlerFunction.IsEmpty() || receiver.IsEmpty()) return v8::Local<v8::Value>(); - // FIXME: Can |context| be 0 here? - if (!context) + if (!scriptState()->executionContext()->isDocument()) return v8::Local<v8::Value>(); - if (!context->isDocument()) - return v8::Local<v8::Value>(); - - Frame* frame = toDocument(context)->frame(); + LocalFrame* frame = toDocument(scriptState()->executionContext())->frame(); if (!frame) return v8::Local<v8::Value>(); @@ -105,11 +101,32 @@ v8::Local<v8::Value> V8LazyEventListener::callListenerFunction(ExecutionContext* static void V8LazyEventListenerToString(const v8::FunctionCallbackInfo<v8::Value>& info) { - v8SetReturnValue(info, info.Holder()->GetHiddenValue(V8HiddenPropertyName::toStringString(info.GetIsolate()))); + v8SetReturnValue(info, V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::toStringString(info.GetIsolate()))); +} + +void V8LazyEventListener::handleEvent(ExecutionContext* context, Event* event) +{ + v8::HandleScope handleScope(toIsolate(context)); + // V8LazyEventListener doesn't know the associated context when created. + // Thus we lazily get the associated context and set a ScriptState on V8AbstractEventListener. + v8::Local<v8::Context> v8Context = toV8Context(context, world()); + if (v8Context.IsEmpty()) + return; + setScriptState(ScriptState::from(v8Context)); + + V8AbstractEventListener::handleEvent(context, event); } void V8LazyEventListener::prepareListenerObject(ExecutionContext* context) { + v8::HandleScope handleScope(toIsolate(context)); + // V8LazyEventListener doesn't know the associated context when created. + // Thus we lazily get the associated context and set a ScriptState on V8AbstractEventListener. + v8::Local<v8::Context> v8Context = toV8Context(context, world()); + if (v8Context.IsEmpty()) + return; + setScriptState(ScriptState::from(v8Context)); + if (context->isDocument() && !toDocument(context)->allowInlineEventHandlers(m_node, this, m_sourceURL, m_position.m_line)) { clearListenerObject(); return; @@ -120,17 +137,7 @@ void V8LazyEventListener::prepareListenerObject(ExecutionContext* context) ASSERT(context->isDocument()); - v8::Isolate* isolate = toIsolate(context); - v8::HandleScope handleScope(isolate); - - // Use the outer scope to hold context. - v8::Local<v8::Context> v8Context = toV8Context(context, world()); - // Bail out if we cannot get the context. - if (v8Context.IsEmpty()) - return; - - v8::Context::Scope scope(v8Context); - + ScriptState::Scope scope(scriptState()); String listenerSource = InspectorInstrumentation::preprocessEventListener(toDocument(context)->frame(), m_code, m_sourceURL, m_functionName); // FIXME: Remove the following 'with' hack. @@ -159,9 +166,9 @@ void V8LazyEventListener::prepareListenerObject(ExecutionContext* context) "};" "}}}})"; - v8::Handle<v8::String> codeExternalString = v8String(isolate, code); + v8::Handle<v8::String> codeExternalString = v8String(isolate(), code); - v8::Local<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(codeExternalString, isolate, m_sourceURL, m_position, 0); + v8::Local<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(codeExternalString, isolate(), m_sourceURL, m_position); if (result.IsEmpty()) return; @@ -173,22 +180,22 @@ void V8LazyEventListener::prepareListenerObject(ExecutionContext* context) if (m_node && m_node->isHTMLElement()) formElement = toHTMLElement(m_node)->formOwner(); - v8::Handle<v8::Object> nodeWrapper = toObjectWrapper<Node>(m_node, isolate); - v8::Handle<v8::Object> formWrapper = toObjectWrapper<HTMLFormElement>(formElement, isolate); - v8::Handle<v8::Object> documentWrapper = toObjectWrapper<Document>(m_node ? m_node->ownerDocument() : 0, isolate); + v8::Handle<v8::Object> nodeWrapper = toObjectWrapper<Node>(m_node, scriptState()); + v8::Handle<v8::Object> formWrapper = toObjectWrapper<HTMLFormElement>(formElement, scriptState()); + v8::Handle<v8::Object> documentWrapper = toObjectWrapper<Document>(m_node ? m_node->ownerDocument() : 0, scriptState()); - v8::Local<v8::Object> thisObject = v8::Object::New(); + v8::Local<v8::Object> thisObject = v8::Object::New(isolate()); if (thisObject.IsEmpty()) return; - if (!thisObject->ForceSet(v8::Integer::New(0, isolate), nodeWrapper)) + if (!thisObject->ForceSet(v8::Integer::New(isolate(), 0), nodeWrapper)) return; - if (!thisObject->ForceSet(v8::Integer::New(1, isolate), formWrapper)) + if (!thisObject->ForceSet(v8::Integer::New(isolate(), 1), formWrapper)) return; - if (!thisObject->ForceSet(v8::Integer::New(2, isolate), documentWrapper)) + if (!thisObject->ForceSet(v8::Integer::New(isolate(), 2), documentWrapper)) return; // FIXME: Remove this code when we stop doing the 'with' hack above. - v8::Local<v8::Value> innerValue = V8ScriptRunner::callInternalFunction(intermediateFunction, thisObject, 0, 0, isolate); + v8::Local<v8::Value> innerValue = V8ScriptRunner::callInternalFunction(intermediateFunction, thisObject, 0, 0, isolate()); if (innerValue.IsEmpty() || !innerValue->IsFunction()) return; @@ -202,20 +209,12 @@ void V8LazyEventListener::prepareListenerObject(ExecutionContext* context) // source returned (sometimes a RegExp is applied as well) for some // other use. That fails miserably if the actual wrapper source is // returned. - v8::Handle<v8::FunctionTemplate> toStringTemplate = - V8PerIsolateData::current()->lazyEventListenerToStringTemplate(); - if (toStringTemplate.IsEmpty()) - toStringTemplate = v8::FunctionTemplate::New(isolate, V8LazyEventListenerToString); - v8::Local<v8::Function> toStringFunction; - if (!toStringTemplate.IsEmpty()) - toStringFunction = toStringTemplate->GetFunction(); - if (!toStringFunction.IsEmpty()) { - String toStringString = "function " + m_functionName + "(" + m_eventParameterName + ") {\n " + m_code + "\n}"; - wrappedFunction->SetHiddenValue(V8HiddenPropertyName::toStringString(isolate), v8String(isolate, toStringString)); - wrappedFunction->Set(v8AtomicString(isolate, "toString"), toStringFunction); - } - - wrappedFunction->SetName(v8String(isolate, m_functionName)); + v8::Local<v8::Function> toStringFunction = v8::Function::New(isolate(), V8LazyEventListenerToString); + ASSERT(!toStringFunction.IsEmpty()); + String toStringString = "function " + m_functionName + "(" + m_eventParameterName + ") {\n " + m_code + "\n}"; + V8HiddenValue::setHiddenValue(isolate(), wrappedFunction, V8HiddenValue::toStringString(isolate()), v8String(isolate(), toStringString)); + wrappedFunction->Set(v8AtomicString(isolate(), "toString"), toStringFunction); + wrappedFunction->SetName(v8String(isolate(), m_functionName)); // FIXME: Remove the following comment-outs. // See https://bugs.webkit.org/show_bug.cgi?id=85152 for more details. diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8LazyEventListener.h b/chromium/third_party/WebKit/Source/bindings/v8/V8LazyEventListener.h index 4bc040ff95b..7ab4d7d7c18 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8LazyEventListener.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8LazyEventListener.h @@ -40,34 +40,38 @@ namespace WebCore { class Event; - class Frame; + class LocalFrame; class HTMLFormElement; class Node; // V8LazyEventListener is a wrapper for a JavaScript code string that is compiled and evaluated when an event is fired. // A V8LazyEventListener is either a HTML or SVG event handler. - class V8LazyEventListener : public V8AbstractEventListener { + class V8LazyEventListener FINAL : public V8AbstractEventListener { public: static PassRefPtr<V8LazyEventListener> create(const AtomicString& functionName, const AtomicString& eventParameterName, const String& code, const String& sourceURL, const TextPosition& position, Node* node, v8::Isolate* isolate) { return adoptRef(new V8LazyEventListener(functionName, eventParameterName, code, sourceURL, position, node, isolate)); } - virtual bool isLazy() const { return true; } + virtual bool isLazy() const OVERRIDE { return true; } + // V8LazyEventListener is always for the main world. + virtual DOMWrapperWorld& world() const OVERRIDE { return DOMWrapperWorld::mainWorld(); } + + virtual void handleEvent(ExecutionContext*, Event*) OVERRIDE; protected: - virtual void prepareListenerObject(ExecutionContext*); + virtual void prepareListenerObject(ExecutionContext*) OVERRIDE; private: V8LazyEventListener(const AtomicString& functionName, const AtomicString& eventParameterName, const String& code, const String sourceURL, const TextPosition&, Node*, v8::Isolate*); - virtual v8::Local<v8::Value> callListenerFunction(ExecutionContext*, v8::Handle<v8::Value> jsEvent, Event*); + virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsEvent, Event*) OVERRIDE; // Needs to return true for all event handlers implemented in JavaScript so that // the SVG code does not add the event handler in both // SVGUseElement::buildShadowTree and again in // SVGUseElement::transferEventListenersToShadowTree - virtual bool wasCreatedFromMarkup() const { return true; } + virtual bool wasCreatedFromMarkup() const OVERRIDE { return true; } AtomicString m_functionName; AtomicString m_eventParameterName; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8MutationCallback.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8MutationCallback.cpp index 6be6f16d6fc..8e0581acdcc 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8MutationCallback.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8MutationCallback.cpp @@ -26,44 +26,39 @@ #include "config.h" #include "bindings/v8/V8MutationCallback.h" -#include "V8MutationObserver.h" -#include "V8MutationRecord.h" +#include "bindings/core/v8/V8MutationObserver.h" +#include "bindings/core/v8/V8MutationRecord.h" #include "bindings/v8/ScriptController.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "core/dom/ExecutionContext.h" #include "wtf/Assertions.h" namespace WebCore { -V8MutationCallback::V8MutationCallback(v8::Handle<v8::Function> callback, ExecutionContext* context, v8::Handle<v8::Object> owner, v8::Isolate* isolate) - : ActiveDOMCallback(context) - , m_callback(isolate, callback) - , m_world(DOMWrapperWorld::current()) - , m_isolate(isolate) +V8MutationCallback::V8MutationCallback(v8::Handle<v8::Function> callback, v8::Handle<v8::Object> owner, ScriptState* scriptState) + : ActiveDOMCallback(scriptState->executionContext()) + , m_callback(scriptState->isolate(), callback) + , m_scriptState(scriptState) { - owner->SetHiddenValue(V8HiddenPropertyName::callback(m_isolate), callback); + V8HiddenValue::setHiddenValue(scriptState->isolate(), owner, V8HiddenValue::callback(scriptState->isolate()), callback); m_callback.setWeak(this, &setWeakCallback); } -void V8MutationCallback::call(const Vector<RefPtr<MutationRecord> >& mutations, MutationObserver* observer) +void V8MutationCallback::call(const WillBeHeapVector<RefPtrWillBeMember<MutationRecord> >& mutations, MutationObserver* observer) { if (!canInvokeCallback()) return; - v8::HandleScope handleScope(m_isolate); + v8::Isolate* isolate = m_scriptState->isolate(); - v8::Handle<v8::Context> v8Context = toV8Context(executionContext(), m_world.get()); - if (v8Context.IsEmpty()) + if (m_scriptState->contextIsEmpty()) return; + ScriptState::Scope scope(m_scriptState.get()); - v8::Context::Scope scope(v8Context); - - v8::Handle<v8::Function> callback = m_callback.newLocal(m_isolate); - if (callback.IsEmpty()) + if (m_callback.isEmpty()) return; - - v8::Handle<v8::Value> observerHandle = toV8(observer, v8::Handle<v8::Object>(), m_isolate); + v8::Handle<v8::Value> observerHandle = toV8(observer, m_scriptState->context()->Global(), isolate); if (observerHandle.IsEmpty()) { if (!isScriptControllerTerminating()) CRASH(); @@ -74,11 +69,11 @@ void V8MutationCallback::call(const Vector<RefPtr<MutationRecord> >& mutations, return; v8::Handle<v8::Object> thisObject = v8::Handle<v8::Object>::Cast(observerHandle); - v8::Handle<v8::Value> argv[] = { v8Array(mutations, m_isolate), observerHandle }; + v8::Handle<v8::Value> argv[] = { v8Array(mutations, m_scriptState->context()->Global(), isolate), observerHandle }; v8::TryCatch exceptionCatcher; exceptionCatcher.SetVerbose(true); - ScriptController::callFunction(executionContext(), callback, thisObject, 2, argv, m_isolate); + ScriptController::callFunction(executionContext(), m_callback.newLocal(isolate), thisObject, WTF_ARRAY_LENGTH(argv), argv, isolate); } void V8MutationCallback::setWeakCallback(const v8::WeakCallbackData<v8::Function, V8MutationCallback>& data) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8MutationCallback.h b/chromium/third_party/WebKit/Source/bindings/v8/V8MutationCallback.h index 93a4820998a..fc5589a629b 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8MutationCallback.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8MutationCallback.h @@ -27,9 +27,8 @@ #define V8MutationCallback_h #include "bindings/v8/ActiveDOMCallback.h" -#include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/ScopedPersistent.h" -#include "bindings/v8/V8Utilities.h" +#include "bindings/v8/ScriptState.h" #include "core/dom/MutationCallback.h" #include "wtf/OwnPtr.h" #include "wtf/RefPtr.h" @@ -39,25 +38,23 @@ namespace WebCore { class ExecutionContext; -class V8MutationCallback : public MutationCallback, public ActiveDOMCallback { +class V8MutationCallback FINAL : public MutationCallback, public ActiveDOMCallback { public: - static PassOwnPtr<V8MutationCallback> create(v8::Handle<v8::Function> callback, ExecutionContext* context, v8::Handle<v8::Object> owner, v8::Isolate* isolate) + static PassOwnPtr<V8MutationCallback> create(v8::Handle<v8::Function> callback, v8::Handle<v8::Object> owner, ScriptState* scriptState) { - ASSERT(context); - return adoptPtr(new V8MutationCallback(callback, context, owner, isolate)); + return adoptPtr(new V8MutationCallback(callback, owner, scriptState)); } - virtual void call(const Vector<RefPtr<MutationRecord> >&, MutationObserver*) OVERRIDE; + virtual void call(const WillBeHeapVector<RefPtrWillBeMember<MutationRecord> >&, MutationObserver*) OVERRIDE; virtual ExecutionContext* executionContext() const OVERRIDE { return ContextLifecycleObserver::executionContext(); } private: - V8MutationCallback(v8::Handle<v8::Function>, ExecutionContext*, v8::Handle<v8::Object>, v8::Isolate*); + V8MutationCallback(v8::Handle<v8::Function>, v8::Handle<v8::Object>, ScriptState*); static void setWeakCallback(const v8::WeakCallbackData<v8::Function, V8MutationCallback>&); ScopedPersistent<v8::Function> m_callback; - RefPtr<DOMWrapperWorld> m_world; - v8::Isolate* m_isolate; + RefPtr<ScriptState> m_scriptState; }; } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8NPObject.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8NPObject.cpp index 2912723fb82..a16369915c4 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8NPObject.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8NPObject.cpp @@ -32,17 +32,18 @@ #include "bindings/v8/V8NPObject.h" -#include "V8HTMLAppletElement.h" -#include "V8HTMLEmbedElement.h" -#include "V8HTMLObjectElement.h" +#include "bindings/core/v8/V8HTMLAppletElement.h" +#include "bindings/core/v8/V8HTMLEmbedElement.h" +#include "bindings/core/v8/V8HTMLObjectElement.h" #include "bindings/v8/NPV8Object.h" -#include "bindings/v8/UnsafePersistent.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8NPUtils.h" #include "bindings/v8/V8ObjectConstructor.h" +#include "bindings/v8/V8PersistentValueMap.h" #include "bindings/v8/npruntime_impl.h" #include "bindings/v8/npruntime_priv.h" #include "core/html/HTMLPlugInElement.h" +#include "v8-util.h" #include "wtf/OwnPtr.h" namespace WebCore { @@ -69,21 +70,18 @@ struct IdentifierRep { static void npObjectInvokeImpl(const v8::FunctionCallbackInfo<v8::Value>& info, InvokeFunctionType functionId) { NPObject* npObject; + v8::Isolate* isolate = info.GetIsolate(); - WrapperWorldType currentWorldType = worldType(info.GetIsolate()); // These three types are subtypes of HTMLPlugInElement. - if (V8HTMLAppletElement::hasInstance(info.Holder(), info.GetIsolate(), currentWorldType) || V8HTMLEmbedElement::hasInstance(info.Holder(), info.GetIsolate(), currentWorldType) - || V8HTMLObjectElement::hasInstance(info.Holder(), info.GetIsolate(), currentWorldType)) { - // The holder object is a subtype of HTMLPlugInElement. - HTMLPlugInElement* element; - if (V8HTMLAppletElement::hasInstance(info.Holder(), info.GetIsolate(), currentWorldType)) - element = V8HTMLAppletElement::toNative(info.Holder()); - else if (V8HTMLEmbedElement::hasInstance(info.Holder(), info.GetIsolate(), currentWorldType)) - element = V8HTMLEmbedElement::toNative(info.Holder()); - else - element = V8HTMLObjectElement::toNative(info.Holder()); + HTMLPlugInElement* element = V8HTMLAppletElement::toNativeWithTypeCheck(isolate, info.Holder()); + if (!element) { + element = V8HTMLEmbedElement::toNativeWithTypeCheck(isolate, info.Holder()); + if (!element) { + element = V8HTMLObjectElement::toNativeWithTypeCheck(isolate, info.Holder()); + } + } + if (element) { if (RefPtr<SharedPersistent<v8::Object> > wrapper = element->pluginWrapper()) { - v8::Isolate* isolate = v8::Isolate::GetCurrent(); v8::HandleScope handleScope(isolate); npObject = v8ObjectToNPObject(wrapper->newLocal(isolate)); } else @@ -101,7 +99,7 @@ static void npObjectInvokeImpl(const v8::FunctionCallbackInfo<v8::Value>& info, // Verify that our wrapper wasn't using a NPObject which has already been deleted. if (!npObject || !_NPN_IsAlive(npObject)) { - throwError(v8ReferenceError, "NPObject deleted", info.GetIsolate()); + throwError(v8ReferenceError, "NPObject deleted", isolate); return; } @@ -110,7 +108,7 @@ static void npObjectInvokeImpl(const v8::FunctionCallbackInfo<v8::Value>& info, OwnPtr<NPVariant[]> npArgs = adoptArrayPtr(new NPVariant[numArgs]); for (int i = 0; i < numArgs; i++) - convertV8ObjectToNPVariant(info[i], npObject, &npArgs[i], info.GetIsolate()); + convertV8ObjectToNPVariant(info[i], npObject, &npArgs[i], isolate); NPVariant result; VOID_TO_NPVARIANT(result); @@ -137,7 +135,7 @@ static void npObjectInvokeImpl(const v8::FunctionCallbackInfo<v8::Value>& info, } if (!retval) - throwError(v8GeneralError, "Error calling method on NPObject.", info.GetIsolate()); + throwError(v8GeneralError, "Error calling method on NPObject.", isolate); for (int i = 0; i < numArgs; i++) _NPN_ReleaseVariantValue(&npArgs[i]); @@ -145,7 +143,7 @@ static void npObjectInvokeImpl(const v8::FunctionCallbackInfo<v8::Value>& info, // Unwrap return values. v8::Handle<v8::Value> returnValue; if (_NPN_IsAlive(npObject)) - returnValue = convertNPVariantToV8Object(&result, npObject, info.GetIsolate()); + returnValue = convertNPVariantToV8Object(&result, npObject, isolate); _NPN_ReleaseVariantValue(&result); v8SetReturnValue(info, returnValue); @@ -168,54 +166,72 @@ void npObjectInvokeDefaultHandler(const v8::FunctionCallbackInfo<v8::Value>& inf npObjectInvokeImpl(info, InvokeDefault); } +class V8TemplateMapTraits : public V8PersistentValueMapTraits<PrivateIdentifier*, v8::FunctionTemplate, true> { +public: + typedef v8::PersistentValueMap<PrivateIdentifier*, v8::FunctionTemplate, V8TemplateMapTraits> MapType; + typedef PrivateIdentifier WeakCallbackDataType; + + static WeakCallbackDataType* WeakCallbackParameter(MapType* map, PrivateIdentifier* key, const v8::Local<v8::FunctionTemplate>& value) + { + return key; + } + + static void DisposeCallbackData(WeakCallbackDataType* callbackData) { } + + static MapType* MapFromWeakCallbackData( + const v8::WeakCallbackData<v8::FunctionTemplate, WeakCallbackDataType>&); + + static PrivateIdentifier* KeyFromWeakCallbackData( + const v8::WeakCallbackData<v8::FunctionTemplate, WeakCallbackDataType>& data) + { + return data.GetParameter(); + } + + // Dispose traits: + static void Dispose(v8::Isolate* isolate, v8::UniquePersistent<v8::FunctionTemplate> value, PrivateIdentifier* key) { } +}; + + class V8NPTemplateMap { public: // NPIdentifier is PrivateIdentifier*. - typedef HashMap<PrivateIdentifier*, UnsafePersistent<v8::FunctionTemplate> > MapType; + typedef v8::PersistentValueMap<PrivateIdentifier*, v8::FunctionTemplate, V8TemplateMapTraits> MapType; - UnsafePersistent<v8::FunctionTemplate> get(PrivateIdentifier* key) + v8::Local<v8::FunctionTemplate> get(PrivateIdentifier* key) { - return m_map.get(key); + return m_map.Get(key); } void set(PrivateIdentifier* key, v8::Handle<v8::FunctionTemplate> handle) { - ASSERT(!m_map.contains(key)); - v8::Persistent<v8::FunctionTemplate> wrapper(m_isolate, handle); - wrapper.SetWeak(key, &setWeakCallback); - m_map.set(key, UnsafePersistent<v8::FunctionTemplate>(wrapper)); + ASSERT(!m_map.Contains(key)); + m_map.Set(key, handle); } static V8NPTemplateMap& sharedInstance(v8::Isolate* isolate) { DEFINE_STATIC_LOCAL(V8NPTemplateMap, map, (isolate)); - ASSERT(isolate == map.m_isolate); + ASSERT(isolate == map.m_map.GetIsolate()); return map; } + friend class V8TemplateMapTraits; + private: explicit V8NPTemplateMap(v8::Isolate* isolate) - : m_isolate(isolate) - { - } - - void clear(PrivateIdentifier* key) + : m_map(isolate) { - MapType::iterator it = m_map.find(key); - ASSERT_WITH_SECURITY_IMPLICATION(it != m_map.end()); - it->value.dispose(); - m_map.remove(it); - } - - static void setWeakCallback(const v8::WeakCallbackData<v8::FunctionTemplate, PrivateIdentifier>& data) - { - V8NPTemplateMap::sharedInstance(data.GetIsolate()).clear(data.GetParameter()); } MapType m_map; - v8::Isolate* m_isolate; }; +V8TemplateMapTraits::MapType* V8TemplateMapTraits::MapFromWeakCallbackData(const v8::WeakCallbackData<v8::FunctionTemplate, WeakCallbackDataType>& data) +{ + return &V8NPTemplateMap::sharedInstance(data.GetIsolate()).m_map; +} + + static v8::Handle<v8::Value> npObjectGetProperty(v8::Local<v8::Object> self, NPIdentifier identifier, v8::Local<v8::Value> key, v8::Isolate* isolate) { NPObject* npObject = v8ObjectToNPObject(self); @@ -251,19 +267,15 @@ static v8::Handle<v8::Value> npObjectGetProperty(v8::Local<v8::Object> self, NPI return throwError(v8ReferenceError, "NPObject deleted", isolate); PrivateIdentifier* id = static_cast<PrivateIdentifier*>(identifier); - UnsafePersistent<v8::FunctionTemplate> functionTemplate = V8NPTemplateMap::sharedInstance(isolate).get(id); - // FunctionTemplate caches function for each context. - v8::Local<v8::Function> v8Function; + v8::Local<v8::FunctionTemplate> functionTemplate = V8NPTemplateMap::sharedInstance(isolate).get(id); // Cache templates using identifier as the key. - if (functionTemplate.isEmpty()) { + if (functionTemplate.IsEmpty()) { // Create a new template. - v8::Local<v8::FunctionTemplate> temp = v8::FunctionTemplate::New(isolate); - temp->SetCallHandler(npObjectMethodHandler, key); - V8NPTemplateMap::sharedInstance(isolate).set(id, temp); - v8Function = temp->GetFunction(); - } else { - v8Function = functionTemplate.newLocal(isolate)->GetFunction(); + functionTemplate = v8::FunctionTemplate::New(isolate); + functionTemplate->SetCallHandler(npObjectMethodHandler, key); + V8NPTemplateMap::sharedInstance(isolate).set(id, functionTemplate); } + v8::Local<v8::Function> v8Function = functionTemplate->GetFunction(); v8Function->SetName(v8::Handle<v8::String>::Cast(key)); return v8Function; } @@ -367,13 +379,22 @@ void npObjectPropertyEnumerator(const v8::PropertyCallbackInfo<v8::Array>& info, uint32_t count; NPIdentifier* identifiers; if (npObject->_class->enumerate(npObject, &identifiers, &count)) { - v8::Handle<v8::Array> properties = v8::Array::New(info.GetIsolate(), count); + uint32_t propertiesCount = 0; for (uint32_t i = 0; i < count; ++i) { IdentifierRep* identifier = static_cast<IdentifierRep*>(identifiers[i]); - if (namedProperty) - properties->Set(v8::Integer::New(i, info.GetIsolate()), v8AtomicString(info.GetIsolate(), identifier->string())); - else - properties->Set(v8::Integer::New(i, info.GetIsolate()), v8::Integer::New(identifier->number(), info.GetIsolate())); + if (namedProperty == identifier->m_isString) + ++propertiesCount; + } + v8::Handle<v8::Array> properties = v8::Array::New(info.GetIsolate(), propertiesCount); + for (uint32_t i = 0, propertyIndex = 0; i < count; ++i) { + IdentifierRep* identifier = static_cast<IdentifierRep*>(identifiers[i]); + if (namedProperty == identifier->m_isString) { + ASSERT(propertyIndex < propertiesCount); + if (namedProperty) + properties->Set(v8::Integer::New(info.GetIsolate(), propertyIndex++), v8AtomicString(info.GetIsolate(), identifier->string())); + else + properties->Set(v8::Integer::New(info.GetIsolate(), propertyIndex++), v8::Integer::New(info.GetIsolate(), identifier->number())); + } } v8SetReturnValue(info, properties); @@ -398,18 +419,13 @@ static DOMWrapperMap<NPObject>& staticNPObjectMap() return npObjectMap; } -template<> -inline void DOMWrapperMap<NPObject>::setWeakCallback(const v8::WeakCallbackData<v8::Object, DOMWrapperMap<NPObject> >& data) +template <> +inline void DOMWrapperMap<NPObject>::PersistentValueMapTraits::Dispose( + v8::Isolate* isolate, + v8::UniquePersistent<v8::Object> value, + NPObject* npObject) { - NPObject* npObject = static_cast<NPObject*>(toNative(data.GetValue())); - ASSERT(npObject); - ASSERT(staticNPObjectMap().containsKeyAndValue(npObject, data.GetValue())); - - // Must remove from our map before calling _NPN_ReleaseObject(). _NPN_ReleaseObject can - // call forgetV8ObjectForNPObject, which uses the table as well. - staticNPObjectMap().removeAndDispose(npObject); - if (_NPN_IsAlive(npObject)) _NPN_ReleaseObject(npObject); } @@ -447,7 +463,7 @@ v8::Local<v8::Object> createV8ObjectForNPObject(NPObject* object, NPObject* root // V8DOMWrapper::associateObjectWithWrapper() // to create a wrapper object. v8::Handle<v8::Function> v8Function = npObjectDesc.Get(isolate)->GetFunction(); - v8::Local<v8::Object> value = V8ObjectConstructor::newInstance(v8Function); + v8::Local<v8::Object> value = V8ObjectConstructor::newInstance(isolate, v8Function); if (value.IsEmpty()) return value; @@ -459,7 +475,7 @@ v8::Local<v8::Object> createV8ObjectForNPObject(NPObject* object, NPObject* root WrapperConfiguration configuration = buildWrapperConfiguration(object, WrapperConfiguration::Dependent); staticNPObjectMap().set(object, value, configuration); - ASSERT(V8DOMWrapper::maybeDOMWrapper(value)); + ASSERT(V8DOMWrapper::isDOMWrapper(value)); return value; } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8NPObject.h b/chromium/third_party/WebKit/Source/bindings/v8/V8NPObject.h index 4465b039868..dc5d336fbe5 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8NPObject.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8NPObject.h @@ -31,9 +31,10 @@ #ifndef V8NPObject_h #define V8NPObject_h -#include <bindings/npruntime.h> #include <v8.h> +struct NPObject; + namespace WebCore { // These functions can be replaced by normal JS operation. diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8NPUtils.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8NPUtils.cpp index 7c0645f7a1f..df6eefe3b42 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8NPUtils.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8NPUtils.cpp @@ -36,7 +36,7 @@ #include "bindings/v8/V8NPObject.h" #include "bindings/v8/npruntime_impl.h" #include "bindings/v8/npruntime_priv.h" -#include "core/frame/DOMWindow.h" +#include "core/frame/LocalDOMWindow.h" #include "wtf/text/WTFString.h" #include <stdlib.h> @@ -69,7 +69,7 @@ void convertV8ObjectToNPVariant(v8::Local<v8::Value> object, NPObject* owner, NP str->WriteUtf8(utf8Chars, length, 0, v8::String::HINT_MANY_WRITES_EXPECTED); STRINGN_TO_NPVARIANT(utf8Chars, length-1, *result); } else if (object->IsObject()) { - DOMWindow* window = toDOMWindow(isolate->GetCurrentContext()); + LocalDOMWindow* window = currentDOMWindow(isolate); NPObject* npobject = npCreateV8ScriptObject(0, v8::Handle<v8::Object>::Cast(object), window, isolate); if (npobject) _NPN_RegisterObject(npobject, owner); @@ -83,7 +83,7 @@ v8::Handle<v8::Value> convertNPVariantToV8Object(const NPVariant* variant, NPObj switch (type) { case NPVariantType_Int32: - return v8::Integer::New(NPVARIANT_TO_INT32(*variant), isolate); + return v8::Integer::New(isolate, NPVARIANT_TO_INT32(*variant)); case NPVariantType_Double: return v8::Number::New(isolate, NPVARIANT_TO_DOUBLE(*variant)); case NPVariantType_Bool: diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8NodeFilterCondition.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8NodeFilterCondition.cpp index 3fcbc3c0f94..deecfa7b5c6 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8NodeFilterCondition.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8NodeFilterCondition.cpp @@ -31,35 +31,41 @@ #include "config.h" #include "bindings/v8/V8NodeFilterCondition.h" -#include "V8Node.h" +#include "bindings/core/v8/V8Node.h" #include "bindings/v8/ScriptController.h" -#include "bindings/v8/ScriptState.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "core/dom/Node.h" #include "core/dom/NodeFilter.h" #include "wtf/OwnPtr.h" namespace WebCore { -V8NodeFilterCondition::V8NodeFilterCondition(v8::Handle<v8::Value> filter, v8::Handle<v8::Object> owner, v8::Isolate* isolate) - : m_filter(isolate, filter) +V8NodeFilterCondition::V8NodeFilterCondition(v8::Handle<v8::Value> filter, v8::Handle<v8::Object> owner, ScriptState* scriptState) + : m_scriptState(scriptState) { - owner->SetHiddenValue(V8HiddenPropertyName::condition(isolate), filter); - m_filter.setWeak(this, &setWeakCallback); + // ..acceptNode(..) will only dispatch m_filter if m_filter->IsObject(). + // We'll make sure m_filter is either usable by acceptNode or empty. + // (See the fast/dom/node-filter-gc test for a case where 'empty' happens.) + if (!filter.IsEmpty() && filter->IsObject()) { + V8HiddenValue::setHiddenValue(scriptState->isolate(), owner, V8HiddenValue::condition(scriptState->isolate()), filter); + m_filter.set(scriptState->isolate(), filter); + m_filter.setWeak(this, &setWeakCallback); + } } V8NodeFilterCondition::~V8NodeFilterCondition() { } -short V8NodeFilterCondition::acceptNode(ScriptState* state, Node* node) const +short V8NodeFilterCondition::acceptNode(Node* node, ExceptionState& exceptionState) const { - v8::Isolate* isolate = state->isolate(); - ASSERT(isolate->InContext()); + v8::Isolate* isolate = m_scriptState->isolate(); + ASSERT(!m_scriptState->context().IsEmpty()); v8::HandleScope handleScope(isolate); v8::Handle<v8::Value> filter = m_filter.newLocal(isolate); - ASSERT(!filter.IsEmpty()); - if (!filter->IsObject()) + + ASSERT(filter.IsEmpty() || filter->IsObject()); + if (filter.IsEmpty()) return NodeFilter::FILTER_ACCEPT; v8::TryCatch exceptionCatcher; @@ -69,21 +75,21 @@ short V8NodeFilterCondition::acceptNode(ScriptState* state, Node* node) const callback = v8::Handle<v8::Function>::Cast(filter); else { v8::Local<v8::Value> value = filter->ToObject()->Get(v8AtomicString(isolate, "acceptNode")); - if (!value->IsFunction()) { - throwTypeError("NodeFilter object does not have an acceptNode function", state->isolate()); + if (value.IsEmpty() || !value->IsFunction()) { + exceptionState.throwTypeError("NodeFilter object does not have an acceptNode function"); return NodeFilter::FILTER_REJECT; } callback = v8::Handle<v8::Function>::Cast(value); } OwnPtr<v8::Handle<v8::Value>[]> info = adoptArrayPtr(new v8::Handle<v8::Value>[1]); - info[0] = toV8(node, v8::Handle<v8::Object>(), state->isolate()); + v8::Handle<v8::Object> context = m_scriptState->context()->Global(); + info[0] = toV8(node, context, isolate); - v8::Handle<v8::Object> object = isolate->GetCurrentContext()->Global(); - v8::Handle<v8::Value> result = ScriptController::callFunction(state->executionContext(), callback, object, 1, info.get(), isolate); + v8::Handle<v8::Value> result = ScriptController::callFunction(m_scriptState->executionContext(), callback, context, 1, info.get(), isolate); if (exceptionCatcher.HasCaught()) { - state->setException(exceptionCatcher.Exception()); + exceptionState.rethrowV8Exception(exceptionCatcher.Exception()); return NodeFilter::FILTER_REJECT; } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8NodeFilterCondition.h b/chromium/third_party/WebKit/Source/bindings/v8/V8NodeFilterCondition.h index 3d87020d5f2..de42cb5c13a 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8NodeFilterCondition.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8NodeFilterCondition.h @@ -32,14 +32,16 @@ #define V8NodeFilterCondition_h #include "bindings/v8/ScopedPersistent.h" +#include "bindings/v8/ScriptState.h" #include "core/dom/NodeFilterCondition.h" +#include "platform/heap/Handle.h" #include <v8.h> #include "wtf/PassRefPtr.h" namespace WebCore { class Node; -class ScriptState; +class ExceptionState; // V8NodeFilterCondition maintains a Javascript implemented callback for // filtering Node returned by NodeIterator/TreeWalker. @@ -58,25 +60,26 @@ class ScriptState; // v | v | v // NodeIterator --HiddenValue--> NodeFilter --HiddenValue--> JS Callback // (V8) -class V8NodeFilterCondition : public NodeFilterCondition { +class V8NodeFilterCondition FINAL : public NodeFilterCondition { public: - static PassRefPtr<V8NodeFilterCondition> create(v8::Handle<v8::Value> filter, v8::Handle<v8::Object> owner, v8::Isolate* isolate) + static PassRefPtrWillBeRawPtr<V8NodeFilterCondition> create(v8::Handle<v8::Value> filter, v8::Handle<v8::Object> owner, ScriptState* scriptState) { - return adoptRef(new V8NodeFilterCondition(filter, owner, isolate)); + return adoptRefWillBeNoop(new V8NodeFilterCondition(filter, owner, scriptState)); } virtual ~V8NodeFilterCondition(); - virtual short acceptNode(ScriptState*, Node*) const; + virtual short acceptNode(Node*, ExceptionState&) const OVERRIDE; private: // As the value |filter| is maintained by V8GC, the |owner| which references // V8NodeFilterCondition, usually a wrapper of NodeFilter, is specified here // to hold a strong reference to |filter|. - V8NodeFilterCondition(v8::Handle<v8::Value> filter, v8::Handle<v8::Object> owner, v8::Isolate*); + V8NodeFilterCondition(v8::Handle<v8::Value> filter, v8::Handle<v8::Object> owner, ScriptState*); static void setWeakCallback(const v8::WeakCallbackData<v8::Value, V8NodeFilterCondition>&); + RefPtr<ScriptState> m_scriptState; ScopedPersistent<v8::Value> m_filter; }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8ObjectConstructor.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8ObjectConstructor.cpp index 6ebfbab7b71..d52bdc1a910 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8ObjectConstructor.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8ObjectConstructor.cpp @@ -28,46 +28,38 @@ #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8ScriptRunner.h" #include "core/dom/Document.h" -#include "core/frame/Frame.h" +#include "core/frame/LocalFrame.h" #include "platform/TraceEvent.h" namespace WebCore { -v8::Local<v8::Object> V8ObjectConstructor::newInstance(v8::Handle<v8::Function> function) +v8::Local<v8::Object> V8ObjectConstructor::newInstance(v8::Isolate* isolate, v8::Handle<v8::Function> function) { if (function.IsEmpty()) return v8::Local<v8::Object>(); - ConstructorMode constructorMode; - return V8ScriptRunner::instantiateObject(function); + ConstructorMode constructorMode(isolate); + return V8ScriptRunner::instantiateObject(isolate, function); } -v8::Local<v8::Object> V8ObjectConstructor::newInstance(v8::Handle<v8::ObjectTemplate> objectTemplate) -{ - if (objectTemplate.IsEmpty()) - return v8::Local<v8::Object>(); - ConstructorMode constructorMode; - return V8ScriptRunner::instantiateObject(objectTemplate); -} - -v8::Local<v8::Object> V8ObjectConstructor::newInstance(v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[]) +v8::Local<v8::Object> V8ObjectConstructor::newInstance(v8::Isolate* isolate, v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[]) { if (function.IsEmpty()) return v8::Local<v8::Object>(); - ConstructorMode constructorMode; - return V8ScriptRunner::instantiateObject(function, argc, argv); + ConstructorMode constructorMode(isolate); + return V8ScriptRunner::instantiateObject(isolate, function, argc, argv); } -v8::Local<v8::Object> V8ObjectConstructor::newInstanceInDocument(v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[], Document* document) +v8::Local<v8::Object> V8ObjectConstructor::newInstanceInDocument(v8::Isolate* isolate, v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[], Document* document) { if (function.IsEmpty()) return v8::Local<v8::Object>(); - return V8ScriptRunner::instantiateObjectInDocument(function, document, argc, argv); + return V8ScriptRunner::instantiateObjectInDocument(isolate, function, document, argc, argv); } void V8ObjectConstructor::isValidConstructorMode(const v8::FunctionCallbackInfo<v8::Value>& info) { - if (ConstructorMode::current() == ConstructorMode::CreateNewObject) { + if (ConstructorMode::current(info.GetIsolate()) == ConstructorMode::CreateNewObject) { throwTypeError("Illegal constructor", info.GetIsolate()); return; } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8ObjectConstructor.h b/chromium/third_party/WebKit/Source/bindings/v8/V8ObjectConstructor.h index 2c9f6a26020..e1d204fa606 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8ObjectConstructor.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8ObjectConstructor.h @@ -32,6 +32,7 @@ #define V8ObjectConstructor_h #include "bindings/v8/V8PerIsolateData.h" +#include "bindings/v8/V8RecursionScope.h" #include <v8.h> @@ -46,31 +47,37 @@ public: CreateNewObject }; - ConstructorMode() + ConstructorMode(v8::Isolate* isolate) + : m_isolate(isolate) + , m_microtaskSuppression(isolate) { - V8PerIsolateData* data = V8PerIsolateData::current(); + V8PerIsolateData* data = V8PerIsolateData::from(m_isolate); m_previous = data->m_constructorMode; data->m_constructorMode = WrapExistingObject; } ~ConstructorMode() { - V8PerIsolateData* data = V8PerIsolateData::current(); + V8PerIsolateData* data = V8PerIsolateData::from(m_isolate); data->m_constructorMode = m_previous; } - static bool current() { return V8PerIsolateData::current()->m_constructorMode; } + static bool current(v8::Isolate* isolate) + { + return V8PerIsolateData::from(isolate)->m_constructorMode; + } private: + v8::Isolate* m_isolate; bool m_previous; + V8RecursionScope::MicrotaskSuppression m_microtaskSuppression; }; class V8ObjectConstructor { public: - static v8::Local<v8::Object> newInstance(v8::Handle<v8::Function>); - static v8::Local<v8::Object> newInstance(v8::Handle<v8::ObjectTemplate>); - static v8::Local<v8::Object> newInstance(v8::Handle<v8::Function>, int, v8::Handle<v8::Value> argv[]); - static v8::Local<v8::Object> newInstanceInDocument(v8::Handle<v8::Function>, int, v8::Handle<v8::Value> argv[], Document*); + static v8::Local<v8::Object> newInstance(v8::Isolate*, v8::Handle<v8::Function>); + static v8::Local<v8::Object> newInstance(v8::Isolate*, v8::Handle<v8::Function>, int, v8::Handle<v8::Value> argv[]); + static v8::Local<v8::Object> newInstanceInDocument(v8::Isolate*, v8::Handle<v8::Function>, int, v8::Handle<v8::Value> argv[], Document*); static void isValidConstructorMode(const v8::FunctionCallbackInfo<v8::Value>&); }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8PerContextData.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8PerContextData.cpp index 8bf80076f08..1456bed0748 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8PerContextData.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8PerContextData.cpp @@ -31,6 +31,7 @@ #include "config.h" #include "bindings/v8/V8PerContextData.h" +#include "bindings/v8/ScriptState.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8ObjectConstructor.h" #include "wtf/StringExtras.h" @@ -39,67 +40,49 @@ namespace WebCore { -template<typename Map> -static void disposeMapWithUnsafePersistentValues(Map* map) +V8PerContextData::V8PerContextData(v8::Handle<v8::Context> context) + : m_wrapperBoilerplates(context->GetIsolate()) + , m_constructorMap(context->GetIsolate()) + , m_isolate(context->GetIsolate()) + , m_contextHolder(adoptPtr(new gin::ContextHolder(context->GetIsolate()))) + , m_context(m_isolate, context) + , m_customElementBindings(adoptPtr(new CustomElementBindingMap())) + , m_activityLogger(0) { - typename Map::iterator it = map->begin(); - for (; it != map->end(); ++it) - it->value.dispose(); - map->clear(); + m_contextHolder->SetContext(context); + + v8::Context::Scope contextScope(context); + ASSERT(m_errorPrototype.isEmpty()); + v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(context->Global()->Get(v8AtomicString(m_isolate, "Error"))); + ASSERT(!object.IsEmpty()); + v8::Handle<v8::Value> prototypeValue = object->Get(v8AtomicString(m_isolate, "prototype")); + ASSERT(!prototypeValue.IsEmpty()); + m_errorPrototype.set(m_isolate, prototypeValue); } -void V8PerContextData::dispose() +V8PerContextData::~V8PerContextData() { - v8::HandleScope handleScope(m_isolate); - V8PerContextDataHolder::from(v8::Local<v8::Context>::New(m_isolate, m_context))->setPerContextData(0); - - disposeMapWithUnsafePersistentValues(&m_wrapperBoilerplates); - disposeMapWithUnsafePersistentValues(&m_constructorMap); - m_customElementBindings.clear(); - - m_context.Reset(); } -#define V8_STORE_PRIMORDIAL(name, Name) \ -{ \ - ASSERT(m_##name##Prototype.isEmpty()); \ - v8::Handle<v8::String> symbol = v8::String::NewFromUtf8(m_isolate, #Name, v8::String::kInternalizedString); \ - if (symbol.IsEmpty()) \ - return false; \ - v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(v8::Local<v8::Context>::New(m_isolate, m_context)->Global()->Get(symbol)); \ - if (object.IsEmpty()) \ - return false; \ - v8::Handle<v8::Value> prototypeValue = object->Get(prototypeString); \ - if (prototypeValue.IsEmpty()) \ - return false; \ - m_##name##Prototype.set(m_isolate, prototypeValue); \ +PassOwnPtr<V8PerContextData> V8PerContextData::create(v8::Handle<v8::Context> context) +{ + return adoptPtr(new V8PerContextData(context)); } -bool V8PerContextData::init() +V8PerContextData* V8PerContextData::from(v8::Handle<v8::Context> context) { - v8::Handle<v8::Context> context = v8::Local<v8::Context>::New(m_isolate, m_context); - V8PerContextDataHolder::from(context)->setPerContextData(this); - - v8::Handle<v8::String> prototypeString = v8AtomicString(m_isolate, "prototype"); - if (prototypeString.IsEmpty()) - return false; - - V8_STORE_PRIMORDIAL(error, Error); - - return true; + return ScriptState::from(context)->perContextData(); } -#undef V8_STORE_PRIMORDIAL - v8::Local<v8::Object> V8PerContextData::createWrapperFromCacheSlowCase(const WrapperTypeInfo* type) { ASSERT(!m_errorPrototype.isEmpty()); - v8::Context::Scope scope(v8::Local<v8::Context>::New(m_isolate, m_context)); + v8::Context::Scope scope(context()); v8::Local<v8::Function> function = constructorForType(type); - v8::Local<v8::Object> instanceTemplate = V8ObjectConstructor::newInstance(function); + v8::Local<v8::Object> instanceTemplate = V8ObjectConstructor::newInstance(m_isolate, function); if (!instanceTemplate.IsEmpty()) { - m_wrapperBoilerplates.set(type, UnsafePersistent<v8::Object>(m_isolate, instanceTemplate)); + m_wrapperBoilerplates.Set(type, instanceTemplate); return instanceTemplate->Clone(); } return v8::Local<v8::Object>(); @@ -109,8 +92,8 @@ v8::Local<v8::Function> V8PerContextData::constructorForTypeSlowCase(const Wrapp { ASSERT(!m_errorPrototype.isEmpty()); - v8::Context::Scope scope(v8::Local<v8::Context>::New(m_isolate, m_context)); - v8::Handle<v8::FunctionTemplate> functionTemplate = type->domTemplate(m_isolate, worldType(m_isolate)); + v8::Context::Scope scope(context()); + v8::Handle<v8::FunctionTemplate> functionTemplate = type->domTemplate(m_isolate); // Getting the function might fail if we're running out of stack or memory. v8::TryCatch tryCatch; v8::Local<v8::Function> function = functionTemplate->GetFunction(); @@ -131,11 +114,11 @@ v8::Local<v8::Function> V8PerContextData::constructorForTypeSlowCase(const Wrapp && type->wrapperTypePrototype == WrapperTypeObjectPrototype) prototypeObject->SetAlignedPointerInInternalField(v8PrototypeTypeIndex, const_cast<WrapperTypeInfo*>(type)); type->installPerContextEnabledMethods(prototypeObject, m_isolate); - if (type->wrapperTypePrototype == WrapperTypeErrorPrototype) + if (type->wrapperTypePrototype == WrapperTypeExceptionPrototype) prototypeObject->SetPrototype(m_errorPrototype.newLocal(m_isolate)); } - m_constructorMap.set(type, UnsafePersistent<v8::Function>(m_isolate, function)); + m_constructorMap.Set(type, function); return function; } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8PerContextData.h b/chromium/third_party/WebKit/Source/bindings/v8/V8PerContextData.h index 63634f85cbe..7987c616892 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8PerContextData.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8PerContextData.h @@ -33,8 +33,7 @@ #include "bindings/v8/CustomElementBinding.h" #include "bindings/v8/ScopedPersistent.h" -#include "bindings/v8/UnsafePersistent.h" -#include "bindings/v8/V8DOMActivityLogger.h" +#include "bindings/v8/V8PersistentValueMap.h" #include "bindings/v8/WrapperTypeInfo.h" #include "gin/public/context_holder.h" #include "gin/public/gin_embedders.h" @@ -48,7 +47,7 @@ namespace WebCore { class CustomElementDefinition; -class DOMWrapperWorld; +class V8DOMActivityLogger; class V8PerContextData; struct V8NPObject; typedef WTF::Vector<V8NPObject*> V8NPObjectVector; @@ -59,139 +58,69 @@ enum V8ContextEmbedderDataField { v8ContextPerContextDataIndex = static_cast<int>(gin::kPerContextDataStartIndex + gin::kEmbedderBlink), }; -class V8PerContextDataHolder { - WTF_MAKE_NONCOPYABLE(V8PerContextDataHolder); -public: - static void install(v8::Handle<v8::Context> context) - { - new V8PerContextDataHolder(context); - } - - static V8PerContextDataHolder* from(v8::Handle<v8::Context> context) - { - return static_cast<V8PerContextDataHolder*>(context->GetAlignedPointerFromEmbedderData(v8ContextPerContextDataIndex)); - } - - V8PerContextData* perContextData() const { return m_perContextData; } - void setPerContextData(V8PerContextData* data) { m_perContextData = data; } - - DOMWrapperWorld* isolatedWorld() const { return m_isolatedWorld; } - void setIsolatedWorld(DOMWrapperWorld* world) { m_isolatedWorld = world; } - -private: - explicit V8PerContextDataHolder(v8::Handle<v8::Context> context) - : m_context(v8::Isolate::GetCurrent(), context) - , m_perContextData(0) - , m_isolatedWorld(0) - { - m_context.SetWeak(this, &V8PerContextDataHolder::weakCallback); - context->SetAlignedPointerInEmbedderData(v8ContextPerContextDataIndex, this); - } - - ~V8PerContextDataHolder() {} - - static void weakCallback(const v8::WeakCallbackData<v8::Context, V8PerContextDataHolder>& data) - { - data.GetValue()->SetAlignedPointerInEmbedderData(v8ContextPerContextDataIndex, 0); - data.GetParameter()->m_context.Reset(); - delete data.GetParameter(); - } - - v8::Persistent<v8::Context> m_context; - V8PerContextData* m_perContextData; - DOMWrapperWorld* m_isolatedWorld; -}; - class V8PerContextData { public: - static PassOwnPtr<V8PerContextData> create(v8::Handle<v8::Context> context) - { - return adoptPtr(new V8PerContextData(context)); - } + static PassOwnPtr<V8PerContextData> create(v8::Handle<v8::Context>); - ~V8PerContextData() - { - dispose(); - } + static V8PerContextData* from(v8::Handle<v8::Context>); - bool init(); + ~V8PerContextData(); - static V8PerContextData* from(v8::Handle<v8::Context> context) - { - return V8PerContextDataHolder::from(context)->perContextData(); - } + v8::Handle<v8::Context> context() { return m_context.newLocal(m_isolate); } // To create JS Wrapper objects, we create a cache of a 'boiler plate' // object, and then simply Clone that object each time we need a new one. // This is faster than going through the full object creation process. v8::Local<v8::Object> createWrapperFromCache(const WrapperTypeInfo* type) { - UnsafePersistent<v8::Object> boilerplate = m_wrapperBoilerplates.get(type); - return !boilerplate.isEmpty() ? boilerplate.newLocal(v8::Isolate::GetCurrent())->Clone() : createWrapperFromCacheSlowCase(type); + v8::Local<v8::Object> boilerplate = m_wrapperBoilerplates.Get(type); + return !boilerplate.IsEmpty() ? boilerplate->Clone() : createWrapperFromCacheSlowCase(type); } v8::Local<v8::Function> constructorForType(const WrapperTypeInfo* type) { - UnsafePersistent<v8::Function> function = m_constructorMap.get(type); - if (!function.isEmpty()) - return function.newLocal(v8::Isolate::GetCurrent()); - return constructorForTypeSlowCase(type); + v8::Local<v8::Function> function = m_constructorMap.Get(type); + return (!function.IsEmpty()) ? function : constructorForTypeSlowCase(type); } v8::Local<v8::Object> prototypeForType(const WrapperTypeInfo*); - V8NPObjectMap* v8NPObjectMap() - { - return &m_v8NPObjectMap; - } - - V8DOMActivityLogger* activityLogger() - { - return m_activityLogger; - } - - void setActivityLogger(V8DOMActivityLogger* logger) - { - m_activityLogger = logger; - } + V8NPObjectMap* v8NPObjectMap() { return &m_v8NPObjectMap; } void addCustomElementBinding(CustomElementDefinition*, PassOwnPtr<CustomElementBinding>); void clearCustomElementBinding(CustomElementDefinition*); CustomElementBinding* customElementBinding(CustomElementDefinition*); -private: - explicit V8PerContextData(v8::Handle<v8::Context> context) - : m_activityLogger(0) - , m_isolate(v8::Isolate::GetCurrent()) - , m_context(m_isolate, context) - , m_customElementBindings(adoptPtr(new CustomElementBindingMap())) - { - } + V8DOMActivityLogger* activityLogger() const { return m_activityLogger; } + void setActivityLogger(V8DOMActivityLogger* activityLogger) { m_activityLogger = activityLogger; } - void dispose(); +private: + V8PerContextData(v8::Handle<v8::Context>); v8::Local<v8::Object> createWrapperFromCacheSlowCase(const WrapperTypeInfo*); v8::Local<v8::Function> constructorForTypeSlowCase(const WrapperTypeInfo*); // For each possible type of wrapper, we keep a boilerplate object. // The boilerplate is used to create additional wrappers of the same type. - typedef WTF::HashMap<const WrapperTypeInfo*, UnsafePersistent<v8::Object> > WrapperBoilerplateMap; + typedef V8PersistentValueMap<const WrapperTypeInfo*, v8::Object, false> WrapperBoilerplateMap; WrapperBoilerplateMap m_wrapperBoilerplates; - typedef WTF::HashMap<const WrapperTypeInfo*, UnsafePersistent<v8::Function> > ConstructorMap; + typedef V8PersistentValueMap<const WrapperTypeInfo*, v8::Function, false> ConstructorMap; ConstructorMap m_constructorMap; V8NPObjectMap m_v8NPObjectMap; - // We cache a pointer to the V8DOMActivityLogger associated with the world - // corresponding to this context. The ownership of the pointer is retained - // by the DOMActivityLoggerMap in DOMWrapperWorld. - V8DOMActivityLogger* m_activityLogger; + v8::Isolate* m_isolate; - v8::Persistent<v8::Context> m_context; + OwnPtr<gin::ContextHolder> m_contextHolder; + + ScopedPersistent<v8::Context> m_context; ScopedPersistent<v8::Value> m_errorPrototype; typedef WTF::HashMap<CustomElementDefinition*, OwnPtr<CustomElementBinding> > CustomElementBindingMap; OwnPtr<CustomElementBindingMap> m_customElementBindings; + + // This is owned by a static hash map in V8DOMActivityLogger. + V8DOMActivityLogger* m_activityLogger; }; class V8PerContextDebugData { diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8PerIsolateData.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8PerIsolateData.cpp index 10064bc2dde..43dd26351e8 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8PerIsolateData.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8PerIsolateData.cpp @@ -27,48 +27,74 @@ #include "bindings/v8/V8PerIsolateData.h" #include "bindings/v8/DOMDataStore.h" +#include "bindings/v8/PageScriptDebugServer.h" #include "bindings/v8/ScriptGCEvent.h" #include "bindings/v8/ScriptProfiler.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "bindings/v8/V8ObjectConstructor.h" +#include "bindings/v8/V8RecursionScope.h" #include "bindings/v8/V8ScriptRunner.h" +#include "public/platform/Platform.h" +#include "wtf/MainThread.h" namespace WebCore { +static V8PerIsolateData* mainThreadPerIsolateData = 0; + +#ifndef NDEBUG +static void assertV8RecursionScope() +{ + ASSERT(V8RecursionScope::properlyUsed(v8::Isolate::GetCurrent())); +} +#endif + V8PerIsolateData::V8PerIsolateData(v8::Isolate* isolate) : m_isolate(isolate) - , m_stringCache(adoptPtr(new StringCache())) - , m_workerDomDataStore(0) - , m_hiddenPropertyName(adoptPtr(new V8HiddenPropertyName())) + , m_isolateHolder(adoptPtr(new gin::IsolateHolder(m_isolate, v8ArrayBufferAllocator()))) + , m_stringCache(adoptPtr(new StringCache(m_isolate))) + , m_hiddenValue(adoptPtr(new V8HiddenValue())) , m_constructorMode(ConstructorMode::CreateNewObject) , m_recursionLevel(0) #ifndef NDEBUG , m_internalScriptRecursionLevel(0) #endif , m_gcEventData(adoptPtr(new GCEventData())) - , m_shouldCollectGarbageSoon(false) + , m_performingMicrotaskCheckpoint(false) { +#ifndef NDEBUG + // currentThread will always be non-null in production, but can be null in Chromium unit tests. + if (blink::Platform::current()->currentThread()) + isolate->AddCallCompletedCallback(&assertV8RecursionScope); +#endif + if (isMainThread()) { + mainThreadPerIsolateData = this; + PageScriptDebugServer::setMainThreadIsolate(isolate); + } } V8PerIsolateData::~V8PerIsolateData() { + if (m_scriptRegexpScriptState) + m_scriptRegexpScriptState->disposePerContextData(); + if (isMainThread()) + mainThreadPerIsolateData = 0; } -V8PerIsolateData* V8PerIsolateData::create(v8::Isolate* isolate) +v8::Isolate* V8PerIsolateData::mainThreadIsolate() { - ASSERT(isolate); - ASSERT(!isolate->GetData(gin::kEmbedderBlink)); - V8PerIsolateData* data = new V8PerIsolateData(isolate); - isolate->SetData(gin::kEmbedderBlink, data); - return data; + ASSERT(isMainThread()); + ASSERT(mainThreadPerIsolateData); + return mainThreadPerIsolateData->isolate(); } void V8PerIsolateData::ensureInitialized(v8::Isolate* isolate) { ASSERT(isolate); - if (!isolate->GetData(gin::kEmbedderBlink)) - create(isolate); + if (!isolate->GetData(gin::kEmbedderBlink)) { + V8PerIsolateData* data = new V8PerIsolateData(isolate); + isolate->SetData(gin::kEmbedderBlink, data); + } } v8::Persistent<v8::Value>& V8PerIsolateData::ensureLiveRoot() @@ -80,76 +106,92 @@ v8::Persistent<v8::Value>& V8PerIsolateData::ensureLiveRoot() void V8PerIsolateData::dispose(v8::Isolate* isolate) { +#ifndef NDEBUG + if (blink::Platform::current()->currentThread()) + isolate->RemoveCallCompletedCallback(&assertV8RecursionScope); +#endif void* data = isolate->GetData(gin::kEmbedderBlink); delete static_cast<V8PerIsolateData*>(data); isolate->SetData(gin::kEmbedderBlink, 0); } -v8::Handle<v8::FunctionTemplate> V8PerIsolateData::toStringTemplate() +V8PerIsolateData::DOMTemplateMap& V8PerIsolateData::currentDOMTemplateMap() { - if (m_toStringTemplate.isEmpty()) - m_toStringTemplate.set(m_isolate, v8::FunctionTemplate::New(m_isolate, constructorOfToString)); - return m_toStringTemplate.newLocal(m_isolate); + if (DOMWrapperWorld::current(m_isolate).isMainWorld()) + return m_domTemplateMapForMainWorld; + return m_domTemplateMapForNonMainWorld; } -v8::Handle<v8::FunctionTemplate> V8PerIsolateData::privateTemplate(WrapperWorldType currentWorldType, void* privatePointer, v8::FunctionCallback callback, v8::Handle<v8::Value> data, v8::Handle<v8::Signature> signature, int length) +v8::Handle<v8::FunctionTemplate> V8PerIsolateData::domTemplate(void* domTemplateKey, v8::FunctionCallback callback, v8::Handle<v8::Value> data, v8::Handle<v8::Signature> signature, int length) { - TemplateMap& templates = templateMap(currentWorldType); - TemplateMap::iterator result = templates.find(privatePointer); - if (result != templates.end()) - return result->value.newLocal(m_isolate); + DOMTemplateMap& domTemplateMap = currentDOMTemplateMap(); + DOMTemplateMap::iterator result = domTemplateMap.find(domTemplateKey); + if (result != domTemplateMap.end()) + return result->value.Get(m_isolate); + v8::Local<v8::FunctionTemplate> templ = v8::FunctionTemplate::New(m_isolate, callback, data, signature, length); - templates.add(privatePointer, UnsafePersistent<v8::FunctionTemplate>(m_isolate, templ)); + domTemplateMap.add(domTemplateKey, v8::Eternal<v8::FunctionTemplate>(m_isolate, templ)); return templ; } -v8::Handle<v8::FunctionTemplate> V8PerIsolateData::privateTemplateIfExists(WrapperWorldType currentWorldType, void* privatePointer) +v8::Handle<v8::FunctionTemplate> V8PerIsolateData::existingDOMTemplate(void* domTemplateKey) { - TemplateMap& templates = templateMap(currentWorldType); - TemplateMap::iterator result = templates.find(privatePointer); - if (result != templates.end()) - return result->value.newLocal(m_isolate); + DOMTemplateMap& domTemplateMap = currentDOMTemplateMap(); + DOMTemplateMap::iterator result = domTemplateMap.find(domTemplateKey); + if (result != domTemplateMap.end()) + return result->value.Get(m_isolate); return v8::Local<v8::FunctionTemplate>(); } -void V8PerIsolateData::setPrivateTemplate(WrapperWorldType currentWorldType, void* privatePointer, v8::Handle<v8::FunctionTemplate> templ) +void V8PerIsolateData::setDOMTemplate(void* domTemplateKey, v8::Handle<v8::FunctionTemplate> templ) { - templateMap(currentWorldType).add(privatePointer, UnsafePersistent<v8::FunctionTemplate>(m_isolate, templ)); + currentDOMTemplateMap().add(domTemplateKey, v8::Eternal<v8::FunctionTemplate>(m_isolate, v8::Local<v8::FunctionTemplate>(templ))); } -v8::Handle<v8::FunctionTemplate> V8PerIsolateData::rawDOMTemplate(const WrapperTypeInfo* info, WrapperWorldType currentWorldType) +v8::Local<v8::Context> V8PerIsolateData::ensureScriptRegexpContext() { - TemplateMap& templates = rawDOMTemplateMap(currentWorldType); - TemplateMap::iterator result = templates.find(info); - if (result != templates.end()) - return result->value.newLocal(m_isolate); - - v8::EscapableHandleScope handleScope(m_isolate); - v8::Local<v8::FunctionTemplate> templ = createRawTemplate(m_isolate); - templates.add(info, UnsafePersistent<v8::FunctionTemplate>(m_isolate, templ)); - return handleScope.Escape(templ); + if (!m_scriptRegexpScriptState) { + v8::Local<v8::Context> context(v8::Context::New(m_isolate)); + m_scriptRegexpScriptState = ScriptState::create(context, DOMWrapperWorld::create()); + } + return m_scriptRegexpScriptState->context(); } -v8::Local<v8::Context> V8PerIsolateData::ensureRegexContext() +bool V8PerIsolateData::hasInstance(const WrapperTypeInfo* info, v8::Handle<v8::Value> value) { - if (m_regexContext.isEmpty()) { - v8::HandleScope handleScope(m_isolate); - m_regexContext.set(m_isolate, v8::Context::New(m_isolate)); - } - return m_regexContext.newLocal(m_isolate); + return hasInstance(info, value, m_domTemplateMapForMainWorld) + || hasInstance(info, value, m_domTemplateMapForNonMainWorld); } -bool V8PerIsolateData::hasInstance(const WrapperTypeInfo* info, v8::Handle<v8::Value> value, WrapperWorldType currentWorldType) +bool V8PerIsolateData::hasInstance(const WrapperTypeInfo* info, v8::Handle<v8::Value> value, DOMTemplateMap& domTemplateMap) { - TemplateMap& templates = rawDOMTemplateMap(currentWorldType); - TemplateMap::iterator result = templates.find(info); - if (result == templates.end()) + DOMTemplateMap::iterator result = domTemplateMap.find(info); + if (result == domTemplateMap.end()) return false; - v8::HandleScope handleScope(m_isolate); - return result->value.newLocal(m_isolate)->HasInstance(value); + v8::Handle<v8::FunctionTemplate> templ = result->value.Get(m_isolate); + return templ->HasInstance(value); } -void V8PerIsolateData::constructorOfToString(const v8::FunctionCallbackInfo<v8::Value>& info) +v8::Handle<v8::Object> V8PerIsolateData::findInstanceInPrototypeChain(const WrapperTypeInfo* info, v8::Handle<v8::Value> value) +{ + v8::Handle<v8::Object> wrapper = findInstanceInPrototypeChain(info, value, m_domTemplateMapForMainWorld); + if (!wrapper.IsEmpty()) + return wrapper; + return findInstanceInPrototypeChain(info, value, m_domTemplateMapForNonMainWorld); +} + +v8::Handle<v8::Object> V8PerIsolateData::findInstanceInPrototypeChain(const WrapperTypeInfo* info, v8::Handle<v8::Value> value, DOMTemplateMap& domTemplateMap) +{ + if (value.IsEmpty() || !value->IsObject()) + return v8::Handle<v8::Object>(); + DOMTemplateMap::iterator result = domTemplateMap.find(info); + if (result == domTemplateMap.end()) + return v8::Handle<v8::Object>(); + v8::Handle<v8::FunctionTemplate> templ = result->value.Get(m_isolate); + return v8::Handle<v8::Object>::Cast(value)->FindInstanceInPrototypeChain(templ); +} + +static void constructorOfToString(const v8::FunctionCallbackInfo<v8::Value>& info) { // The DOM constructors' toString functions grab the current toString // for Functions by taking the toString function of itself and then @@ -164,7 +206,14 @@ void V8PerIsolateData::constructorOfToString(const v8::FunctionCallbackInfo<v8:: v8SetReturnValue(info, v8::String::Empty(info.GetIsolate())); return; } - v8SetReturnValue(info, V8ScriptRunner::callInternalFunction(v8::Handle<v8::Function>::Cast(value), info.This(), 0, 0, v8::Isolate::GetCurrent())); + v8SetReturnValue(info, V8ScriptRunner::callInternalFunction(v8::Handle<v8::Function>::Cast(value), info.This(), 0, 0, info.GetIsolate())); +} + +v8::Handle<v8::FunctionTemplate> V8PerIsolateData::toStringTemplate() +{ + if (m_toStringTemplate.isEmpty()) + m_toStringTemplate.set(m_isolate, v8::FunctionTemplate::New(m_isolate, constructorOfToString)); + return m_toStringTemplate.newLocal(m_isolate); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8PerIsolateData.h b/chromium/third_party/WebKit/Source/bindings/v8/V8PerIsolateData.h index bfe9f5a636f..ead107cfd1f 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8PerIsolateData.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8PerIsolateData.h @@ -27,9 +27,11 @@ #define V8PerIsolateData_h #include "bindings/v8/ScopedPersistent.h" -#include "bindings/v8/UnsafePersistent.h" +#include "bindings/v8/ScriptState.h" +#include "bindings/v8/V8HiddenValue.h" #include "bindings/v8/WrapperTypeInfo.h" #include "gin/public/gin_embedders.h" +#include "gin/public/isolate_holder.h" #include <v8.h> #include "wtf/Forward.h" #include "wtf/HashMap.h" @@ -41,21 +43,15 @@ namespace WebCore { class DOMDataStore; class GCEventData; class StringCache; -class V8HiddenPropertyName; struct WrapperTypeInfo; class ExternalStringVisitor; -typedef WTF::Vector<DOMDataStore*> DOMDataList; +typedef WTF::Vector<DOMDataStore*> DOMDataStoreList; class V8PerIsolateData { public: - static V8PerIsolateData* create(v8::Isolate*); static void ensureInitialized(v8::Isolate*); - static V8PerIsolateData* current() - { - return from(v8::Isolate::GetCurrent()); - } static V8PerIsolateData* from(v8::Isolate* isolate) { ASSERT(isolate); @@ -63,57 +59,23 @@ public: return static_cast<V8PerIsolateData*>(isolate->GetData(gin::kEmbedderBlink)); } static void dispose(v8::Isolate*); + static v8::Isolate* mainThreadIsolate(); - typedef HashMap<const void*, UnsafePersistent<v8::FunctionTemplate> > TemplateMap; - - TemplateMap& rawDOMTemplateMap(WrapperWorldType worldType) - { - if (worldType == MainWorld) - return m_rawDOMTemplatesForMainWorld; - return m_rawDOMTemplatesForNonMainWorld; - } - - TemplateMap& templateMap(WrapperWorldType worldType) - { - if (worldType == MainWorld) - return m_templatesForMainWorld; - return m_templatesForNonMainWorld; - } + v8::Isolate* isolate() { return m_isolate; } v8::Handle<v8::FunctionTemplate> toStringTemplate(); - v8::Handle<v8::FunctionTemplate> lazyEventListenerToStringTemplate() - { - return v8::Local<v8::FunctionTemplate>::New(m_isolate, m_lazyEventListenerToStringTemplate); - } StringCache* stringCache() { return m_stringCache.get(); } v8::Persistent<v8::Value>& ensureLiveRoot(); - DOMDataList& allStores() { return m_domDataList; } - - V8HiddenPropertyName* hiddenPropertyName() { return m_hiddenPropertyName.get(); } - - void registerDOMDataStore(DOMDataStore* domDataStore) - { - ASSERT(m_domDataList.find(domDataStore) == kNotFound); - m_domDataList.append(domDataStore); - } - - void unregisterDOMDataStore(DOMDataStore* domDataStore) - { - ASSERT(m_domDataList.find(domDataStore) != kNotFound); - m_domDataList.remove(m_domDataList.find(domDataStore)); - } - - // DOMDataStore is owned outside V8PerIsolateData. - DOMDataStore* workerDOMDataStore() { return m_workerDomDataStore; } - void setWorkerDOMDataStore(DOMDataStore* store) { m_workerDomDataStore = store; } - int recursionLevel() const { return m_recursionLevel; } int incrementRecursionLevel() { return ++m_recursionLevel; } int decrementRecursionLevel() { return --m_recursionLevel; } + bool performingMicrotaskCheckpoint() const { return m_performingMicrotaskCheckpoint; } + void setPerformingMicrotaskCheckpoint(bool performingMicrotaskCheckpoint) { m_performingMicrotaskCheckpoint = performingMicrotaskCheckpoint; } + #ifndef NDEBUG int internalScriptRecursionLevel() const { return m_internalScriptRecursionLevel; } int incrementInternalScriptRecursionLevel() { return ++m_internalScriptRecursionLevel; } @@ -121,24 +83,16 @@ public: #endif GCEventData* gcEventData() { return m_gcEventData.get(); } + V8HiddenValue* hiddenValue() { return m_hiddenValue.get(); } - // Gives the system a hint that we should request garbage collection - // upon the next close or navigation event, because some expensive - // objects have been allocated that we want to take every opportunity - // to collect. - void setShouldCollectGarbageSoon() { m_shouldCollectGarbageSoon = true; } - void clearShouldCollectGarbageSoon() { m_shouldCollectGarbageSoon = false; } - bool shouldCollectGarbageSoon() const { return m_shouldCollectGarbageSoon; } - - v8::Handle<v8::FunctionTemplate> privateTemplate(WrapperWorldType, void* privatePointer, v8::FunctionCallback = 0, v8::Handle<v8::Value> data = v8::Handle<v8::Value>(), v8::Handle<v8::Signature> = v8::Handle<v8::Signature>(), int length = 0); - v8::Handle<v8::FunctionTemplate> privateTemplateIfExists(WrapperWorldType, void* privatePointer); - void setPrivateTemplate(WrapperWorldType, void* privatePointer, v8::Handle<v8::FunctionTemplate>); - - v8::Handle<v8::FunctionTemplate> rawDOMTemplate(const WrapperTypeInfo*, WrapperWorldType); + v8::Handle<v8::FunctionTemplate> domTemplate(void* domTemplateKey, v8::FunctionCallback = 0, v8::Handle<v8::Value> data = v8::Handle<v8::Value>(), v8::Handle<v8::Signature> = v8::Handle<v8::Signature>(), int length = 0); + v8::Handle<v8::FunctionTemplate> existingDOMTemplate(void* domTemplateKey); + void setDOMTemplate(void* domTemplateKey, v8::Handle<v8::FunctionTemplate>); - bool hasInstance(const WrapperTypeInfo*, v8::Handle<v8::Value>, WrapperWorldType); + bool hasInstance(const WrapperTypeInfo*, v8::Handle<v8::Value>); + v8::Handle<v8::Object> findInstanceInPrototypeChain(const WrapperTypeInfo*, v8::Handle<v8::Value>); - v8::Local<v8::Context> ensureRegexContext(); + v8::Local<v8::Context> ensureScriptRegexpContext(); const char* previousSamplingState() const { return m_previousSamplingState; } void setPreviousSamplingState(const char* name) { m_previousSamplingState = name; } @@ -146,23 +100,21 @@ public: private: explicit V8PerIsolateData(v8::Isolate*); ~V8PerIsolateData(); - static void constructorOfToString(const v8::FunctionCallbackInfo<v8::Value>&); + + typedef HashMap<const void*, v8::Eternal<v8::FunctionTemplate> > DOMTemplateMap; + DOMTemplateMap& currentDOMTemplateMap(); + bool hasInstance(const WrapperTypeInfo*, v8::Handle<v8::Value>, DOMTemplateMap&); + v8::Handle<v8::Object> findInstanceInPrototypeChain(const WrapperTypeInfo*, v8::Handle<v8::Value>, DOMTemplateMap&); v8::Isolate* m_isolate; - TemplateMap m_rawDOMTemplatesForMainWorld; - TemplateMap m_rawDOMTemplatesForNonMainWorld; - TemplateMap m_templatesForMainWorld; - TemplateMap m_templatesForNonMainWorld; + OwnPtr<gin::IsolateHolder> m_isolateHolder; + DOMTemplateMap m_domTemplateMapForMainWorld; + DOMTemplateMap m_domTemplateMapForNonMainWorld; ScopedPersistent<v8::FunctionTemplate> m_toStringTemplate; - v8::Persistent<v8::FunctionTemplate> m_lazyEventListenerToStringTemplate; OwnPtr<StringCache> m_stringCache; - - Vector<DOMDataStore*> m_domDataList; - DOMDataStore* m_workerDomDataStore; - - OwnPtr<V8HiddenPropertyName> m_hiddenPropertyName; + OwnPtr<V8HiddenValue> m_hiddenValue; ScopedPersistent<v8::Value> m_liveRoot; - ScopedPersistent<v8::Context> m_regexContext; + RefPtr<ScriptState> m_scriptRegexpScriptState; const char* m_previousSamplingState; @@ -175,7 +127,7 @@ private: int m_internalScriptRecursionLevel; #endif OwnPtr<GCEventData> m_gcEventData; - bool m_shouldCollectGarbageSoon; + bool m_performingMicrotaskCheckpoint; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8PersistentValueMap.h b/chromium/third_party/WebKit/Source/bindings/v8/V8PersistentValueMap.h new file mode 100644 index 00000000000..0fa2ac2c902 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8PersistentValueMap.h @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2014 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 V8PersistentValueMap_h +#define V8PersistentValueMap_h + +#include "wtf/HashMap.h" +#include <v8-util.h> +#include <v8.h> + +namespace WebCore { + +/** + * A Traits class for v8::PersistentValueMap that uses wtf/HashMap as a + * backing store. + * + * The parameter is_weak will determine whether the references are 'weak'. + * If so, entries will be removed from the map as the weak references are + * collected. + */ +template<class KeyType, class ValueType, bool is_weak> +class V8PersistentValueMapTraits { +public: + // Map traits: + typedef HashMap<KeyType, v8::PersistentContainerValue> Impl; + typedef typename Impl::iterator Iterator; + static size_t Size(const Impl* impl) { return impl->size(); } + static bool Empty(Impl* impl) { return impl->isEmpty(); } + static void Swap(Impl& impl, Impl& other) { impl.swap(other); } + static Iterator Begin(Impl* impl) { return impl->begin(); } + static Iterator End(Impl* impl) { return impl->end(); } + static v8::PersistentContainerValue Value(Iterator& iter) + { + return iter->value; + } + static KeyType Key(Iterator& iter) { return iter->key; } + static v8::PersistentContainerValue Set( + Impl* impl, KeyType key, v8::PersistentContainerValue value) + { + v8::PersistentContainerValue oldValue = Get(impl, key); + impl->set(key, value); + return oldValue; + } + static v8::PersistentContainerValue Get(const Impl* impl, KeyType key) + { + return impl->get(key); + } + + static v8::PersistentContainerValue Remove(Impl* impl, KeyType key) + { + return impl->take(key); + } + + // Weak traits: + static const v8::PersistentContainerCallbackType kCallbackType = is_weak ? v8::kWeak : v8::kNotWeak; + typedef v8::PersistentValueMap<KeyType, ValueType, V8PersistentValueMapTraits<KeyType, ValueType, is_weak> > MapType; + + typedef void WeakCallbackDataType; + + static WeakCallbackDataType* WeakCallbackParameter(MapType* map, KeyType key, const v8::Local<ValueType>& value) + { + return 0; + } + + static void DisposeCallbackData(WeakCallbackDataType* callbackData) + { + } + + static MapType* MapFromWeakCallbackData( + const v8::WeakCallbackData<ValueType, WeakCallbackDataType>& data) + { + return 0; + } + + static KeyType KeyFromWeakCallbackData( + const v8::WeakCallbackData<ValueType, WeakCallbackDataType>& data) + { + return KeyType(); + } + + // Dispose traits: + static void Dispose(v8::Isolate* isolate, v8::UniquePersistent<ValueType> value, KeyType key) { } +}; + +/** + * A map for safely storing persistent V8 values, based on + * v8::PersistentValueMap. + * + * If is_weak is set, values will be held weakly and map entries will be + * removed as their values are being collected. + */ +template<class KeyType, class ValueType, bool is_weak = true> +class V8PersistentValueMap : public v8::PersistentValueMap<KeyType, ValueType, V8PersistentValueMapTraits<KeyType, ValueType, is_weak> > { +public: + typedef V8PersistentValueMapTraits<KeyType, ValueType, is_weak> Traits; + explicit V8PersistentValueMap(v8::Isolate* isolate) : v8::PersistentValueMap<KeyType, ValueType, Traits>(isolate) { } +}; + +} // namespace WebCore + +#endif // V8PersistentValueMap_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8NodeListCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8PersistentValueVector.h index 341f1c23d5d..02f8314e937 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8NodeListCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8PersistentValueVector.h @@ -28,33 +28,50 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "config.h" -#include "V8NodeList.h" +#ifndef V8PersistentValueVector_h +#define V8PersistentValueVector_h -#include "V8Node.h" -#include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8GCController.h" -#include "core/dom/LiveNodeList.h" -#include "core/dom/NodeList.h" -#include "wtf/RefPtr.h" -#include "wtf/StdLibExtras.h" +#include "wtf/Vector.h" +#include <v8-util.h> +#include <v8.h> namespace WebCore { -void V8NodeList::visitDOMWrapper(void* object, const v8::Persistent<v8::Object>& wrapper, v8::Isolate* isolate) -{ - NodeList* impl = static_cast<NodeList*>(object); - if (!impl->isLiveNodeList()) { - setObjectGroup(object, wrapper, isolate); - return; +class WTFVectorPersistentValueVectorTraits { +public: + typedef Vector<v8::PersistentContainerValue> Impl; + static void Append(Impl* impl, v8::PersistentContainerValue value) + { + impl->append(value); } - Node* owner = static_cast<LiveNodeList*>(impl)->ownerNode(); - if (!owner) { - setObjectGroup(object, wrapper, isolate); - return; + static bool IsEmpty(const Impl* impl) + { + return impl->isEmpty(); } + static size_t Size(const Impl* impl) + { + return impl->size(); + } + static v8::PersistentContainerValue Get(const Impl* impl, size_t i) + { + return (i < impl->size()) ? impl->at(i) : v8::kPersistentContainerNotFound; + } + static void ReserveCapacity(Impl* impl, size_t capacity) + { + impl->reserveCapacity(capacity); + } + static void Clear(Impl* impl) + { + impl->clear(); + } +}; - setObjectGroup(V8GCController::opaqueRootForGC(owner, isolate), wrapper, isolate); -} +template<class ValueType> +class V8PersistentValueVector : public v8::PersistentValueVector<ValueType, WTFVectorPersistentValueVectorTraits> { +public: + explicit V8PersistentValueVector(v8::Isolate* isolate) : v8::PersistentValueVector<ValueType, WTFVectorPersistentValueVectorTraits>(isolate) { } +}; } // namespace WebCore + +#endif // V8PersistentValueVector_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8RecursionScope.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8RecursionScope.cpp index c08fba7c855..2519250f28f 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8RecursionScope.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8RecursionScope.cpp @@ -38,14 +38,11 @@ namespace WebCore { void V8RecursionScope::didLeaveScriptContext() { - // FIXME: Instrument any work that takes place when script exits to c++ (e.g. Mutation Observers). + Microtask::performCheckpoint(); // 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(); - - if (m_isDocumentContext) - Microtask::performCheckpoint(); + IDBPendingTransactionMonitor::from(m_executionContext).deactivateNewTransactions(); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8RecursionScope.h b/chromium/third_party/WebKit/Source/bindings/v8/V8RecursionScope.h index 3bc3da7d024..a73d93a8dc0 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8RecursionScope.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8RecursionScope.h @@ -33,7 +33,9 @@ #include "bindings/v8/V8PerIsolateData.h" #include "core/dom/ExecutionContext.h" +#include "core/dom/ScriptForbiddenScope.h" #include "wtf/Noncopyable.h" +#include <v8.h> namespace WebCore { @@ -57,51 +59,66 @@ namespace WebCore { class V8RecursionScope { WTF_MAKE_NONCOPYABLE(V8RecursionScope); public: - explicit V8RecursionScope(ExecutionContext* context) - : m_isDocumentContext(context && context->isDocument()) + V8RecursionScope(v8::Isolate* isolate, ExecutionContext* context) + : m_isolate(isolate) + , m_executionContext(*context) { - V8PerIsolateData::current()->incrementRecursionLevel(); + V8PerIsolateData::from(m_isolate)->incrementRecursionLevel(); + ASSERT(!ScriptForbiddenScope::isScriptForbidden()); + // If you want V8 to autorun microtasks, this class needs to have a + // v8::Isolate::SuppressMicrotaskExecutionScope member. + ASSERT(!isolate->WillAutorunMicrotasks()); } ~V8RecursionScope() { - if (!V8PerIsolateData::current()->decrementRecursionLevel()) + if (!V8PerIsolateData::from(m_isolate)->decrementRecursionLevel()) didLeaveScriptContext(); } - static int recursionLevel() + static int recursionLevel(v8::Isolate* isolate) { - return V8PerIsolateData::current()->recursionLevel(); + return V8PerIsolateData::from(isolate)->recursionLevel(); } #ifndef NDEBUG - static bool properlyUsed() + static bool properlyUsed(v8::Isolate* isolate) { - return recursionLevel() > 0 || V8PerIsolateData::current()->internalScriptRecursionLevel() > 0; + return recursionLevel(isolate) > 0 || V8PerIsolateData::from(isolate)->internalScriptRecursionLevel() > 0; } #endif class MicrotaskSuppression { public: - MicrotaskSuppression() + MicrotaskSuppression(v8::Isolate* isolate) +#ifndef NDEBUG + : m_isolate(isolate) +#endif { + ASSERT(!ScriptForbiddenScope::isScriptForbidden()); #ifndef NDEBUG - V8PerIsolateData::current()->incrementInternalScriptRecursionLevel(); + V8PerIsolateData::from(m_isolate)->incrementInternalScriptRecursionLevel(); #endif } ~MicrotaskSuppression() { #ifndef NDEBUG - V8PerIsolateData::current()->decrementInternalScriptRecursionLevel(); + V8PerIsolateData::from(m_isolate)->decrementInternalScriptRecursionLevel(); #endif } + + private: +#ifndef NDEBUG + v8::Isolate* m_isolate; +#endif }; private: void didLeaveScriptContext(); - bool m_isDocumentContext; + v8::Isolate* m_isolate; + ExecutionContext& m_executionContext; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8ScriptRunner.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8ScriptRunner.cpp index ed6a1730117..625fddf8095 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8ScriptRunner.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8ScriptRunner.cpp @@ -26,6 +26,7 @@ #include "config.h" #include "bindings/v8/V8ScriptRunner.h" +#include "bindings/v8/ScriptSourceCode.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8GCController.h" #include "bindings/v8/V8RecursionScope.h" @@ -36,70 +37,74 @@ namespace WebCore { -PassOwnPtr<v8::ScriptData> V8ScriptRunner::precompileScript(v8::Handle<v8::String> code, ScriptResource* resource) +v8::Local<v8::Script> V8ScriptRunner::compileScript(const ScriptSourceCode& source, v8::Isolate* isolate, AccessControlStatus corsStatus) +{ + return compileScript(v8String(isolate, source.source()), source.url(), source.startPosition(), source.resource(), isolate, corsStatus); +} + +v8::Local<v8::Script> V8ScriptRunner::compileScript(v8::Handle<v8::String> code, const String& fileName, const TextPosition& scriptStartPosition, ScriptResource* resource, v8::Isolate* isolate, AccessControlStatus corsStatus) { - TRACE_EVENT0("v8", "v8.compile"); - TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Compile"); // A pseudo-randomly chosen ID used to store and retrieve V8 ScriptData from // the ScriptResource. If the format changes, this ID should be changed too. static const unsigned dataTypeID = 0xECC13BD7; - // Very small scripts are not worth the effort to preparse. - static const int minPreparseLength = 1024; - - if (!resource || code->Length() < minPreparseLength) - return nullptr; - - CachedMetadata* cachedMetadata = resource->cachedMetadata(dataTypeID); - if (cachedMetadata) - return adoptPtr(v8::ScriptData::New(cachedMetadata->data(), cachedMetadata->size())); - - OwnPtr<v8::ScriptData> scriptData = adoptPtr(v8::ScriptData::PreCompile(code)); - if (!scriptData) - return nullptr; + // Very small scripts are not worth the effort to store cached data. + static const int minLengthForCachedData = 1024; - resource->setCachedMetadata(dataTypeID, scriptData->Data(), scriptData->Length()); + TRACE_EVENT1("v8", "v8.compile", "fileName", fileName.utf8()); + TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "V8Compile"); - return scriptData.release(); -} - -v8::Local<v8::Script> V8ScriptRunner::compileScript(v8::Handle<v8::String> code, const String& fileName, const TextPosition& scriptStartPosition, v8::ScriptData* scriptData, v8::Isolate* isolate, AccessControlStatus corsStatus) -{ - TRACE_EVENT0("v8", "v8.compile"); - TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Compile"); + // NOTE: For compatibility with WebCore, ScriptSourceCode's line starts at + // 1, whereas v8 starts at 0. v8::Handle<v8::String> name = v8String(isolate, fileName); - v8::Handle<v8::Integer> line = v8::Integer::New(scriptStartPosition.m_line.zeroBasedInt(), isolate); - v8::Handle<v8::Integer> column = v8::Integer::New(scriptStartPosition.m_column.zeroBasedInt(), isolate); + v8::Handle<v8::Integer> line = v8::Integer::New(isolate, scriptStartPosition.m_line.zeroBasedInt()); + v8::Handle<v8::Integer> column = v8::Integer::New(isolate, scriptStartPosition.m_column.zeroBasedInt()); v8::Handle<v8::Boolean> isSharedCrossOrigin = corsStatus == SharableCrossOrigin ? v8::True(isolate) : v8::False(isolate); v8::ScriptOrigin origin(name, line, column, isSharedCrossOrigin); - return v8::Script::Compile(code, &origin, scriptData); + + v8::ScriptCompiler::CompileOptions options = v8::ScriptCompiler::kNoCompileOptions; + OwnPtr<v8::ScriptCompiler::CachedData> cachedData; + if (resource) { + CachedMetadata* cachedMetadata = resource->cachedMetadata(dataTypeID); + if (cachedMetadata) { + // Ownership of the buffer is not transferred to CachedData. + cachedData = adoptPtr(new v8::ScriptCompiler::CachedData(reinterpret_cast<const uint8_t*>(cachedMetadata->data()), cachedMetadata->size())); + } else if (code->Length() >= minLengthForCachedData) { + options = v8::ScriptCompiler::kProduceDataToCache; + } + } + // source takes ownership of cachedData. + v8::ScriptCompiler::Source source(code, origin, cachedData.leakPtr()); + v8::Local<v8::Script> script = v8::ScriptCompiler::Compile(isolate, &source, options); + if (options == v8::ScriptCompiler::kProduceDataToCache) { + const v8::ScriptCompiler::CachedData* newCachedData = source.GetCachedData(); + if (newCachedData) { + // Ownership of the buffer is not transferred; source's cachedData continues to own it. + resource->setCachedMetadata(dataTypeID, reinterpret_cast<const char*>(newCachedData->data), newCachedData->length); + } + } + return script; } v8::Local<v8::Value> V8ScriptRunner::runCompiledScript(v8::Handle<v8::Script> script, ExecutionContext* context, v8::Isolate* isolate) { - TRACE_EVENT0("v8", "v8.run"); - TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); if (script.IsEmpty()) return v8::Local<v8::Value>(); + TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "V8Execution"); + TRACE_EVENT1("v8", "v8.run", "fileName", TRACE_STR_COPY(*v8::String::Utf8Value(script->GetUnboundScript()->GetScriptName()))); - if (V8RecursionScope::recursionLevel() >= kMaxRecursionDepth) + if (V8RecursionScope::recursionLevel(isolate) >= kMaxRecursionDepth) return handleMaxRecursionDepthExceeded(isolate); - if (handleOutOfMemory()) - return v8::Local<v8::Value>(); - RELEASE_ASSERT(!context->isIteratingOverObservers()); // Run the script and keep track of the current recursion depth. v8::Local<v8::Value> result; { - V8RecursionScope recursionScope(context); + V8RecursionScope recursionScope(isolate, context); result = script->Run(); } - if (handleOutOfMemory()) - ASSERT(result.IsEmpty()); - if (result.IsEmpty()) return v8::Local<v8::Value>(); @@ -107,95 +112,84 @@ v8::Local<v8::Value> V8ScriptRunner::runCompiledScript(v8::Handle<v8::Script> sc return result; } -v8::Local<v8::Value> V8ScriptRunner::compileAndRunInternalScript(v8::Handle<v8::String> source, v8::Isolate* isolate, const String& fileName, const TextPosition& scriptStartPosition, v8::ScriptData* scriptData) +v8::Local<v8::Value> V8ScriptRunner::compileAndRunInternalScript(v8::Handle<v8::String> source, v8::Isolate* isolate, const String& fileName, const TextPosition& scriptStartPosition) { TRACE_EVENT0("v8", "v8.run"); - TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); - v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(source, fileName, scriptStartPosition, scriptData, isolate); + TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "V8Execution"); + v8::Handle<v8::Script> script = V8ScriptRunner::compileScript(source, fileName, scriptStartPosition, 0, isolate); if (script.IsEmpty()) return v8::Local<v8::Value>(); - V8RecursionScope::MicrotaskSuppression recursionScope; + V8RecursionScope::MicrotaskSuppression recursionScope(isolate); v8::Local<v8::Value> result = script->Run(); crashIfV8IsDead(); return result; } -v8::Local<v8::Value> V8ScriptRunner::callFunction(v8::Handle<v8::Function> function, ExecutionContext* context, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[], v8::Isolate* isolate) +v8::Local<v8::Value> V8ScriptRunner::callFunction(v8::Handle<v8::Function> function, ExecutionContext* context, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> args[], v8::Isolate* isolate) { TRACE_EVENT0("v8", "v8.callFunction"); - TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); + TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "V8Execution"); - if (V8RecursionScope::recursionLevel() >= kMaxRecursionDepth) + if (V8RecursionScope::recursionLevel(isolate) >= kMaxRecursionDepth) return handleMaxRecursionDepthExceeded(isolate); RELEASE_ASSERT(!context->isIteratingOverObservers()); - V8RecursionScope recursionScope(context); - v8::Local<v8::Value> result = function->Call(receiver, argc, info); + V8RecursionScope recursionScope(isolate, context); + v8::Local<v8::Value> result = function->Call(receiver, argc, args); crashIfV8IsDead(); return result; } -v8::Local<v8::Value> V8ScriptRunner::callInternalFunction(v8::Handle<v8::Function> function, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[], v8::Isolate* isolate) +v8::Local<v8::Value> V8ScriptRunner::callInternalFunction(v8::Handle<v8::Function> function, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> args[], v8::Isolate* isolate) { TRACE_EVENT0("v8", "v8.callFunction"); - TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); - V8RecursionScope::MicrotaskSuppression recursionScope; - v8::Local<v8::Value> result = function->Call(receiver, argc, info); - crashIfV8IsDead(); - return result; -} - -v8::Local<v8::Value> V8ScriptRunner::callAsFunction(v8::Handle<v8::Object> object, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[]) -{ - TRACE_EVENT0("v8", "v8.callFunction"); - TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); - - V8RecursionScope::MicrotaskSuppression recursionScope; - v8::Local<v8::Value> result = object->CallAsFunction(receiver, argc, info); + TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "V8Execution"); + V8RecursionScope::MicrotaskSuppression recursionScope(isolate); + v8::Local<v8::Value> result = function->Call(receiver, argc, args); crashIfV8IsDead(); return result; } -v8::Local<v8::Value> V8ScriptRunner::callAsConstructor(v8::Handle<v8::Object> object, int argc, v8::Handle<v8::Value> info[]) +v8::Local<v8::Value> V8ScriptRunner::callAsFunction(v8::Isolate* isolate, v8::Handle<v8::Object> object, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> args[]) { TRACE_EVENT0("v8", "v8.callFunction"); - TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); + TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "V8Execution"); - V8RecursionScope::MicrotaskSuppression recursionScope; - v8::Local<v8::Value> result = object->CallAsConstructor(argc, info); + V8RecursionScope::MicrotaskSuppression recursionScope(isolate); + v8::Local<v8::Value> result = object->CallAsFunction(receiver, argc, args); crashIfV8IsDead(); return result; } -v8::Local<v8::Object> V8ScriptRunner::instantiateObject(v8::Handle<v8::ObjectTemplate> objectTemplate) +v8::Local<v8::Object> V8ScriptRunner::instantiateObject(v8::Isolate* isolate, v8::Handle<v8::ObjectTemplate> objectTemplate) { TRACE_EVENT0("v8", "v8.newInstance"); - TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); + TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "V8Execution"); - V8RecursionScope::MicrotaskSuppression scope; + V8RecursionScope::MicrotaskSuppression scope(isolate); v8::Local<v8::Object> result = objectTemplate->NewInstance(); crashIfV8IsDead(); return result; } -v8::Local<v8::Object> V8ScriptRunner::instantiateObject(v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[]) +v8::Local<v8::Object> V8ScriptRunner::instantiateObject(v8::Isolate* isolate, v8::Handle<v8::Function> function, int argc, v8::Handle<v8::Value> argv[]) { TRACE_EVENT0("v8", "v8.newInstance"); - TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); + TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "V8Execution"); - V8RecursionScope::MicrotaskSuppression scope; + V8RecursionScope::MicrotaskSuppression scope(isolate); v8::Local<v8::Object> result = function->NewInstance(argc, argv); crashIfV8IsDead(); return result; } -v8::Local<v8::Object> V8ScriptRunner::instantiateObjectInDocument(v8::Handle<v8::Function> function, ExecutionContext* context, int argc, v8::Handle<v8::Value> argv[]) +v8::Local<v8::Object> V8ScriptRunner::instantiateObjectInDocument(v8::Isolate* isolate, v8::Handle<v8::Function> function, ExecutionContext* context, int argc, v8::Handle<v8::Value> argv[]) { TRACE_EVENT0("v8", "v8.newInstance"); - TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "Execution"); - V8RecursionScope scope(context); + TRACE_EVENT_SCOPED_SAMPLING_STATE("V8", "V8Execution"); + V8RecursionScope scope(isolate, context); v8::Local<v8::Object> result = function->NewInstance(argc, argv); crashIfV8IsDead(); return result; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8ScriptRunner.h b/chromium/third_party/WebKit/Source/bindings/v8/V8ScriptRunner.h index b36102f20ba..368401be41f 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8ScriptRunner.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8ScriptRunner.h @@ -35,23 +35,23 @@ namespace WebCore { class ScriptResource; +class ScriptSourceCode; class ExecutionContext; class V8ScriptRunner { public: // For the following methods, the caller sites have to hold // a HandleScope and a ContextScope. - static PassOwnPtr<v8::ScriptData> precompileScript(v8::Handle<v8::String>, ScriptResource*); - static v8::Local<v8::Script> compileScript(v8::Handle<v8::String>, const String&, const TextPosition&, v8::ScriptData*, v8::Isolate*, AccessControlStatus = SharableCrossOrigin); + static v8::Local<v8::Script> compileScript(const ScriptSourceCode&, v8::Isolate*, AccessControlStatus = SharableCrossOrigin); + static v8::Local<v8::Script> compileScript(v8::Handle<v8::String>, const String& fileName, const TextPosition&, ScriptResource*, v8::Isolate*, AccessControlStatus = SharableCrossOrigin); static v8::Local<v8::Value> runCompiledScript(v8::Handle<v8::Script>, ExecutionContext*, v8::Isolate*); - static v8::Local<v8::Value> compileAndRunInternalScript(v8::Handle<v8::String>, v8::Isolate*, const String& = String(), const TextPosition& = TextPosition(), v8::ScriptData* = 0); + static v8::Local<v8::Value> compileAndRunInternalScript(v8::Handle<v8::String>, v8::Isolate*, const String& = String(), const TextPosition& = TextPosition()); static v8::Local<v8::Value> callInternalFunction(v8::Handle<v8::Function>, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[], v8::Isolate*); static v8::Local<v8::Value> callFunction(v8::Handle<v8::Function>, ExecutionContext*, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[], v8::Isolate*); - static v8::Local<v8::Value> callAsFunction(v8::Handle<v8::Object>, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[]); - static v8::Local<v8::Value> callAsConstructor(v8::Handle<v8::Object>, int argc, v8::Handle<v8::Value> info[]); - static v8::Local<v8::Object> instantiateObject(v8::Handle<v8::ObjectTemplate>); - static v8::Local<v8::Object> instantiateObject(v8::Handle<v8::Function>, int argc = 0, v8::Handle<v8::Value> argv[] = 0); - static v8::Local<v8::Object> instantiateObjectInDocument(v8::Handle<v8::Function>, ExecutionContext*, int argc = 0, v8::Handle<v8::Value> argv[] = 0); + static v8::Local<v8::Value> callAsFunction(v8::Isolate*, v8::Handle<v8::Object>, v8::Handle<v8::Value> receiver, int argc, v8::Handle<v8::Value> info[]); + static v8::Local<v8::Object> instantiateObject(v8::Isolate*, v8::Handle<v8::ObjectTemplate>); + static v8::Local<v8::Object> instantiateObject(v8::Isolate*, v8::Handle<v8::Function>, int argc = 0, v8::Handle<v8::Value> argv[] = 0); + static v8::Local<v8::Object> instantiateObjectInDocument(v8::Isolate*, v8::Handle<v8::Function>, ExecutionContext*, int argc = 0, v8::Handle<v8::Value> argv[] = 0); }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8StringResource.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8StringResource.cpp index bce62d4c2fa..3b76e8243f9 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8StringResource.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8StringResource.cpp @@ -32,27 +32,9 @@ namespace WebCore { -WebCoreStringResourceBase* WebCoreStringResourceBase::toWebCoreStringResourceBase(v8::Handle<v8::String> string) -{ - v8::String::Encoding encoding; - v8::String::ExternalStringResourceBase* resource = string->GetExternalStringResourceBase(&encoding); - if (!resource) - return 0; - if (encoding == v8::String::ONE_BYTE_ENCODING) - return static_cast<WebCoreStringResource8*>(resource); - return static_cast<WebCoreStringResource16*>(resource); -} - -void WebCoreStringResourceBase::visitStrings(ExternalStringVisitor* visitor) -{ - visitor->visitJSExternalString(m_plainString.impl()); - if (m_plainString.impl() != m_atomicString.impl() && !m_atomicString.isNull()) - visitor->visitJSExternalString(m_atomicString.impl()); -} - template<class StringClass> struct StringTraits { static const StringClass& fromStringResource(WebCoreStringResourceBase*); - template<bool oneByte> + template <typename V8StringTrait> static StringClass fromV8String(v8::Handle<v8::String>, int); }; @@ -62,7 +44,7 @@ struct StringTraits<String> { { return resource->webcoreString(); } - template<bool oneByte> + template <typename V8StringTrait> static String fromV8String(v8::Handle<v8::String>, int); }; @@ -72,59 +54,49 @@ struct StringTraits<AtomicString> { { return resource->atomicString(); } - template<bool oneByte> + template <typename V8StringTrait> static AtomicString fromV8String(v8::Handle<v8::String>, int); }; -template<> -String StringTraits<String>::fromV8String<false>(v8::Handle<v8::String> v8String, int length) -{ - ASSERT(v8String->Length() == length); - UChar* buffer; - String result = String::createUninitialized(length, buffer); - v8String->Write(reinterpret_cast<uint16_t*>(buffer), 0, length); - return result; -} +struct V8StringTwoBytesTrait { + typedef UChar CharType; + ALWAYS_INLINE static void write(v8::Handle<v8::String> v8String, CharType* buffer, int length) + { + v8String->Write(reinterpret_cast<uint16_t*>(buffer), 0, length); + } +}; -template<> -AtomicString StringTraits<AtomicString>::fromV8String<false>(v8::Handle<v8::String> v8String, int length) -{ - ASSERT(v8String->Length() == length); - static const int inlineBufferSize = 16; - if (length <= inlineBufferSize) { - UChar inlineBuffer[inlineBufferSize]; - v8String->Write(reinterpret_cast<uint16_t*>(inlineBuffer), 0, length); - return AtomicString(inlineBuffer, length); +struct V8StringOneByteTrait { + typedef LChar CharType; + ALWAYS_INLINE static void write(v8::Handle<v8::String> v8String, CharType* buffer, int length) + { + v8String->WriteOneByte(buffer, 0, length); } - UChar* buffer; - String result = String::createUninitialized(length, buffer); - v8String->Write(reinterpret_cast<uint16_t*>(buffer), 0, length); - return AtomicString(result); -} +}; -template<> -String StringTraits<String>::fromV8String<true>(v8::Handle<v8::String> v8String, int length) +template <typename V8StringTrait> +String StringTraits<String>::fromV8String(v8::Handle<v8::String> v8String, int length) { ASSERT(v8String->Length() == length); - LChar* buffer; + typename V8StringTrait::CharType* buffer; String result = String::createUninitialized(length, buffer); - v8String->WriteOneByte(buffer, 0, length); + V8StringTrait::write(v8String, buffer, length); return result; } -template<> -AtomicString StringTraits<AtomicString>::fromV8String<true>(v8::Handle<v8::String> v8String, int length) +template <typename V8StringTrait> +AtomicString StringTraits<AtomicString>::fromV8String(v8::Handle<v8::String> v8String, int length) { ASSERT(v8String->Length() == length); - static const int inlineBufferSize = 32; + static const int inlineBufferSize = 32 / sizeof(typename V8StringTrait::CharType); if (length <= inlineBufferSize) { - LChar inlineBuffer[inlineBufferSize]; - v8String->WriteOneByte(inlineBuffer, 0, length); + typename V8StringTrait::CharType inlineBuffer[inlineBufferSize]; + V8StringTrait::write(v8String, inlineBuffer, length); return AtomicString(inlineBuffer, length); } - LChar* buffer; + typename V8StringTrait::CharType* buffer; String string = String::createUninitialized(length, buffer); - v8String->WriteOneByte(buffer, 0, length); + V8StringTrait::write(v8String, buffer, length); return AtomicString(string); } @@ -132,7 +104,6 @@ template<typename StringType> StringType v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode external) { { - // A lot of WebCoreStringResourceBase::toWebCoreStringResourceBase is copied here by hand for performance reasons. // This portion of this function is very hot in certain Dromeao benchmarks. v8::String::Encoding encoding; v8::String::ExternalStringResourceBase* resource = v8String->GetExternalStringResourceBase(&encoding); @@ -151,7 +122,7 @@ StringType v8StringToWebCoreString(v8::Handle<v8::String> v8String, ExternalMode return StringType(""); bool oneByte = v8String->ContainsOnlyOneByte(); - StringType result(oneByte ? StringTraits<StringType>::template fromV8String<true>(v8String, length) : StringTraits<StringType>::template fromV8String<false>(v8String, length)); + StringType result(oneByte ? StringTraits<StringType>::template fromV8String<V8StringOneByteTrait>(v8String, length) : StringTraits<StringType>::template fromV8String<V8StringTwoBytesTrait>(v8String, length)); if (external != Externalize || !v8String->CanMakeExternal()) return result; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8StringResource.h b/chromium/third_party/WebKit/Source/bindings/v8/V8StringResource.h index b8b57944a47..69f849b31e9 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8StringResource.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8StringResource.h @@ -39,8 +39,6 @@ class ExternalStringVisitor; // to manage the life-cycle of the underlying buffer of the external string. class WebCoreStringResourceBase { public: - static WebCoreStringResourceBase* toWebCoreStringResourceBase(v8::Handle<v8::String>); - explicit WebCoreStringResourceBase(const String& string) : m_plainString(string) { @@ -89,8 +87,6 @@ public: return m_atomicString; } - void visitStrings(ExternalStringVisitor*); - protected: // A shallow copy of the string. Keeps the string buffer alive until the V8 engine garbage collects it. String m_plainString; @@ -111,7 +107,7 @@ private: #endif }; -class WebCoreStringResource16 : public WebCoreStringResourceBase, public v8::String::ExternalStringResource { +class WebCoreStringResource16 FINAL : public WebCoreStringResourceBase, public v8::String::ExternalStringResource { public: explicit WebCoreStringResource16(const String& string) : WebCoreStringResourceBase(string) @@ -132,7 +128,7 @@ public: } }; -class WebCoreStringResource8 : public WebCoreStringResourceBase, public v8::String::ExternalAsciiStringResource { +class WebCoreStringResource8 FINAL : public WebCoreStringResourceBase, public v8::String::ExternalAsciiStringResource { public: explicit WebCoreStringResource8(const String& string) : WebCoreStringResourceBase(string) @@ -173,23 +169,37 @@ enum V8StringResourceMode { template <V8StringResourceMode Mode = DefaultMode> class V8StringResource { public: + V8StringResource() + : m_mode(Externalize) + { + } + V8StringResource(v8::Handle<v8::Value> object) : m_v8Object(object) , m_mode(Externalize) - , m_string() { } - bool prepare(); - operator String() const { return toString<String>(); } - operator AtomicString() const { return toString<AtomicString>(); } + void operator=(v8::Handle<v8::Value> object) + { + m_v8Object = object; + } -private: - bool prepareBase() + void operator=(const String& string) + { + setString(string); + } + + bool prepare() { if (m_v8Object.IsEmpty()) return true; + if (!isValid()) { + setString(String()); + return true; + } + if (LIKELY(m_v8Object->IsString())) return true; @@ -208,6 +218,11 @@ private: } return true; } + operator String() const { return toString<String>(); } + operator AtomicString() const { return toString<AtomicString>(); } + +private: + bool isValid() const; void setString(const String& string) { @@ -229,27 +244,19 @@ private: String m_string; }; -template<> inline bool V8StringResource<DefaultMode>::prepare() +template<> inline bool V8StringResource<DefaultMode>::isValid() const { - return prepareBase(); + return true; } -template<> inline bool V8StringResource<WithNullCheck>::prepare() +template<> inline bool V8StringResource<WithNullCheck>::isValid() const { - if (m_v8Object.IsEmpty() || m_v8Object->IsNull()) { - setString(String()); - return true; - } - return prepareBase(); + return !m_v8Object->IsNull(); } -template<> inline bool V8StringResource<WithUndefinedOrNullCheck>::prepare() +template<> inline bool V8StringResource<WithUndefinedOrNullCheck>::isValid() const { - if (m_v8Object.IsEmpty() || m_v8Object->IsNull() || m_v8Object->IsUndefined()) { - setString(String()); - return true; - } - return prepareBase(); + return !m_v8Object->IsNull() && !m_v8Object->IsUndefined(); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8ThrowException.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8ThrowException.cpp index 0f1ffcc69d3..ae2be273cff 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8ThrowException.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8ThrowException.cpp @@ -25,7 +25,7 @@ #include "config.h" #include "bindings/v8/V8ThrowException.h" -#include "V8DOMException.h" +#include "bindings/core/v8/V8DOMException.h" #include "bindings/v8/V8Binding.h" #include "core/dom/DOMException.h" #include "core/dom/ExceptionCode.h" @@ -55,7 +55,7 @@ v8::Handle<v8::Value> V8ThrowException::createDOMException(int ec, const String& if (ec == TypeError) return V8ThrowException::createTypeError(sanitizedMessage, isolate); - RefPtr<DOMException> domException = DOMException::create(ec, sanitizedMessage, unsanitizedMessage); + RefPtrWillBeRawPtr<DOMException> domException = DOMException::create(ec, sanitizedMessage, unsanitizedMessage); v8::Handle<v8::Value> exception = toV8(domException, creationContext, isolate); if (exception.IsEmpty()) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8ThrowException.h b/chromium/third_party/WebKit/Source/bindings/v8/V8ThrowException.h index 7a4d20f0609..26addf08538 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8ThrowException.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8ThrowException.h @@ -47,10 +47,6 @@ public: } static v8::Handle<v8::Value> createDOMException(int, const String& sanitizedMessage, const String& unsanitizedMessage, const v8::Handle<v8::Object>& creationContext, v8::Isolate*); - static v8::Handle<v8::Value> throwDOMException(int ec, const v8::Handle<v8::Object>& creationContext, v8::Isolate* isolate) - { - return throwDOMException(ec, String(), creationContext, isolate); - } static v8::Handle<v8::Value> throwDOMException(int ec, const String& message, const v8::Handle<v8::Object>& creationContext, v8::Isolate* isolate) { return throwDOMException(ec, message, String(), creationContext, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8Utilities.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8Utilities.cpp deleted file mode 100644 index 6a70b502c32..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8Utilities.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright (C) 2008, 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" -#include "bindings/v8/V8Utilities.h" - -#include "V8MessagePort.h" -#include "bindings/v8/ExceptionMessages.h" -#include "bindings/v8/ScriptState.h" -#include "bindings/v8/V8AbstractEventListener.h" -#include "bindings/v8/V8Binding.h" -#include "bindings/v8/custom/V8ArrayBufferCustom.h" -#include "core/dom/Document.h" -#include "core/dom/ExceptionCode.h" -#include "core/dom/ExecutionContext.h" -#include "core/dom/MessagePort.h" -#include "core/frame/Frame.h" -#include "core/workers/WorkerGlobalScope.h" -#include "wtf/ArrayBuffer.h" -#include "wtf/text/WTFString.h" -#include <v8.h> - - -namespace WebCore { - -// Use an array to hold dependents. It works like a ref-counted scheme. -// A value can be added more than once to the DOM object. -void createHiddenDependency(v8::Handle<v8::Object> object, v8::Local<v8::Value> value, int cacheIndex, v8::Isolate* isolate) -{ - v8::Local<v8::Value> cache = object->GetInternalField(cacheIndex); - if (cache->IsNull() || cache->IsUndefined()) { - cache = v8::Array::New(isolate); - object->SetInternalField(cacheIndex, cache); - } - - v8::Local<v8::Array> cacheArray = v8::Local<v8::Array>::Cast(cache); - cacheArray->Set(v8::Integer::New(cacheArray->Length(), isolate), value); -} - -bool extractTransferables(v8::Local<v8::Value> value, MessagePortArray& ports, ArrayBufferArray& arrayBuffers, bool& notASequence, v8::Isolate* isolate) -{ - if (isUndefinedOrNull(value)) { - ports.resize(0); - arrayBuffers.resize(0); - return true; - } - - uint32_t length = 0; - if (value->IsArray()) { - v8::Local<v8::Array> array = v8::Local<v8::Array>::Cast(value); - length = array->Length(); - } else if (toV8Sequence(value, length, isolate).IsEmpty()) { - notASequence = true; - return false; - } - - v8::Local<v8::Object> transferrables = v8::Local<v8::Object>::Cast(value); - - // Validate the passed array of transferrables. - for (unsigned int i = 0; i < length; ++i) { - v8::Local<v8::Value> transferrable = transferrables->Get(i); - // Validation of non-null objects, per HTML5 spec 10.3.3. - if (isUndefinedOrNull(transferrable)) { - setDOMException(DataCloneError, isolate); - return false; - } - // Validation of Objects implementing an interface, per WebIDL spec 4.1.15. - if (V8MessagePort::hasInstance(transferrable, isolate, worldType(isolate))) { - RefPtr<MessagePort> port = V8MessagePort::toNative(v8::Handle<v8::Object>::Cast(transferrable)); - // Check for duplicate MessagePorts. - if (ports.contains(port)) { - setDOMException(DataCloneError, isolate); - return false; - } - ports.append(port.release()); - } else if (V8ArrayBuffer::hasInstance(transferrable, isolate, worldType(isolate))) - arrayBuffers.append(V8ArrayBuffer::toNative(v8::Handle<v8::Object>::Cast(transferrable))); - else { - setDOMException(DataCloneError, isolate); - return false; - } - } - return true; -} - -bool getMessagePortArray(v8::Local<v8::Value> value, const String& propertyName, MessagePortArray& ports, v8::Isolate* isolate) -{ - if (isUndefinedOrNull(value)) { - ports.resize(0); - return true; - } - if (!value->IsArray()) { - throwTypeError(ExceptionMessages::notASequenceTypeProperty(propertyName), isolate); - return false; - } - bool success = false; - ports = toRefPtrNativeArray<MessagePort, V8MessagePort>(value, propertyName, isolate, &success); - return success; -} - -bool getMessagePortArray(v8::Local<v8::Value> value, int argumentIndex, MessagePortArray& ports, v8::Isolate* isolate) -{ - if (isUndefinedOrNull(value)) { - ports.resize(0); - return true; - } - if (!value->IsArray()) { - throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(argumentIndex), isolate); - return false; - } - bool success = false; - ports = toRefPtrNativeArray<MessagePort, V8MessagePort>(value, argumentIndex, isolate, &success); - return success; -} - -void removeHiddenDependency(v8::Handle<v8::Object> object, v8::Local<v8::Value> value, int cacheIndex, v8::Isolate* isolate) -{ - v8::Local<v8::Value> cache = object->GetInternalField(cacheIndex); - if (!cache->IsArray()) - return; - v8::Local<v8::Array> cacheArray = v8::Local<v8::Array>::Cast(cache); - for (int i = cacheArray->Length() - 1; i >= 0; --i) { - v8::Local<v8::Value> cached = cacheArray->Get(v8::Integer::New(i, isolate)); - if (cached->StrictEquals(value)) { - cacheArray->Delete(i); - return; - } - } -} - -void transferHiddenDependency(v8::Handle<v8::Object> object, EventListener* oldValue, v8::Local<v8::Value> newValue, int cacheIndex, v8::Isolate* isolate) -{ - if (oldValue) { - V8AbstractEventListener* oldListener = V8AbstractEventListener::cast(oldValue); - if (oldListener) { - v8::Local<v8::Object> oldListenerObject = oldListener->getExistingListenerObject(); - if (!oldListenerObject.IsEmpty()) - removeHiddenDependency(object, oldListenerObject, cacheIndex, isolate); - } - } - // Non-callable input is treated as null and ignored - if (newValue->IsFunction()) - createHiddenDependency(object, newValue, cacheIndex, isolate); -} - -ExecutionContext* getExecutionContext() -{ - if (WorkerScriptController* controller = WorkerScriptController::controllerForContext()) - return &controller->workerGlobalScope(); - - return currentDocument(); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8Utilities.h b/chromium/third_party/WebKit/Source/bindings/v8/V8Utilities.h deleted file mode 100644 index 4a0efd41b96..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8Utilities.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2006, 2007, 2008, 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 V8Utilities_h -#define V8Utilities_h - -#include "wtf/Forward.h" -#include <v8.h> - -namespace WTF { -class ArrayBuffer; -} - -namespace WebCore { - - class EventListener; - class MessagePort; - class ExecutionContext; - - // Use an array to hold dependents. It works like a ref-counted scheme. A value can be added more than once to the DOM object. - void createHiddenDependency(v8::Handle<v8::Object>, v8::Local<v8::Value>, int cacheIndex, v8::Isolate*); - void removeHiddenDependency(v8::Handle<v8::Object>, v8::Local<v8::Value>, int cacheIndex, v8::Isolate*); - - // Combo create/remove, for EventHandler setters in generated bindings: - void transferHiddenDependency(v8::Handle<v8::Object>, EventListener* oldValue, v8::Local<v8::Value> newValue, int cacheIndex, v8::Isolate*); - - ExecutionContext* getExecutionContext(); - - typedef WTF::Vector<RefPtr<MessagePort>, 1> MessagePortArray; - typedef WTF::Vector<RefPtr<ArrayBuffer>, 1> ArrayBufferArray; - - // 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 and generates exceptions as appropriate. If the supplied argument's type isn't - // a JS sequence, a type error is signalled by setting 'notASequence' to true -- the caller - // then being responsible for generating a TypeError having a message that fits the context. - // Returns true if the array was filled, or false if the passed value was not of an appropriate type. - bool extractTransferables(v8::Local<v8::Value>, MessagePortArray&, ArrayBufferArray&, bool& notASequence, v8::Isolate*); - - bool getMessagePortArray(v8::Local<v8::Value>, const String& propertyName, MessagePortArray&, v8::Isolate*); - bool getMessagePortArray(v8::Local<v8::Value>, int argumentIndex, MessagePortArray&, v8::Isolate*); - -} // namespace WebCore - -#endif // V8Utilities_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8ValueCache.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8ValueCache.cpp index 0681d0c059b..6d64a56169c 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8ValueCache.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8ValueCache.cpp @@ -27,11 +27,33 @@ #include "bindings/v8/V8ValueCache.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "wtf/text/StringHash.h" namespace WebCore { +StringCacheMapTraits::MapType* StringCacheMapTraits::MapFromWeakCallbackData( + const v8::WeakCallbackData<v8::String, WeakCallbackDataType>& data) +{ + return &(V8PerIsolateData::from(data.GetIsolate())->stringCache()->m_stringCache); +} + + +void StringCacheMapTraits::Dispose( + v8::Isolate* isolate, v8::UniquePersistent<v8::String> value, StringImpl* key) +{ + V8PerIsolateData::from(isolate)->stringCache()->InvalidateLastString(); + key->deref(); +} + + +StringCache::~StringCache() +{ + // The MapType::Dispose callback calls StringCache::InvalidateLastString, + // which will only work while the destructor has not yet finished. Thus, + // we need to clear the map before the destructor has completed. + m_stringCache.Clear(); +} + static v8::Local<v8::String> makeExternalString(const String& string, v8::Isolate* isolate) { if (string.is8Bit()) { @@ -54,11 +76,11 @@ v8::Handle<v8::String> StringCache::v8ExternalStringSlow(StringImpl* stringImpl, if (!stringImpl->length()) return v8::String::Empty(isolate); - UnsafePersistent<v8::String> cachedV8String = m_stringCache.get(stringImpl); - if (!cachedV8String.isEmpty()) { + StringCacheMapTraits::MapType::PersistentValueReference cachedV8String = m_stringCache.GetReference(stringImpl); + if (!cachedV8String.IsEmpty()) { m_lastStringImpl = stringImpl; m_lastV8String = cachedV8String; - return cachedV8String.newLocal(isolate); + return m_lastV8String.NewLocal(isolate); } return createStringAndInsertIntoCache(stringImpl, isolate); @@ -71,11 +93,11 @@ void StringCache::setReturnValueFromStringSlow(v8::ReturnValue<v8::Value> return return; } - UnsafePersistent<v8::String> cachedV8String = m_stringCache.get(stringImpl); - if (!cachedV8String.isEmpty()) { + StringCacheMapTraits::MapType::PersistentValueReference cachedV8String = m_stringCache.GetReference(stringImpl); + if (!cachedV8String.IsEmpty()) { m_lastStringImpl = stringImpl; m_lastV8String = cachedV8String; - returnValue.Set(*cachedV8String.persistent()); + m_lastV8String.SetReturnValue(returnValue); return; } @@ -84,34 +106,27 @@ void StringCache::setReturnValueFromStringSlow(v8::ReturnValue<v8::Value> return v8::Local<v8::String> StringCache::createStringAndInsertIntoCache(StringImpl* stringImpl, v8::Isolate* isolate) { - ASSERT(!m_stringCache.contains(stringImpl)); + ASSERT(!m_stringCache.Contains(stringImpl)); ASSERT(stringImpl->length()); v8::Local<v8::String> newString = makeExternalString(String(stringImpl), isolate); if (newString.IsEmpty()) return newString; - v8::Persistent<v8::String> wrapper(isolate, newString); + v8::UniquePersistent<v8::String> wrapper(isolate, newString); stringImpl->ref(); wrapper.MarkIndependent(); - wrapper.SetWeak(stringImpl, &setWeakCallback); - m_lastV8String = UnsafePersistent<v8::String>(wrapper); + m_stringCache.Set(stringImpl, wrapper.Pass(), &m_lastV8String); m_lastStringImpl = stringImpl; - m_stringCache.set(stringImpl, m_lastV8String); return newString; } -void StringCache::setWeakCallback(const v8::WeakCallbackData<v8::String, StringImpl>& data) +void StringCache::InvalidateLastString() { - StringCache* stringCache = V8PerIsolateData::from(data.GetIsolate())->stringCache(); - stringCache->m_lastStringImpl = 0; - stringCache->m_lastV8String.clear(); - ASSERT(stringCache->m_stringCache.contains(data.GetParameter())); - stringCache->m_stringCache.get(data.GetParameter()).dispose(); - stringCache->m_stringCache.remove(data.GetParameter()); - data.GetParameter()->deref(); + m_lastStringImpl = nullptr; + m_lastV8String.Reset(); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8ValueCache.h b/chromium/third_party/WebKit/Source/bindings/v8/V8ValueCache.h index 44ee8db6e80..8110cd38d27 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8ValueCache.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8ValueCache.h @@ -26,7 +26,7 @@ #ifndef V8ValueCache_h #define V8ValueCache_h -#include "bindings/v8/UnsafePersistent.h" +#include "bindings/v8/V8PersistentValueMap.h" #include <v8.h> #include "wtf/HashMap.h" #include "wtf/RefPtr.h" @@ -35,15 +35,39 @@ namespace WebCore { +class StringCacheMapTraits : public V8PersistentValueMapTraits<StringImpl*, v8::String, true> { +public: + // Weak traits: + typedef StringImpl WeakCallbackDataType; + typedef v8::PersistentValueMap<StringImpl*, v8::String, StringCacheMapTraits> MapType; + + static WeakCallbackDataType* WeakCallbackParameter( + MapType* map, StringImpl* key, v8::Local<v8::String>& value) { return key; } + static void DisposeCallbackData(WeakCallbackDataType* callbackData) { } + + static MapType* MapFromWeakCallbackData( + const v8::WeakCallbackData<v8::String, WeakCallbackDataType>&); + + static StringImpl* KeyFromWeakCallbackData( + const v8::WeakCallbackData<v8::String, WeakCallbackDataType>& data) + { + return data.GetParameter(); + } + + static void Dispose(v8::Isolate*, v8::UniquePersistent<v8::String> value, StringImpl* key); +}; + + class StringCache { public: - StringCache() { } + StringCache(v8::Isolate* isolate) : m_stringCache(isolate) { } + ~StringCache(); v8::Handle<v8::String> v8ExternalString(StringImpl* stringImpl, v8::Isolate* isolate) { ASSERT(stringImpl); if (m_lastStringImpl.get() == stringImpl) - return m_lastV8String.newLocal(isolate); + return m_lastV8String.NewLocal(isolate); return v8ExternalStringSlow(stringImpl, isolate); } @@ -51,20 +75,22 @@ public: { ASSERT(stringImpl); if (m_lastStringImpl.get() == stringImpl) - returnValue.Set(*m_lastV8String.persistent()); + m_lastV8String.SetReturnValue(returnValue); else setReturnValueFromStringSlow(returnValue, stringImpl); } -private: - static void setWeakCallback(const v8::WeakCallbackData<v8::String, StringImpl>&); + friend class StringCacheMapTraits; +private: v8::Handle<v8::String> v8ExternalStringSlow(StringImpl*, v8::Isolate*); void setReturnValueFromStringSlow(v8::ReturnValue<v8::Value>, StringImpl*); v8::Local<v8::String> createStringAndInsertIntoCache(StringImpl*, v8::Isolate*); + void InvalidateLastString(); + + StringCacheMapTraits::MapType m_stringCache; + StringCacheMapTraits::MapType::PersistentValueReference m_lastV8String; - HashMap<StringImpl*, UnsafePersistent<v8::String> > m_stringCache; - UnsafePersistent<v8::String> m_lastV8String; // Note: RefPtr is a must as we cache by StringImpl* equality, not identity // hence lastStringImpl might be not a key of the cache (in sense of identity) // and hence it's not refed on addition. diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8WindowShell.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8WindowShell.cpp index 3474312da86..8b9e8b2dbfb 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8WindowShell.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8WindowShell.cpp @@ -31,28 +31,30 @@ #include "config.h" #include "bindings/v8/V8WindowShell.h" -#include "RuntimeEnabledFeatures.h" -#include "V8Document.h" -#include "V8HTMLCollection.h" -#include "V8HTMLDocument.h" -#include "V8Window.h" +#include "bindings/core/v8/V8Document.h" +#include "bindings/core/v8/V8HTMLCollection.h" +#include "bindings/core/v8/V8HTMLDocument.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/ScriptController.h" #include "bindings/v8/V8Binding.h" +#include "bindings/v8/V8DOMActivityLogger.h" #include "bindings/v8/V8GCForContextDispose.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "bindings/v8/V8Initializer.h" #include "bindings/v8/V8ObjectConstructor.h" -#include "bindings/v8/V8PerContextData.h" +#include "core/dom/ScriptForbiddenScope.h" +#include "core/frame/LocalFrame.h" +#include "core/frame/csp/ContentSecurityPolicy.h" #include "core/html/HTMLCollection.h" #include "core/html/HTMLIFrameElement.h" #include "core/inspector/InspectorInstrumentation.h" #include "core/loader/DocumentLoader.h" #include "core/loader/FrameLoader.h" #include "core/loader/FrameLoaderClient.h" -#include "core/frame/ContentSecurityPolicy.h" -#include "core/frame/Frame.h" +#include "platform/RuntimeEnabledFeatures.h" #include "platform/TraceEvent.h" +#include "platform/heap/Handle.h" #include "platform/weborigin/SecurityOrigin.h" #include "public/platform/Platform.h" #include "wtf/Assertions.h" @@ -77,33 +79,31 @@ static void setInjectedScriptContextDebugId(v8::Handle<v8::Context> targetContex V8PerContextDebugData::setContextDebugData(targetContext, "injected", debugId); } -PassOwnPtr<V8WindowShell> V8WindowShell::create(Frame* frame, PassRefPtr<DOMWrapperWorld> world, v8::Isolate* isolate) +PassOwnPtr<V8WindowShell> V8WindowShell::create(LocalFrame* frame, DOMWrapperWorld& world, v8::Isolate* isolate) { - return adoptPtr(new V8WindowShell(frame, world, isolate)); + return adoptPtr(new V8WindowShell(frame, &world, isolate)); } -V8WindowShell::V8WindowShell(Frame* frame, PassRefPtr<DOMWrapperWorld> world, v8::Isolate* isolate) +V8WindowShell::V8WindowShell(LocalFrame* frame, PassRefPtr<DOMWrapperWorld> world, v8::Isolate* isolate) : m_frame(frame) - , m_world(world) , m_isolate(isolate) + , m_world(world) { } void V8WindowShell::disposeContext(GlobalDetachmentBehavior behavior) { - m_perContextData.clear(); - - if (!m_contextHolder) + if (!isContextInitialized()) return; v8::HandleScope handleScope(m_isolate); - v8::Handle<v8::Context> context = m_contextHolder->context(); + v8::Handle<v8::Context> context = m_scriptState->context(); m_frame->loader().client()->willReleaseScriptContext(context, m_world->worldId()); if (behavior == DetachGlobal) context->DetachGlobal(); - m_contextHolder.clear(); + m_scriptState->disposePerContextData(); // It's likely that disposing the context has created a lot of // garbage. Notify V8 about this so it'll have a chance of cleaning @@ -111,12 +111,9 @@ void V8WindowShell::disposeContext(GlobalDetachmentBehavior behavior) V8GCForContextDispose::instanceTemplate().notifyContextDisposed(m_frame->isMainFrame()); } -void V8WindowShell::clearForClose(bool destroyGlobal) +void V8WindowShell::clearForClose() { - if (destroyGlobal) - m_global.clear(); - - if (!m_contextHolder) + if (!isContextInitialized()) return; m_document.clear(); @@ -125,21 +122,19 @@ void V8WindowShell::clearForClose(bool destroyGlobal) void V8WindowShell::clearForNavigation() { - if (!m_contextHolder) + if (!isContextInitialized()) return; - v8::HandleScope handleScope(m_isolate); - m_document.clear(); + ScriptState::Scope scope(m_scriptState.get()); - v8::Handle<v8::Context> context = m_contextHolder->context(); - v8::Context::Scope contextScope(context); + m_document.clear(); // Clear the document wrapper cache before turning on access checks on - // the old DOMWindow wrapper. This way, access to the document wrapper - // will be protected by the security checks on the DOMWindow wrapper. + // the old LocalDOMWindow wrapper. This way, access to the document wrapper + // will be protected by the security checks on the LocalDOMWindow wrapper. clearDocumentProperty(); - v8::Handle<v8::Object> windowWrapper = m_global.newLocal(m_isolate)->FindInstanceInPrototypeChain(V8Window::domTemplate(m_isolate, worldTypeInMainThread(m_isolate))); + v8::Handle<v8::Object> windowWrapper = V8Window::findInstanceInPrototypeChain(m_global.newLocal(m_isolate), m_isolate); ASSERT(!windowWrapper.IsEmpty()); windowWrapper->TurnOnAccessCheck(); disposeContext(DetachGlobal); @@ -147,16 +142,16 @@ void V8WindowShell::clearForNavigation() // Create a new environment and setup the global object. // -// The global object corresponds to a DOMWindow instance. However, to -// allow properties of the JS DOMWindow instance to be shadowed, we -// use a shadow object as the global object and use the JS DOMWindow -// instance as the prototype for that shadow object. The JS DOMWindow +// The global object corresponds to a LocalDOMWindow instance. However, to +// allow properties of the JS LocalDOMWindow instance to be shadowed, we +// use a shadow object as the global object and use the JS LocalDOMWindow +// instance as the prototype for that shadow object. The JS LocalDOMWindow // instance is undetectable from JavaScript code because the __proto__ // accessors skip that object. // -// The shadow object and the DOMWindow instance are seen as one object +// The shadow object and the LocalDOMWindow instance are seen as one object // from JavaScript. The JavaScript object that corresponds to a -// DOMWindow instance is the shadow object. When mapping a DOMWindow +// LocalDOMWindow instance is the shadow object. When mapping a LocalDOMWindow // instance to a V8 object, we return the shadow object. // // To implement split-window, see @@ -169,7 +164,7 @@ void V8WindowShell::clearForNavigation() // global object of the context. A variable declared in the global // scope is a property of the inner window. // -// The outer window sticks to a Frame, it is exposed to JavaScript +// The outer window sticks to a LocalFrame, it is exposed to JavaScript // via window.window, window.self, window.parent, etc. The outer window // has a security token which is the domain. The outer window cannot // have its own properties. window.foo = 'x' is delegated to the @@ -182,27 +177,31 @@ void V8WindowShell::clearForNavigation() // it won't be able to reach the outer window via its global object. bool V8WindowShell::initializeIfNeeded() { - if (m_contextHolder) + if (isContextInitialized()) return true; - TRACE_EVENT0("v8", "V8WindowShell::initializeIfNeeded"); - - v8::HandleScope handleScope(m_isolate); - - createContext(); - if (!m_contextHolder) - return false; + DOMWrapperWorld::setWorldOfInitializingWindow(m_world.get()); + bool result = initialize(); + DOMWrapperWorld::setWorldOfInitializingWindow(0); + return result; +} - v8::Handle<v8::Context> context = m_contextHolder->context(); +bool V8WindowShell::initialize() +{ + TRACE_EVENT0("v8", "V8WindowShell::initialize"); + TRACE_EVENT_SCOPED_SAMPLING_STATE("Blink", "InitializeWindow"); - V8PerContextDataHolder::install(context); + ScriptForbiddenScope::AllowUserAgentScript allowScript; - m_world->setIsolatedWorldField(context); + v8::HandleScope handleScope(m_isolate); - bool isMainWorld = m_world->isMainWorld(); + createContext(); - v8::Context::Scope contextScope(context); + if (!isContextInitialized()) + return false; + ScriptState::Scope scope(m_scriptState.get()); + v8::Handle<v8::Context> context = m_scriptState->context(); if (m_global.isEmpty()) { m_global.set(m_isolate, context->Global()); if (m_global.isEmpty()) { @@ -211,44 +210,32 @@ bool V8WindowShell::initializeIfNeeded() } } - if (!isMainWorld) { - V8WindowShell* mainWindow = m_frame->script().existingWindowShell(mainThreadNormalWorld()); + if (!m_world->isMainWorld()) { + V8WindowShell* mainWindow = m_frame->script().existingWindowShell(DOMWrapperWorld::mainWorld()); if (mainWindow && !mainWindow->context().IsEmpty()) setInjectedScriptContextDebugId(context, m_frame->script().contextDebugId(mainWindow->context())); } - m_perContextData = V8PerContextData::create(context); - if (!m_perContextData->init()) { - disposeContext(DoNotDetachGlobal); - return false; - } - m_perContextData->setActivityLogger(DOMWrapperWorld::activityLogger(m_world->worldId())); if (!installDOMWindow()) { disposeContext(DoNotDetachGlobal); return false; } - if (isMainWorld) { + if (m_world->isMainWorld()) { + // ActivityLogger for main world is updated within updateDocument(). updateDocument(); - setSecurityToken(); if (m_frame->document()) { + setSecurityToken(m_frame->document()->securityOrigin()); ContentSecurityPolicy* csp = m_frame->document()->contentSecurityPolicy(); context->AllowCodeGenerationFromStrings(csp->allowEval(0, ContentSecurityPolicy::SuppressReport)); context->SetErrorMessageForCodeGenerationFromStrings(v8String(m_isolate, csp->evalDisabledErrorMessage())); } } else { - // Using the default security token means that the canAccess is always - // called, which is slow. - // FIXME: Use tokens where possible. This will mean keeping track of all - // created contexts so that they can all be updated when the - // document domain - // changes. - context->UseDefaultSecurityToken(); - + updateActivityLogger(); SecurityOrigin* origin = m_world->isolatedWorldSecurityOrigin(); + setSecurityToken(origin); if (origin && InspectorInstrumentation::hasFrontends()) { - ScriptState* scriptState = ScriptState::forContext(v8::Local<v8::Context>::New(m_isolate, context)); - InspectorInstrumentation::didCreateIsolatedContext(m_frame, scriptState, origin); + InspectorInstrumentation::didCreateIsolatedContext(m_frame, m_scriptState.get(), origin); } } m_frame->loader().client()->didCreateScriptContext(context, m_world->extensionGroup(), m_world->worldId()); @@ -257,14 +244,14 @@ bool V8WindowShell::initializeIfNeeded() void V8WindowShell::createContext() { - // The activeDocumentLoader pointer could be 0 during frame shutdown. + // The documentLoader pointer could be 0 during frame shutdown. // FIXME: Can we remove this check? - if (!m_frame->loader().activeDocumentLoader()) + if (!m_frame->loader().documentLoader()) return; // Create a new environment using an empty template for the shadow // object. Reuse the global object if one has been created earlier. - v8::Handle<v8::ObjectTemplate> globalTemplate = V8Window::GetShadowObjectTemplate(m_isolate, m_world->isMainWorld() ? MainWorld : IsolatedWorld); + v8::Handle<v8::ObjectTemplate> globalTemplate = V8Window::getShadowObjectTemplate(m_isolate); if (globalTemplate.IsEmpty()) return; @@ -284,12 +271,10 @@ void V8WindowShell::createContext() } v8::ExtensionConfiguration extensionConfiguration(index, extensionNames.get()); - v8::HandleScope handleScope(m_isolate); v8::Handle<v8::Context> context = v8::Context::New(m_isolate, &extensionConfiguration, globalTemplate, m_global.newLocal(m_isolate)); - if (!context.IsEmpty()) { - m_contextHolder = adoptPtr(new gin::ContextHolder(m_isolate)); - m_contextHolder->SetContext(context); - } + if (context.IsEmpty()) + return; + m_scriptState = ScriptState::create(context, m_world); double contextCreationDurationInMilliseconds = (currentTime() - contextCreationStartInSeconds) * 1000; const char* histogramName = "WebCore.V8WindowShell.createContext.MainWorld"; @@ -298,36 +283,46 @@ void V8WindowShell::createContext() blink::Platform::current()->histogramCustomCounts(histogramName, contextCreationDurationInMilliseconds, 0, 10000, 50); } +static v8::Handle<v8::Object> toInnerGlobalObject(v8::Handle<v8::Context> context) +{ + return v8::Handle<v8::Object>::Cast(context->Global()->GetPrototype()); +} + bool V8WindowShell::installDOMWindow() { - DOMWrapperWorld::setInitializingWindow(true); - DOMWindow* window = m_frame->domWindow(); - v8::Local<v8::Object> windowWrapper = V8ObjectConstructor::newInstance(V8PerContextData::from(m_contextHolder->context())->constructorForType(&V8Window::wrapperTypeInfo)); + LocalDOMWindow* window = m_frame->domWindow(); + v8::Local<v8::Object> windowWrapper = V8ObjectConstructor::newInstance(m_isolate, m_scriptState->perContextData()->constructorForType(&V8Window::wrapperTypeInfo)); if (windowWrapper.IsEmpty()) return false; V8Window::installPerContextEnabledProperties(windowWrapper, window, m_isolate); - V8DOMWrapper::setNativeInfo(v8::Handle<v8::Object>::Cast(windowWrapper->GetPrototype()), &V8Window::wrapperTypeInfo, window); + V8DOMWrapper::setNativeInfoForHiddenWrapper(v8::Handle<v8::Object>::Cast(windowWrapper->GetPrototype()), &V8Window::wrapperTypeInfo, window); // Install the windowWrapper as the prototype of the innerGlobalObject. // The full structure of the global object is as follows: // // outerGlobalObject (Empty object, remains after navigation) // -- has prototype --> innerGlobalObject (Holds global variables, changes during navigation) - // -- has prototype --> DOMWindow instance + // -- has prototype --> LocalDOMWindow instance // -- has prototype --> Window.prototype // -- has prototype --> Object.prototype // // Note: Much of this prototype structure is hidden from web content. The - // outer, inner, and DOMWindow instance all appear to be the same + // outer, inner, and LocalDOMWindow instance all appear to be the same // JavaScript object. // - v8::Handle<v8::Object> innerGlobalObject = toInnerGlobalObject(m_contextHolder->context()); - V8DOMWrapper::setNativeInfo(innerGlobalObject, &V8Window::wrapperTypeInfo, window); + // Note: With Oilpan, the LocalDOMWindow object is garbage collected. + // Persistent references to this inner global object view of the LocalDOMWindow + // aren't kept, as that would prevent the global object from ever being released. + // It is safe not to do so, as the wrapper for the LocalDOMWindow being installed here + // already keeps a persistent reference, and it along with the inner global object + // views of the LocalDOMWindow will die together once that wrapper clears the persistent + // reference. + v8::Handle<v8::Object> innerGlobalObject = toInnerGlobalObject(m_scriptState->context()); + V8DOMWrapper::setNativeInfoForHiddenWrapper(innerGlobalObject, &V8Window::wrapperTypeInfo, window); innerGlobalObject->SetPrototype(windowWrapper); - V8DOMWrapper::associateObjectWithWrapper<V8Window>(PassRefPtr<DOMWindow>(window), &V8Window::wrapperTypeInfo, windowWrapper, m_isolate, WrapperConfiguration::Dependent); - DOMWrapperWorld::setInitializingWindow(false); + V8DOMWrapper::associateObjectWithWrapper<V8Window>(PassRefPtrWillBeRawPtr<LocalDOMWindow>(window), &V8Window::wrapperTypeInfo, windowWrapper, m_isolate, WrapperConfiguration::Dependent); return true; } @@ -342,18 +337,16 @@ void V8WindowShell::updateDocumentProperty() if (!m_world->isMainWorld()) return; - v8::HandleScope handleScope(m_isolate); - v8::Handle<v8::Context> context = m_contextHolder->context(); - v8::Context::Scope contextScope(context); - - v8::Handle<v8::Value> documentWrapper = toV8(m_frame->document(), v8::Handle<v8::Object>(), context->GetIsolate()); + ScriptState::Scope scope(m_scriptState.get()); + v8::Handle<v8::Context> context = m_scriptState->context(); + v8::Handle<v8::Value> documentWrapper = toV8(m_frame->document(), context->Global(), context->GetIsolate()); ASSERT(documentWrapper == m_document.newLocal(m_isolate) || m_document.isEmpty()); if (m_document.isEmpty()) updateDocumentWrapper(v8::Handle<v8::Object>::Cast(documentWrapper)); checkDocumentWrapper(m_document.newLocal(m_isolate), m_frame->document()); // If instantiation of the document wrapper fails, clear the cache - // and let the DOMWindow accessor handle access to the document. + // and let the LocalDOMWindow accessor handle access to the document. if (documentWrapper.IsEmpty()) { clearDocumentProperty(); return; @@ -362,38 +355,40 @@ void V8WindowShell::updateDocumentProperty() context->Global()->ForceSet(v8AtomicString(m_isolate, "document"), documentWrapper, static_cast<v8::PropertyAttribute>(v8::ReadOnly | v8::DontDelete)); // We also stash a reference to the document on the inner global object so that - // DOMWindow objects we obtain from JavaScript references are guaranteed to have + // LocalDOMWindow objects we obtain from JavaScript references are guaranteed to have // live Document objects. - toInnerGlobalObject(context)->SetHiddenValue(V8HiddenPropertyName::document(m_isolate), documentWrapper); + V8HiddenValue::setHiddenValue(m_isolate, toInnerGlobalObject(context), V8HiddenValue::document(m_isolate), documentWrapper); } void V8WindowShell::clearDocumentProperty() { - ASSERT(m_contextHolder); + ASSERT(isContextInitialized()); if (!m_world->isMainWorld()) return; v8::HandleScope handleScope(m_isolate); - m_contextHolder->context()->Global()->ForceDelete(v8AtomicString(m_isolate, "document")); + m_scriptState->context()->Global()->ForceDelete(v8AtomicString(m_isolate, "document")); } -void V8WindowShell::setSecurityToken() +void V8WindowShell::updateActivityLogger() { - ASSERT(m_world->isMainWorld()); - - Document* document = m_frame->document(); + m_scriptState->perContextData()->setActivityLogger(V8DOMActivityLogger::activityLogger( + m_world->worldId(), m_frame->document() ? m_frame->document()->baseURI() : KURL())); +} - // Ask the document's SecurityOrigin to generate a security token. +void V8WindowShell::setSecurityToken(SecurityOrigin* origin) +{ // If two tokens are equal, then the SecurityOrigins canAccess each other. // If two tokens are not equal, then we have to call canAccess. // Note: we can't use the HTTPOrigin if it was set from the DOM. - SecurityOrigin* origin = document->securityOrigin(); String token; // We stick with an empty token if document.domain was modified or if we // are in the initial empty document, so that we can do a full canAccess // check in those cases. - if (!origin->domainWasSetInDOM() - && !m_frame->loader().stateMachine()->isDisplayingInitialEmptyDocument()) - token = document->securityOrigin()->toString(); + bool delaySet = m_world->isMainWorld() + && (origin->domainWasSetInDOM() + || m_frame->loader().stateMachine()->isDisplayingInitialEmptyDocument()); + if (origin && !delaySet) + token = origin->toString(); // An empty or "null" token means we always have to call // canAccess. The toString method on securityOrigins returns the @@ -402,7 +397,7 @@ void V8WindowShell::setSecurityToken() // case, we use the global object as the security token to avoid // calling canAccess when a script accesses its own objects. v8::HandleScope handleScope(m_isolate); - v8::Handle<v8::Context> context = m_contextHolder->context(); + v8::Handle<v8::Context> context = m_scriptState->context(); if (token.isEmpty() || token == "null") { context->UseDefaultSecurityToken(); return; @@ -417,12 +412,13 @@ void V8WindowShell::setSecurityToken() void V8WindowShell::updateDocument() { ASSERT(m_world->isMainWorld()); - if (m_global.isEmpty()) + if (!isGlobalInitialized()) return; - if (!m_contextHolder) + if (!isContextInitialized()) return; + updateActivityLogger(); updateDocumentProperty(); - updateSecurityOrigin(); + updateSecurityOrigin(m_frame->document()->securityOrigin()); } static v8::Handle<v8::Value> getNamedProperty(HTMLDocument* htmlDocument, const AtomicString& key, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) @@ -430,16 +426,17 @@ static v8::Handle<v8::Value> getNamedProperty(HTMLDocument* htmlDocument, const if (!htmlDocument->hasNamedItem(key) && !htmlDocument->hasExtraNamedItem(key)) return v8Undefined(); - RefPtr<HTMLCollection> items = htmlDocument->documentNamedItems(key); + RefPtrWillBeRawPtr<HTMLCollection> items = htmlDocument->documentNamedItems(key); if (items->isEmpty()) return v8Undefined(); if (items->hasExactlyOneItem()) { - Node* node = items->item(0); + Element* element = items->item(0); + ASSERT(element); Frame* frame = 0; - if (node->hasTagName(HTMLNames::iframeTag) && (frame = toHTMLIFrameElement(node)->contentFrame())) + if (isHTMLIFrameElement(*element) && (frame = toHTMLIFrameElement(*element).contentFrame())) return toV8(frame->domWindow(), creationContext, isolate); - return toV8(node, creationContext, isolate); + return toV8(element, creationContext, isolate); } return toV8(items.release(), creationContext, isolate); } @@ -466,12 +463,10 @@ void V8WindowShell::namedItemAdded(HTMLDocument* document, const AtomicString& n { ASSERT(m_world->isMainWorld()); - if (!m_contextHolder) + if (!isContextInitialized()) return; - v8::HandleScope handleScope(m_isolate); - v8::Context::Scope contextScope(m_contextHolder->context()); - + ScriptState::Scope scope(m_scriptState.get()); ASSERT(!m_document.isEmpty()); v8::Handle<v8::Object> documentHandle = m_document.newLocal(m_isolate); checkDocumentWrapper(documentHandle, document); @@ -482,28 +477,25 @@ void V8WindowShell::namedItemRemoved(HTMLDocument* document, const AtomicString& { ASSERT(m_world->isMainWorld()); - if (!m_contextHolder) + if (!isContextInitialized()) return; if (document->hasNamedItem(name) || document->hasExtraNamedItem(name)) return; - v8::HandleScope handleScope(m_isolate); - v8::Context::Scope contextScope(m_contextHolder->context()); - + ScriptState::Scope scope(m_scriptState.get()); ASSERT(!m_document.isEmpty()); v8::Handle<v8::Object> documentHandle = m_document.newLocal(m_isolate); checkDocumentWrapper(documentHandle, document); documentHandle->Delete(v8String(m_isolate, name)); } -void V8WindowShell::updateSecurityOrigin() +void V8WindowShell::updateSecurityOrigin(SecurityOrigin* origin) { ASSERT(m_world->isMainWorld()); - if (!m_contextHolder) + if (!isContextInitialized()) return; - v8::HandleScope handleScope(m_isolate); - setSecurityToken(); + setSecurityToken(origin); } } // WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8WindowShell.h b/chromium/third_party/WebKit/Source/bindings/v8/V8WindowShell.h index b1c65ab9f42..548caa388fe 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8WindowShell.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8WindowShell.h @@ -33,9 +33,8 @@ #include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/ScopedPersistent.h" -#include "bindings/v8/V8PerContextData.h" +#include "bindings/v8/ScriptState.h" #include "bindings/v8/WrapperTypeInfo.h" -#include "gin/public/context_holder.h" #include "platform/weborigin/SecurityOrigin.h" #include "wtf/Forward.h" #include "wtf/HashMap.h" @@ -47,17 +46,19 @@ namespace WebCore { -class DOMWindow; -class Frame; +class LocalDOMWindow; +class LocalFrame; class HTMLDocument; +class SecurityOrigin; -// V8WindowShell represents all the per-global object state for a Frame that +// V8WindowShell represents all the per-global object state for a LocalFrame that // persist between navigations. class V8WindowShell { public: - static PassOwnPtr<V8WindowShell> create(Frame*, PassRefPtr<DOMWrapperWorld>, v8::Isolate*); + static PassOwnPtr<V8WindowShell> create(LocalFrame*, DOMWrapperWorld&, v8::Isolate*); - v8::Local<v8::Context> context() const { return m_contextHolder ? m_contextHolder->context() : v8::Local<v8::Context>(); } + v8::Local<v8::Context> context() const { return m_scriptState ? m_scriptState->context() : v8::Local<v8::Context>(); } + ScriptState* scriptState() const { return m_scriptState.get(); } // Update document object of the frame. void updateDocument(); @@ -67,21 +68,22 @@ public: // Update the security origin of a document // (e.g., after setting docoument.domain). - void updateSecurityOrigin(); + void updateSecurityOrigin(SecurityOrigin*); - bool isContextInitialized() { return m_contextHolder; } + bool isContextInitialized() { return m_scriptState && !!m_scriptState->perContextData(); } bool isGlobalInitialized() { return !m_global.isEmpty(); } bool initializeIfNeeded(); void updateDocumentWrapper(v8::Handle<v8::Object> wrapper); void clearForNavigation(); - void clearForClose(bool destroyGlobal); + void clearForClose(); - DOMWrapperWorld* world() { return m_world.get(); } + DOMWrapperWorld& world() { return *m_world; } private: - V8WindowShell(Frame*, PassRefPtr<DOMWrapperWorld>, v8::Isolate*); + V8WindowShell(LocalFrame*, PassRefPtr<DOMWrapperWorld>, v8::Isolate*); + bool initialize(); enum GlobalDetachmentBehavior { DoNotDetachGlobal, @@ -89,7 +91,7 @@ private: }; void disposeContext(GlobalDetachmentBehavior); - void setSecurityToken(); + void setSecurityToken(SecurityOrigin*); // The JavaScript wrapper for the document object is cached on the global // object for fast access. UpdateDocumentProperty sets the wrapper @@ -98,18 +100,18 @@ private: void updateDocumentProperty(); void clearDocumentProperty(); + // Updates Activity Logger for the current context. + void updateActivityLogger(); + void createContext(); bool installDOMWindow(); static V8WindowShell* enteredIsolatedWorldContext(); - Frame* m_frame; - RefPtr<DOMWrapperWorld> m_world; + LocalFrame* m_frame; v8::Isolate* m_isolate; - - OwnPtr<V8PerContextData> m_perContextData; - - OwnPtr<gin::ContextHolder> m_contextHolder; + RefPtr<ScriptState> m_scriptState; + RefPtr<DOMWrapperWorld> m_world; ScopedPersistent<v8::Object> m_global; ScopedPersistent<v8::Object> m_document; }; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8WorkerGlobalScopeEventListener.cpp b/chromium/third_party/WebKit/Source/bindings/v8/V8WorkerGlobalScopeEventListener.cpp index da79d52d1c8..c66b8a24dc9 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8WorkerGlobalScopeEventListener.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8WorkerGlobalScopeEventListener.cpp @@ -32,94 +32,84 @@ #include "bindings/v8/V8WorkerGlobalScopeEventListener.h" -#include "V8Event.h" -#include "V8EventTarget.h" +#include "bindings/core/v8/V8Event.h" +#include "bindings/core/v8/V8EventTarget.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8DOMWrapper.h" #include "bindings/v8/V8GCController.h" #include "bindings/v8/V8ScriptRunner.h" #include "bindings/v8/WorkerScriptController.h" #include "core/inspector/InspectorInstrumentation.h" +#include "core/inspector/InspectorTraceEvents.h" #include "core/workers/WorkerGlobalScope.h" namespace WebCore { -V8WorkerGlobalScopeEventListener::V8WorkerGlobalScopeEventListener(v8::Local<v8::Object> listener, bool isInline, v8::Isolate* isolate) - : V8EventListener(listener, isInline, isolate) +V8WorkerGlobalScopeEventListener::V8WorkerGlobalScopeEventListener(v8::Local<v8::Object> listener, bool isInline, ScriptState* scriptState) + : V8EventListener(listener, isInline, scriptState) { } -void V8WorkerGlobalScopeEventListener::handleEvent(ExecutionContext* context, Event* event) +void V8WorkerGlobalScopeEventListener::handleEvent(ExecutionContext*, Event* event) { - if (!context) - return; - // The callback function on XMLHttpRequest can clear the event listener and destroys 'this' object. Keep a local reference to it. // See issue 889829. RefPtr<V8AbstractEventListener> protect(this); - v8::Isolate* isolate = toIsolate(context); - v8::HandleScope handleScope(isolate); - - WorkerScriptController* script = toWorkerGlobalScope(context)->script(); + WorkerScriptController* script = toWorkerGlobalScope(scriptState()->executionContext())->script(); if (!script) return; - v8::Handle<v8::Context> v8Context = script->context(); - if (v8Context.IsEmpty()) + if (scriptState()->contextIsEmpty()) return; - - // Enter the V8 context in which to perform the event handling. - v8::Context::Scope scope(v8Context); + ScriptState::Scope scope(scriptState()); // Get the V8 wrapper for the event object. - v8::Handle<v8::Value> jsEvent = toV8(event, v8::Handle<v8::Object>(), isolate); + v8::Handle<v8::Value> jsEvent = toV8(event, scriptState()->context()->Global(), isolate()); - invokeEventHandler(context, event, v8::Local<v8::Value>::New(isolate, jsEvent)); + invokeEventHandler(event, v8::Local<v8::Value>::New(isolate(), jsEvent)); } -v8::Local<v8::Value> V8WorkerGlobalScopeEventListener::callListenerFunction(ExecutionContext* context, v8::Handle<v8::Value> jsEvent, Event* event) +v8::Local<v8::Value> V8WorkerGlobalScopeEventListener::callListenerFunction(v8::Handle<v8::Value> jsEvent, Event* event) { - v8::Local<v8::Function> handlerFunction = getListenerFunction(context); - v8::Local<v8::Object> receiver = getReceiverObject(context, event); + v8::Local<v8::Function> handlerFunction = getListenerFunction(scriptState()->executionContext()); + v8::Local<v8::Object> receiver = getReceiverObject(event); if (handlerFunction.IsEmpty() || receiver.IsEmpty()) return v8::Local<v8::Value>(); + TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "FunctionCall", "data", devToolsTraceEventData(scriptState()->executionContext(), handlerFunction, isolate())); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack()); + // FIXME(361045): remove InspectorInstrumentation calls once DevTools Timeline migrates to tracing. InspectorInstrumentationCookie cookie; - if (InspectorInstrumentation::timelineAgentEnabled(context)) { - String resourceName("undefined"); + if (InspectorInstrumentation::timelineAgentEnabled(scriptState()->executionContext())) { + int scriptId = 0; + String resourceName; int lineNumber = 1; - v8::ScriptOrigin origin = handlerFunction->GetScriptOrigin(); - if (!origin.ResourceName().IsEmpty()) { - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringResourceName, origin.ResourceName(), v8::Local<v8::Value>()); - resourceName = stringResourceName; - lineNumber = handlerFunction->GetScriptLineNumber() + 1; - } - cookie = InspectorInstrumentation::willCallFunction(context, resourceName, lineNumber); + GetDevToolsFunctionInfo(handlerFunction, isolate(), scriptId, resourceName, lineNumber); + cookie = InspectorInstrumentation::willCallFunction(scriptState()->executionContext(), scriptId, resourceName, lineNumber); } - v8::Isolate* isolate = toIsolate(context); v8::Handle<v8::Value> parameters[1] = { jsEvent }; - v8::Local<v8::Value> result = V8ScriptRunner::callFunction(handlerFunction, context, receiver, WTF_ARRAY_LENGTH(parameters), parameters, isolate); + v8::Local<v8::Value> result = V8ScriptRunner::callFunction(handlerFunction, scriptState()->executionContext(), receiver, WTF_ARRAY_LENGTH(parameters), parameters, isolate()); InspectorInstrumentation::didCallFunction(cookie); + TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data()); return result; } -v8::Local<v8::Object> V8WorkerGlobalScopeEventListener::getReceiverObject(ExecutionContext* context, Event* event) +v8::Local<v8::Object> V8WorkerGlobalScopeEventListener::getReceiverObject(Event* event) { - v8::Local<v8::Object> listener = getListenerObject(context); + v8::Local<v8::Object> listener = getListenerObject(scriptState()->executionContext()); if (!listener.IsEmpty() && !listener->IsFunction()) return listener; EventTarget* target = event->currentTarget(); - v8::Isolate* isolate = toIsolate(context); - v8::Handle<v8::Value> value = toV8(target, v8::Handle<v8::Object>(), isolate); + v8::Handle<v8::Value> value = toV8(target, scriptState()->context()->Global(), isolate()); if (value.IsEmpty()) return v8::Local<v8::Object>(); - return v8::Local<v8::Object>::New(isolate, v8::Handle<v8::Object>::Cast(value)); + return v8::Local<v8::Object>::New(isolate(), v8::Handle<v8::Object>::Cast(value)); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/V8WorkerGlobalScopeEventListener.h b/chromium/third_party/WebKit/Source/bindings/v8/V8WorkerGlobalScopeEventListener.h index 1acf7c44d7d..355a424afbc 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/V8WorkerGlobalScopeEventListener.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/V8WorkerGlobalScopeEventListener.h @@ -39,21 +39,21 @@ namespace WebCore { class Event; - class V8WorkerGlobalScopeEventListener : public V8EventListener { + class V8WorkerGlobalScopeEventListener FINAL : public V8EventListener { public: - static PassRefPtr<V8WorkerGlobalScopeEventListener> create(v8::Local<v8::Object> listener, bool isInline, v8::Isolate* isolate) + static PassRefPtr<V8WorkerGlobalScopeEventListener> create(v8::Local<v8::Object> listener, bool isInline, ScriptState* scriptState) { - return adoptRef(new V8WorkerGlobalScopeEventListener(listener, isInline, isolate)); + return adoptRef(new V8WorkerGlobalScopeEventListener(listener, isInline, scriptState)); } - virtual void handleEvent(ExecutionContext*, Event*); + virtual void handleEvent(ExecutionContext*, Event*) OVERRIDE; protected: - V8WorkerGlobalScopeEventListener(v8::Local<v8::Object> listener, bool isInline, v8::Isolate*); + V8WorkerGlobalScopeEventListener(v8::Local<v8::Object> listener, bool isInline, ScriptState*); private: - virtual v8::Local<v8::Value> callListenerFunction(ExecutionContext*, v8::Handle<v8::Value> jsEvent, Event*); - v8::Local<v8::Object> getReceiverObject(ExecutionContext*, Event*); + virtual v8::Local<v8::Value> callListenerFunction(v8::Handle<v8::Value> jsEvent, Event*) OVERRIDE; + v8::Local<v8::Object> getReceiverObject(Event*); }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptController.cpp b/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptController.cpp index 27170fecf89..3381f46b221 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptController.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptController.cpp @@ -32,10 +32,10 @@ #include "bindings/v8/WorkerScriptController.h" -#include "V8DedicatedWorkerGlobalScope.h" -#include "V8ServiceWorkerGlobalScope.h" -#include "V8SharedWorkerGlobalScope.h" -#include "V8WorkerGlobalScope.h" +#include "bindings/core/v8/V8DedicatedWorkerGlobalScope.h" +#include "bindings/core/v8/V8SharedWorkerGlobalScope.h" +#include "bindings/core/v8/V8WorkerGlobalScope.h" +#include "bindings/modules/v8/V8ServiceWorkerGlobalScope.h" #include "bindings/v8/ScriptSourceCode.h" #include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8ErrorHandler.h" @@ -50,6 +50,7 @@ #include "core/workers/WorkerGlobalScope.h" #include "core/workers/WorkerObjectProxy.h" #include "core/workers/WorkerThread.h" +#include "platform/heap/ThreadState.h" #include <v8.h> #include "public/platform/Platform.h" @@ -58,67 +59,77 @@ namespace WebCore { WorkerScriptController::WorkerScriptController(WorkerGlobalScope& workerGlobalScope) - : m_workerGlobalScope(workerGlobalScope) + : m_isolate(v8::Isolate::New()) + , m_workerGlobalScope(workerGlobalScope) , m_executionForbidden(false) , m_executionScheduledToTerminate(false) { - v8::Isolate* isolate = v8::Isolate::New(); - isolate->Enter(); - V8Initializer::initializeWorker(isolate); + m_isolate->Enter(); + V8Initializer::initializeWorker(m_isolate); v8::V8::Initialize(); - m_isolateHolder = adoptPtr(new gin::IsolateHolder(isolate)); - V8PerIsolateData* data = V8PerIsolateData::create(isolate); - m_domDataStore = adoptPtr(new DOMDataStore(WorkerWorld)); - data->setWorkerDOMDataStore(m_domDataStore.get()); + V8PerIsolateData::ensureInitialized(m_isolate); + m_world = DOMWrapperWorld::create(WorkerWorldId); + m_interruptor = adoptPtr(new V8IsolateInterruptor(m_isolate)); + ThreadState::current()->addInterruptor(m_interruptor.get()); } +// We need to postpone V8 Isolate destruction until the very end of +// worker thread finalization when all objects on the worker heap +// are destroyed. +class IsolateCleanupTask : public ThreadState::CleanupTask { +public: + static PassOwnPtr<IsolateCleanupTask> create(v8::Isolate* isolate) + { + return adoptPtr(new IsolateCleanupTask(isolate)); + } + + virtual void postCleanup() + { + V8PerIsolateData::dispose(m_isolate); + m_isolate->Exit(); + m_isolate->Dispose(); + } + +private: + explicit IsolateCleanupTask(v8::Isolate* isolate) : m_isolate(isolate) { } + + v8::Isolate* m_isolate; +}; + WorkerScriptController::~WorkerScriptController() { - m_domDataStore.clear(); + ThreadState::current()->removeInterruptor(m_interruptor.get()); + + m_world->dispose(); // The corresponding call to didStartWorkerRunLoop is in // WorkerThread::workerThread(). // See http://webkit.org/b/83104#c14 for why this is here. blink::Platform::current()->didStopWorkerRunLoop(blink::WebWorkerRunLoop(&m_workerGlobalScope.thread()->runLoop())); - disposeContext(); - V8PerIsolateData::dispose(isolate()); - v8::Isolate* v8Isolate = isolate(); - v8Isolate->Exit(); - m_isolateHolder.clear(); - v8Isolate->Dispose(); -} + if (isContextInitialized()) + m_scriptState->disposePerContextData(); -void WorkerScriptController::disposeContext() -{ - m_perContextData.clear(); - m_contextHolder.clear(); + ThreadState::current()->addCleanupTask(IsolateCleanupTask::create(m_isolate)); } bool WorkerScriptController::initializeContextIfNeeded() { - if (m_contextHolder) + v8::HandleScope handleScope(m_isolate); + + if (isContextInitialized()) return true; - v8::Handle<v8::Context> context = v8::Context::New(isolate()); + v8::Handle<v8::Context> context = v8::Context::New(m_isolate); if (context.IsEmpty()) return false; - m_contextHolder = adoptPtr(new gin::ContextHolder(isolate())); - m_contextHolder->SetContext(context); - - v8::Context::Scope scope(context); - - V8PerContextDataHolder::install(context); + m_scriptState = ScriptState::create(context, m_world); - m_perContextData = V8PerContextData::create(context); - if (!m_perContextData->init()) { - disposeContext(); - return false; - } + ScriptState::Scope scope(m_scriptState.get()); // Set DebugId for the new context. - context->SetEmbedderData(0, v8AtomicString(isolate(), "worker")); + context->SetEmbedderData(0, v8AtomicString(m_isolate, "worker")); // Create a new JS object and use it as the prototype for the shadow global object. const WrapperTypeInfo* contextType = &V8DedicatedWorkerGlobalScope::wrapperTypeInfo; @@ -126,17 +137,17 @@ bool WorkerScriptController::initializeContextIfNeeded() contextType = &V8ServiceWorkerGlobalScope::wrapperTypeInfo; else if (!m_workerGlobalScope.isDedicatedWorkerGlobalScope()) contextType = &V8SharedWorkerGlobalScope::wrapperTypeInfo; - v8::Handle<v8::Function> workerGlobalScopeConstructor = m_perContextData->constructorForType(contextType); - v8::Local<v8::Object> jsWorkerGlobalScope = V8ObjectConstructor::newInstance(workerGlobalScopeConstructor); + v8::Handle<v8::Function> workerGlobalScopeConstructor = m_scriptState->perContextData()->constructorForType(contextType); + v8::Local<v8::Object> jsWorkerGlobalScope = V8ObjectConstructor::newInstance(m_isolate, workerGlobalScopeConstructor); if (jsWorkerGlobalScope.IsEmpty()) { - disposeContext(); + m_scriptState->disposePerContextData(); return false; } - V8DOMWrapper::associateObjectWithWrapper<V8WorkerGlobalScope>(PassRefPtr<WorkerGlobalScope>(m_workerGlobalScope), contextType, jsWorkerGlobalScope, isolate(), WrapperConfiguration::Dependent); + V8DOMWrapper::associateObjectWithWrapper<V8WorkerGlobalScope>(PassRefPtrWillBeRawPtr<WorkerGlobalScope>(&m_workerGlobalScope), contextType, jsWorkerGlobalScope, m_isolate, WrapperConfiguration::Dependent); // Insert the object instance as the prototype of the shadow object. - v8::Handle<v8::Object> globalObject = v8::Handle<v8::Object>::Cast(m_contextHolder->context()->Global()->GetPrototype()); + v8::Handle<v8::Object> globalObject = v8::Handle<v8::Object>::Cast(m_scriptState->context()->Global()->GetPrototype()); globalObject->SetPrototype(jsWorkerGlobalScope); return true; @@ -144,25 +155,22 @@ bool WorkerScriptController::initializeContextIfNeeded() ScriptValue WorkerScriptController::evaluate(const String& script, const String& fileName, const TextPosition& scriptStartPosition, WorkerGlobalScopeExecutionState* state) { - v8::HandleScope handleScope(isolate()); - if (!initializeContextIfNeeded()) return ScriptValue(); - v8::Handle<v8::Context> context = m_contextHolder->context(); + ScriptState::Scope scope(m_scriptState.get()); + if (!m_disableEvalPending.isEmpty()) { - context->AllowCodeGenerationFromStrings(false); - context->SetErrorMessageForCodeGenerationFromStrings(v8String(isolate(), m_disableEvalPending)); + m_scriptState->context()->AllowCodeGenerationFromStrings(false); + m_scriptState->context()->SetErrorMessageForCodeGenerationFromStrings(v8String(m_isolate, m_disableEvalPending)); m_disableEvalPending = String(); } - v8::Context::Scope scope(context); - v8::TryCatch block; - v8::Handle<v8::String> scriptString = v8String(isolate(), script); - v8::Handle<v8::Script> compiledScript = V8ScriptRunner::compileScript(scriptString, fileName, scriptStartPosition, 0, isolate()); - v8::Local<v8::Value> result = V8ScriptRunner::runCompiledScript(compiledScript, &m_workerGlobalScope, isolate()); + v8::Handle<v8::String> scriptString = v8String(m_isolate, script); + v8::Handle<v8::Script> compiledScript = V8ScriptRunner::compileScript(scriptString, fileName, scriptStartPosition, 0, m_isolate); + v8::Local<v8::Value> result = V8ScriptRunner::runCompiledScript(compiledScript, &m_workerGlobalScope, m_isolate); if (!block.CanContinue()) { m_workerGlobalScope.script()->forbidExecution(); @@ -175,9 +183,9 @@ ScriptValue WorkerScriptController::evaluate(const String& script, const String& state->errorMessage = toCoreString(message->Get()); state->lineNumber = message->GetLineNumber(); state->columnNumber = message->GetStartColumn() + 1; - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, sourceURL, message->GetScriptResourceName(), ScriptValue()); + TOSTRING_DEFAULT(V8StringResource<>, sourceURL, message->GetScriptResourceName(), ScriptValue()); state->sourceURL = sourceURL; - state->exception = ScriptValue(block.Exception(), isolate()); + state->exception = ScriptValue(m_scriptState.get(), block.Exception()); block.Reset(); } else state->hadException = false; @@ -185,10 +193,10 @@ ScriptValue WorkerScriptController::evaluate(const String& script, const String& if (result.IsEmpty() || result->IsUndefined()) return ScriptValue(); - return ScriptValue(result, isolate()); + return ScriptValue(m_scriptState.get(), result); } -void WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, RefPtr<ErrorEvent>* errorEvent) +void WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, RefPtrWillBeRawPtr<ErrorEvent>* errorEvent) { if (isExecutionForbidden()) return; @@ -198,12 +206,17 @@ void WorkerScriptController::evaluate(const ScriptSourceCode& sourceCode, RefPtr if (state.hadException) { if (errorEvent) { *errorEvent = m_workerGlobalScope.shouldSanitizeScriptError(state.sourceURL, NotSharableCrossOrigin) ? - ErrorEvent::createSanitizedError(0) : ErrorEvent::create(state.errorMessage, state.sourceURL, state.lineNumber, state.columnNumber, 0); - V8ErrorHandler::storeExceptionOnErrorEventWrapper(errorEvent->get(), state.exception.v8Value(), isolate()); + ErrorEvent::createSanitizedError(m_world.get()) : ErrorEvent::create(state.errorMessage, state.sourceURL, state.lineNumber, state.columnNumber, m_world.get()); + V8ErrorHandler::storeExceptionOnErrorEventWrapper(errorEvent->get(), state.exception.v8Value(), m_scriptState->context()->Global(), m_isolate); } else { ASSERT(!m_workerGlobalScope.shouldSanitizeScriptError(state.sourceURL, NotSharableCrossOrigin)); - RefPtr<ErrorEvent> event = m_errorEventFromImportedScript ? m_errorEventFromImportedScript.release() : ErrorEvent::create(state.errorMessage, state.sourceURL, state.lineNumber, state.columnNumber, 0); - m_workerGlobalScope.reportException(event, 0, NotSharableCrossOrigin); + RefPtrWillBeRawPtr<ErrorEvent> event = nullptr; + if (m_errorEventFromImportedScript) { + event = m_errorEventFromImportedScript.release(); + } else { + event = ErrorEvent::create(state.errorMessage, state.sourceURL, state.lineNumber, state.columnNumber, m_world.get()); + } + m_workerGlobalScope.reportException(event, nullptr, NotSharableCrossOrigin); } } } @@ -217,7 +230,7 @@ void WorkerScriptController::scheduleExecutionTermination() MutexLocker locker(m_scheduledTerminationMutex); m_executionScheduledToTerminate = true; } - v8::V8::TerminateExecution(isolate()); + v8::V8::TerminateExecution(m_isolate); } bool WorkerScriptController::isExecutionTerminating() const @@ -244,26 +257,10 @@ void WorkerScriptController::disableEval(const String& errorMessage) m_disableEvalPending = errorMessage; } -void WorkerScriptController::rethrowExceptionFromImportedScript(PassRefPtr<ErrorEvent> errorEvent) +void WorkerScriptController::rethrowExceptionFromImportedScript(PassRefPtrWillBeRawPtr<ErrorEvent> errorEvent) { m_errorEventFromImportedScript = errorEvent; - throwError(V8ThrowException::createError(v8GeneralError, m_errorEventFromImportedScript->message(), isolate()), isolate()); -} - -WorkerScriptController* WorkerScriptController::controllerForContext() -{ - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - // Happens on frame destruction, check otherwise GetCurrent() will crash. - if (!isolate || !isolate->InContext()) - return 0; - v8::Handle<v8::Context> context = isolate->GetCurrentContext(); - v8::Handle<v8::Object> global = context->Global(); - global = global->FindInstanceInPrototypeChain(V8WorkerGlobalScope::domTemplate(isolate, WorkerWorld)); - // Return 0 if the current executing context is not the worker context. - if (global.IsEmpty()) - return 0; - WorkerGlobalScope* workerGlobalScope = V8WorkerGlobalScope::toNative(global); - return workerGlobalScope->script(); + throwError(V8ThrowException::createError(v8GeneralError, m_errorEventFromImportedScript->message(), m_isolate), m_isolate); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptController.h b/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptController.h index 7b7ea1af507..2559269fdd0 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptController.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptController.h @@ -34,17 +34,11 @@ #include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8Binding.h" #include "core/events/ErrorEvent.h" -#include "gin/public/context_holder.h" -#include "gin/public/isolate_holder.h" #include "wtf/OwnPtr.h" #include "wtf/ThreadingPrimitives.h" #include "wtf/text/TextPosition.h" #include <v8.h> -namespace gin { -class IsolateHolder; -} - namespace WebCore { class ScriptSourceCode; @@ -74,9 +68,11 @@ namespace WebCore { WorkerGlobalScope& workerGlobalScope() { return m_workerGlobalScope; } - void evaluate(const ScriptSourceCode&, RefPtr<ErrorEvent>* = 0); + bool initializeContextIfNeeded(); + + void evaluate(const ScriptSourceCode&, RefPtrWillBeRawPtr<ErrorEvent>* = 0); - void rethrowExceptionFromImportedScript(PassRefPtr<ErrorEvent>); + void rethrowExceptionFromImportedScript(PassRefPtrWillBeRawPtr<ErrorEvent>); // Async request to terminate a future JS execution. Eventually causes termination // exception raised during JS execution, if the worker thread happens to run JS. @@ -93,36 +89,32 @@ namespace WebCore { void disableEval(const String&); - // Returns WorkerScriptController for the currently executing context. 0 will be returned if the current executing context is not the worker context. - static WorkerScriptController* controllerForContext(); - // Evaluate a script file in the current execution environment. ScriptValue evaluate(const String& script, const String& fileName, const TextPosition& scriptStartPosition, WorkerGlobalScopeExecutionState*); - // Returns a local handle of the context. - v8::Local<v8::Context> context() { return m_contextHolder ? m_contextHolder->context() : v8::Local<v8::Context>(); } + v8::Isolate* isolate() const { return m_isolate; } + DOMWrapperWorld& world() const { return *m_world; } + ScriptState* scriptState() { return m_scriptState.get(); } + v8::Local<v8::Context> context() { return m_scriptState ? m_scriptState->context() : v8::Local<v8::Context>(); } + bool isContextInitialized() { return m_scriptState && !!m_scriptState->perContextData(); } // Send a notification about current thread is going to be idle. // Returns true if the embedder should stop calling idleNotification // until real work has been done. bool idleNotification() { return v8::V8::IdleNotification(); } - v8::Isolate* isolate() const { return m_isolateHolder->isolate(); } private: - bool initializeContextIfNeeded(); - void disposeContext(); - + v8::Isolate* m_isolate; WorkerGlobalScope& m_workerGlobalScope; - OwnPtr<gin::IsolateHolder> m_isolateHolder; - OwnPtr<gin::ContextHolder> m_contextHolder; - OwnPtr<V8PerContextData> m_perContextData; + RefPtr<ScriptState> m_scriptState; + RefPtr<DOMWrapperWorld> m_world; String m_disableEvalPending; - OwnPtr<DOMDataStore> m_domDataStore; bool m_executionForbidden; bool m_executionScheduledToTerminate; mutable Mutex m_scheduledTerminationMutex; - RefPtr<ErrorEvent> m_errorEventFromImportedScript; + RefPtrWillBePersistent<ErrorEvent> m_errorEventFromImportedScript; + OwnPtr<V8IsolateInterruptor> m_interruptor; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptDebugServer.cpp b/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptDebugServer.cpp index 935a2d26dc5..920508e1e43 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptDebugServer.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptDebugServer.cpp @@ -42,11 +42,10 @@ namespace WebCore { -WorkerScriptDebugServer::WorkerScriptDebugServer(WorkerGlobalScope* workerGlobalScope, const String& mode) +WorkerScriptDebugServer::WorkerScriptDebugServer(WorkerGlobalScope* workerGlobalScope) : ScriptDebugServer(v8::Isolate::GetCurrent()) , m_listener(0) , m_workerGlobalScope(workerGlobalScope) - , m_debuggerTaskMode(mode) { ASSERT(m_isolate); } @@ -54,16 +53,17 @@ WorkerScriptDebugServer::WorkerScriptDebugServer(WorkerGlobalScope* workerGlobal void WorkerScriptDebugServer::addListener(ScriptDebugListener* listener) { v8::HandleScope scope(m_isolate); - v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); - v8::Context::Scope contextScope(debuggerContext); - ASSERT(!m_listener); - m_listener = listener; + v8::Debug::SetDebugEventListener(&WorkerScriptDebugServer::v8DebugEventCallback, v8::External::New(m_isolate, this)); ensureDebuggerScriptCompiled(); + m_listener = listener; + + v8::Local<v8::Context> debuggerContext = v8::Debug::GetDebugContext(); + v8::Context::Scope contextScope(debuggerContext); + v8::Local<v8::Object> debuggerScript = m_debuggerScript.newLocal(m_isolate); ASSERT(!debuggerScript->IsUndefined()); - v8::Debug::SetDebugEventListener2(&WorkerScriptDebugServer::v8DebugEventCallback, v8::External::New(m_isolate, this)); v8::Handle<v8::Function> getScriptsFunction = v8::Local<v8::Function>::Cast(debuggerScript->Get(v8AtomicString(m_isolate, "getWorkerScripts"))); v8::Handle<v8::Value> value = V8ScriptRunner::callInternalFunction(getScriptsFunction, debuggerScript, 0, 0, m_isolate); @@ -72,15 +72,16 @@ void WorkerScriptDebugServer::addListener(ScriptDebugListener* listener) ASSERT(!value->IsUndefined() && value->IsArray()); v8::Handle<v8::Array> scriptsArray = v8::Handle<v8::Array>::Cast(value); for (unsigned i = 0; i < scriptsArray->Length(); ++i) - dispatchDidParseSource(listener, v8::Handle<v8::Object>::Cast(scriptsArray->Get(v8::Integer::New(i, m_isolate)))); + dispatchDidParseSource(listener, v8::Handle<v8::Object>::Cast(scriptsArray->Get(v8::Integer::New(m_isolate, i)))); } void WorkerScriptDebugServer::removeListener(ScriptDebugListener* listener) { ASSERT(m_listener == listener); continueProgram(); + discardDebuggerScript(); m_listener = 0; - v8::Debug::SetDebugEventListener2(0); + v8::Debug::SetDebugEventListener(0); } void WorkerScriptDebugServer::interruptAndRunTask(PassOwnPtr<Task> task) @@ -98,7 +99,7 @@ void WorkerScriptDebugServer::runMessageLoopOnPause(v8::Handle<v8::Context>) { MessageQueueWaitResult result; do { - result = m_workerGlobalScope->thread()->runLoop().runInMode(m_workerGlobalScope, m_debuggerTaskMode); + result = m_workerGlobalScope->thread()->runLoop().runDebuggerTask(); // Keep waiting until execution is resumed. } while (result == MessageQueueMessageReceived && isPaused()); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptDebugServer.h b/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptDebugServer.h index befaaa90942..81fde7da0e5 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptDebugServer.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/WorkerScriptDebugServer.h @@ -32,21 +32,18 @@ #define WorkerScriptDebugServer_h #include "bindings/v8/ScriptDebugServer.h" - -namespace v8 { -class Isolate; -} +#include <v8.h> namespace WebCore { class WorkerGlobalScope; class WorkerThread; -class WorkerScriptDebugServer : public ScriptDebugServer { +class WorkerScriptDebugServer FINAL : public ScriptDebugServer { WTF_MAKE_NONCOPYABLE(WorkerScriptDebugServer); public: - WorkerScriptDebugServer(WorkerGlobalScope*, const String&); - ~WorkerScriptDebugServer() { } + explicit WorkerScriptDebugServer(WorkerGlobalScope*); + virtual ~WorkerScriptDebugServer() { } void addListener(ScriptDebugListener*); void removeListener(ScriptDebugListener*); @@ -54,14 +51,13 @@ public: void interruptAndRunTask(PassOwnPtr<Task>); private: - virtual ScriptDebugListener* getDebugListenerForContext(v8::Handle<v8::Context>); - virtual void runMessageLoopOnPause(v8::Handle<v8::Context>); - virtual void quitMessageLoopOnPause(); + virtual ScriptDebugListener* getDebugListenerForContext(v8::Handle<v8::Context>) OVERRIDE; + virtual void runMessageLoopOnPause(v8::Handle<v8::Context>) OVERRIDE; + virtual void quitMessageLoopOnPause() OVERRIDE; typedef HashMap<WorkerGlobalScope*, ScriptDebugListener*> ListenersMap; ScriptDebugListener* m_listener; WorkerGlobalScope* m_workerGlobalScope; - String m_debuggerTaskMode; }; } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/WrapperTypeInfo.h b/chromium/third_party/WebKit/Source/bindings/v8/WrapperTypeInfo.h index 227083d018b..3d92f6adb0d 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/WrapperTypeInfo.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/WrapperTypeInfo.h @@ -32,13 +32,13 @@ #define WrapperTypeInfo_h #include "gin/public/wrapper_info.h" +#include "platform/heap/Handle.h" #include "wtf/Assertions.h" #include <v8.h> namespace WebCore { class ActiveDOMObject; - class DOMDataStore; class EventTarget; class Node; @@ -51,13 +51,7 @@ namespace WebCore { static const uint16_t v8DOMNodeClassId = 1; static const uint16_t v8DOMObjectClassId = 2; - enum WrapperWorldType { - MainWorld, - IsolatedWorld, - WorkerWorld - }; - - typedef v8::Handle<v8::FunctionTemplate> (*DomTemplateFunction)(v8::Isolate*, WrapperWorldType); + typedef v8::Handle<v8::FunctionTemplate> (*DomTemplateFunction)(v8::Isolate*); typedef void (*DerefObjectFunction)(void*); typedef ActiveDOMObject* (*ToActiveDOMObjectFunction)(v8::Handle<v8::Object>); typedef EventTarget* (*ToEventTargetFunction)(v8::Handle<v8::Object>); @@ -66,7 +60,13 @@ namespace WebCore { enum WrapperTypePrototype { WrapperTypeObjectPrototype, - WrapperTypeErrorPrototype + WrapperTypeExceptionPrototype + }; + + enum GCType { + GarbageCollectedObject, + WillBeGarbageCollectedObject, + RefCountedObject, }; inline void setObjectGroup(void* object, const v8::Persistent<v8::Object>& wrapper, v8::Isolate* isolate) @@ -100,12 +100,9 @@ namespace WebCore { return false; } - v8::Handle<v8::FunctionTemplate> domTemplate(v8::Isolate* isolate, WrapperWorldType worldType) const { return domTemplateFunction(isolate, worldType); } - - void derefObject(void* object) const + v8::Handle<v8::FunctionTemplate> domTemplate(v8::Isolate* isolate) const { - if (derefObjectFunction) - derefObjectFunction(object); + return domTemplateFunction(isolate); } void installPerContextEnabledMethods(v8::Handle<v8::Object> prototypeTemplate, v8::Isolate* isolate) const @@ -147,6 +144,7 @@ namespace WebCore { const InstallPerContextEnabledPrototypePropertiesFunction installPerContextEnabledMethodsFunction; const WrapperTypeInfo* parentClass; const WrapperTypePrototype wrapperTypePrototype; + const GCType gcType; }; @@ -162,30 +160,60 @@ namespace WebCore { } template<typename T, int offset> - inline T* getInternalField(v8::Handle<v8::Object> object) + inline T* getInternalField(v8::Handle<v8::Object> wrapper) { - ASSERT(offset < object->InternalFieldCount()); - return static_cast<T*>(object->GetAlignedPointerFromInternalField(offset)); + ASSERT(offset < wrapper->InternalFieldCount()); + return static_cast<T*>(wrapper->GetAlignedPointerFromInternalField(offset)); + } + + inline void* toNative(const v8::Persistent<v8::Object>& wrapper) + { + return getInternalField<void, v8DOMWrapperObjectIndex>(wrapper); + } + + inline void* toNative(v8::Handle<v8::Object> wrapper) + { + return getInternalField<void, v8DOMWrapperObjectIndex>(wrapper); } - inline void* toNative(const v8::Persistent<v8::Object>& object) + inline const WrapperTypeInfo* toWrapperTypeInfo(const v8::Persistent<v8::Object>& wrapper) { - return getInternalField<void, v8DOMWrapperObjectIndex>(object); + return getInternalField<WrapperTypeInfo, v8DOMWrapperTypeIndex>(wrapper); } - inline void* toNative(v8::Handle<v8::Object> object) + inline const WrapperTypeInfo* toWrapperTypeInfo(v8::Handle<v8::Object> wrapper) { - return getInternalField<void, v8DOMWrapperObjectIndex>(object); + return getInternalField<WrapperTypeInfo, v8DOMWrapperTypeIndex>(wrapper); } - inline const WrapperTypeInfo* toWrapperTypeInfo(const v8::Persistent<v8::Object>& object) + inline const PersistentNode* toPersistentHandle(const v8::Handle<v8::Object>& wrapper) { - return getInternalField<WrapperTypeInfo, v8DOMWrapperTypeIndex>(object); + // Persistent handle is stored in the last internal field. + return static_cast<PersistentNode*>(wrapper->GetAlignedPointerFromInternalField(wrapper->InternalFieldCount() - 1)); } - inline const WrapperTypeInfo* toWrapperTypeInfo(v8::Handle<v8::Object> object) + inline void releaseObject(v8::Handle<v8::Object> wrapper) { - return getInternalField<WrapperTypeInfo, v8DOMWrapperTypeIndex>(object); + const WrapperTypeInfo* typeInfo = toWrapperTypeInfo(wrapper); + if (typeInfo->gcType == GarbageCollectedObject) { + const PersistentNode* handle = toPersistentHandle(wrapper); + // This will be null iff a wrapper for a hidden wrapper object, + // see V8DOMWrapper::setNativeInfoForHiddenWrapper(). + delete handle; + } else if (typeInfo->gcType == WillBeGarbageCollectedObject) { +#if ENABLE(OILPAN) + const PersistentNode* handle = toPersistentHandle(wrapper); + // This will be null iff a wrapper for a hidden wrapper object, + // see V8DOMWrapper::setNativeInfoForHiddenWrapper(). + delete handle; +#else + ASSERT(typeInfo->derefObjectFunction); + typeInfo->derefObjectFunction(toNative(wrapper)); +#endif + } else { + ASSERT(typeInfo->derefObjectFunction); + typeInfo->derefObjectFunction(toNative(wrapper)); + } } struct WrapperConfiguration { @@ -194,7 +222,7 @@ namespace WebCore { Dependent, Independent }; - void configureWrapper(v8::Persistent<v8::Object>* wrapper) const + void configureWrapper(v8::PersistentBase<v8::Object>* wrapper) const { wrapper->SetWrapperClassId(classId); if (lifetime == Independent) @@ -216,11 +244,6 @@ namespace WebCore { WrapperConfiguration configuration = {v8DOMNodeClassId, lifetime}; return configuration; } - - template<class ElementType> - class WrapperTypeTraits { - // specialized classes have thier own functions, which are generated by binding generator. - }; } #endif // WrapperTypeInfo_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8AlgorithmCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8AlgorithmCustom.cpp deleted file mode 100644 index c8c4ccaa0e8..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8AlgorithmCustom.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2013 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 "V8Algorithm.h" - -#include "V8AesCbcParams.h" -#include "V8AesCtrParams.h" -#include "V8AesKeyGenParams.h" -#include "V8HmacKeyParams.h" -#include "V8HmacParams.h" -#include "V8RsaKeyGenParams.h" -#include "V8RsaSsaParams.h" -#include "platform/NotImplemented.h" - -namespace WebCore { - -v8::Handle<v8::Object> wrap(Algorithm* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) -{ - ASSERT(impl); - - // Wrap as the more derived type. - switch (impl->type()) { - case blink::WebCryptoAlgorithmParamsTypeNone: - return V8Algorithm::createWrapper(impl, creationContext, isolate); - case blink::WebCryptoAlgorithmParamsTypeAesCbcParams: - return wrap(static_cast<AesCbcParams*>(impl), creationContext, isolate); - case blink::WebCryptoAlgorithmParamsTypeAesKeyGenParams: - return wrap(static_cast<AesKeyGenParams*>(impl), creationContext, isolate); - case blink::WebCryptoAlgorithmParamsTypeHmacParams: - return wrap(static_cast<HmacParams*>(impl), creationContext, isolate); - case blink::WebCryptoAlgorithmParamsTypeHmacKeyParams: - return wrap(static_cast<HmacKeyParams*>(impl), creationContext, isolate); - case blink::WebCryptoAlgorithmParamsTypeRsaSsaParams: - return wrap(static_cast<RsaSsaParams*>(impl), creationContext, isolate); - case blink::WebCryptoAlgorithmParamsTypeRsaKeyGenParams: - return wrap(static_cast<RsaKeyGenParams*>(impl), creationContext, isolate); - case blink::WebCryptoAlgorithmParamsTypeAesCtrParams: - return wrap(static_cast<AesCtrParams*>(impl), creationContext, isolate); - case blink::WebCryptoAlgorithmParamsTypeAesGcmParams: - case blink::WebCryptoAlgorithmParamsTypeRsaOaepParams: - // TODO - notImplemented(); - break; - } - - ASSERT_NOT_REACHED(); - return v8::Handle<v8::Object>(); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferCustom.cpp index 8eb4c2b818d..f3494cf694e 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferCustom.cpp @@ -31,7 +31,6 @@ #include "config.h" #include "bindings/v8/custom/V8ArrayBufferCustom.h" -#include "bindings/v8/ScriptPromiseResolver.h" #include "bindings/v8/V8Binding.h" #include "wtf/ArrayBuffer.h" #include "wtf/StdLibExtras.h" @@ -49,15 +48,10 @@ V8ArrayBufferDeallocationObserver* V8ArrayBufferDeallocationObserver::instanceTe const WrapperTypeInfo V8ArrayBuffer::wrapperTypeInfo = { gin::kEmbedderBlink, 0, V8ArrayBuffer::derefObject, - 0, 0, 0, 0, 0, WrapperTypeObjectPrototype + 0, 0, 0, 0, 0, WrapperTypeObjectPrototype, RefCountedObject }; -bool V8ArrayBuffer::hasInstance(v8::Handle<v8::Value> value, v8::Isolate*, WrapperWorldType) -{ - return value->IsArrayBuffer(); -} - -bool V8ArrayBuffer::hasInstanceInAnyWorld(v8::Handle<v8::Value> value, v8::Isolate*) +bool V8ArrayBuffer::hasInstance(v8::Handle<v8::Value> value, v8::Isolate*) { return value->IsArrayBuffer(); } @@ -82,12 +76,11 @@ v8::Handle<v8::Object> V8ArrayBuffer::createWrapper(PassRefPtr<ArrayBuffer> impl ArrayBuffer* V8ArrayBuffer::toNative(v8::Handle<v8::Object> object) { ASSERT(object->IsArrayBuffer()); - void* arraybufferPtr = object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex); - if (arraybufferPtr) - return reinterpret_cast<ArrayBuffer*>(arraybufferPtr); - v8::Local<v8::ArrayBuffer> v8buffer = object.As<v8::ArrayBuffer>(); - ASSERT(!v8buffer->IsExternal()); + if (v8buffer->IsExternal()) { + RELEASE_ASSERT(toWrapperTypeInfo(object)->ginEmbedder == gin::kEmbedderBlink); + return reinterpret_cast<ArrayBuffer*>(WebCore::toNative(object)); + } v8::ArrayBuffer::Contents v8Contents = v8buffer->Externalize(); ArrayBufferContents contents(v8Contents.Data(), v8Contents.ByteLength(), @@ -95,9 +88,12 @@ ArrayBuffer* V8ArrayBuffer::toNative(v8::Handle<v8::Object> object) RefPtr<ArrayBuffer> buffer = ArrayBuffer::create(contents); V8DOMWrapper::associateObjectWithWrapper<V8ArrayBuffer>(buffer.release(), &wrapperTypeInfo, object, v8::Isolate::GetCurrent(), WrapperConfiguration::Dependent); - arraybufferPtr = object->GetAlignedPointerFromInternalField(v8DOMWrapperObjectIndex); - ASSERT(arraybufferPtr); - return reinterpret_cast<ArrayBuffer*>(arraybufferPtr); + return reinterpret_cast<ArrayBuffer*>(WebCore::toNative(object)); +} + +ArrayBuffer* V8ArrayBuffer::toNativeWithTypeCheck(v8::Isolate* isolate, v8::Handle<v8::Value> value) +{ + return V8ArrayBuffer::hasInstance(value, isolate) ? V8ArrayBuffer::toNative(v8::Handle<v8::Object>::Cast(value)) : 0; } template<> diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferCustom.h index 2c5ff8e1cac..779095f7c9a 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferCustom.h @@ -34,9 +34,9 @@ namespace WebCore { -class V8ArrayBufferDeallocationObserver: public WTF::ArrayBufferDeallocationObserver { +class V8ArrayBufferDeallocationObserver FINAL: public WTF::ArrayBufferDeallocationObserver { public: - virtual void arrayBufferDeallocated(unsigned sizeInBytes) + virtual void arrayBufferDeallocated(unsigned sizeInBytes) OVERRIDE { v8::Isolate::GetCurrent()->AdjustAmountOfExternalAllocatedMemory(-static_cast<int>(sizeInBytes)); } @@ -51,9 +51,9 @@ protected: class V8ArrayBuffer { public: - static bool hasInstance(v8::Handle<v8::Value>, v8::Isolate*, WrapperWorldType); - static bool hasInstanceInAnyWorld(v8::Handle<v8::Value>, v8::Isolate*); + static bool hasInstance(v8::Handle<v8::Value>, v8::Isolate*); static ArrayBuffer* toNative(v8::Handle<v8::Object>); + static ArrayBuffer* toNativeWithTypeCheck(v8::Isolate*, v8::Handle<v8::Value>); static void derefObject(void*); static const WrapperTypeInfo wrapperTypeInfo; static const int internalFieldCount = v8DefaultWrapperInternalFieldCount; @@ -75,13 +75,6 @@ private: static v8::Handle<v8::Object> createWrapper(PassRefPtr<ArrayBuffer>, v8::Handle<v8::Object> creationContext, v8::Isolate*); }; -template<> -class WrapperTypeTraits<ArrayBuffer > { -public: - static const WrapperTypeInfo* wrapperTypeInfo() { return &V8ArrayBuffer::wrapperTypeInfo; } -}; - - inline v8::Handle<v8::Object> wrap(ArrayBuffer* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { ASSERT(impl); @@ -115,7 +108,7 @@ inline void v8SetReturnValue(const CallbackInfo& info, ArrayBuffer* impl) template<class CallbackInfo> inline void v8SetReturnValueForMainWorld(const CallbackInfo& info, ArrayBuffer* impl) { - ASSERT(worldType(info.GetIsolate()) == MainWorld); + ASSERT(DOMWrapperWorld::current(info.GetIsolate()).isMainWorld()); if (UNLIKELY(!impl)) { v8SetReturnValueNull(info); return; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferViewCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferViewCustom.cpp index 4f00d0df933..5ee873dd6cb 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferViewCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferViewCustom.cpp @@ -82,5 +82,9 @@ ArrayBufferView* V8ArrayBufferView::toNative(v8::Handle<v8::Object> object) return 0; } +ArrayBufferView* V8ArrayBufferView::toNativeWithTypeCheck(v8::Isolate* isolate, v8::Handle<v8::Value> value) +{ + return V8ArrayBufferView::hasInstance(value, isolate) ? V8ArrayBufferView::toNative(v8::Handle<v8::Object>::Cast(value)) : 0; +} } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferViewCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferViewCustom.h index 94fcd1344d8..7ff95bf68ee 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferViewCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferViewCustom.h @@ -43,15 +43,12 @@ namespace WebCore { class V8ArrayBufferView { public: - static bool hasInstance(v8::Handle<v8::Value> value, v8::Isolate*, WrapperWorldType) - { - return value->IsArrayBufferView(); - } - static bool hasInstanceInAnyWorld(v8::Handle<v8::Value> value, v8::Isolate*) + static bool hasInstance(v8::Handle<v8::Value> value, v8::Isolate*) { return value->IsArrayBufferView(); } static ArrayBufferView* toNative(v8::Handle<v8::Object>); + static ArrayBufferView* toNativeWithTypeCheck(v8::Isolate*, v8::Handle<v8::Value>); static inline void* toInternalPointer(ArrayBufferView* impl) { diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferViewCustomScript.js b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferViewCustomScript.js deleted file mode 100644 index d3448599a90..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ArrayBufferViewCustomScript.js +++ /dev/null @@ -1,36 +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: - * 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. - */ - -(function() { - return function(source, length, offset) { - if (offset == 0) { - for (var i = 0; i < length; i++) - this[i] = source[i]; - } else { - for (var i = 0; i < length; i++) - this[i + offset] = source[i]; - } - } -})(); - diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8AudioNodeCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8AudioNodeCustom.cpp index fcc9d085027..762b58580fb 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8AudioNodeCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8AudioNodeCustom.cpp @@ -24,25 +24,25 @@ #include "config.h" #if ENABLE(WEB_AUDIO) -#include "V8AudioNode.h" +#include "bindings/modules/v8/V8AudioNode.h" -#include "V8AnalyserNode.h" -#include "V8AudioBufferSourceNode.h" -#include "V8AudioDestinationNode.h" -#include "V8BiquadFilterNode.h" -#include "V8ChannelMergerNode.h" -#include "V8ChannelSplitterNode.h" -#include "V8ConvolverNode.h" -#include "V8DelayNode.h" -#include "V8DynamicsCompressorNode.h" -#include "V8GainNode.h" -#include "V8MediaElementAudioSourceNode.h" -#include "V8MediaStreamAudioDestinationNode.h" -#include "V8MediaStreamAudioSourceNode.h" -#include "V8OscillatorNode.h" -#include "V8PannerNode.h" -#include "V8ScriptProcessorNode.h" -#include "V8WaveShaperNode.h" +#include "bindings/modules/v8/V8AnalyserNode.h" +#include "bindings/modules/v8/V8AudioBufferSourceNode.h" +#include "bindings/modules/v8/V8AudioDestinationNode.h" +#include "bindings/modules/v8/V8BiquadFilterNode.h" +#include "bindings/modules/v8/V8ChannelMergerNode.h" +#include "bindings/modules/v8/V8ChannelSplitterNode.h" +#include "bindings/modules/v8/V8ConvolverNode.h" +#include "bindings/modules/v8/V8DelayNode.h" +#include "bindings/modules/v8/V8DynamicsCompressorNode.h" +#include "bindings/modules/v8/V8GainNode.h" +#include "bindings/modules/v8/V8MediaElementAudioSourceNode.h" +#include "bindings/modules/v8/V8MediaStreamAudioDestinationNode.h" +#include "bindings/modules/v8/V8MediaStreamAudioSourceNode.h" +#include "bindings/modules/v8/V8OscillatorNode.h" +#include "bindings/modules/v8/V8PannerNode.h" +#include "bindings/modules/v8/V8ScriptProcessorNode.h" +#include "bindings/modules/v8/V8WaveShaperNode.h" #include "bindings/v8/V8Binding.h" #include "modules/webaudio/AnalyserNode.h" #include "modules/webaudio/AudioBufferSourceNode.h" diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BiquadFilterNodeCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BiquadFilterNodeCustom.cpp deleted file mode 100644 index 862d040c3b4..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BiquadFilterNodeCustom.cpp +++ /dev/null @@ -1,60 +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 "V8BiquadFilterNode.h" - -#include "bindings/v8/V8Binding.h" -#include "modules/webaudio/BiquadFilterNode.h" - -namespace WebCore { - -void V8BiquadFilterNode::typeAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) -{ - BiquadFilterNode* imp = V8BiquadFilterNode::toNative(info.Holder()); - - if (value->IsNumber()) { - bool ok = false; - uint32_t type = toUInt32(value, ok); - ASSERT(ok); - if (!imp->setType(type)) - throwTypeError("Illegal BiquadFilterNode type", info.GetIsolate()); - return; - } - - if (value->IsString()) { - String type = toCoreString(value.As<v8::String>()); - if (type == "lowpass" || type == "highpass" || type == "bandpass" || type == "lowshelf" || type == "highshelf" || type == "peaking" || type == "notch" || type == "allpass") { - imp->setType(type); - return; - } - } - - throwTypeError("Illegal BiquadFilterNode type", info.GetIsolate()); -} - -} // namespace WebCore - -#endif // ENABLE(WEB_AUDIO) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustom.cpp index db9fbbb4295..594b9772cbd 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustom.cpp @@ -29,11 +29,10 @@ */ #include "config.h" -#include "V8Blob.h" +#include "bindings/core/v8/V8Blob.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/custom/V8BlobCustomHelpers.h" -#include "core/fileapi/BlobBuilder.h" namespace WebCore { @@ -41,7 +40,7 @@ void V8Blob::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { ExceptionState exceptionState(ExceptionState::ConstructionContext, "Blob", info.Holder(), info.GetIsolate()); if (!info.Length()) { - RefPtr<Blob> blob = Blob::create(); + RefPtrWillBeRawPtr<Blob> blob = Blob::create(); v8SetReturnValue(info, blob.release()); return; } @@ -72,12 +71,14 @@ void V8Blob::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info) } } - BlobBuilder blobBuilder; + OwnPtr<BlobData> blobData = BlobData::create(); + blobData->setContentType(properties.contentType()); v8::Local<v8::Object> blobParts = v8::Local<v8::Object>::Cast(info[0]); - if (!V8BlobCustomHelpers::processBlobParts(blobParts, length, properties.endings(), blobBuilder, info.GetIsolate())) + if (!V8BlobCustomHelpers::processBlobParts(blobParts, length, properties.normalizeLineEndingsToNative(), *blobData, info.GetIsolate())) return; - RefPtr<Blob> blob = blobBuilder.createBlob(properties.contentType()); + long long blobSize = blobData->length(); + RefPtrWillBeRawPtr<Blob> blob = Blob::create(BlobDataHandle::create(blobData.release(), blobSize)); v8SetReturnValue(info, blob.release()); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.cpp index 62bdc36e7b2..e6ec3535ba6 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.cpp @@ -29,16 +29,14 @@ */ #include "config.h" -#include "V8BlobCustomHelpers.h" +#include "bindings/v8/custom/V8BlobCustomHelpers.h" -#include "V8Blob.h" +#include "bindings/core/v8/V8Blob.h" #include "bindings/v8/Dictionary.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "bindings/v8/custom/V8ArrayBufferCustom.h" #include "bindings/v8/custom/V8ArrayBufferViewCustom.h" -#include "core/fileapi/BlobBuilder.h" #include "wtf/DateMath.h" namespace WebCore { @@ -46,7 +44,7 @@ namespace WebCore { namespace V8BlobCustomHelpers { ParsedProperties::ParsedProperties(bool hasFileProperties) - : m_endings("transparent") + : m_normalizeLineEndingsToNative(false) , m_hasFileProperties(hasFileProperties) #ifndef NDEBUG , m_hasLastModified(false) @@ -71,19 +69,20 @@ void ParsedProperties::setDefaultLastModified() bool ParsedProperties::parseBlobPropertyBag(v8::Local<v8::Value> propertyBag, const char* blobClassName, ExceptionState& exceptionState, v8::Isolate* isolate) { - ASSERT(m_endings == "transparent"); + TONATIVE_DEFAULT(Dictionary, dictionary, Dictionary(propertyBag, isolate), false); - V8TRYCATCH_RETURN(Dictionary, dictionary, Dictionary(propertyBag, isolate), false); - - V8TRYCATCH_RETURN(bool, containsEndings, dictionary.get("endings", m_endings), false); + String endings; + TONATIVE_DEFAULT(bool, containsEndings, dictionary.get("endings", endings), false); if (containsEndings) { - if (m_endings != "transparent" && m_endings != "native") { + if (endings != "transparent" && endings != "native") { exceptionState.throwTypeError("The 'endings' property must be either 'transparent' or 'native'."); return false; } + if (endings == "native") + m_normalizeLineEndingsToNative = true; } - V8TRYCATCH_RETURN(bool, containsType, dictionary.get("type", m_contentType), false); + TONATIVE_DEFAULT(bool, containsType, dictionary.get("type", m_contentType), false); if (containsType) { if (!m_contentType.containsOnlyASCII()) { exceptionState.throwDOMException(SyntaxError, "The 'type' property must consist of ASCII characters."); @@ -96,9 +95,9 @@ bool ParsedProperties::parseBlobPropertyBag(v8::Local<v8::Value> propertyBag, co return true; v8::Local<v8::Value> lastModified; - V8TRYCATCH_RETURN(bool, containsLastModified, dictionary.get("lastModified", lastModified), false); + TONATIVE_DEFAULT(bool, containsLastModified, dictionary.get("lastModified", lastModified), false); if (containsLastModified) { - V8TRYCATCH_RETURN(long long, lastModifiedInt, toInt64(lastModified), false); + TONATIVE_DEFAULT(long long, lastModifiedInt, toInt64(lastModified), false); setLastModified(static_cast<double>(lastModifiedInt) / msPerSecond); } else { setDefaultLastModified(); @@ -107,30 +106,28 @@ bool ParsedProperties::parseBlobPropertyBag(v8::Local<v8::Value> propertyBag, co return true; } -bool processBlobParts(v8::Local<v8::Object> blobParts, uint32_t blobPartsLength, const String& endings, BlobBuilder& blobBuilder, v8::Isolate* isolate) +bool processBlobParts(v8::Local<v8::Object> blobParts, uint32_t blobPartsLength, bool normalizeLineEndingsToNative, BlobData& blobData, v8::Isolate* isolate) { - ASSERT(endings == "transparent" || endings == "native"); - for (uint32_t i = 0; i < blobPartsLength; ++i) { - v8::Local<v8::Value> item = blobParts->Get(v8::Uint32::New(i, isolate)); + v8::Local<v8::Value> item = blobParts->Get(v8::Uint32::New(isolate, i)); if (item.IsEmpty()) return false; - if (V8ArrayBuffer::hasInstance(item, isolate, worldType(isolate))) { + if (V8ArrayBuffer::hasInstance(item, isolate)) { ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(v8::Handle<v8::Object>::Cast(item)); ASSERT(arrayBuffer); - blobBuilder.append(arrayBuffer); - } else if (V8ArrayBufferView::hasInstance(item, isolate, worldType(isolate))) { + blobData.appendArrayBuffer(arrayBuffer); + } else if (V8ArrayBufferView::hasInstance(item, isolate)) { ArrayBufferView* arrayBufferView = V8ArrayBufferView::toNative(v8::Handle<v8::Object>::Cast(item)); ASSERT(arrayBufferView); - blobBuilder.append(arrayBufferView); - } else if (V8Blob::hasInstance(item, isolate, worldType(isolate))) { + blobData.appendArrayBufferView(arrayBufferView); + } else if (V8Blob::hasInstance(item, isolate)) { Blob* blob = V8Blob::toNative(v8::Handle<v8::Object>::Cast(item)); ASSERT(blob); - blobBuilder.append(blob); + blob->appendTo(blobData); } else { - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, stringValue, item, false); - blobBuilder.append(stringValue, endings); + TOSTRING_DEFAULT(V8StringResource<>, stringValue, item, false); + blobData.appendText(stringValue, normalizeLineEndingsToNative); } } return true; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.h index 37a173120bb..93cc08dce79 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8BlobCustomHelpers.h @@ -35,7 +35,7 @@ namespace WebCore { -class BlobBuilder; +class BlobData; class ExceptionState; // Shared code between the custom constructor bindings for Blob and File. @@ -53,7 +53,7 @@ public: explicit ParsedProperties(bool hasFileProperties); const String& contentType() const { return m_contentType; } - const String& endings() const { return m_endings; } + bool normalizeLineEndingsToNative() const { return m_normalizeLineEndingsToNative; } void setLastModified(double); void setDefaultLastModified(); double lastModified() const @@ -70,7 +70,7 @@ public: private: String m_contentType; - String m_endings; + bool m_normalizeLineEndingsToNative; // False if this contains the properties of a BlobPropertyBag. bool m_hasFileProperties; @@ -81,10 +81,10 @@ private: #endif // NDEBUG }; -// Appends the blobParts passed to a Blob or File constructor into a BlobBuilder. +// Appends the blobParts passed to a Blob or File constructor into a BlobData. // http://www.w3.org/TR/FileAPI/#constructorParams // Returns true if everything went well, false if a JS exception was thrown. -bool processBlobParts(v8::Local<v8::Object> blobParts, uint32_t blobPartsLength, const String& endings, BlobBuilder&, v8::Isolate*); +bool processBlobParts(v8::Local<v8::Object> blobParts, uint32_t blobPartsLength, bool normalizeLineEndingsToNative, BlobData&, v8::Isolate*); } // namespace V8BlobCustomHelpers diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSRuleCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSRuleCustom.cpp index 0fbd080bbd4..4aff8aa4090 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSRuleCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSRuleCustom.cpp @@ -29,20 +29,19 @@ */ #include "config.h" -#include "V8CSSRule.h" +#include "bindings/core/v8/V8CSSRule.h" -#include "V8CSSCharsetRule.h" -#include "V8CSSFontFaceRule.h" -#include "V8CSSImportRule.h" -#include "V8CSSKeyframeRule.h" -#include "V8CSSKeyframesRule.h" -#include "V8CSSMediaRule.h" -#include "V8CSSPageRule.h" -#include "V8CSSStyleRule.h" -#include "V8CSSSupportsRule.h" -#include "V8CSSViewportRule.h" -#include "V8WebKitCSSFilterRule.h" -#include "V8WebKitCSSRegionRule.h" +#include "bindings/core/v8/V8CSSCharsetRule.h" +#include "bindings/core/v8/V8CSSFontFaceRule.h" +#include "bindings/core/v8/V8CSSImportRule.h" +#include "bindings/core/v8/V8CSSKeyframeRule.h" +#include "bindings/core/v8/V8CSSKeyframesRule.h" +#include "bindings/core/v8/V8CSSMediaRule.h" +#include "bindings/core/v8/V8CSSPageRule.h" +#include "bindings/core/v8/V8CSSStyleRule.h" +#include "bindings/core/v8/V8CSSSupportsRule.h" +#include "bindings/core/v8/V8CSSViewportRule.h" +#include "bindings/core/v8/V8WebKitCSSFilterRule.h" namespace WebCore { @@ -52,7 +51,7 @@ v8::Handle<v8::Object> wrap(CSSRule* impl, v8::Handle<v8::Object> creationContex switch (impl->type()) { case CSSRule::UNKNOWN_RULE: // CSSUnknownRule.idl is explicitly excluded as it doesn't add anything - // over CSSRule.idl (see bindings/derived_sources.gyp: 'idl_files'). + // over CSSRule.idl (see core/core.gypi: 'core_idl_files'). // -> Use the base class wrapper here. return V8CSSRule::createWrapper(impl, creationContext, isolate); case CSSRule::STYLE_RULE: @@ -75,8 +74,6 @@ v8::Handle<v8::Object> wrap(CSSRule* impl, v8::Handle<v8::Object> creationContex return wrap(toCSSSupportsRule(impl), creationContext, isolate); case CSSRule::VIEWPORT_RULE: return wrap(toCSSViewportRule(impl), creationContext, isolate); - case CSSRule::WEBKIT_REGION_RULE: - return wrap(toCSSRegionRule(impl), creationContext, isolate); case CSSRule::WEBKIT_FILTER_RULE: return wrap(toCSSFilterRule(impl), creationContext, isolate); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp index 6d118a383c3..c7f3d7ab009 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSStyleDeclarationCustom.cpp @@ -29,12 +29,12 @@ */ #include "config.h" -#include "V8CSSStyleDeclaration.h" +#include "bindings/core/v8/V8CSSStyleDeclaration.h" -#include "CSSPropertyNames.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" -#include "core/css/CSSParser.h" +#include "core/CSSPropertyNames.h" +#include "core/css/parser/BisonCSSParser.h" #include "core/css/CSSPrimitiveValue.h" #include "core/css/CSSStyleDeclaration.h" #include "core/css/CSSValue.h" @@ -49,7 +49,6 @@ #include "wtf/text/StringConcatenate.h" using namespace WTF; -using namespace std; namespace WebCore { @@ -81,17 +80,51 @@ static bool hasCSSPropertyNamePrefix(const String& propertyName, const char* pre } struct CSSPropertyInfo { - unsigned propID: 30; // CSSPropertyID - unsigned nameWithDash: 1; - unsigned nameWithCssPrefix: 1; + CSSPropertyID propID; }; -static inline void countCssPropertyInfoUsage(const CSSPropertyInfo& propInfo) +static CSSPropertyID cssResolvedPropertyID(const String& propertyName) { - if (propInfo.nameWithDash) - UseCounter::count(activeDOMWindow(), UseCounter::CSSStyleDeclarationPropertyName); - if (propInfo.propID == CSSPropertyFloat && !propInfo.nameWithCssPrefix) - UseCounter::count(activeDOMWindow(), UseCounter::CSSStyleDeclarationFloatPropertyName); + unsigned length = propertyName.length(); + if (!length) + return CSSPropertyInvalid; + + StringBuilder builder; + builder.reserveCapacity(length); + + unsigned i = 0; + bool hasSeenDash = false; + + if (hasCSSPropertyNamePrefix(propertyName, "css")) + i += 3; + else if (hasCSSPropertyNamePrefix(propertyName, "webkit")) + builder.append('-'); + else if (isASCIIUpper(propertyName[0])) + return CSSPropertyInvalid; + + bool hasSeenUpper = isASCIIUpper(propertyName[i]); + + builder.append(toASCIILower(propertyName[i++])); + + for (; i < length; ++i) { + UChar c = propertyName[i]; + if (!isASCIIUpper(c)) { + if (c == '-') + hasSeenDash = true; + builder.append(c); + } else { + hasSeenUpper = true; + builder.append('-'); + builder.append(toASCIILower(c)); + } + } + + // Reject names containing both dashes and upper-case characters, such as "border-rightColor". + if (hasSeenDash && hasSeenUpper) + return CSSPropertyInvalid; + + String propName = builder.toString(); + return cssPropertyID(propName); } // When getting properties on CSSStyleDeclarations, the name used from @@ -110,52 +143,13 @@ static CSSPropertyInfo* cssPropertyInfo(v8::Handle<v8::String> v8PropertyName) DEFINE_STATIC_LOCAL(CSSPropertyInfoMap, map, ()); CSSPropertyInfo* propInfo = map.get(propertyName); if (!propInfo) { - unsigned length = propertyName.length(); - if (!length) - return 0; - - StringBuilder builder; - builder.reserveCapacity(length); - - unsigned i = 0; - bool hasSeenDash = false; - bool hasSeenCssPrefix = false; - - if (hasCSSPropertyNamePrefix(propertyName, "css")) { - hasSeenCssPrefix = true; - i += 3; - } else if (hasCSSPropertyNamePrefix(propertyName, "webkit")) { - builder.append('-'); - } else if (isASCIIUpper(propertyName[0])) { - return 0; - } - - builder.append(toASCIILower(propertyName[i++])); - - for (; i < length; ++i) { - UChar c = propertyName[i]; - if (!isASCIIUpper(c)) { - if (c == '-') - hasSeenDash = true; - builder.append(c); - } - else { - builder.append('-'); - builder.append(toASCIILower(c)); - } - } - - String propName = builder.toString(); - CSSPropertyID propertyID = cssPropertyID(propName); - if (propertyID && RuntimeCSSEnabled::isCSSPropertyEnabled(propertyID)) { - propInfo = new CSSPropertyInfo(); - propInfo->propID = propertyID; - propInfo->nameWithDash = hasSeenDash; - propInfo->nameWithCssPrefix = hasSeenCssPrefix; - map.add(propertyName, propInfo); - } + propInfo = new CSSPropertyInfo(); + propInfo->propID = cssResolvedPropertyID(propertyName); + map.add(propertyName, propInfo); } - return propInfo; + if (propInfo->propID && RuntimeCSSEnabled::isCSSPropertyEnabled(propInfo->propID)) + return propInfo; + return 0; } void V8CSSStyleDeclaration::namedPropertyEnumeratorCustom(const v8::PropertyCallbackInfo<v8::Array>& info) @@ -170,7 +164,7 @@ void V8CSSStyleDeclaration::namedPropertyEnumeratorCustom(const v8::PropertyCall if (RuntimeCSSEnabled::isCSSPropertyEnabled(propertyId)) propertyNames.append(getJSPropertyName(propertyId)); } - sort(propertyNames.begin(), propertyNames.end(), codePointCompareLessThan); + std::sort(propertyNames.begin(), propertyNames.end(), codePointCompareLessThan); propertyNamesLength = propertyNames.size(); } @@ -178,7 +172,7 @@ void V8CSSStyleDeclaration::namedPropertyEnumeratorCustom(const v8::PropertyCall for (unsigned i = 0; i < propertyNamesLength; ++i) { String key = propertyNames.at(i); ASSERT(!key.isNull()); - properties->Set(v8::Integer::New(i, info.GetIsolate()), v8String(info.GetIsolate(), key)); + properties->Set(v8::Integer::New(info.GetIsolate(), i), v8String(info.GetIsolate(), key)); } v8SetReturnValue(info, properties); @@ -188,8 +182,7 @@ void V8CSSStyleDeclaration::namedPropertyQueryCustom(v8::Local<v8::String> v8Nam { // NOTE: cssPropertyInfo lookups incur several mallocs. // Successful lookups have the same cost the first time, but are cached. - if (CSSPropertyInfo* propInfo = cssPropertyInfo(v8Name)) { - countCssPropertyInfoUsage(*propInfo); + if (cssPropertyInfo(v8Name)) { v8SetReturnValueInt(info, 0); return; } @@ -208,32 +201,27 @@ void V8CSSStyleDeclaration::namedPropertyGetterCustom(v8::Local<v8::String> name if (!propInfo) return; - countCssPropertyInfoUsage(*propInfo); - CSSStyleDeclaration* imp = V8CSSStyleDeclaration::toNative(info.Holder()); - RefPtr<CSSValue> cssValue = imp->getPropertyCSSValueInternal(static_cast<CSSPropertyID>(propInfo->propID)); + CSSStyleDeclaration* impl = V8CSSStyleDeclaration::toNative(info.Holder()); + RefPtrWillBeRawPtr<CSSValue> cssValue = impl->getPropertyCSSValueInternal(static_cast<CSSPropertyID>(propInfo->propID)); if (cssValue) { v8SetReturnValueStringOrNull(info, cssValue->cssText(), info.GetIsolate()); return; } - String result = imp->getPropertyValueInternal(static_cast<CSSPropertyID>(propInfo->propID)); - if (result.isNull()) - result = ""; // convert null to empty string. - + String result = impl->getPropertyValueInternal(static_cast<CSSPropertyID>(propInfo->propID)); v8SetReturnValueString(info, result, info.GetIsolate()); } void V8CSSStyleDeclaration::namedPropertySetterCustom(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) { - CSSStyleDeclaration* imp = V8CSSStyleDeclaration::toNative(info.Holder()); + CSSStyleDeclaration* impl = V8CSSStyleDeclaration::toNative(info.Holder()); CSSPropertyInfo* propInfo = cssPropertyInfo(name); if (!propInfo) return; - countCssPropertyInfoUsage(*propInfo); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, propertyValue, value); + TOSTRING_VOID(V8StringResource<WithNullCheck>, propertyValue, value); ExceptionState exceptionState(ExceptionState::SetterContext, getPropertyName(static_cast<CSSPropertyID>(propInfo->propID)), "CSSStyleDeclaration", info.Holder(), info.GetIsolate()); - imp->setPropertyInternal(static_cast<CSSPropertyID>(propInfo->propID), propertyValue, false, exceptionState); + impl->setPropertyInternal(static_cast<CSSPropertyID>(propInfo->propID), propertyValue, false, exceptionState); if (exceptionState.throwIfNeeded()) return; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSValueCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSValueCustom.cpp index 3db5c35477c..44dc8e69ab8 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSValueCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CSSValueCustom.cpp @@ -29,16 +29,12 @@ */ #include "config.h" -#include "V8CSSValue.h" +#include "bindings/core/v8/V8CSSValue.h" -#include "V8CSSPrimitiveValue.h" -#include "V8CSSValueList.h" -#include "V8SVGColor.h" -#include "V8SVGPaint.h" -#include "V8WebKitCSSFilterValue.h" -#include "V8WebKitCSSMixFunctionValue.h" -#include "V8WebKitCSSTransformValue.h" -#include "core/css/CSSMixFunctionValue.h" +#include "bindings/core/v8/V8CSSPrimitiveValue.h" +#include "bindings/core/v8/V8CSSValueList.h" +#include "bindings/core/v8/V8WebKitCSSFilterValue.h" +#include "bindings/core/v8/V8WebKitCSSTransformValue.h" namespace WebCore { @@ -47,18 +43,12 @@ v8::Handle<v8::Object> wrap(CSSValue* impl, v8::Handle<v8::Object> creationConte ASSERT(impl); if (impl->isTransformValue()) return wrap(toCSSTransformValue(impl), creationContext, isolate); - if (impl->isMixFunctionValue()) - return wrap(toCSSMixFunctionValue(impl), creationContext, isolate); if (impl->isFilterValue()) return wrap(toCSSFilterValue(impl), creationContext, isolate); if (impl->isValueList()) return wrap(toCSSValueList(impl), creationContext, isolate); if (impl->isPrimitiveValue()) return wrap(toCSSPrimitiveValue(impl), creationContext, isolate); - if (impl->isSVGPaint()) - return wrap(toSVGPaint(impl), creationContext, isolate); - if (impl->isSVGColor()) - return wrap(toSVGColor(impl), creationContext, isolate); return V8CSSValue::createWrapper(impl, creationContext, isolate); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp index 3e13d83e57e..d9d036df3cc 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CanvasRenderingContext2DCustom.cpp @@ -29,14 +29,14 @@ */ #include "config.h" -#include "V8CanvasRenderingContext2D.h" +#include "bindings/core/v8/V8CanvasRenderingContext2D.h" -#include "V8CanvasGradient.h" -#include "V8CanvasPattern.h" -#include "V8HTMLCanvasElement.h" -#include "V8HTMLImageElement.h" -#include "V8HTMLVideoElement.h" -#include "V8ImageData.h" +#include "bindings/core/v8/V8CanvasGradient.h" +#include "bindings/core/v8/V8CanvasPattern.h" +#include "bindings/core/v8/V8HTMLCanvasElement.h" +#include "bindings/core/v8/V8HTMLImageElement.h" +#include "bindings/core/v8/V8HTMLVideoElement.h" +#include "bindings/core/v8/V8ImageData.h" #include "bindings/v8/V8Binding.h" #include "core/html/canvas/CanvasGradient.h" #include "core/html/canvas/CanvasPattern.h" @@ -59,13 +59,10 @@ static v8::Handle<v8::Value> toV8Object(CanvasStyle* style, v8::Handle<v8::Objec static PassRefPtr<CanvasStyle> toCanvasStyle(v8::Handle<v8::Value> value, v8::Isolate* isolate) { - if (V8CanvasGradient::hasInstance(value, isolate, worldType(isolate))) - return CanvasStyle::createFromGradient(V8CanvasGradient::toNative(v8::Handle<v8::Object>::Cast(value))); - - if (V8CanvasPattern::hasInstance(value, isolate, worldType(isolate))) - return CanvasStyle::createFromPattern(V8CanvasPattern::toNative(v8::Handle<v8::Object>::Cast(value))); - - return 0; + RefPtr<CanvasStyle> canvasStyle = CanvasStyle::createFromGradient(V8CanvasGradient::toNativeWithTypeCheck(isolate, value)); + if (canvasStyle) + return canvasStyle; + return CanvasStyle::createFromPattern(V8CanvasPattern::toNativeWithTypeCheck(isolate, value)); } void V8CanvasRenderingContext2D::strokeStyleAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) @@ -77,10 +74,12 @@ void V8CanvasRenderingContext2D::strokeStyleAttributeGetterCustom(const v8::Prop void V8CanvasRenderingContext2D::strokeStyleAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) { CanvasRenderingContext2D* impl = V8CanvasRenderingContext2D::toNative(info.Holder()); - if (value->IsString()) - impl->setStrokeColor(toCoreString(value.As<v8::String>())); - else - impl->setStrokeStyle(toCanvasStyle(value, info.GetIsolate())); + if (RefPtr<CanvasStyle> canvasStyle = toCanvasStyle(value, info.GetIsolate())) { + impl->setStrokeStyle(canvasStyle); + } else { + TOSTRING_VOID(V8StringResource<>, colorString, value); + impl->setStrokeColor(colorString); + } } void V8CanvasRenderingContext2D::fillStyleAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) @@ -92,10 +91,12 @@ void V8CanvasRenderingContext2D::fillStyleAttributeGetterCustom(const v8::Proper void V8CanvasRenderingContext2D::fillStyleAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) { CanvasRenderingContext2D* impl = V8CanvasRenderingContext2D::toNative(info.Holder()); - if (value->IsString()) - impl->setFillColor(toCoreString(value.As<v8::String>())); - else - impl->setFillStyle(toCanvasStyle(value, info.GetIsolate())); + if (RefPtr<CanvasStyle> canvasStyle = toCanvasStyle(value, info.GetIsolate())) { + impl->setFillStyle(canvasStyle); + } else { + TOSTRING_VOID(V8StringResource<>, colorString, value); + impl->setFillColor(colorString); + } } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CanvasRenderingContextCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CanvasRenderingContextCustom.cpp deleted file mode 100644 index 66a73c48541..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CanvasRenderingContextCustom.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2007-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" -#include "V8CanvasRenderingContext.h" - -#include "V8CanvasRenderingContext2D.h" -#include "V8WebGLRenderingContext.h" -#include "core/html/canvas/CanvasRenderingContext.h" - -namespace WebCore { - -v8::Handle<v8::Object> wrap(CanvasRenderingContext* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) -{ - ASSERT(impl); - if (impl->is2d()) - return wrap(toCanvasRenderingContext2D(impl), creationContext, isolate); - if (impl->is3d()) - return wrap(toWebGLRenderingContext(impl), creationContext, isolate); - ASSERT_NOT_REACHED(); - return v8::Handle<v8::Object>(); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ClientCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ClientCustom.cpp new file mode 100644 index 00000000000..b7975759511 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ClientCustom.cpp @@ -0,0 +1,39 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "bindings/modules/v8/V8Client.h" + +#include "bindings/v8/ExceptionMessages.h" +#include "bindings/v8/ExceptionState.h" +#include "bindings/v8/SerializedScriptValue.h" +#include "bindings/v8/V8Binding.h" +#include "core/dom/MessagePort.h" +#include "modules/serviceworkers/ServiceWorker.h" +#include "wtf/ArrayBuffer.h" + +namespace WebCore { + +void V8Client::postMessageMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "postMessage", "ServiceWorker", info.Holder(), info.GetIsolate()); + Client* client = V8Client::toNative(info.Holder()); + MessagePortArray ports; + ArrayBufferArray arrayBuffers; + if (info.Length() > 1) { + const int transferablesArgIndex = 1; + if (!SerializedScriptValue::extractTransferables(info[transferablesArgIndex], transferablesArgIndex, ports, arrayBuffers, exceptionState, info.GetIsolate())) { + exceptionState.throwIfNeeded(); + return; + } + } + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(info[0], &ports, &arrayBuffers, exceptionState, info.GetIsolate()); + if (exceptionState.throwIfNeeded()) + return; + ExecutionContext* context = currentExecutionContext(info.GetIsolate()); + client->postMessage(context, message.release(), &ports, exceptionState); + exceptionState.throwIfNeeded(); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CryptoCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CryptoCustom.cpp index d183e31f9f5..d69042811c2 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CryptoCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CryptoCustom.cpp @@ -23,12 +23,11 @@ */ #include "config.h" -#include "V8Crypto.h" +#include "bindings/modules/v8/V8Crypto.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "bindings/v8/custom/V8ArrayBufferViewCustom.h" #include "core/dom/ExceptionCode.h" #include "modules/crypto/Crypto.h" @@ -36,9 +35,6 @@ namespace WebCore { -// This custom binding is shared by V8WorkerCrypto. As such: -// * Do not call V8Crypto::toNative() -// * Must be threadsafe void V8Crypto::getRandomValuesMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { ExceptionState exceptionState(ExceptionState::ExecutionContext, "getRandomValues", "Crypto", info.Holder(), info.GetIsolate()); @@ -49,13 +45,14 @@ void V8Crypto::getRandomValuesMethodCustom(const v8::FunctionCallbackInfo<v8::Va } v8::Handle<v8::Value> buffer = info[0]; - if (!V8ArrayBufferView::hasInstance(buffer, info.GetIsolate(), worldType(info.GetIsolate()))) { + if (!V8ArrayBufferView::hasInstance(buffer, info.GetIsolate())) { exceptionState.throwTypeError("First argument is not an ArrayBufferView"); } else { ArrayBufferView* arrayBufferView = V8ArrayBufferView::toNative(v8::Handle<v8::Object>::Cast(buffer)); ASSERT(arrayBufferView); - Crypto::getRandomValues(arrayBufferView, exceptionState); + Crypto* crypto = V8Crypto::toNative(info.Holder()); + crypto->getRandomValues(arrayBufferView, exceptionState); } if (exceptionState.throwIfNeeded()) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomEventCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomEventCustom.cpp index 143f0cac326..f0ef6e4d600 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomEventCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomEventCustom.cpp @@ -29,23 +29,22 @@ */ #include "config.h" -#include "V8CustomEvent.h" +#include "bindings/core/v8/V8CustomEvent.h" -#include "RuntimeEnabledFeatures.h" -#include "V8Event.h" +#include "bindings/core/v8/V8Event.h" #include "bindings/v8/Dictionary.h" -#include "bindings/v8/ScriptState.h" #include "bindings/v8/SerializedScriptValue.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8DOMWrapper.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "core/dom/ContextFeatures.h" +#include "platform/RuntimeEnabledFeatures.h" namespace WebCore { static v8::Handle<v8::Value> cacheState(v8::Handle<v8::Object> customEvent, v8::Handle<v8::Value> detail, v8::Isolate* isolate) { - customEvent->SetHiddenValue(V8HiddenPropertyName::detail(isolate), detail); + V8HiddenValue::setHiddenValue(isolate, customEvent, V8HiddenValue::detail(isolate), detail); return detail; } @@ -54,7 +53,7 @@ void V8CustomEvent::detailAttributeGetterCustom(const v8::PropertyCallbackInfo<v { CustomEvent* event = V8CustomEvent::toNative(info.Holder()); - v8::Handle<v8::Value> result = info.Holder()->GetHiddenValue(V8HiddenPropertyName::detail(info.GetIsolate())); + v8::Handle<v8::Value> result = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::detail(info.GetIsolate())); if (!result.IsEmpty()) { v8SetReturnValue(info, result); @@ -64,7 +63,7 @@ void V8CustomEvent::detailAttributeGetterCustom(const v8::PropertyCallbackInfo<v if (!event->serializedDetail()) { // If we're in an isolated world and the event was created in the main world, // we need to find the 'detail' property on the main world wrapper and clone it. - v8::Local<v8::Value> mainWorldDetail = getHiddenValueFromMainWorldWrapper(info.GetIsolate(), event, V8HiddenPropertyName::detail(info.GetIsolate())); + v8::Local<v8::Value> mainWorldDetail = V8HiddenValue::getHiddenValueFromMainWorldWrapper(info.GetIsolate(), event, V8HiddenValue::detail(info.GetIsolate())); if (!mainWorldDetail.IsEmpty()) event->setSerializedDetail(SerializedScriptValue::createAndSwallowExceptions(mainWorldDetail, info.GetIsolate())); } @@ -83,16 +82,16 @@ void V8CustomEvent::initCustomEventMethodCustom(const v8::FunctionCallbackInfo<v CustomEvent* event = V8CustomEvent::toNative(info.Holder()); ASSERT(!event->serializedDetail()); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, typeArg, info[0]); - V8TRYCATCH_VOID(bool, canBubbleArg, info[1]->BooleanValue()); - V8TRYCATCH_VOID(bool, cancelableArg, info[2]->BooleanValue()); + TOSTRING_VOID(V8StringResource<>, typeArg, info[0]); + TONATIVE_VOID(bool, canBubbleArg, info[1]->BooleanValue()); + TONATIVE_VOID(bool, cancelableArg, info[2]->BooleanValue()); v8::Handle<v8::Value> detailsArg = info[3]; event->initEvent(typeArg, canBubbleArg, cancelableArg); if (!detailsArg.IsEmpty()) { - info.Holder()->SetHiddenValue(V8HiddenPropertyName::detail(info.GetIsolate()), detailsArg); - if (isolatedWorldForIsolate(info.GetIsolate())) + V8HiddenValue::setHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::detail(info.GetIsolate()), detailsArg); + if (DOMWrapperWorld::current(info.GetIsolate()).isIsolatedWorld()) event->setSerializedDetail(SerializedScriptValue::createAndSwallowExceptions(detailsArg, info.GetIsolate())); } } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp index fc597c11034..0f411122352 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomSQLStatementErrorCallback.cpp @@ -29,10 +29,10 @@ */ #include "config.h" -#include "V8SQLStatementErrorCallback.h" -#include "V8SQLError.h" -#include "V8SQLTransaction.h" +#include "bindings/modules/v8/V8SQLError.h" +#include "bindings/modules/v8/V8SQLStatementErrorCallback.h" +#include "bindings/modules/v8/V8SQLTransaction.h" #include "bindings/v8/ScriptController.h" #include "core/dom/ExecutionContext.h" #include "wtf/Assertions.h" @@ -44,23 +44,22 @@ bool V8SQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, SQLEr if (!canInvokeCallback()) return true; - v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::HandleScope handleScope(isolate); - - v8::Handle<v8::Context> v8Context = toV8Context(executionContext(), m_world.get()); - if (v8Context.IsEmpty()) + v8::Isolate* isolate = m_scriptState->isolate(); + if (m_scriptState->contextIsEmpty()) return true; - v8::Context::Scope scope(v8Context); + ScriptState::Scope scope(m_scriptState.get()); - v8::Handle<v8::Value> transactionHandle = toV8(transaction, v8::Handle<v8::Object>(), v8Context->GetIsolate()); - v8::Handle<v8::Value> errorHandle = toV8(error, v8::Handle<v8::Object>(), isolate); + v8::Handle<v8::Value> transactionHandle = toV8(transaction, m_scriptState->context()->Global(), isolate); + v8::Handle<v8::Value> errorHandle = toV8(error, m_scriptState->context()->Global(), isolate); if (transactionHandle.IsEmpty() || errorHandle.IsEmpty()) { if (!isScriptControllerTerminating()) CRASH(); return true; } + ASSERT(transactionHandle->IsObject()); + v8::Handle<v8::Value> argv[] = { transactionHandle, errorHandle @@ -69,7 +68,7 @@ bool V8SQLStatementErrorCallback::handleEvent(SQLTransaction* transaction, SQLEr v8::TryCatch exceptionCatcher; exceptionCatcher.SetVerbose(true); - v8::Handle<v8::Value> result = ScriptController::callFunction(executionContext(), m_callback.newLocal(isolate), isolate->GetCurrentContext()->Global(), 2, argv, isolate); + v8::Handle<v8::Value> result = ScriptController::callFunction(executionContext(), m_callback.newLocal(isolate), m_scriptState->context()->Global(), WTF_ARRAY_LENGTH(argv), argv, isolate); // FIXME: This comment doesn't make much sense given what the code is actually doing. // diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomXPathNSResolver.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomXPathNSResolver.cpp index f2c4d730d24..6331ef1bf99 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomXPathNSResolver.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomXPathNSResolver.cpp @@ -32,20 +32,19 @@ #include "bindings/v8/ScriptController.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "core/dom/ExecutionContext.h" +#include "core/frame/LocalDOMWindow.h" +#include "core/frame/FrameConsole.h" +#include "core/frame/FrameHost.h" +#include "core/frame/LocalFrame.h" #include "core/inspector/ScriptCallStack.h" -#include "core/frame/DOMWindow.h" -#include "core/frame/Frame.h" -#include "core/page/Page.h" -#include "core/page/PageConsole.h" #include "wtf/text/WTFString.h" namespace WebCore { -PassRefPtr<V8CustomXPathNSResolver> V8CustomXPathNSResolver::create(v8::Handle<v8::Object> resolver, v8::Isolate* isolate) +PassRefPtrWillBeRawPtr<V8CustomXPathNSResolver> V8CustomXPathNSResolver::create(v8::Handle<v8::Object> resolver, v8::Isolate* isolate) { - return adoptRef(new V8CustomXPathNSResolver(resolver, isolate)); + return adoptRefWillBeNoop(new V8CustomXPathNSResolver(resolver, isolate)); } V8CustomXPathNSResolver::V8CustomXPathNSResolver(v8::Handle<v8::Object> resolver, v8::Isolate* isolate) @@ -71,9 +70,9 @@ AtomicString V8CustomXPathNSResolver::lookupNamespaceURI(const String& prefix) } if (lookupNamespaceURIFunc.IsEmpty() && !m_resolver->IsFunction()) { - Frame* frame = activeDOMWindow()->frame(); - if (frame && frame->page()) - frame->page()->console().addMessage(JSMessageSource, ErrorMessageLevel, "XPathNSResolver does not have a lookupNamespaceURI method."); + LocalFrame* frame = callingDOMWindow(m_isolate)->frame(); + if (frame && frame->host()) + frame->console().addMessage(JSMessageSource, ErrorMessageLevel, "XPathNSResolver does not have a lookupNamespaceURI method."); return nullAtom; } @@ -85,14 +84,19 @@ AtomicString V8CustomXPathNSResolver::lookupNamespaceURI(const String& prefix) v8::Handle<v8::Value> argv[argc] = { v8String(m_isolate, prefix) }; v8::Handle<v8::Function> function = lookupNamespaceURIFunc.IsEmpty() ? v8::Handle<v8::Function>::Cast(m_resolver) : lookupNamespaceURIFunc; - v8::Handle<v8::Value> retval = ScriptController::callFunction(activeExecutionContext(), function, m_resolver, argc, argv, m_isolate); + v8::Handle<v8::Value> retval = ScriptController::callFunction(callingExecutionContext(m_isolate), function, m_resolver, argc, argv, m_isolate); // Eat exceptions from namespace resolver and return an empty string. This will most likely cause NamespaceError. if (tryCatch.HasCaught()) return nullAtom; - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<WithNullCheck>, returnString, retval, nullAtom); + TOSTRING_DEFAULT(V8StringResource<WithNullCheck>, returnString, retval, nullAtom); return returnString; } +void V8CustomXPathNSResolver::trace(Visitor* visitor) +{ + XPathNSResolver::trace(visitor); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomXPathNSResolver.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomXPathNSResolver.h index aa3e01a243d..4c6712bb9f3 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomXPathNSResolver.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8CustomXPathNSResolver.h @@ -42,13 +42,15 @@ namespace WebCore { // V8CustomXPathNSResolver does not create a persistent handle to the // given resolver object. So the lifetime of V8CustomXPathNSResolver // must not exceed the lifetime of the passed handle. -class V8CustomXPathNSResolver : public XPathNSResolver { +class V8CustomXPathNSResolver FINAL : public XPathNSResolver { public: - static PassRefPtr<V8CustomXPathNSResolver> create(v8::Handle<v8::Object> resolver, v8::Isolate*); + static PassRefPtrWillBeRawPtr<V8CustomXPathNSResolver> create(v8::Handle<v8::Object> resolver, v8::Isolate*); virtual ~V8CustomXPathNSResolver(); virtual AtomicString lookupNamespaceURI(const String& prefix) OVERRIDE; + virtual void trace(Visitor*) OVERRIDE; + private: V8CustomXPathNSResolver(v8::Handle<v8::Object> resolver, v8::Isolate*); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DataViewCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DataViewCustom.cpp index 73efbd69ad4..3d7572ca3ca 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DataViewCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DataViewCustom.cpp @@ -35,7 +35,7 @@ namespace WebCore { static void initializeScriptWrappableForInterface(DataView* object) { if (ScriptWrappable::wrapperCanBeStoredInObject(object)) - ScriptWrappable::setTypeInfoInObject(object, &V8DataView::wrapperTypeInfo); + ScriptWrappable::fromObject(object)->setTypeInfo(&V8DataView::wrapperTypeInfo); else ASSERT_NOT_REACHED(); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DataViewCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DataViewCustom.h index 502c010fe46..6459cbdd6e2 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DataViewCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DataViewCustom.h @@ -59,10 +59,6 @@ public: typedef V8TypedArray<DataView> V8DataView; -template<> -class WrapperTypeTraits<DataView> : public TypedArrayWrapperTraits<DataView> { }; - - inline v8::Handle<v8::Object> wrap(DataView* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { return V8TypedArray<DataView>::wrap(impl, creationContext, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DedicatedWorkerGlobalScopeCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DedicatedWorkerGlobalScopeCustom.cpp index a356f03e4fe..b95c50747e7 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DedicatedWorkerGlobalScopeCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DedicatedWorkerGlobalScopeCustom.cpp @@ -29,13 +29,12 @@ */ #include "config.h" -#include "V8DedicatedWorkerGlobalScope.h" +#include "bindings/core/v8/V8DedicatedWorkerGlobalScope.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/SerializedScriptValue.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "bindings/v8/V8WorkerGlobalScopeEventListener.h" #include "core/workers/DedicatedWorkerGlobalScope.h" #include "wtf/ArrayBuffer.h" @@ -44,23 +43,21 @@ namespace WebCore { void V8DedicatedWorkerGlobalScope::postMessageMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { + ExceptionState exceptionState(ExceptionState::ExecutionContext, "postMessage", "WorkerGlobalScope", info.Holder(), info.GetIsolate()); DedicatedWorkerGlobalScope* workerGlobalScope = V8DedicatedWorkerGlobalScope::toNative(info.Holder()); MessagePortArray ports; ArrayBufferArray arrayBuffers; if (info.Length() > 1) { const int transferablesArgIndex = 1; - bool notASequence = false; - if (!extractTransferables(info[transferablesArgIndex], ports, arrayBuffers, notASequence, info.GetIsolate())) { - if (notASequence) - throwTypeError(ExceptionMessages::failedToExecute("postMessage", "WorkerGlobalScope", ExceptionMessages::notAnArrayTypeArgumentOrValue(transferablesArgIndex + 1)), info.GetIsolate()); + if (!SerializedScriptValue::extractTransferables(info[transferablesArgIndex], transferablesArgIndex, ports, arrayBuffers, exceptionState, info.GetIsolate())) { + exceptionState.throwIfNeeded(); return; } } - bool didThrow = false; - RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(info[0], &ports, &arrayBuffers, didThrow, info.GetIsolate()); - if (didThrow) + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(info[0], &ports, &arrayBuffers, exceptionState, info.GetIsolate()); + if (exceptionState.throwIfNeeded()) return; - ExceptionState exceptionState(info.Holder(), info.GetIsolate()); + workerGlobalScope->postMessage(message.release(), &ports, exceptionState); exceptionState.throwIfNeeded(); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DeviceMotionEventCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DeviceMotionEventCustom.cpp index a170e1cde5f..ecf0ca7e9ee 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DeviceMotionEventCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DeviceMotionEventCustom.cpp @@ -24,7 +24,7 @@ */ #include "config.h" -#include "V8DeviceMotionEvent.h" +#include "bindings/modules/v8/V8DeviceMotionEvent.h" #include "bindings/v8/V8Binding.h" #include "modules/device_orientation/DeviceMotionData.h" @@ -34,66 +34,66 @@ namespace WebCore { namespace { -RefPtr<DeviceMotionData::Acceleration> readAccelerationArgument(v8::Local<v8::Value> value, v8::Isolate* isolate) +PassRefPtrWillBeRawPtr<DeviceMotionData::Acceleration> readAccelerationArgument(v8::Local<v8::Value> value, v8::Isolate* isolate) { if (isUndefinedOrNull(value)) - return 0; + return nullptr; // Given the test above, this will always yield an object. v8::Local<v8::Object> object = value->ToObject(); v8::Local<v8::Value> xValue = object->Get(v8AtomicString(isolate, "x")); if (xValue.IsEmpty()) - return 0; + return nullptr; bool canProvideX = !isUndefinedOrNull(xValue); double x = xValue->NumberValue(); v8::Local<v8::Value> yValue = object->Get(v8AtomicString(isolate, "y")); if (yValue.IsEmpty()) - return 0; + return nullptr; bool canProvideY = !isUndefinedOrNull(yValue); double y = yValue->NumberValue(); v8::Local<v8::Value> zValue = object->Get(v8AtomicString(isolate, "z")); if (zValue.IsEmpty()) - return 0; + return nullptr; bool canProvideZ = !isUndefinedOrNull(zValue); double z = zValue->NumberValue(); if (!canProvideX && !canProvideY && !canProvideZ) - return 0; + return nullptr; return DeviceMotionData::Acceleration::create(canProvideX, x, canProvideY, y, canProvideZ, z); } -RefPtr<DeviceMotionData::RotationRate> readRotationRateArgument(v8::Local<v8::Value> value, v8::Isolate* isolate) +PassRefPtrWillBeRawPtr<DeviceMotionData::RotationRate> readRotationRateArgument(v8::Local<v8::Value> value, v8::Isolate* isolate) { if (isUndefinedOrNull(value)) - return 0; + return nullptr; // Given the test above, this will always yield an object. v8::Local<v8::Object> object = value->ToObject(); v8::Local<v8::Value> alphaValue = object->Get(v8AtomicString(isolate, "alpha")); if (alphaValue.IsEmpty()) - return 0; + return nullptr; bool canProvideAlpha = !isUndefinedOrNull(alphaValue); double alpha = alphaValue->NumberValue(); v8::Local<v8::Value> betaValue = object->Get(v8AtomicString(isolate, "beta")); if (betaValue.IsEmpty()) - return 0; + return nullptr; bool canProvideBeta = !isUndefinedOrNull(betaValue); double beta = betaValue->NumberValue(); v8::Local<v8::Value> gammaValue = object->Get(v8AtomicString(isolate, "gamma")); if (gammaValue.IsEmpty()) - return 0; + return nullptr; bool canProvideGamma = !isUndefinedOrNull(gammaValue); double gamma = gammaValue->NumberValue(); if (!canProvideAlpha && !canProvideBeta && !canProvideGamma) - return 0; + return nullptr; return DeviceMotionData::RotationRate::create(canProvideAlpha, alpha, canProvideBeta, beta, canProvideGamma, gamma); } @@ -102,18 +102,18 @@ RefPtr<DeviceMotionData::RotationRate> readRotationRateArgument(v8::Local<v8::Va void V8DeviceMotionEvent::initDeviceMotionEventMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - DeviceMotionEvent* imp = V8DeviceMotionEvent::toNative(info.Holder()); + DeviceMotionEvent* impl = V8DeviceMotionEvent::toNative(info.Holder()); v8::Isolate* isolate = info.GetIsolate(); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, info[0]); + TOSTRING_VOID(V8StringResource<>, type, info[0]); bool bubbles = info[1]->BooleanValue(); bool cancelable = info[2]->BooleanValue(); - RefPtr<DeviceMotionData::Acceleration> acceleration = readAccelerationArgument(info[3], isolate); - RefPtr<DeviceMotionData::Acceleration> accelerationIncludingGravity = readAccelerationArgument(info[4], isolate); - RefPtr<DeviceMotionData::RotationRate> rotationRate = readRotationRateArgument(info[5], isolate); + RefPtrWillBeRawPtr<DeviceMotionData::Acceleration> acceleration = readAccelerationArgument(info[3], isolate); + RefPtrWillBeRawPtr<DeviceMotionData::Acceleration> accelerationIncludingGravity = readAccelerationArgument(info[4], isolate); + RefPtrWillBeRawPtr<DeviceMotionData::RotationRate> rotationRate = readRotationRateArgument(info[5], isolate); bool intervalProvided = !isUndefinedOrNull(info[6]); double interval = info[6]->NumberValue(); - RefPtr<DeviceMotionData> deviceMotionData = DeviceMotionData::create(acceleration, accelerationIncludingGravity, rotationRate, intervalProvided, interval); - imp->initDeviceMotionEvent(type, bubbles, cancelable, deviceMotionData.get()); + RefPtrWillBeRawPtr<DeviceMotionData> deviceMotionData = DeviceMotionData::create(acceleration.release(), accelerationIncludingGravity.release(), rotationRate.release(), intervalProvided, interval); + impl->initDeviceMotionEvent(type, bubbles, cancelable, deviceMotionData.get()); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DeviceOrientationEventCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DeviceOrientationEventCustom.cpp index ef2a0a92e48..c9d68ec2057 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DeviceOrientationEventCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DeviceOrientationEventCustom.cpp @@ -24,7 +24,7 @@ */ #include "config.h" -#include "V8DeviceOrientationEvent.h" +#include "bindings/modules/v8/V8DeviceOrientationEvent.h" #include "bindings/v8/V8Binding.h" #include "modules/device_orientation/DeviceOrientationData.h" @@ -34,8 +34,8 @@ namespace WebCore { void V8DeviceOrientationEvent::initDeviceOrientationEventMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - DeviceOrientationEvent* imp = V8DeviceOrientationEvent::toNative(info.Holder()); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, info[0]); + DeviceOrientationEvent* impl = V8DeviceOrientationEvent::toNative(info.Holder()); + TOSTRING_VOID(V8StringResource<>, type, info[0]); bool bubbles = info[1]->BooleanValue(); bool cancelable = info[2]->BooleanValue(); // If alpha, beta, gamma or absolute are null or undefined, mark them as not provided. @@ -48,8 +48,8 @@ void V8DeviceOrientationEvent::initDeviceOrientationEventMethodCustom(const v8:: double gamma = info[5]->NumberValue(); bool absoluteProvided = !isUndefinedOrNull(info[6]); bool absolute = info[6]->BooleanValue(); - RefPtr<DeviceOrientationData> orientation = DeviceOrientationData::create(alphaProvided, alpha, betaProvided, beta, gammaProvided, gamma, absoluteProvided, absolute); - imp->initDeviceOrientationEvent(type, bubbles, cancelable, orientation.get()); + RefPtrWillBeRawPtr<DeviceOrientationData> orientation = DeviceOrientationData::create(alphaProvided, alpha, betaProvided, beta, gammaProvided, gamma, absoluteProvided, absolute); + impl->initDeviceOrientationEvent(type, bubbles, cancelable, orientation.get()); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DocumentCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DocumentCustom.cpp index 94ed248cb90..930ba77f07d 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DocumentCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8DocumentCustom.cpp @@ -29,16 +29,16 @@ */ #include "config.h" -#include "V8Document.h" +#include "bindings/core/v8/V8Document.h" -#include "V8CanvasRenderingContext2D.h" -#include "V8DOMImplementation.h" -#include "V8Node.h" -#include "V8Touch.h" -#include "V8TouchList.h" -#include "V8WebGLRenderingContext.h" -#include "V8XPathNSResolver.h" -#include "V8XPathResult.h" +#include "bindings/core/v8/V8CanvasRenderingContext2D.h" +#include "bindings/core/v8/V8DOMImplementation.h" +#include "bindings/core/v8/V8Node.h" +#include "bindings/core/v8/V8Touch.h" +#include "bindings/core/v8/V8TouchList.h" +#include "bindings/core/v8/V8WebGLRenderingContext.h" +#include "bindings/core/v8/V8XPathNSResolver.h" +#include "bindings/core/v8/V8XPathResult.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ScriptController.h" @@ -49,8 +49,8 @@ #include "core/dom/ExceptionCode.h" #include "core/dom/Node.h" #include "core/dom/TouchList.h" +#include "core/frame/LocalFrame.h" #include "core/html/canvas/CanvasRenderingContext.h" -#include "core/frame/Frame.h" #include "core/xml/DocumentXPathEvaluator.h" #include "core/xml/XPathNSResolver.h" #include "core/xml/XPathResult.h" @@ -60,27 +60,23 @@ namespace WebCore { void V8Document::evaluateMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - RefPtr<Document> document = V8Document::toNative(info.Holder()); + RefPtrWillBeRawPtr<Document> document = V8Document::toNative(info.Holder()); + ASSERT(document); ExceptionState exceptionState(ExceptionState::ExecutionContext, "evaluate", "Document", info.Holder(), info.GetIsolate()); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, expression, info[0]); - RefPtr<Node> contextNode; - if (V8Node::hasInstance(info[1], info.GetIsolate(), worldType(info.GetIsolate()))) - contextNode = V8Node::toNative(v8::Handle<v8::Object>::Cast(info[1])); + TOSTRING_VOID(V8StringResource<>, expression, info[0]); + RefPtrWillBeRawPtr<Node> contextNode = V8Node::toNativeWithTypeCheck(info.GetIsolate(), info[1]); const int resolverArgumentIndex = 2; - RefPtr<XPathNSResolver> resolver = toXPathNSResolver(info[resolverArgumentIndex], info.GetIsolate()); + RefPtrWillBeRawPtr<XPathNSResolver> resolver = toXPathNSResolver(info[resolverArgumentIndex], info.GetIsolate()); if (!resolver && !isUndefinedOrNull(info[resolverArgumentIndex])) { - exceptionState.throwTypeError(ExceptionMessages::incorrectArgumentType(resolverArgumentIndex + 1, "is not a resolver function.")); + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(resolverArgumentIndex + 1, "XPathNSResolver")); exceptionState.throwIfNeeded(); return; } int type = toInt32(info[3]); - RefPtr<XPathResult> inResult; - if (V8XPathResult::hasInstance(info[4], info.GetIsolate(), worldType(info.GetIsolate()))) - inResult = V8XPathResult::toNative(v8::Handle<v8::Object>::Cast(info[4])); - - V8TRYCATCH_VOID(RefPtr<XPathResult>, result, DocumentXPathEvaluator::evaluate(document.get(), expression, contextNode.get(), resolver.release(), type, inResult.get(), exceptionState)); + RefPtrWillBeRawPtr<XPathResult> inResult = V8XPathResult::toNativeWithTypeCheck(info.GetIsolate(), info[4]); + TONATIVE_VOID(RefPtrWillBeRawPtr<XPathResult>, result, DocumentXPathEvaluator::evaluate(*document, expression, contextNode.get(), resolver.release(), type, inResult.get(), exceptionState)); if (exceptionState.throwIfNeeded()) return; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ElementCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ElementCustom.cpp new file mode 100644 index 00000000000..0083ac9b055 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ElementCustom.cpp @@ -0,0 +1,236 @@ +/* + * Copyright (C) 2014 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 "bindings/core/v8/V8Element.h" + +#include "bindings/core/v8/V8AnimationEffect.h" +#include "bindings/core/v8/V8AnimationPlayer.h" +#include "bindings/v8/Dictionary.h" +#include "bindings/v8/ExceptionState.h" +#include "bindings/v8/V8Binding.h" +#include "bindings/v8/V8BindingMacros.h" +#include "core/animation/ElementAnimation.h" +#include "core/dom/Element.h" +#include "core/frame/UseCounter.h" +#include "platform/RuntimeEnabledFeatures.h" +#include "wtf/GetPtr.h" + +namespace WebCore { + +void V8Element::scrollLeftAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) +{ + ExceptionState exceptionState(ExceptionState::SetterContext, "scrollLeft", "Element", info.Holder(), info.GetIsolate()); + Element* impl = V8Element::toNative(info.Holder()); + + if (RuntimeEnabledFeatures::cssomSmoothScrollEnabled() && value->IsObject()) { + TONATIVE_VOID(Dictionary, scrollOptionsHorizontal, Dictionary(value, info.GetIsolate())); + impl->setScrollLeft(scrollOptionsHorizontal, exceptionState); + exceptionState.throwIfNeeded(); + return; + } + + TONATIVE_VOID_EXCEPTIONSTATE(float, position, toInt32(value, exceptionState), exceptionState); + impl->setScrollLeft(position); +} + +void V8Element::scrollTopAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) +{ + ExceptionState exceptionState(ExceptionState::SetterContext, "scrollTop", "Element", info.Holder(), info.GetIsolate()); + Element* impl = V8Element::toNative(info.Holder()); + + if (RuntimeEnabledFeatures::cssomSmoothScrollEnabled() && value->IsObject()) { + TONATIVE_VOID(Dictionary, scrollOptionsVertical, Dictionary(value, info.GetIsolate())); + impl->setScrollTop(scrollOptionsVertical, exceptionState); + exceptionState.throwIfNeeded(); + return; + } + + TONATIVE_VOID_EXCEPTIONSTATE(float, position, toInt32(value, exceptionState), exceptionState); + impl->setScrollTop(position); +} + +//////////////////////////////////////////////////////////////////////////////// +// Overload resolution for animate() +// FIXME: needs support for union types http://crbug.com/240176 +//////////////////////////////////////////////////////////////////////////////// + +// AnimationPlayer animate(AnimationEffect? effect); +void animate1Method(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + Element* impl = V8Element::toNative(info.Holder()); + TONATIVE_VOID(AnimationEffect*, effect, V8AnimationEffect::toNativeWithTypeCheck(info.GetIsolate(), info[0])); + v8SetReturnValueFast(info, WTF::getPtr(ElementAnimation::animate(*impl, effect)), impl); +} + +// [RaisesException] AnimationPlayer animate(sequence<Dictionary> effect); +void animate2Method(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "animate", "Element", info.Holder(), info.GetIsolate()); + Element* impl = V8Element::toNative(info.Holder()); + TONATIVE_VOID(Vector<Dictionary>, keyframes, toNativeArray<Dictionary>(info[0], 1, info.GetIsolate())); + RefPtr<AnimationPlayer> result = ElementAnimation::animate(*impl, keyframes, exceptionState); + if (exceptionState.throwIfNeeded()) + return; + v8SetReturnValueFast(info, WTF::getPtr(result.release()), impl); +} + +// AnimationPlayer animate(AnimationEffect? effect, double timing); +void animate3Method(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + Element* impl = V8Element::toNative(info.Holder()); + TONATIVE_VOID(AnimationEffect*, effect, V8AnimationEffect::toNativeWithTypeCheck(info.GetIsolate(), info[0])); + TONATIVE_VOID(double, duration, static_cast<double>(info[1]->NumberValue())); + v8SetReturnValueFast(info, WTF::getPtr(ElementAnimation::animate(*impl, effect, duration)), impl); +} + +// AnimationPlayer animate(AnimationEffect? effect, Dictionary timing); +void animate4Method(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + Element* impl = V8Element::toNative(info.Holder()); + TONATIVE_VOID(AnimationEffect*, effect, V8AnimationEffect::toNativeWithTypeCheck(info.GetIsolate(), info[0])); + TONATIVE_VOID(Dictionary, timingInput, Dictionary(info[1], info.GetIsolate())); + if (!timingInput.isUndefinedOrNull() && !timingInput.isObject()) { + throwTypeError(ExceptionMessages::failedToExecute("animate", "Element", "parameter 2 ('timingInput') is not an object."), info.GetIsolate()); + return; + } + v8SetReturnValueFast(info, WTF::getPtr(ElementAnimation::animate(*impl, effect, timingInput)), impl); +} + +// [RaisesException] AnimationPlayer animate(sequence<Dictionary> effect, double timing); +void animate5Method(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "animate", "Element", info.Holder(), info.GetIsolate()); + Element* impl = V8Element::toNative(info.Holder()); + TONATIVE_VOID(Vector<Dictionary>, keyframes, toNativeArray<Dictionary>(info[0], 1, info.GetIsolate())); + TONATIVE_VOID(double, duration, static_cast<double>(info[1]->NumberValue())); + RefPtr<AnimationPlayer> result = ElementAnimation::animate(*impl, keyframes, duration, exceptionState); + if (exceptionState.throwIfNeeded()) + return; + v8SetReturnValueFast(info, WTF::getPtr(result.release()), impl); +} + +// [RaisesException] AnimationPlayer animate(sequence<Dictionary> effect, Dictionary timing); +void animate6Method(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "animate", "Element", info.Holder(), info.GetIsolate()); + Element* impl = V8Element::toNative(info.Holder()); + TONATIVE_VOID(Vector<Dictionary>, keyframes, toNativeArray<Dictionary>(info[0], 1, info.GetIsolate())); + TONATIVE_VOID(Dictionary, timingInput, Dictionary(info[1], info.GetIsolate())); + if (!timingInput.isUndefinedOrNull() && !timingInput.isObject()) { + exceptionState.throwTypeError("parameter 2 ('timingInput') is not an object."); + exceptionState.throwIfNeeded(); + return; + } + RefPtr<AnimationPlayer> result = ElementAnimation::animate(*impl, keyframes, timingInput, exceptionState); + if (exceptionState.throwIfNeeded()) + return; + v8SetReturnValueFast(info, WTF::getPtr(result.release()), impl); +} + +void V8Element::animateMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + v8::Isolate* isolate = info.GetIsolate(); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "animate", "Element", info.Holder(), isolate); + // AnimationPlayer animate( + // (AnimationEffect or sequence<Dictionary>)? effect, + // optional (double or Dictionary) timing); + switch (info.Length()) { + case 1: + // null resolved as to AnimationEffect, as if the member were nullable: + // (AnimationEffect? or sequence<Dictionary>) + // instead of the *union* being nullable: + // (AnimationEffect or sequence<Dictionary>)? + // AnimationPlayer animate(AnimationEffect? effect); + if (info[0]->IsNull()) { + animate1Method(info); + return; + } + // AnimationPlayer animate(AnimationEffect effect); + if (V8AnimationEffect::hasInstance(info[0], isolate)) { + animate1Method(info); + return; + } + // [MeasureAs=ElementAnimateKeyframeListEffectNoTiming] + // AnimationPlayer animate(sequence<Dictionary> effect); + if (info[0]->IsArray()) { + UseCounter::count(callingExecutionContext(isolate), UseCounter::ElementAnimateKeyframeListEffectNoTiming); + animate2Method(info); + return; + } + break; + case 2: + // As above, null resolved to AnimationEffect + // AnimationPlayer animate(AnimationEffect? effect, Dictionary timing); + if (info[0]->IsNull() && info[1]->IsObject()) { + animate4Method(info); + return; + } + // AnimationPlayer animate(AnimationEffect? effect, double timing); + if (info[0]->IsNull()) { + animate3Method(info); + return; + } + // AnimationPlayer animate(AnimationEffect effect, Dictionary timing); + if (V8AnimationEffect::hasInstance(info[0], isolate) + && info[1]->IsObject()) { + animate4Method(info); + return; + } + // AnimationPlayer animate(AnimationEffect effect, double timing); + if (V8AnimationEffect::hasInstance(info[0], isolate)) { + animate3Method(info); + return; + } + // [MeasureAs=ElementAnimateKeyframeListEffectObjectTiming] + // AnimationPlayer animate(sequence<Dictionary> effect, Dictionary timing); + if (info[0]->IsArray() && info[1]->IsObject()) { + UseCounter::count(callingExecutionContext(isolate), UseCounter::ElementAnimateKeyframeListEffectObjectTiming); + animate6Method(info); + return; + } + // [MeasureAs=ElementAnimateKeyframeListEffectDoubleTiming] + // AnimationPlayer animate(sequence<Dictionary> effect, double timing); + if (info[0]->IsArray()) { + UseCounter::count(callingExecutionContext(isolate), UseCounter::ElementAnimateKeyframeListEffectDoubleTiming); + animate5Method(info); + return; + } + break; + default: + throwArityTypeError(exceptionState, "[1]", info.Length()); + return; + break; + } + exceptionState.throwTypeError("No function was found that matched the signature provided."); + exceptionState.throwIfNeeded(); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EntryCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EntryCustom.cpp index 98fc46d1cbf..e74cf314240 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EntryCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EntryCustom.cpp @@ -29,11 +29,11 @@ */ #include "config.h" -#include "V8Entry.h" +#include "bindings/modules/v8/V8Entry.h" -#include "V8Attr.h" -#include "V8DirectoryEntry.h" -#include "V8FileEntry.h" +#include "bindings/core/v8/V8Attr.h" +#include "bindings/modules/v8/V8DirectoryEntry.h" +#include "bindings/modules/v8/V8FileEntry.h" #include "bindings/v8/V8Binding.h" #include "wtf/RefPtr.h" diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EntrySyncCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EntrySyncCustom.cpp index 2ebd101e94f..b079b7699ad 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EntrySyncCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EntrySyncCustom.cpp @@ -29,11 +29,11 @@ */ #include "config.h" -#include "V8EntrySync.h" +#include "bindings/modules/v8/V8EntrySync.h" -#include "V8Attr.h" -#include "V8DirectoryEntrySync.h" -#include "V8FileEntrySync.h" +#include "bindings/core/v8/V8Attr.h" +#include "bindings/modules/v8/V8DirectoryEntrySync.h" +#include "bindings/modules/v8/V8FileEntrySync.h" #include "bindings/v8/V8Binding.h" #include "wtf/RefPtr.h" diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ErrorEventCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ErrorEventCustom.cpp index 01ed71acdac..8021350dfbd 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ErrorEventCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ErrorEventCustom.cpp @@ -29,25 +29,23 @@ */ #include "config.h" -#include "V8ErrorEvent.h" +#include "bindings/core/v8/V8ErrorEvent.h" -#include "RuntimeEnabledFeatures.h" -#include "V8Event.h" +#include "bindings/core/v8/V8Event.h" #include "bindings/v8/DOMWrapperWorld.h" #include "bindings/v8/Dictionary.h" -#include "bindings/v8/ScriptState.h" #include "bindings/v8/SerializedScriptValue.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8DOMWrapper.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "core/dom/ContextFeatures.h" +#include "platform/RuntimeEnabledFeatures.h" namespace WebCore { void V8ErrorEvent::errorAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) { - v8::Handle<v8::Value> error = info.Holder()->GetHiddenValue(V8HiddenPropertyName::error(info.GetIsolate())); - + v8::Handle<v8::Value> error = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::error(info.GetIsolate())); if (!error.IsEmpty()) { v8SetReturnValue(info, error); return; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EventCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EventCustom.cpp index d313239f485..86217c40a83 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EventCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EventCustom.cpp @@ -29,16 +29,15 @@ */ #include "config.h" -#include "V8Event.h" +#include "bindings/core/v8/V8Event.h" -#include "EventHeaders.h" -#include "EventInterfaces.h" -#include "V8Clipboard.h" +#include "EventModulesHeaders.h" +#include "EventModulesInterfaces.h" +#include "bindings/core/v8/V8DataTransfer.h" #include "bindings/v8/V8Binding.h" -#include "core/dom/Clipboard.h" +#include "core/clipboard/Clipboard.h" #include "core/events/ClipboardEvent.h" #include "core/events/Event.h" -#include "core/events/ThreadLocalEventNames.h" namespace WebCore { @@ -67,6 +66,7 @@ v8::Handle<v8::Object> wrap(Event* event, v8::Handle<v8::Object> creationContext return V8Event::createWrapper(event, creationContext, isolate); EVENT_INTERFACES_FOR_EACH(TRY_TO_WRAP_WITH_INTERFACE) + EVENT_MODULES_INTERFACES_FOR_EACH(TRY_TO_WRAP_WITH_INTERFACE) return V8Event::createWrapper(event, creationContext, isolate); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EventTargetCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EventTargetCustom.cpp index 8bb41db3bcb..89e7b660449 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EventTargetCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8EventTargetCustom.cpp @@ -29,10 +29,12 @@ */ #include "config.h" -#include "V8EventTarget.h" +#include "bindings/core/v8/V8EventTarget.h" -#include "EventTargetHeaders.h" -#include "EventTargetInterfaces.h" +#include "core/EventTargetHeaders.h" +#include "core/EventTargetInterfaces.h" +#include "modules/EventTargetModulesHeaders.h" +#include "modules/EventTargetModulesInterfaces.h" namespace WebCore { @@ -47,6 +49,7 @@ v8::Handle<v8::Value> toV8(EventTarget* impl, v8::Handle<v8::Object> creationCon AtomicString desiredInterface = impl->interfaceName(); EVENT_TARGET_INTERFACES_FOR_EACH(TRY_TO_WRAP_WITH_INTERFACE) + EVENT_TARGET_MODULES_INTERFACES_FOR_EACH(TRY_TO_WRAP_WITH_INTERFACE) ASSERT_NOT_REACHED(); return v8Undefined(); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8FileCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8FileCustom.cpp index ecbb7815d46..d01acf369cc 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8FileCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8FileCustom.cpp @@ -29,12 +29,11 @@ */ #include "config.h" -#include "V8File.h" +#include "bindings/core/v8/V8File.h" -#include "RuntimeEnabledFeatures.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/custom/V8BlobCustomHelpers.h" -#include "core/fileapi/BlobBuilder.h" +#include "platform/RuntimeEnabledFeatures.h" namespace WebCore { @@ -66,7 +65,7 @@ void V8File::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info) } } - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, fileName, info[1]); + TOSTRING_VOID(V8StringResource<>, fileName, info[1]); V8BlobCustomHelpers::ParsedProperties properties(true); if (info.Length() > 2) { @@ -84,12 +83,14 @@ void V8File::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info) properties.setDefaultLastModified(); } - BlobBuilder blobBuilder; + OwnPtr<BlobData> blobData = BlobData::create(); + blobData->setContentType(properties.contentType()); v8::Local<v8::Object> blobParts = v8::Local<v8::Object>::Cast(info[0]); - if (!V8BlobCustomHelpers::processBlobParts(blobParts, length, properties.endings(), blobBuilder, info.GetIsolate())) + if (!V8BlobCustomHelpers::processBlobParts(blobParts, length, properties.normalizeLineEndingsToNative(), *blobData, info.GetIsolate())) return; - RefPtr<File> file = blobBuilder.createFile(properties.contentType(), fileName, properties.lastModified()); + long long fileSize = blobData->length(); + RefPtrWillBeRawPtr<File> file = File::create(fileName, properties.lastModified(), BlobDataHandle::create(blobData.release(), fileSize)); v8SetReturnValue(info, file.release()); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8FileReaderCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8FileReaderCustom.cpp index c6ee39e6f4b..333040712e5 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8FileReaderCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8FileReaderCustom.cpp @@ -29,7 +29,7 @@ */ #include "config.h" -#include "V8FileReader.h" +#include "bindings/core/v8/V8FileReader.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/custom/V8ArrayBufferCustom.h" @@ -40,12 +40,12 @@ namespace WebCore { void V8FileReader::resultAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) { v8::Handle<v8::Object> holder = info.Holder(); - FileReader* imp = V8FileReader::toNative(holder); - if (imp->readType() == FileReaderLoader::ReadAsArrayBuffer) { - v8SetReturnValueFast(info, imp->arrayBufferResult(), imp); + FileReader* impl = V8FileReader::toNative(holder); + if (impl->readType() == FileReaderLoader::ReadAsArrayBuffer) { + v8SetReturnValueFast(info, impl->arrayBufferResult(), impl); return; } - v8SetReturnValueStringOrNull(info, imp->stringResult(), info.GetIsolate()); + v8SetReturnValueStringOrNull(info, impl->stringResult(), info.GetIsolate()); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Float32ArrayCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Float32ArrayCustom.h index 17ef9710e0a..3caa7d1da2a 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Float32ArrayCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Float32ArrayCustom.h @@ -59,10 +59,6 @@ public: typedef V8TypedArray<Float32Array> V8Float32Array; -template<> -class WrapperTypeTraits<Float32Array> : public TypedArrayWrapperTraits<Float32Array> { }; - - inline v8::Handle<v8::Object> wrap(Float32Array* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { return V8TypedArray<Float32Array>::wrap(impl, creationContext, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Float64ArrayCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Float64ArrayCustom.h index 30ec270d288..0e793b6525f 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Float64ArrayCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Float64ArrayCustom.h @@ -59,10 +59,6 @@ public: typedef V8TypedArray<Float64Array> V8Float64Array; -template<> -class WrapperTypeTraits<Float64Array> : public TypedArrayWrapperTraits<Float64Array> { }; - - inline v8::Handle<v8::Object> wrap(Float64Array* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { return V8TypedArray<Float64Array>::wrap(impl, creationContext, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8FormDataCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8FormDataCustom.cpp deleted file mode 100644 index 890bf034789..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8FormDataCustom.cpp +++ /dev/null @@ -1,71 +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 "V8FormData.h" - -#include "V8Blob.h" -#include "V8HTMLFormElement.h" -#include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" -#include "core/html/DOMFormData.h" - -namespace WebCore { - -void V8FormData::appendMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - if (info.Length() < 2) { - throwError(v8SyntaxError, "Not enough arguments", info.GetIsolate()); - return; - } - - DOMFormData* domFormData = V8FormData::toNative(info.Holder()); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, name, info[0]); - - v8::Handle<v8::Value> arg = info[1]; - if (V8Blob::hasInstance(arg, info.GetIsolate(), worldType(info.GetIsolate()))) { - v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); - Blob* blob = V8Blob::toNative(object); - ASSERT(blob); - - String filename; - if (info.Length() >= 3) { - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, filenameResource, info[2]); - filename = filenameResource; - } - - domFormData->append(name, blob, filename); - } else { - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, argString, arg); - domFormData->append(name, argString); - } -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8GeolocationCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8GeolocationCustom.cpp index 3ce2878edde..e09d99c34bd 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8GeolocationCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8GeolocationCustom.cpp @@ -24,31 +24,29 @@ */ #include "config.h" -#include "V8Geolocation.h" +#include "bindings/modules/v8/V8Geolocation.h" -#include "V8PositionCallback.h" -#include "V8PositionErrorCallback.h" +#include "bindings/modules/v8/V8PositionCallback.h" +#include "bindings/modules/v8/V8PositionErrorCallback.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8Callback.h" -#include "bindings/v8/V8Utilities.h" #include "modules/geolocation/Geolocation.h" -using namespace std; using namespace WTF; namespace WebCore { -static PassRefPtr<PositionOptions> createPositionOptions(v8::Local<v8::Value> value, v8::Isolate* isolate, bool& succeeded) +static PositionOptions* createPositionOptions(v8::Local<v8::Value> value, v8::Isolate* isolate, bool& succeeded, ExceptionState& exceptionState) { succeeded = true; // Create default options. - RefPtr<PositionOptions> options = PositionOptions::create(); + PositionOptions* options = PositionOptions::create(); // Argument is optional (hence undefined is allowed), and null is allowed. if (isUndefinedOrNull(value)) { // Use default options. - return options.release(); + return options; } // Given the above test, this will always yield an object. @@ -61,13 +59,13 @@ static PassRefPtr<PositionOptions> createPositionOptions(v8::Local<v8::Value> va v8::Local<v8::Value> enableHighAccuracyValue = object->Get(v8AtomicString(isolate, "enableHighAccuracy")); if (enableHighAccuracyValue.IsEmpty()) { succeeded = false; - return 0; + return nullptr; } if (!enableHighAccuracyValue->IsUndefined()) { v8::Local<v8::Boolean> enableHighAccuracyBoolean = enableHighAccuracyValue->ToBoolean(); if (enableHighAccuracyBoolean.IsEmpty()) { succeeded = false; - return 0; + return nullptr; } options->setEnableHighAccuracy(enableHighAccuracyBoolean->Value()); } @@ -75,100 +73,88 @@ static PassRefPtr<PositionOptions> createPositionOptions(v8::Local<v8::Value> va v8::Local<v8::Value> timeoutValue = object->Get(v8AtomicString(isolate, "timeout")); if (timeoutValue.IsEmpty()) { succeeded = false; - return 0; + return nullptr; } if (!timeoutValue->IsUndefined()) { v8::Local<v8::Number> timeoutNumber = timeoutValue->ToNumber(); if (timeoutNumber.IsEmpty()) { succeeded = false; - return 0; - } - double timeoutDouble = timeoutNumber->Value(); - // If the value is positive infinity, there's nothing to do. - if (!(std::isinf(timeoutDouble) && timeoutDouble > 0)) { - v8::Local<v8::Int32> timeoutInt32 = timeoutValue->ToInt32(); - if (timeoutInt32.IsEmpty()) { - succeeded = false; - return 0; - } - // Wrap to int32 and force non-negative to match behavior of window.setTimeout. - options->setTimeout(max(0, timeoutInt32->Value())); + return nullptr; } + if (timeoutNumber->Value() <= 0) + options->setTimeout(0); + else + options->setTimeout(toUInt32(timeoutValue, Clamp, exceptionState)); } v8::Local<v8::Value> maximumAgeValue = object->Get(v8AtomicString(isolate, "maximumAge")); if (maximumAgeValue.IsEmpty()) { succeeded = false; - return 0; + return nullptr; } if (!maximumAgeValue->IsUndefined()) { v8::Local<v8::Number> maximumAgeNumber = maximumAgeValue->ToNumber(); if (maximumAgeNumber.IsEmpty()) { succeeded = false; - return 0; - } - double maximumAgeDouble = maximumAgeNumber->Value(); - if (std::isinf(maximumAgeDouble) && maximumAgeDouble > 0) { - // If the value is positive infinity, clear maximumAge. - options->clearMaximumAge(); - } else { - v8::Local<v8::Int32> maximumAgeInt32 = maximumAgeValue->ToInt32(); - if (maximumAgeInt32.IsEmpty()) { - succeeded = false; - return 0; - } - // Wrap to int32 and force non-negative to match behavior of window.setTimeout. - options->setMaximumAge(max(0, maximumAgeInt32->Value())); + return nullptr; } + if (maximumAgeNumber->Value() <= 0) + options->setMaximumAge(0); + else + options->setMaximumAge(toUInt32(maximumAgeValue, Clamp, exceptionState)); } - return options.release(); + return options; } void V8Geolocation::getCurrentPositionMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { bool succeeded = false; - OwnPtr<PositionCallback> positionCallback = createFunctionOnlyCallback<V8PositionCallback>(info[0], succeeded, info.GetIsolate()); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getCurrentPosition", "Geolocation", info.Holder(), info.GetIsolate()); + + OwnPtr<PositionCallback> positionCallback = createFunctionOnlyCallback<V8PositionCallback>(info[0], 1, succeeded, info.GetIsolate(), exceptionState); if (!succeeded) return; ASSERT(positionCallback); // Argument is optional (hence undefined is allowed), and null is allowed. - OwnPtr<PositionErrorCallback> positionErrorCallback = createFunctionOnlyCallback<V8PositionErrorCallback>(info[1], succeeded, info.GetIsolate(), CallbackAllowUndefined | CallbackAllowNull); + OwnPtr<PositionErrorCallback> positionErrorCallback = createFunctionOnlyCallback<V8PositionErrorCallback>(info[1], 2, succeeded, info.GetIsolate(), exceptionState, CallbackAllowUndefined | CallbackAllowNull); if (!succeeded) return; - RefPtr<PositionOptions> positionOptions = createPositionOptions(info[2], info.GetIsolate(), succeeded); + PositionOptions* positionOptions = createPositionOptions(info[2], info.GetIsolate(), succeeded, exceptionState); if (!succeeded) return; ASSERT(positionOptions); Geolocation* geolocation = V8Geolocation::toNative(info.Holder()); - geolocation->getCurrentPosition(positionCallback.release(), positionErrorCallback.release(), positionOptions.release()); + geolocation->getCurrentPosition(positionCallback.release(), positionErrorCallback.release(), positionOptions); } void V8Geolocation::watchPositionMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { bool succeeded = false; - OwnPtr<PositionCallback> positionCallback = createFunctionOnlyCallback<V8PositionCallback>(info[0], succeeded, info.GetIsolate()); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "watchCurrentPosition", "Geolocation", info.Holder(), info.GetIsolate()); + + OwnPtr<PositionCallback> positionCallback = createFunctionOnlyCallback<V8PositionCallback>(info[0], 1, succeeded, info.GetIsolate(), exceptionState); if (!succeeded) return; ASSERT(positionCallback); // Argument is optional (hence undefined is allowed), and null is allowed. - OwnPtr<PositionErrorCallback> positionErrorCallback = createFunctionOnlyCallback<V8PositionErrorCallback>(info[1], succeeded, info.GetIsolate(), CallbackAllowUndefined | CallbackAllowNull); + OwnPtr<PositionErrorCallback> positionErrorCallback = createFunctionOnlyCallback<V8PositionErrorCallback>(info[1], 2, succeeded, info.GetIsolate(), exceptionState, CallbackAllowUndefined | CallbackAllowNull); if (!succeeded) return; - RefPtr<PositionOptions> positionOptions = createPositionOptions(info[2], info.GetIsolate(), succeeded); + PositionOptions* positionOptions = createPositionOptions(info[2], info.GetIsolate(), succeeded, exceptionState); if (!succeeded) return; ASSERT(positionOptions); Geolocation* geolocation = V8Geolocation::toNative(info.Holder()); - int watchId = geolocation->watchPosition(positionCallback.release(), positionErrorCallback.release(), positionOptions.release()); + int watchId = geolocation->watchPosition(positionCallback.release(), positionErrorCallback.release(), positionOptions); v8SetReturnValue(info, watchId); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLAllCollectionCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLAllCollectionCustom.cpp index 670b36cbadd..c0383741326 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLAllCollectionCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLAllCollectionCustom.cpp @@ -29,10 +29,10 @@ */ #include "config.h" -#include "V8HTMLAllCollection.h" +#include "bindings/core/v8/V8HTMLAllCollection.h" -#include "V8Node.h" -#include "V8NodeList.h" +#include "bindings/core/v8/V8Element.h" +#include "bindings/core/v8/V8NodeList.h" #include "bindings/v8/V8Binding.h" #include "core/dom/NamedNodesCollection.h" #include "core/html/HTMLAllCollection.h" @@ -43,7 +43,7 @@ namespace WebCore { template<class CallbackInfo> static v8::Handle<v8::Value> getNamedItems(HTMLAllCollection* collection, AtomicString name, const CallbackInfo& info) { - Vector<RefPtr<Node> > namedItems; + WillBeHeapVector<RefPtrWillBeMember<Element> > namedItems; collection->namedItems(name, namedItems); if (!namedItems.size()) @@ -62,7 +62,7 @@ static v8::Handle<v8::Value> getItem(HTMLAllCollection* collection, v8::Handle<v { v8::Local<v8::Uint32> index = argument->ToArrayIndex(); if (index.IsEmpty()) { - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<>, name, argument, v8::Undefined(info.GetIsolate())); + TOSTRING_DEFAULT(V8StringResource<>, name, argument, v8::Undefined(info.GetIsolate())); v8::Handle<v8::Value> result = getNamedItems(collection, name, info); if (result.IsEmpty()) @@ -71,29 +71,14 @@ static v8::Handle<v8::Value> getItem(HTMLAllCollection* collection, v8::Handle<v return result; } - RefPtr<Node> result = collection->item(index->Uint32Value()); + RefPtrWillBeRawPtr<Element> result = collection->item(index->Uint32Value()); return toV8(result.release(), info.Holder(), info.GetIsolate()); } void V8HTMLAllCollection::itemMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - HTMLAllCollection* imp = V8HTMLAllCollection::toNative(info.Holder()); - v8SetReturnValue(info, getItem(imp, info[0], info)); -} - -void V8HTMLAllCollection::namedItemMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, name, info[0]); - - HTMLAllCollection* imp = V8HTMLAllCollection::toNative(info.Holder()); - v8::Handle<v8::Value> result = getNamedItems(imp, name, info); - - if (result.IsEmpty()) { - v8SetReturnValueNull(info); - return; - } - - v8SetReturnValue(info, result); + HTMLAllCollection* impl = V8HTMLAllCollection::toNative(info.Holder()); + v8SetReturnValue(info, getItem(impl, info[0], info)); } void V8HTMLAllCollection::legacyCallCustom(const v8::FunctionCallbackInfo<v8::Value>& info) @@ -101,25 +86,24 @@ void V8HTMLAllCollection::legacyCallCustom(const v8::FunctionCallbackInfo<v8::Va if (info.Length() < 1) return; - HTMLAllCollection* imp = V8HTMLAllCollection::toNative(info.Holder()); - Node* ownerNode = imp->ownerNode(); - ASSERT(ownerNode); + HTMLAllCollection* impl = V8HTMLAllCollection::toNative(info.Holder()); + Node& ownerNode = impl->ownerNode(); - UseCounter::count(ownerNode->document(), UseCounter::DocumentAllLegacyCall); + UseCounter::count(ownerNode.document(), UseCounter::DocumentAllLegacyCall); if (info.Length() == 1) { - v8SetReturnValue(info, getItem(imp, info[0], info)); + v8SetReturnValue(info, getItem(impl, info[0], info)); return; } // If there is a second argument it is the index of the item we want. - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, name, info[0]); + TOSTRING_VOID(V8StringResource<>, name, info[0]); v8::Local<v8::Uint32> index = info[1]->ToArrayIndex(); if (index.IsEmpty()) return; - if (Node* node = imp->namedItemWithIndex(name, index->Uint32Value())) { - v8SetReturnValueFast(info, node, imp); + if (Node* node = impl->namedItemWithIndex(name, index->Uint32Value())) { + v8SetReturnValueFast(info, node, impl); return; } } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp index c69cbdde418..46a15946f72 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLCanvasElementCustom.cpp @@ -30,13 +30,12 @@ */ #include "config.h" -#include "V8HTMLCanvasElement.h" +#include "bindings/core/v8/V8HTMLCanvasElement.h" -#include "V8CanvasRenderingContext2D.h" -#include "V8Node.h" -#include "V8WebGLRenderingContext.h" +#include "bindings/core/v8/V8CanvasRenderingContext2D.h" +#include "bindings/core/v8/V8Node.h" +#include "bindings/core/v8/V8WebGLRenderingContext.h" #include "bindings/v8/ExceptionState.h" -#include "bindings/v8/ScriptState.h" #include "bindings/v8/V8Binding.h" #include "core/html/HTMLCanvasElement.h" #include "core/html/canvas/Canvas2DContextAttributes.h" @@ -52,34 +51,34 @@ void V8HTMLCanvasElement::getContextMethodCustom(const v8::FunctionCallbackInfo< { v8::Handle<v8::Object> holder = info.Holder(); v8::Isolate* isolate = info.GetIsolate(); - HTMLCanvasElement* imp = V8HTMLCanvasElement::toNative(holder); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, contextIdResource, info[0]); + HTMLCanvasElement* impl = V8HTMLCanvasElement::toNative(holder); + TOSTRING_VOID(V8StringResource<>, contextIdResource, info[0]); String contextId = contextIdResource; RefPtr<CanvasContextAttributes> attributes; - if (contextId == "webgl" || contextId == "experimental-webgl" || contextId == "webkit-3d") { + if (contextId == "webgl" || contextId == "experimental-webgl") { RefPtr<WebGLContextAttributes> webGLAttributes = WebGLContextAttributes::create(); if (info.Length() > 1 && info[1]->IsObject()) { v8::Handle<v8::Object> jsAttributes = info[1]->ToObject(); v8::Handle<v8::String> alpha = v8AtomicString(isolate, "alpha"); - if (jsAttributes->Has(alpha)) + if (jsAttributes->Has(alpha) && !isUndefinedOrNull(jsAttributes->Get(alpha))) webGLAttributes->setAlpha(jsAttributes->Get(alpha)->BooleanValue()); v8::Handle<v8::String> depth = v8AtomicString(isolate, "depth"); - if (jsAttributes->Has(depth)) + if (jsAttributes->Has(depth) && !isUndefinedOrNull(jsAttributes->Get(depth))) webGLAttributes->setDepth(jsAttributes->Get(depth)->BooleanValue()); v8::Handle<v8::String> stencil = v8AtomicString(isolate, "stencil"); - if (jsAttributes->Has(stencil)) + if (jsAttributes->Has(stencil) && !isUndefinedOrNull(jsAttributes->Get(stencil))) webGLAttributes->setStencil(jsAttributes->Get(stencil)->BooleanValue()); v8::Handle<v8::String> antialias = v8AtomicString(isolate, "antialias"); - if (jsAttributes->Has(antialias)) + if (jsAttributes->Has(antialias) && !isUndefinedOrNull(jsAttributes->Get(antialias))) webGLAttributes->setAntialias(jsAttributes->Get(antialias)->BooleanValue()); v8::Handle<v8::String> premultipliedAlpha = v8AtomicString(isolate, "premultipliedAlpha"); - if (jsAttributes->Has(premultipliedAlpha)) + if (jsAttributes->Has(premultipliedAlpha) && !isUndefinedOrNull(jsAttributes->Get(premultipliedAlpha))) webGLAttributes->setPremultipliedAlpha(jsAttributes->Get(premultipliedAlpha)->BooleanValue()); v8::Handle<v8::String> preserveDrawingBuffer = v8AtomicString(isolate, "preserveDrawingBuffer"); - if (jsAttributes->Has(preserveDrawingBuffer)) + if (jsAttributes->Has(preserveDrawingBuffer) && !isUndefinedOrNull(jsAttributes->Get(preserveDrawingBuffer))) webGLAttributes->setPreserveDrawingBuffer(jsAttributes->Get(preserveDrawingBuffer)->BooleanValue()); v8::Handle<v8::String> failIfMajorPerformanceCaveat = v8AtomicString(isolate, "failIfMajorPerformanceCaveat"); - if (jsAttributes->Has(failIfMajorPerformanceCaveat)) + if (jsAttributes->Has(failIfMajorPerformanceCaveat) && !isUndefinedOrNull(jsAttributes->Get(failIfMajorPerformanceCaveat))) webGLAttributes->setFailIfMajorPerformanceCaveat(jsAttributes->Get(failIfMajorPerformanceCaveat)->BooleanValue()); } attributes = webGLAttributes; @@ -88,23 +87,23 @@ void V8HTMLCanvasElement::getContextMethodCustom(const v8::FunctionCallbackInfo< if (info.Length() > 1 && info[1]->IsObject()) { v8::Handle<v8::Object> jsAttributes = info[1]->ToObject(); v8::Handle<v8::String> alpha = v8AtomicString(isolate, "alpha"); - if (jsAttributes->Has(alpha)) + if (jsAttributes->Has(alpha) && !isUndefinedOrNull(jsAttributes->Get(alpha))) canvas2DAttributes->setAlpha(jsAttributes->Get(alpha)->BooleanValue()); } attributes = canvas2DAttributes; } - CanvasRenderingContext* result = imp->getContext(contextId, attributes.get()); + CanvasRenderingContext* result = impl->getContext(contextId, attributes.get()); if (!result) { v8SetReturnValueNull(info); return; } if (result->is2d()) { v8::Handle<v8::Value> v8Result = toV8(toCanvasRenderingContext2D(result), info.Holder(), info.GetIsolate()); - if (InspectorInstrumentation::canvasAgentEnabled(&imp->document())) { - ScriptState* scriptState = ScriptState::forContext(isolate->GetCurrentContext()); - ScriptObject context(scriptState, v8::Handle<v8::Object>::Cast(v8Result)); - ScriptObject wrapped = InspectorInstrumentation::wrapCanvas2DRenderingContextForInstrumentation(&imp->document(), context); - if (!wrapped.hasNoValue()) { + if (InspectorInstrumentation::canvasAgentEnabled(&impl->document())) { + ScriptState* scriptState = ScriptState::current(isolate); + ScriptValue context(scriptState, v8Result); + ScriptValue wrapped = InspectorInstrumentation::wrapCanvas2DRenderingContextForInstrumentation(&impl->document(), context); + if (!wrapped.isEmpty()) { v8SetReturnValue(info, wrapped.v8Value()); return; } @@ -114,11 +113,11 @@ void V8HTMLCanvasElement::getContextMethodCustom(const v8::FunctionCallbackInfo< } if (result->is3d()) { v8::Handle<v8::Value> v8Result = toV8(toWebGLRenderingContext(result), info.Holder(), info.GetIsolate()); - if (InspectorInstrumentation::canvasAgentEnabled(&imp->document())) { - ScriptState* scriptState = ScriptState::forContext(isolate->GetCurrentContext()); - ScriptObject glContext(scriptState, v8::Handle<v8::Object>::Cast(v8Result)); - ScriptObject wrapped = InspectorInstrumentation::wrapWebGLRenderingContextForInstrumentation(&imp->document(), glContext); - if (!wrapped.hasNoValue()) { + if (InspectorInstrumentation::canvasAgentEnabled(&impl->document())) { + ScriptState* scriptState = ScriptState::current(isolate); + ScriptValue glContext(scriptState, v8Result); + ScriptValue wrapped = InspectorInstrumentation::wrapWebGLRenderingContextForInstrumentation(&impl->document(), glContext); + if (!wrapped.isEmpty()) { v8SetReturnValue(info, wrapped.v8Value()); return; } @@ -136,7 +135,7 @@ void V8HTMLCanvasElement::toDataURLMethodCustom(const v8::FunctionCallbackInfo<v HTMLCanvasElement* canvas = V8HTMLCanvasElement::toNative(holder); ExceptionState exceptionState(ExceptionState::ExecutionContext, "toDataURL", "HTMLCanvasElement", info.Holder(), info.GetIsolate()); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, type, info[0]); + TOSTRING_VOID(V8StringResource<>, type, info[0]); double quality; double* qualityPtr = 0; if (info.Length() > 1 && info[1]->IsNumber()) { diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLCollectionCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLCollectionCustom.cpp index 33fd4ca1d38..05883e60cee 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLCollectionCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLCollectionCustom.cpp @@ -29,12 +29,12 @@ */ #include "config.h" -#include "V8HTMLCollection.h" +#include "bindings/core/v8/V8HTMLCollection.h" -#include "V8HTMLAllCollection.h" -#include "V8HTMLFormControlsCollection.h" -#include "V8HTMLOptionsCollection.h" -#include "V8Node.h" +#include "bindings/core/v8/V8HTMLAllCollection.h" +#include "bindings/core/v8/V8HTMLFormControlsCollection.h" +#include "bindings/core/v8/V8HTMLOptionsCollection.h" +#include "bindings/core/v8/V8Node.h" #include "bindings/v8/V8Binding.h" #include "core/html/HTMLCollection.h" @@ -45,11 +45,11 @@ v8::Handle<v8::Object> wrap(HTMLCollection* impl, v8::Handle<v8::Object> creatio ASSERT(impl); switch (impl->type()) { case FormControls: - return wrap(static_cast<HTMLFormControlsCollection*>(impl), creationContext, isolate); + return wrap(toHTMLFormControlsCollection(impl), creationContext, isolate); case SelectOptions: - return wrap(static_cast<HTMLOptionsCollection*>(impl), creationContext, isolate); + return wrap(toHTMLOptionsCollection(impl), creationContext, isolate); case DocAll: - return wrap(static_cast<HTMLAllCollection*>(impl), creationContext, isolate); + return wrap(toHTMLAllCollection(impl), creationContext, isolate); default: break; } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLDocumentCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLDocumentCustom.cpp index 49f76e73080..1f1a99bf49f 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLDocumentCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLDocumentCustom.cpp @@ -29,20 +29,20 @@ */ #include "config.h" -#include "V8HTMLDocument.h" +#include "bindings/core/v8/V8HTMLDocument.h" -#include "HTMLNames.h" -#include "V8HTMLAllCollection.h" -#include "V8HTMLCollection.h" -#include "V8Node.h" -#include "V8Window.h" +#include "bindings/core/v8/V8HTMLAllCollection.h" +#include "bindings/core/v8/V8HTMLCollection.h" +#include "bindings/core/v8/V8Node.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/ScriptController.h" #include "bindings/v8/V8Binding.h" +#include "core/HTMLNames.h" +#include "core/frame/LocalFrame.h" #include "core/html/HTMLAllCollection.h" #include "core/html/HTMLCollection.h" #include "core/html/HTMLDocument.h" #include "core/html/HTMLIFrameElement.h" -#include "core/frame/Frame.h" #include "wtf/OwnPtr.h" #include "wtf/RefPtr.h" #include "wtf/StdLibExtras.h" @@ -56,15 +56,18 @@ void V8HTMLDocument::openMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& HTMLDocument* htmlDocument = V8HTMLDocument::toNative(info.Holder()); if (info.Length() > 2) { - if (RefPtr<Frame> frame = htmlDocument->frame()) { + if (RefPtr<LocalFrame> frame = htmlDocument->frame()) { // Fetch the global object for the frame. - v8::Local<v8::Context> context = frame->script().currentWorldContext(); + v8::Local<v8::Context> context = toV8Context(frame.get(), DOMWrapperWorld::current(info.GetIsolate())); // Bail out if we cannot get the context. if (context.IsEmpty()) return; v8::Local<v8::Object> global = context->Global(); // Get the open property of the global object. v8::Local<v8::Value> function = global->Get(v8AtomicString(info.GetIsolate(), "open")); + // Failed; return without throwing (new) exception. + if (function.IsEmpty()) + return; // If the open property is not a function throw a type error. if (!function->IsFunction()) { throwTypeError("open is not a function", info.GetIsolate()); @@ -80,7 +83,11 @@ void V8HTMLDocument::openMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& } } - htmlDocument->open(activeDOMWindow()->document()); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "open", "Document", info.Holder(), info.GetIsolate()); + htmlDocument->open(callingDOMWindow(info.GetIsolate())->document(), exceptionState); + if (exceptionState.throwIfNeeded()) + return; + v8SetReturnValue(info, info.Holder()); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLElementCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLElementCustom.cpp index dae4512d1dc..78706afe722 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLElementCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLElementCustom.cpp @@ -29,9 +29,9 @@ */ #include "config.h" -#include "V8HTMLElement.h" +#include "bindings/core/v8/V8HTMLElement.h" -#include "V8HTMLElementWrapperFactory.h" +#include "core/V8HTMLElementWrapperFactory.h" // FIXME: should be bindings/core/v8 namespace WebCore { diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLFormControlsCollectionCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLFormControlsCollectionCustom.cpp deleted file mode 100644 index ab84454965f..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLFormControlsCollectionCustom.cpp +++ /dev/null @@ -1,71 +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" -#include "V8HTMLFormControlsCollection.h" - -#include "V8Node.h" -#include "V8RadioNodeList.h" -#include "bindings/v8/V8Binding.h" -#include "core/html/HTMLCollection.h" -#include "core/html/RadioNodeList.h" - -namespace WebCore { - -template<typename CallbackInfo> -static v8::Handle<v8::Value> getNamedItems(HTMLFormControlsCollection* collection, const AtomicString& name, const CallbackInfo& info) -{ - Vector<RefPtr<Node> > namedItems; - collection->namedItems(name, namedItems); - - if (!namedItems.size()) - return v8Undefined(); - - if (namedItems.size() == 1) - return toV8(namedItems.at(0).release(), info.Holder(), info.GetIsolate()); - - return toV8(collection->ownerNode()->radioNodeList(name).get(), info.Holder(), info.GetIsolate()); -} - -void V8HTMLFormControlsCollection::namedItemMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, name, info[0]); - HTMLFormControlsCollection* imp = V8HTMLFormControlsCollection::toNative(info.Holder()); - v8::Handle<v8::Value> result = getNamedItems(imp, name, info); - - if (result.IsEmpty()) { - v8SetReturnValueNull(info); - return; - } - - v8SetReturnValue(info, result); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLFrameElementCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLFrameElementCustom.cpp deleted file mode 100644 index 8c011d0d922..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLFrameElementCustom.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2007-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" -#include "V8HTMLFrameElement.h" - -#include "HTMLNames.h" -#include "bindings/v8/BindingSecurity.h" -#include "bindings/v8/ExceptionState.h" -#include "bindings/v8/V8Binding.h" -#include "core/html/HTMLFrameElement.h" -#include "core/html/parser/HTMLParserIdioms.h" - -namespace WebCore { - -using namespace HTMLNames; - -void V8HTMLFrameElement::locationAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) -{ - HTMLFrameElement* frame = V8HTMLFrameElement::toNative(info.Holder()); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, locationValue, value); - - ExceptionState exceptionState(info.Holder(), info.GetIsolate()); - if (protocolIsJavaScript(stripLeadingAndTrailingHTMLSpaces(locationValue)) && !BindingSecurity::shouldAllowAccessToFrame(frame->contentFrame(), exceptionState)) { - exceptionState.throwIfNeeded(); - return; - } - - frame->setLocation(locationValue); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp index 094bf4acc8b..08ffb16adbd 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLOptionsCollectionCustom.cpp @@ -29,12 +29,11 @@ */ #include "config.h" -#include "V8HTMLOptionsCollection.h" +#include "bindings/core/v8/V8HTMLOptionsCollection.h" -#include "V8HTMLOptionElement.h" -#include "V8Node.h" -#include "V8NodeList.h" -#include "bindings/v8/ExceptionMessages.h" +#include "bindings/core/v8/V8HTMLOptionElement.h" +#include "bindings/core/v8/V8Node.h" +#include "bindings/core/v8/V8NodeList.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" #include "core/dom/ExceptionCode.h" @@ -45,50 +44,23 @@ namespace WebCore { -template<typename CallbackInfo> -static void getNamedItems(HTMLOptionsCollection* collection, const AtomicString& name, const CallbackInfo& info) -{ - Vector<RefPtr<Node> > namedItems; - collection->namedItems(name, namedItems); - - if (!namedItems.size()) { - v8SetReturnValueNull(info); - return; - } - - if (namedItems.size() == 1) { - v8SetReturnValueFast(info, namedItems.at(0).release(), collection); - return; - } - - v8SetReturnValueFast(info, NamedNodesCollection::create(namedItems), collection); -} - -void V8HTMLOptionsCollection::namedItemMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, name, info[0]); - HTMLOptionsCollection* imp = V8HTMLOptionsCollection::toNative(info.Holder()); - getNamedItems(imp, name, info); -} - void V8HTMLOptionsCollection::addMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { ExceptionState exceptionState(ExceptionState::ExecutionContext, "add", "HTMLOptionsCollection", info.Holder(), info.GetIsolate()); - if (!V8HTMLOptionElement::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { + if (!V8HTMLOptionElement::hasInstance(info[0], info.GetIsolate())) { exceptionState.throwTypeError("The element provided was not an HTMLOptionElement."); } else { - HTMLOptionsCollection* imp = V8HTMLOptionsCollection::toNative(info.Holder()); + HTMLOptionsCollection* impl = V8HTMLOptionsCollection::toNative(info.Holder()); HTMLOptionElement* option = V8HTMLOptionElement::toNative(v8::Handle<v8::Object>(v8::Handle<v8::Object>::Cast(info[0]))); if (info.Length() < 2) { - imp->add(option, exceptionState); + impl->add(option, exceptionState); } else { - bool ok; - V8TRYCATCH_VOID(int, index, toInt32(info[1], ok)); - if (!ok) - exceptionState.throwTypeError("The index provided could not be interpreted as an integer."); - else - imp->add(option, index, exceptionState); + int index = toInt32(info[1], exceptionState); + if (exceptionState.throwIfNeeded()) + return; + + impl->add(option, index, exceptionState); } } @@ -97,7 +69,7 @@ void V8HTMLOptionsCollection::addMethodCustom(const v8::FunctionCallbackInfo<v8: void V8HTMLOptionsCollection::lengthAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) { - HTMLOptionsCollection* imp = V8HTMLOptionsCollection::toNative(info.Holder()); + HTMLOptionsCollection* impl = V8HTMLOptionsCollection::toNative(info.Holder()); double v = value->NumberValue(); unsigned newLength = 0; ExceptionState exceptionState(ExceptionState::SetterContext, "length", "HTMLOptionsCollection", info.Holder(), info.GetIsolate()); @@ -113,7 +85,7 @@ void V8HTMLOptionsCollection::lengthAttributeSetterCustom(v8::Local<v8::Value> v if (exceptionState.throwIfNeeded()) return; - imp->setLength(newLength, exceptionState); + impl->setLength(newLength, exceptionState); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLPlugInElementCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLPlugInElementCustom.cpp index d29360ac3cb..ac4f4cde34c 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLPlugInElementCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HTMLPlugInElementCustom.cpp @@ -30,9 +30,9 @@ #include "config.h" -#include "V8HTMLAppletElement.h" -#include "V8HTMLEmbedElement.h" -#include "V8HTMLObjectElement.h" +#include "bindings/core/v8/V8HTMLAppletElement.h" +#include "bindings/core/v8/V8HTMLEmbedElement.h" +#include "bindings/core/v8/V8HTMLObjectElement.h" #include "bindings/v8/SharedPersistent.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8NPObject.h" @@ -46,8 +46,8 @@ namespace WebCore { template <class C> static void npObjectNamedGetter(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info) { - HTMLPlugInElement* imp = C::toNative(info.Holder()); - RefPtr<SharedPersistent<v8::Object> > wrapper = imp->pluginWrapper(); + HTMLPlugInElement* impl = C::toNative(info.Holder()); + RefPtr<SharedPersistent<v8::Object> > wrapper = impl->pluginWrapper(); if (!wrapper) return; @@ -61,8 +61,8 @@ static void npObjectNamedGetter(v8::Local<v8::String> name, const v8::PropertyCa template <class C> static void npObjectNamedSetter(v8::Local<v8::String> name, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) { - HTMLPlugInElement* imp = C::toNative(info.Holder()); - RefPtr<SharedPersistent<v8::Object> > wrapper = imp->pluginWrapper(); + HTMLPlugInElement* impl = C::toNative(info.Holder()); + RefPtr<SharedPersistent<v8::Object> > wrapper = impl->pluginWrapper(); if (!wrapper) return; @@ -105,30 +105,30 @@ void V8HTMLObjectElement::namedPropertySetterCustom(v8::Local<v8::String> name, void V8HTMLAppletElement::legacyCallCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - HTMLPlugInElement* imp = V8HTMLAppletElement::toNative(info.Holder()); - UseCounter::count(imp->document(), UseCounter::HTMLAppletElementLegacyCall); + HTMLPlugInElement* impl = V8HTMLAppletElement::toNative(info.Holder()); + UseCounter::count(impl->document(), UseCounter::HTMLAppletElementLegacyCall); npObjectInvokeDefaultHandler(info); } void V8HTMLEmbedElement::legacyCallCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - HTMLPlugInElement* imp = V8HTMLEmbedElement::toNative(info.Holder()); - UseCounter::count(imp->document(), UseCounter::HTMLEmbedElementLegacyCall); + HTMLPlugInElement* impl = V8HTMLEmbedElement::toNative(info.Holder()); + UseCounter::count(impl->document(), UseCounter::HTMLEmbedElementLegacyCall); npObjectInvokeDefaultHandler(info); } void V8HTMLObjectElement::legacyCallCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - HTMLPlugInElement* imp = V8HTMLObjectElement::toNative(info.Holder()); - UseCounter::count(imp->document(), UseCounter::HTMLObjectElementLegacyCall); + HTMLPlugInElement* impl = V8HTMLObjectElement::toNative(info.Holder()); + UseCounter::count(impl->document(), UseCounter::HTMLObjectElementLegacyCall); npObjectInvokeDefaultHandler(info); } template <class C> void npObjectIndexedGetter(uint32_t index, const v8::PropertyCallbackInfo<v8::Value>& info) { - HTMLPlugInElement* imp = C::toNative(info.Holder()); - RefPtr<SharedPersistent<v8::Object> > wrapper = imp->pluginWrapper(); + HTMLPlugInElement* impl = C::toNative(info.Holder()); + RefPtr<SharedPersistent<v8::Object> > wrapper = impl->pluginWrapper(); if (!wrapper) return; @@ -142,8 +142,8 @@ void npObjectIndexedGetter(uint32_t index, const v8::PropertyCallbackInfo<v8::Va template <class C> void npObjectIndexedSetter(uint32_t index, v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<v8::Value>& info) { - HTMLPlugInElement* imp = C::toNative(info.Holder()); - RefPtr<SharedPersistent<v8::Object> > wrapper = imp->pluginWrapper(); + HTMLPlugInElement* impl = C::toNative(info.Holder()); + RefPtr<SharedPersistent<v8::Object> > wrapper = impl->pluginWrapper(); if (!wrapper) return; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HistoryCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HistoryCustom.cpp index 427e8776532..ec963bf1204 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HistoryCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8HistoryCustom.cpp @@ -29,13 +29,13 @@ */ #include "config.h" -#include "V8History.h" +#include "bindings/core/v8/V8History.h" -#include "V8Window.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/SerializedScriptValue.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "core/dom/ExceptionCode.h" #include "core/frame/History.h" @@ -45,7 +45,7 @@ void V8History::stateAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Va { History* history = V8History::toNative(info.Holder()); - v8::Handle<v8::Value> value = info.Holder()->GetHiddenValue(V8HiddenPropertyName::state(info.GetIsolate())); + v8::Handle<v8::Value> value = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::state(info.GetIsolate())); if (!value.IsEmpty() && !history->stateChanged()) { v8SetReturnValue(info, value); @@ -54,42 +54,40 @@ void V8History::stateAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Va RefPtr<SerializedScriptValue> serialized = history->state(); value = serialized ? serialized->deserialize(info.GetIsolate()) : v8::Handle<v8::Value>(v8::Null(info.GetIsolate())); - info.Holder()->SetHiddenValue(V8HiddenPropertyName::state(info.GetIsolate()), value); + V8HiddenValue::setHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::state(info.GetIsolate()), value); v8SetReturnValue(info, value); } void V8History::pushStateMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - bool didThrow = false; - RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(info[0], 0, 0, didThrow, info.GetIsolate()); - if (didThrow) + ExceptionState exceptionState(ExceptionState::ExecutionContext, "pushState", "History", info.Holder(), info.GetIsolate()); + RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(info[0], 0, 0, exceptionState, info.GetIsolate()); + if (exceptionState.throwIfNeeded()) return; - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, title, info[1]); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, url, argumentOrNull(info, 2)); + TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, title, info[1]); + TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, url, argumentOrNull(info, 2)); - ExceptionState exceptionState(info.Holder(), info.GetIsolate()); History* history = V8History::toNative(info.Holder()); - history->stateObjectAdded(historyState.release(), title, url, SameDocumentNavigationPushState, exceptionState); - info.Holder()->DeleteHiddenValue(V8HiddenPropertyName::state(info.GetIsolate())); + history->stateObjectAdded(historyState.release(), title, url, FrameLoadTypeStandard, exceptionState); + V8HiddenValue::deleteHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::state(info.GetIsolate())); exceptionState.throwIfNeeded(); } void V8History::replaceStateMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - bool didThrow = false; - RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(info[0], 0, 0, didThrow, info.GetIsolate()); - if (didThrow) + ExceptionState exceptionState(ExceptionState::ExecutionContext, "replaceState", "History", info.Holder(), info.GetIsolate()); + RefPtr<SerializedScriptValue> historyState = SerializedScriptValue::create(info[0], 0, 0, exceptionState, info.GetIsolate()); + if (exceptionState.throwIfNeeded()) return; - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, title, info[1]); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, url, argumentOrNull(info, 2)); + TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, title, info[1]); + TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, url, argumentOrNull(info, 2)); - ExceptionState exceptionState(info.Holder(), info.GetIsolate()); History* history = V8History::toNative(info.Holder()); - history->stateObjectAdded(historyState.release(), title, url, SameDocumentNavigationReplaceState, exceptionState); - info.Holder()->DeleteHiddenValue(V8HiddenPropertyName::state(info.GetIsolate())); + history->stateObjectAdded(historyState.release(), title, url, FrameLoadTypeRedirectWithLockedBackForwardList, exceptionState); + V8HiddenValue::deleteHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::state(info.GetIsolate())); exceptionState.throwIfNeeded(); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ImageDataCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ImageDataCustom.cpp index 813731456ec..c940c7c44f8 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ImageDataCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ImageDataCustom.cpp @@ -29,7 +29,7 @@ */ #include "config.h" -#include "V8ImageData.h" +#include "bindings/core/v8/V8ImageData.h" #include "bindings/v8/custom/V8Uint8ClampedArrayCustom.h" diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InjectedScriptHostCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InjectedScriptHostCustom.cpp index cb545e6e3a3..772649e1bfb 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InjectedScriptHostCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InjectedScriptHostCustom.cpp @@ -29,21 +29,21 @@ */ #include "config.h" -#include "V8InjectedScriptHost.h" - -#include "V8Database.h" -#include "V8HTMLAllCollection.h" -#include "V8HTMLCollection.h" -#include "V8Node.h" -#include "V8NodeList.h" -#include "V8Storage.h" +#include "bindings/core/v8/V8InjectedScriptHost.h" + +#include "bindings/core/v8/V8EventTarget.h" +#include "bindings/core/v8/V8HTMLAllCollection.h" +#include "bindings/core/v8/V8HTMLCollection.h" +#include "bindings/core/v8/V8Node.h" +#include "bindings/core/v8/V8NodeList.h" +#include "bindings/core/v8/V8Storage.h" +#include "bindings/modules/v8/V8Database.h" #include "bindings/v8/BindingSecurity.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ScriptDebugServer.h" #include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8AbstractEventListener.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" #include "bindings/v8/V8ScriptRunner.h" #include "bindings/v8/custom/V8Float32ArrayCustom.h" #include "bindings/v8/custom/V8Float64ArrayCustom.h" @@ -54,6 +54,8 @@ #include "bindings/v8/custom/V8Uint32ArrayCustom.h" #include "bindings/v8/custom/V8Uint8ArrayCustom.h" #include "bindings/v8/custom/V8Uint8ClampedArrayCustom.h" +#include "core/events/EventTarget.h" +#include "core/frame/LocalDOMWindow.h" #include "core/inspector/InjectedScript.h" #include "core/inspector/InjectedScriptHost.h" #include "core/inspector/InspectorDOMAgent.h" @@ -62,25 +64,22 @@ namespace WebCore { -Node* InjectedScriptHost::scriptValueAsNode(ScriptValue value) +Node* InjectedScriptHost::scriptValueAsNode(ScriptState* scriptState, ScriptValue value) { - v8::HandleScope scope(value.isolate()); + ScriptState::Scope scope(scriptState); if (!value.isObject() || value.isNull()) return 0; return V8Node::toNative(v8::Handle<v8::Object>::Cast(value.v8Value())); } -ScriptValue InjectedScriptHost::nodeAsScriptValue(ScriptState* state, Node* node) +ScriptValue InjectedScriptHost::nodeAsScriptValue(ScriptState* scriptState, Node* node) { - v8::Isolate* isolate = state->isolate(); - v8::HandleScope scope(isolate); - v8::Local<v8::Context> context = state->context(); - v8::Context::Scope contextScope(context); - - ExceptionState exceptionState(v8::Handle<v8::Object>(), isolate); - if (!BindingSecurity::shouldAllowAccessToNode(node, exceptionState)) - return ScriptValue(v8::Null(isolate), isolate); - return ScriptValue(toV8(node, v8::Handle<v8::Object>(), isolate), isolate); + ScriptState::Scope scope(scriptState); + v8::Isolate* isolate = scriptState->isolate(); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "nodeAsScriptValue", "InjectedScriptHost", scriptState->context()->Global(), isolate); + if (!BindingSecurity::shouldAllowAccessToNode(isolate, node, exceptionState)) + return ScriptValue(scriptState, v8::Null(isolate)); + return ScriptValue(scriptState, toV8(node, scriptState->context()->Global(), isolate)); } void V8InjectedScriptHost::inspectedObjectMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) @@ -95,7 +94,7 @@ void V8InjectedScriptHost::inspectedObjectMethodCustom(const v8::FunctionCallbac InjectedScriptHost* host = V8InjectedScriptHost::toNative(info.Holder()); InjectedScriptHost::InspectableObject* object = host->inspectedObject(info[0]->ToInt32()->Value()); - v8SetReturnValue(info, object->get(ScriptState::current()).v8Value()); + v8SetReturnValue(info, object->get(ScriptState::current(info.GetIsolate())).v8Value()); } void V8InjectedScriptHost::internalConstructorNameMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) @@ -119,7 +118,7 @@ void V8InjectedScriptHost::isHTMLAllCollectionMethodCustom(const v8::FunctionCal return; } - v8SetReturnValue(info, V8HTMLAllCollection::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))); + v8SetReturnValue(info, V8HTMLAllCollection::hasInstance(info[0], info.GetIsolate())); } void V8InjectedScriptHost::typeMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) @@ -153,32 +152,31 @@ void V8InjectedScriptHost::typeMethodCustom(const v8::FunctionCallbackInfo<v8::V v8SetReturnValue(info, v8AtomicString(isolate, "regexp")); return; } - WrapperWorldType currentWorldType = worldType(isolate); - if (V8Node::hasInstance(value, isolate, currentWorldType)) { + if (V8Node::hasInstance(value, isolate)) { v8SetReturnValue(info, v8AtomicString(isolate, "node")); return; } - if (V8NodeList::hasInstance(value, isolate, currentWorldType)) { + if (V8NodeList::hasInstance(value, isolate)) { v8SetReturnValue(info, v8AtomicString(isolate, "array")); return; } - if (V8HTMLCollection::hasInstance(value, isolate, currentWorldType)) { + if (V8HTMLCollection::hasInstance(value, isolate)) { v8SetReturnValue(info, v8AtomicString(isolate, "array")); return; } - if (V8Int8Array::hasInstance(value, isolate, currentWorldType) || V8Int16Array::hasInstance(value, isolate, currentWorldType) || V8Int32Array::hasInstance(value, isolate, currentWorldType)) { + if (V8Int8Array::hasInstance(value, isolate) || V8Int16Array::hasInstance(value, isolate) || V8Int32Array::hasInstance(value, isolate)) { v8SetReturnValue(info, v8AtomicString(isolate, "array")); return; } - if (V8Uint8Array::hasInstance(value, isolate, currentWorldType) || V8Uint16Array::hasInstance(value, isolate, currentWorldType) || V8Uint32Array::hasInstance(value, isolate, currentWorldType)) { + if (V8Uint8Array::hasInstance(value, isolate) || V8Uint16Array::hasInstance(value, isolate) || V8Uint32Array::hasInstance(value, isolate)) { v8SetReturnValue(info, v8AtomicString(isolate, "array")); return; } - if (V8Float32Array::hasInstance(value, isolate, currentWorldType) || V8Float64Array::hasInstance(value, isolate, currentWorldType)) { + if (V8Float32Array::hasInstance(value, isolate) || V8Float64Array::hasInstance(value, isolate)) { v8SetReturnValue(info, v8AtomicString(isolate, "array")); return; } - if (V8Uint8ClampedArray::hasInstance(value, isolate, currentWorldType)) { + if (V8Uint8ClampedArray::hasInstance(value, isolate)) { v8SetReturnValue(info, v8AtomicString(isolate, "array")); return; } @@ -207,12 +205,12 @@ void V8InjectedScriptHost::functionDetailsMethodCustom(const v8::FunctionCallbac int lineNumber = function->GetScriptLineNumber(); int columnNumber = function->GetScriptColumnNumber(); - v8::Local<v8::Object> location = v8::Object::New(); - location->Set(v8AtomicString(isolate, "lineNumber"), v8::Integer::New(lineNumber, isolate)); - location->Set(v8AtomicString(isolate, "columnNumber"), v8::Integer::New(columnNumber, isolate)); - location->Set(v8AtomicString(isolate, "scriptId"), v8::Integer::New(function->ScriptId(), isolate)->ToString()); + v8::Local<v8::Object> location = v8::Object::New(isolate); + location->Set(v8AtomicString(isolate, "lineNumber"), v8::Integer::New(isolate, lineNumber)); + location->Set(v8AtomicString(isolate, "columnNumber"), v8::Integer::New(isolate, columnNumber)); + location->Set(v8AtomicString(isolate, "scriptId"), v8::Integer::New(isolate, function->ScriptId())->ToString()); - v8::Local<v8::Object> result = v8::Object::New(); + v8::Local<v8::Object> result = v8::Object::New(isolate); result->Set(v8AtomicString(isolate, "location"), location); if (!setFunctionName(result, function->GetDisplayName(), isolate) @@ -241,7 +239,7 @@ void V8InjectedScriptHost::getInternalPropertiesMethodCustom(const v8::FunctionC v8SetReturnValue(info, debugServer.getInternalProperties(object)); } -static v8::Handle<v8::Array> getJSListenerFunctions(Document* document, const EventListenerInfo& listenerInfo, v8::Isolate* isolate) +static v8::Handle<v8::Array> getJSListenerFunctions(ExecutionContext* executionContext, const EventListenerInfo& listenerInfo, v8::Isolate* isolate) { v8::Local<v8::Array> result = v8::Array::New(isolate); size_t handlersCount = listenerInfo.eventListenerVector.size(); @@ -252,7 +250,7 @@ static v8::Handle<v8::Array> getJSListenerFunctions(Document* document, const Ev continue; } V8AbstractEventListener* v8Listener = static_cast<V8AbstractEventListener*>(listener.get()); - v8::Local<v8::Context> context = toV8Context(document, v8Listener->world()); + v8::Local<v8::Context> context = toV8Context(executionContext, v8Listener->world()); // Hide listeners from other contexts. if (context != isolate->GetCurrentContext()) continue; @@ -260,12 +258,12 @@ static v8::Handle<v8::Array> getJSListenerFunctions(Document* document, const Ev { // getListenerObject() may cause JS in the event attribute to get compiled, potentially unsuccessfully. v8::TryCatch block; - function = v8Listener->getListenerObject(document); + function = v8Listener->getListenerObject(executionContext); if (block.HasCaught()) continue; } ASSERT(!function.IsEmpty()); - v8::Local<v8::Object> listenerEntry = v8::Object::New(); + v8::Local<v8::Object> listenerEntry = v8::Object::New(isolate); listenerEntry->Set(v8AtomicString(isolate, "listener"), function); listenerEntry->Set(v8AtomicString(isolate, "useCapture"), v8::Boolean::New(isolate, listenerInfo.eventListenerVector[i].useCapture)); result->Set(v8::Number::New(isolate, outputIndex++), listenerEntry); @@ -278,20 +276,24 @@ void V8InjectedScriptHost::getEventListenersMethodCustom(const v8::FunctionCallb if (info.Length() < 1) return; + v8::Local<v8::Value> value = info[0]; - if (!V8Node::hasInstance(value, info.GetIsolate(), worldType(info.GetIsolate()))) - return; - Node* node = V8Node::toNative(value->ToObject()); - if (!node) + EventTarget* target = V8EventTarget::toNativeWithTypeCheck(info.GetIsolate(), value); + + // We need to handle a LocalDOMWindow specially, because a LocalDOMWindow wrapper exists on a prototype chain. + if (!target) + target = toDOMWindow(value, info.GetIsolate()); + + if (!target || !target->executionContext()) return; InjectedScriptHost* host = V8InjectedScriptHost::toNative(info.Holder()); Vector<EventListenerInfo> listenersArray; - host->getEventListenersImpl(node, listenersArray); + host->getEventListenersImpl(target, listenersArray); - v8::Local<v8::Object> result = v8::Object::New(); + v8::Local<v8::Object> result = v8::Object::New(info.GetIsolate()); for (size_t i = 0; i < listenersArray.size(); ++i) { - v8::Handle<v8::Array> listeners = getJSListenerFunctions(&node->document(), listenersArray[i], info.GetIsolate()); + v8::Handle<v8::Array> listeners = getJSListenerFunctions(target->executionContext(), listenersArray[i], info.GetIsolate()); if (!listeners->Length()) continue; AtomicString eventType = listenersArray[i].eventType; @@ -307,34 +309,10 @@ void V8InjectedScriptHost::inspectMethodCustom(const v8::FunctionCallbackInfo<v8 return; InjectedScriptHost* host = V8InjectedScriptHost::toNative(info.Holder()); - ScriptValue object(info[0], info.GetIsolate()); - ScriptValue hints(info[1], info.GetIsolate()); - host->inspectImpl(object.toJSONValue(ScriptState::current()), hints.toJSONValue(ScriptState::current())); -} - -void V8InjectedScriptHost::databaseIdMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - if (info.Length() > 0 && V8Database::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { - Database* database = V8Database::toNative(v8::Handle<v8::Object>::Cast(info[0])); - if (database) { - InjectedScriptHost* host = V8InjectedScriptHost::toNative(info.Holder()); { - v8SetReturnValueStringOrUndefined(info, host->databaseIdImpl(database), info.GetIsolate()); - return; - } - } - } -} - -void V8InjectedScriptHost::storageIdMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - if (info.Length() > 0 && V8Storage::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { - Storage* storage = V8Storage::toNative(v8::Handle<v8::Object>::Cast(info[0])); - if (storage) { - InjectedScriptHost* host = V8InjectedScriptHost::toNative(info.Holder()); - v8SetReturnValueStringOrUndefined(info, host->storageIdImpl(storage), info.GetIsolate()); - return; - } - } + ScriptState* scriptState = ScriptState::current(info.GetIsolate()); + ScriptValue object(scriptState, info[0]); + ScriptValue hints(scriptState, info[1]); + host->inspectImpl(object.toJSONValue(scriptState), hints.toJSONValue(scriptState)); } void V8InjectedScriptHost::evaluateMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) @@ -351,7 +329,7 @@ void V8InjectedScriptHost::evaluateMethodCustom(const v8::FunctionCallbackInfo<v return; } - ASSERT(!isolate->GetCurrentContext().IsEmpty()); + ASSERT(isolate->InContext()); v8::TryCatch tryCatch; v8::Handle<v8::Value> result = V8ScriptRunner::compileAndRunInternalScript(expression, info.GetIsolate()); if (tryCatch.HasCaught()) { @@ -445,4 +423,25 @@ void V8InjectedScriptHost::unmonitorFunctionMethodCustom(const v8::FunctionCallb host->unmonitorFunction(scriptId, lineNumber, columnNumber); } +void V8InjectedScriptHost::suppressWarningsAndCallMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + if (info.Length() < 2 || !info[0]->IsObject() || !info[1]->IsFunction()) + return; + + InjectedScriptHost* host = V8InjectedScriptHost::toNative(info.Holder()); + ScriptDebugServer& debugServer = host->scriptDebugServer(); + debugServer.muteWarningsAndDeprecations(); + + v8::Handle<v8::Object> receiver = v8::Handle<v8::Object>::Cast(info[0]); + v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(info[1]); + size_t argc = info.Length() - 2; + OwnPtr<v8::Handle<v8::Value>[]> argv = adoptArrayPtr(new v8::Handle<v8::Value>[argc]); + for (size_t i = 0; i < argc; ++i) + argv[i] = info[i + 2]; + + v8::Local<v8::Value> result = function->Call(receiver, argc, argv.get()); + debugServer.unmuteWarningsAndDeprecations(); + v8SetReturnValue(info, result); +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InjectedScriptManager.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InjectedScriptManager.cpp index fbe5295d1af..fbeffc2fc2a 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InjectedScriptManager.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InjectedScriptManager.cpp @@ -31,17 +31,17 @@ #include "config.h" #include "core/inspector/InjectedScriptManager.h" -#include "V8InjectedScriptHost.h" -#include "V8Window.h" +#include "bindings/core/v8/V8InjectedScriptHost.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/BindingSecurity.h" #include "bindings/v8/ScopedPersistent.h" #include "bindings/v8/ScriptDebugServer.h" -#include "bindings/v8/ScriptObject.h" +#include "bindings/v8/ScriptValue.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8ObjectConstructor.h" #include "bindings/v8/V8ScriptRunner.h" #include "core/inspector/InjectedScriptHost.h" -#include "core/frame/DOMWindow.h" +#include "core/frame/LocalDOMWindow.h" #include "wtf/RefPtr.h" namespace WebCore { @@ -53,12 +53,12 @@ struct InjectedScriptManager::CallbackData { static v8::Local<v8::Object> createInjectedScriptHostV8Wrapper(InjectedScriptHost* host, v8::Isolate* isolate) { - v8::Local<v8::Function> function = V8InjectedScriptHost::domTemplate(isolate, MainWorld)->GetFunction(); + v8::Local<v8::Function> function = V8InjectedScriptHost::domTemplate(isolate)->GetFunction(); if (function.IsEmpty()) { // Return if allocation failed. return v8::Local<v8::Object>(); } - v8::Local<v8::Object> instanceTemplate = V8ObjectConstructor::newInstance(function); + v8::Local<v8::Object> instanceTemplate = V8ObjectConstructor::newInstance(isolate, function); if (instanceTemplate.IsEmpty()) { // Avoid setting the wrapper if allocation failed. return v8::Local<v8::Object>(); @@ -73,21 +73,18 @@ static v8::Local<v8::Object> createInjectedScriptHostV8Wrapper(InjectedScriptHos return instanceTemplate; } -ScriptObject InjectedScriptManager::createInjectedScript(const String& scriptSource, ScriptState* inspectedScriptState, int id) +ScriptValue InjectedScriptManager::createInjectedScript(const String& scriptSource, ScriptState* inspectedScriptState, int id) { v8::Isolate* isolate = inspectedScriptState->isolate(); - v8::HandleScope handleScope(isolate); - - v8::Local<v8::Context> inspectedContext = inspectedScriptState->context(); - v8::Context::Scope contextScope(inspectedContext); + ScriptState::Scope scope(inspectedScriptState); // Call custom code to create InjectedScripHost wrapper specific for the context // instead of calling toV8() that would create the // wrapper in the current context. // FIXME: make it possible to use generic bindings factory for InjectedScriptHost. - v8::Local<v8::Object> scriptHostWrapper = createInjectedScriptHostV8Wrapper(m_injectedScriptHost.get(), inspectedContext->GetIsolate()); + v8::Local<v8::Object> scriptHostWrapper = createInjectedScriptHostV8Wrapper(m_injectedScriptHost.get(), inspectedScriptState->isolate()); if (scriptHostWrapper.IsEmpty()) - return ScriptObject(); + return ScriptValue(); // Inject javascript into the context. The compiled script is supposed to evaluate into // a single anonymous function(it's anonymous to avoid cluttering the global object with @@ -98,28 +95,24 @@ ScriptObject InjectedScriptManager::createInjectedScript(const String& scriptSou ASSERT(!value.IsEmpty()); ASSERT(value->IsFunction()); - v8::Local<v8::Object> windowGlobal = inspectedContext->Global(); - v8::Handle<v8::Value> info[] = { scriptHostWrapper, windowGlobal, v8::Number::New(inspectedContext->GetIsolate(), id) }; - v8::Local<v8::Value> injectedScriptValue = V8ScriptRunner::callInternalFunction(v8::Local<v8::Function>::Cast(value), windowGlobal, WTF_ARRAY_LENGTH(info), info, inspectedContext->GetIsolate()); - return ScriptObject(inspectedScriptState, v8::Handle<v8::Object>::Cast(injectedScriptValue)); + v8::Local<v8::Object> windowGlobal = inspectedScriptState->context()->Global(); + v8::Handle<v8::Value> info[] = { scriptHostWrapper, windowGlobal, v8::Number::New(inspectedScriptState->isolate(), id) }; + v8::Local<v8::Value> injectedScriptValue = V8ScriptRunner::callInternalFunction(v8::Local<v8::Function>::Cast(value), windowGlobal, WTF_ARRAY_LENGTH(info), info, inspectedScriptState->isolate()); + return ScriptValue(inspectedScriptState, injectedScriptValue); } bool InjectedScriptManager::canAccessInspectedWindow(ScriptState* scriptState) { - v8::HandleScope handleScope(scriptState->isolate()); - v8::Local<v8::Context> context = scriptState->context(); - v8::Local<v8::Object> global = context->Global(); + ScriptState::Scope scope(scriptState); + v8::Local<v8::Object> global = scriptState->context()->Global(); if (global.IsEmpty()) return false; - v8::Handle<v8::Object> holder = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), MainWorld)); - if (holder.IsEmpty()) - holder = global->FindInstanceInPrototypeChain(V8Window::domTemplate(context->GetIsolate(), IsolatedWorld)); + v8::Handle<v8::Object> holder = V8Window::findInstanceInPrototypeChain(global, scriptState->isolate()); if (holder.IsEmpty()) return false; - Frame* frame = V8Window::toNative(holder)->frame(); + LocalFrame* frame = V8Window::toNative(holder)->frame(); - v8::Context::Scope contextScope(context); - return BindingSecurity::shouldAllowAccessToFrame(frame, DoNotReportSecurityError); + return BindingSecurity::shouldAllowAccessToFrame(scriptState->isolate(), frame, DoNotReportSecurityError); } void InjectedScriptManager::setWeakCallback(const v8::WeakCallbackData<v8::Object, InjectedScriptManager::CallbackData>& data) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp index 6fef29ec312..439e9347ee3 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8InspectorFrontendHostCustom.cpp @@ -29,9 +29,9 @@ */ #include "config.h" -#include "V8InspectorFrontendHost.h" +#include "bindings/core/v8/V8InspectorFrontendHost.h" -#include "V8MouseEvent.h" +#include "bindings/core/v8/V8MouseEvent.h" #include "bindings/v8/V8Binding.h" #include "core/inspector/InspectorController.h" #include "core/inspector/InspectorFrontendClient.h" @@ -80,7 +80,7 @@ static bool populateContextMenuItems(v8::Local<v8::Array>& itemArray, ContextMen v8::Local<v8::Array> subItemsArray = v8::Local<v8::Array>::Cast(subItems); if (!populateContextMenuItems(subItemsArray, subMenu, isolate)) return false; - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<WithNullCheck>, labelString, label, false); + TOSTRING_DEFAULT(V8StringResource<WithNullCheck>, labelString, label, false); ContextMenuItem item(SubmenuType, ContextMenuItemCustomTagNoAction, labelString, @@ -88,7 +88,7 @@ static bool populateContextMenuItems(v8::Local<v8::Array>& itemArray, ContextMen menu.appendItem(item); } else { ContextMenuAction typedId = static_cast<ContextMenuAction>(ContextMenuItemBaseCustomTag + id->ToInt32()->Value()); - V8TRYCATCH_FOR_V8STRINGRESOURCE_RETURN(V8StringResource<WithNullCheck>, labelString, label, false); + TOSTRING_DEFAULT(V8StringResource<WithNullCheck>, labelString, label, false); ContextMenuItem menuItem((typeString == "checkbox" ? CheckableActionType : ActionType), typedId, labelString); if (checked->IsBoolean()) menuItem.setChecked(checked->ToBoolean()->Value()); @@ -143,10 +143,5 @@ void V8InspectorFrontendHost::recordPanelShownMethodCustom(const v8::FunctionCal histogramEnumeration("DevTools.PanelShown", info, 20); } -void V8InspectorFrontendHost::recordSettingChangedMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - histogramEnumeration("DevTools.SettingChanged", info, 100); -} - } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int16ArrayCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int16ArrayCustom.h index 30f5f5864d4..58aab8bb3ae 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int16ArrayCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int16ArrayCustom.h @@ -59,10 +59,6 @@ public: typedef V8TypedArray<Int16Array> V8Int16Array; -template<> -class WrapperTypeTraits<Int16Array> : public TypedArrayWrapperTraits<Int16Array> { }; - - inline v8::Handle<v8::Object> wrap(Int16Array* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { return V8TypedArray<Int16Array>::wrap(impl, creationContext, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int32ArrayCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int32ArrayCustom.h index bbb4aafc94d..6c29dca3988 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int32ArrayCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int32ArrayCustom.h @@ -59,10 +59,6 @@ public: typedef V8TypedArray<Int32Array> V8Int32Array; -template<> -class WrapperTypeTraits<Int32Array> : public TypedArrayWrapperTraits<Int32Array> { }; - - inline v8::Handle<v8::Object> wrap(Int32Array* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { return V8TypedArray<Int32Array>::wrap(impl, creationContext, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int8ArrayCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int8ArrayCustom.h index 31a9e356ea4..e8783171357 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int8ArrayCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Int8ArrayCustom.h @@ -59,10 +59,6 @@ public: typedef V8TypedArray<Int8Array> V8Int8Array; -template<> -class WrapperTypeTraits<Int8Array> : public TypedArrayWrapperTraits<Int8Array> { }; - - inline v8::Handle<v8::Object> wrap(Int8Array* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { return V8TypedArray<Int8Array>::wrap(impl, creationContext, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8JavaScriptCallFrameCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8JavaScriptCallFrameCustom.cpp index 0f1a60ad709..c379d9a50dc 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8JavaScriptCallFrameCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8JavaScriptCallFrameCustom.cpp @@ -29,7 +29,7 @@ */ #include "config.h" -#include "V8JavaScriptCallFrame.h" +#include "bindings/core/v8/V8JavaScriptCallFrame.h" #include "bindings/v8/V8Binding.h" diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8LocationCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8LocationCustom.cpp index a9009c9f335..58835d5f127 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8LocationCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8LocationCustom.cpp @@ -29,7 +29,7 @@ */ #include "config.h" -#include "V8Location.h" +#include "bindings/core/v8/V8Location.h" namespace WebCore { diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MIDIOutputCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MIDIOutputCustom.cpp deleted file mode 100644 index fa3b69afea6..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MIDIOutputCustom.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2013 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 "V8MIDIOutput.h" - -#include "V8MIDIAccess.h" -#include "bindings/v8/V8HiddenPropertyName.h" - -namespace WebCore { - -v8::Handle<v8::Object> wrap(MIDIOutput* output, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) -{ - ASSERT(output); - ASSERT(!DOMDataStore::containsWrapper<V8MIDIOutput>(output, isolate)); - - v8::Handle<v8::Object> wrapper = V8MIDIOutput::createWrapper(output, creationContext, isolate); - - if (output->midiAccess()) - V8HiddenPropertyName::setNamedHiddenReference(wrapper, "access", toV8(output->midiAccess(), creationContext, isolate)); - - return wrapper; -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessageChannelCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessageChannelCustom.cpp index 67ec60fbd92..d39c588710d 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessageChannelCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessageChannelCustom.cpp @@ -29,12 +29,11 @@ */ #include "config.h" -#include "V8MessageChannel.h" +#include "bindings/core/v8/V8MessageChannel.h" -#include "V8MessagePort.h" +#include "bindings/core/v8/V8MessagePort.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" -#include "bindings/v8/V8Utilities.h" +#include "bindings/v8/V8HiddenValue.h" #include "core/dom/MessageChannel.h" #include "core/workers/WorkerGlobalScope.h" #include "wtf/RefPtr.h" @@ -43,17 +42,17 @@ namespace WebCore { void V8MessageChannel::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - ExecutionContext* context = getExecutionContext(); + ExecutionContext* context = currentExecutionContext(info.GetIsolate()); - RefPtr<MessageChannel> obj = MessageChannel::create(context); + RefPtrWillBeRawPtr<MessageChannel> obj = MessageChannel::create(context); v8::Local<v8::Object> wrapper = info.Holder(); // Create references from the MessageChannel wrapper to the two // MessagePort wrappers to make sure that the MessagePort wrappers // stay alive as long as the MessageChannel wrapper is around. - V8HiddenPropertyName::setNamedHiddenReference(wrapper, "port1", toV8(obj->port1(), info.Holder(), info.GetIsolate())); - V8HiddenPropertyName::setNamedHiddenReference(wrapper, "port2", toV8(obj->port2(), info.Holder(), info.GetIsolate())); + V8HiddenValue::setHiddenValue(info.GetIsolate(), wrapper, V8HiddenValue::port1(info.GetIsolate()), toV8(obj->port1(), info.Holder(), info.GetIsolate())); + V8HiddenValue::setHiddenValue(info.GetIsolate(), wrapper, V8HiddenValue::port2(info.GetIsolate()), toV8(obj->port2(), info.Holder(), info.GetIsolate())); V8DOMWrapper::associateObjectWithWrapper<V8MessageChannel>(obj.release(), &wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent); info.GetReturnValue().Set(wrapper); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessageEventCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessageEventCustom.cpp index 9060e643728..145af08fab3 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessageEventCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessageEventCustom.cpp @@ -29,19 +29,50 @@ */ #include "config.h" -#include "V8MessageEvent.h" +#include "bindings/core/v8/V8MessageEvent.h" -#include "V8Blob.h" -#include "V8MessagePort.h" -#include "V8Window.h" +#include "bindings/core/v8/V8Blob.h" +#include "bindings/core/v8/V8MessagePort.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/SerializedScriptValue.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "bindings/v8/custom/V8ArrayBufferCustom.h" #include "core/events/MessageEvent.h" namespace WebCore { +// Ensures a wrapper is created for the data to return now so that V8 knows how +// much memory is used via the wrapper. To keep the wrapper alive, it's set to +// the wrapper of the MessageEvent as a hidden value. +static void ensureWrapperCreatedAndAssociated(MessageEvent* eventImpl, v8::Handle<v8::Object> eventWrapper, v8::Isolate* isolate) +{ + switch (eventImpl->dataType()) { + case MessageEvent::DataTypeScriptValue: + case MessageEvent::DataTypeSerializedScriptValue: + break; + case MessageEvent::DataTypeString: { + String stringValue = eventImpl->dataAsString(); + V8HiddenValue::setHiddenValue(isolate, eventWrapper, V8HiddenValue::stringData(isolate), v8String(isolate, stringValue)); + break; + } + case MessageEvent::DataTypeBlob: + break; + case MessageEvent::DataTypeArrayBuffer: + V8HiddenValue::setHiddenValue(isolate, eventWrapper, V8HiddenValue::arrayBufferData(isolate), toV8(eventImpl->dataAsArrayBuffer(), eventWrapper, isolate)); + break; + } +} + +v8::Handle<v8::Object> wrap(MessageEvent* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) +{ + ASSERT(impl); + ASSERT(!DOMDataStore::containsWrapper<V8MessageEvent>(impl, isolate)); + v8::Handle<v8::Object> wrapper = V8MessageEvent::createWrapper(impl, creationContext, isolate); + ensureWrapperCreatedAndAssociated(impl, wrapper, isolate); + return wrapper; +} + void V8MessageEvent::dataAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) { MessageEvent* event = V8MessageEvent::toNative(info.Holder()); @@ -49,12 +80,12 @@ void V8MessageEvent::dataAttributeGetterCustom(const v8::PropertyCallbackInfo<v8 v8::Handle<v8::Value> result; switch (event->dataType()) { case MessageEvent::DataTypeScriptValue: { - result = info.Holder()->GetHiddenValue(V8HiddenPropertyName::data(info.GetIsolate())); + result = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::data(info.GetIsolate())); if (result.IsEmpty()) { if (!event->dataAsSerializedScriptValue()) { // If we're in an isolated world and the event was created in the main world, // we need to find the 'data' property on the main world wrapper and clone it. - v8::Local<v8::Value> mainWorldData = getHiddenValueFromMainWorldWrapper(info.GetIsolate(), event, V8HiddenPropertyName::data(info.GetIsolate())); + v8::Local<v8::Value> mainWorldData = V8HiddenValue::getHiddenValueFromMainWorldWrapper(info.GetIsolate(), event, V8HiddenValue::data(info.GetIsolate())); if (!mainWorldData.IsEmpty()) event->setSerializedData(SerializedScriptValue::createAndSwallowExceptions(mainWorldData, info.GetIsolate())); } @@ -76,8 +107,11 @@ void V8MessageEvent::dataAttributeGetterCustom(const v8::PropertyCallbackInfo<v8 break; case MessageEvent::DataTypeString: { - String stringValue = event->dataAsString(); - result = v8String(info.GetIsolate(), stringValue); + result = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::stringData(info.GetIsolate())); + if (result.IsEmpty()) { + String stringValue = event->dataAsString(); + result = v8String(info.GetIsolate(), stringValue); + } break; } @@ -86,12 +120,14 @@ void V8MessageEvent::dataAttributeGetterCustom(const v8::PropertyCallbackInfo<v8 break; case MessageEvent::DataTypeArrayBuffer: - result = toV8(event->dataAsArrayBuffer(), info.Holder(), info.GetIsolate()); + result = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::arrayBufferData(info.GetIsolate())); + if (result.IsEmpty()) + result = toV8(event->dataAsArrayBuffer(), info.Holder(), info.GetIsolate()); break; } // Overwrite the data attribute so it returns the cached result in future invocations. - // This custom handler (dataAccessGetter) will not be called again. + // This custom getter handler will not be called again. v8::PropertyAttribute dataAttr = static_cast<v8::PropertyAttribute>(v8::DontDelete | v8::ReadOnly); info.Holder()->ForceSet(v8AtomicString(info.GetIsolate(), "data"), result, dataAttr); v8SetReturnValue(info, result); @@ -100,41 +136,29 @@ void V8MessageEvent::dataAttributeGetterCustom(const v8::PropertyCallbackInfo<v8 void V8MessageEvent::initMessageEventMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { MessageEvent* event = V8MessageEvent::toNative(info.Holder()); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, typeArg, info[0]); - V8TRYCATCH_VOID(bool, canBubbleArg, info[1]->BooleanValue()); - V8TRYCATCH_VOID(bool, cancelableArg, info[2]->BooleanValue()); + TOSTRING_VOID(V8StringResource<>, typeArg, info[0]); + TONATIVE_VOID(bool, canBubbleArg, info[1]->BooleanValue()); + TONATIVE_VOID(bool, cancelableArg, info[2]->BooleanValue()); v8::Handle<v8::Value> dataArg = info[3]; - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, originArg, info[4]); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, lastEventIdArg, info[5]); - - DOMWindow* sourceArg = 0; - if (info[6]->IsObject()) { - v8::Handle<v8::Object> wrapper = v8::Handle<v8::Object>::Cast(info[6]); - v8::Handle<v8::Object> window = wrapper->FindInstanceInPrototypeChain(V8Window::domTemplate(info.GetIsolate(), worldTypeInMainThread(info.GetIsolate()))); - if (!window.IsEmpty()) - sourceArg = V8Window::toNative(window); - } + TOSTRING_VOID(V8StringResource<>, originArg, info[4]); + TOSTRING_VOID(V8StringResource<>, lastEventIdArg, info[5]); + LocalDOMWindow* sourceArg = toDOMWindow(info[6], info.GetIsolate()); OwnPtr<MessagePortArray> portArray; - const int portArrayIndex = 7; if (!isUndefinedOrNull(info[portArrayIndex])) { portArray = adoptPtr(new MessagePortArray); - if (!getMessagePortArray(info[portArrayIndex], portArrayIndex + 1, *portArray, info.GetIsolate())) + bool success = false; + *portArray = toRefPtrNativeArray<MessagePort, V8MessagePort>(info[portArrayIndex], portArrayIndex + 1, info.GetIsolate(), &success); + if (!success) return; } event->initMessageEvent(typeArg, canBubbleArg, cancelableArg, originArg, lastEventIdArg, sourceArg, portArray.release()); if (!dataArg.IsEmpty()) { - info.Holder()->SetHiddenValue(V8HiddenPropertyName::data(info.GetIsolate()), dataArg); - if (isolatedWorldForIsolate(info.GetIsolate())) + V8HiddenValue::setHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::data(info.GetIsolate()), dataArg); + if (DOMWrapperWorld::current(info.GetIsolate()).isIsolatedWorld()) event->setSerializedData(SerializedScriptValue::createAndSwallowExceptions(dataArg, info.GetIsolate())); } } -void V8MessageEvent::webkitInitMessageEventMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - initMessageEventMethodCustom(info); -} - - } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessagePortCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessagePortCustom.cpp index f8eb9df2abd..d368989ba93 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessagePortCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MessagePortCustom.cpp @@ -29,13 +29,12 @@ */ #include "config.h" -#include "V8MessagePort.h" +#include "bindings/core/v8/V8MessagePort.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/SerializedScriptValue.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "core/dom/MessagePort.h" #include "wtf/ArrayBuffer.h" @@ -48,19 +47,14 @@ void V8MessagePort::postMessageMethodCustom(const v8::FunctionCallbackInfo<v8::V MessagePortArray portArray; ArrayBufferArray arrayBufferArray; if (info.Length() > 1) { - bool notASequence = false; const int transferablesArgIndex = 1; - if (!extractTransferables(info[transferablesArgIndex], portArray, arrayBufferArray, notASequence, info.GetIsolate())) { - if (notASequence) { - exceptionState.throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(transferablesArgIndex + 1)); - exceptionState.throwIfNeeded(); - } + if (!SerializedScriptValue::extractTransferables(info[transferablesArgIndex], transferablesArgIndex, portArray, arrayBufferArray, exceptionState, info.GetIsolate())) { + exceptionState.throwIfNeeded(); return; } } - bool didThrow = false; - RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(info[0], &portArray, &arrayBufferArray, didThrow, info.GetIsolate()); - if (didThrow) + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(info[0], &portArray, &arrayBufferArray, exceptionState, info.GetIsolate()); + if (exceptionState.throwIfNeeded()) return; messagePort->postMessage(message.release(), &portArray, exceptionState); exceptionState.throwIfNeeded(); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MutationObserverCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MutationObserverCustom.cpp index f19d3eb52ff..f2e62908d48 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MutationObserverCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8MutationObserverCustom.cpp @@ -29,14 +29,14 @@ */ #include "config.h" -#include "V8MutationObserver.h" +#include "bindings/core/v8/V8MutationObserver.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8DOMWrapper.h" +#include "bindings/v8/V8GCController.h" #include "bindings/v8/V8MutationCallback.h" -#include "bindings/v8/V8Utilities.h" #include "core/dom/MutationObserver.h" namespace WebCore { @@ -57,14 +57,23 @@ void V8MutationObserver::constructorCustom(const v8::FunctionCallbackInfo<v8::Va return; } - ExecutionContext* context = getExecutionContext(); v8::Handle<v8::Object> wrapper = info.Holder(); - OwnPtr<MutationCallback> callback = V8MutationCallback::create(v8::Handle<v8::Function>::Cast(arg), context, wrapper, info.GetIsolate()); - RefPtr<MutationObserver> observer = MutationObserver::create(callback.release()); + OwnPtr<MutationCallback> callback = V8MutationCallback::create(v8::Handle<v8::Function>::Cast(arg), wrapper, ScriptState::current(info.GetIsolate())); + RefPtrWillBeRawPtr<MutationObserver> observer = MutationObserver::create(callback.release()); V8DOMWrapper::associateObjectWithWrapper<V8MutationObserver>(observer.release(), &wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent); info.GetReturnValue().Set(wrapper); } +void V8MutationObserver::visitDOMWrapper(void* object, const v8::Persistent<v8::Object>& wrapper, v8::Isolate* isolate) +{ + MutationObserver* observer = static_cast<MutationObserver*>(object); + HashSet<Node*> observedNodes = observer->getObservedNodes(); + for (HashSet<Node*>::iterator it = observedNodes.begin(); it != observedNodes.end(); ++it) { + v8::UniqueId id(reinterpret_cast<intptr_t>(V8GCController::opaqueRootForGC(*it, isolate))); + isolate->SetReferenceFromGroup(id, wrapper); + } +} + } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8NodeCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8NodeCustom.cpp index 854eb42b1e3..159b31e303b 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8NodeCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8NodeCustom.cpp @@ -29,22 +29,21 @@ */ #include "config.h" -#include "V8Node.h" - -#include "V8Attr.h" -#include "V8CDATASection.h" -#include "V8Comment.h" -#include "V8Document.h" -#include "V8DocumentFragment.h" -#include "V8DocumentType.h" -#include "V8Element.h" -#include "V8Entity.h" -#include "V8HTMLElement.h" -#include "V8Notation.h" -#include "V8ProcessingInstruction.h" -#include "V8SVGElement.h" -#include "V8ShadowRoot.h" -#include "V8Text.h" +#include "bindings/core/v8/V8Node.h" + +#include "bindings/core/v8/V8Attr.h" +#include "bindings/core/v8/V8CDATASection.h" +#include "bindings/core/v8/V8Comment.h" +#include "bindings/core/v8/V8Document.h" +#include "bindings/core/v8/V8DocumentFragment.h" +#include "bindings/core/v8/V8DocumentType.h" +#include "bindings/core/v8/V8Element.h" +#include "bindings/core/v8/V8HTMLElement.h" +#include "bindings/core/v8/V8Notation.h" +#include "bindings/core/v8/V8ProcessingInstruction.h" +#include "bindings/core/v8/V8SVGElement.h" +#include "bindings/core/v8/V8ShadowRoot.h" +#include "bindings/core/v8/V8Text.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8AbstractEventListener.h" #include "bindings/v8/V8Binding.h" @@ -62,14 +61,14 @@ namespace WebCore { void V8Node::insertBeforeMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { v8::Handle<v8::Object> holder = info.Holder(); - Node* imp = V8Node::toNative(holder); + Node* impl = V8Node::toNative(holder); CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope; ExceptionState exceptionState(ExceptionState::ExecutionContext, "insertBefore", "Node", info.Holder(), info.GetIsolate()); - Node* newChild = V8Node::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate())) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(info[0])) : 0; - Node* refChild = V8Node::hasInstance(info[1], info.GetIsolate(), worldType(info.GetIsolate())) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(info[1])) : 0; - imp->insertBefore(newChild, refChild, exceptionState); + Node* newChild = V8Node::toNativeWithTypeCheck(info.GetIsolate(), info[0]); + Node* refChild = V8Node::toNativeWithTypeCheck(info.GetIsolate(), info[1]); + impl->insertBefore(newChild, refChild, exceptionState); if (exceptionState.throwIfNeeded()) return; v8SetReturnValue(info, info[0]); @@ -78,14 +77,14 @@ void V8Node::insertBeforeMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& void V8Node::replaceChildMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { v8::Handle<v8::Object> holder = info.Holder(); - Node* imp = V8Node::toNative(holder); + Node* impl = V8Node::toNative(holder); CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope; ExceptionState exceptionState(ExceptionState::ExecutionContext, "replaceChild", "Node", info.Holder(), info.GetIsolate()); - Node* newChild = V8Node::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate())) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(info[0])) : 0; - Node* oldChild = V8Node::hasInstance(info[1], info.GetIsolate(), worldType(info.GetIsolate())) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(info[1])) : 0; - imp->replaceChild(newChild, oldChild, exceptionState); + Node* newChild = V8Node::toNativeWithTypeCheck(info.GetIsolate(), info[0]); + Node* oldChild = V8Node::toNativeWithTypeCheck(info.GetIsolate(), info[1]); + impl->replaceChild(newChild, oldChild, exceptionState); if (exceptionState.throwIfNeeded()) return; v8SetReturnValue(info, info[1]); @@ -94,13 +93,13 @@ void V8Node::replaceChildMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& void V8Node::removeChildMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { v8::Handle<v8::Object> holder = info.Holder(); - Node* imp = V8Node::toNative(holder); + Node* impl = V8Node::toNative(holder); CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope; ExceptionState exceptionState(ExceptionState::ExecutionContext, "removeChild", "Node", info.Holder(), info.GetIsolate()); - Node* oldChild = V8Node::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate())) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(info[0])) : 0; - imp->removeChild(oldChild, exceptionState); + Node* oldChild = V8Node::toNativeWithTypeCheck(info.GetIsolate(), info[0]); + impl->removeChild(oldChild, exceptionState); if (exceptionState.throwIfNeeded()) return; v8SetReturnValue(info, info[0]); @@ -109,13 +108,13 @@ void V8Node::removeChildMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& void V8Node::appendChildMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { v8::Handle<v8::Object> holder = info.Holder(); - Node* imp = V8Node::toNative(holder); + Node* impl = V8Node::toNative(holder); CustomElementCallbackDispatcher::CallbackDeliveryScope deliveryScope; ExceptionState exceptionState(ExceptionState::ExecutionContext, "appendChild", "Node", info.Holder(), info.GetIsolate()); - Node* newChild = V8Node::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate())) ? V8Node::toNative(v8::Handle<v8::Object>::Cast(info[0])) : 0; - imp->appendChild(newChild, exceptionState); + Node* newChild = V8Node::toNativeWithTypeCheck(info.GetIsolate(), info[0]); + impl->appendChild(newChild, exceptionState); if (exceptionState.throwIfNeeded()) return; v8SetReturnValue(info, info[0]); @@ -150,14 +149,8 @@ v8::Handle<v8::Object> wrap(Node* impl, v8::Handle<v8::Object> creationContext, if (impl->isShadowRoot()) return wrap(toShadowRoot(impl), creationContext, isolate); return wrap(toDocumentFragment(impl), creationContext, isolate); - case Node::ENTITY_NODE: - case Node::NOTATION_NODE: - // We never create objects of Entity and Notation. - ASSERT_NOT_REACHED(); - break; - default: - break; // ENTITY_REFERENCE_NODE or XPATH_NAMESPACE_NODE } + ASSERT_NOT_REACHED(); return V8Node::createWrapper(impl, creationContext, isolate); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8OscillatorNodeCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8OscillatorNodeCustom.cpp deleted file mode 100644 index 7216a8ec56b..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8OscillatorNodeCustom.cpp +++ /dev/null @@ -1,60 +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 "V8OscillatorNode.h" - -#include "bindings/v8/V8Binding.h" -#include "modules/webaudio/OscillatorNode.h" - -namespace WebCore { - -void V8OscillatorNode::typeAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) -{ - v8::Handle<v8::Object> holder = info.Holder(); - OscillatorNode* imp = V8OscillatorNode::toNative(holder); - - if (value->IsNumber()) { - bool ok = false; - uint32_t type = toUInt32(value, ok); - if (!ok || !imp->setType(type)) - throwTypeError("Illegal OscillatorNode type", info.GetIsolate()); - return; - } - - if (value->IsString()) { - String type = toCoreString(value.As<v8::String>()); - if (type == "sine" || type == "square" || type == "sawtooth" || type == "triangle") { - imp->setType(type); - return; - } - } - - throwTypeError("Illegal OscillatorNode type", info.GetIsolate()); -} - -} // namespace WebCore - -#endif // ENABLE(WEB_AUDIO) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PannerNodeCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PannerNodeCustom.cpp deleted file mode 100644 index 5e10fda34cf..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PannerNodeCustom.cpp +++ /dev/null @@ -1,84 +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 "V8PannerNode.h" - -#include "bindings/v8/V8Binding.h" -#include "modules/webaudio/PannerNode.h" - -namespace WebCore { - -void V8PannerNode::panningModelAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) -{ - PannerNode* imp = V8PannerNode::toNative(info.Holder()); - - if (value->IsNumber()) { - bool ok = false; - uint32_t model = toUInt32(value, ok); - ASSERT(ok); - if (!imp->setPanningModel(model)) - throwTypeError("Illegal panningModel", info.GetIsolate()); - return; - } - - if (value->IsString()) { - String model = toCoreString(value.As<v8::String>()); - if (model == "equalpower" || model == "HRTF" || model == "soundfield") { - imp->setPanningModel(model); - return; - } - } - - throwTypeError("Illegal panningModel", info.GetIsolate()); -} - -void V8PannerNode::distanceModelAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) -{ - PannerNode* imp = V8PannerNode::toNative(info.Holder()); - - if (value->IsNumber()) { - bool ok = false; - uint32_t model = toUInt32(value, ok); - ASSERT(ok); - if (!imp->setDistanceModel(model)) - throwTypeError("Illegal distanceModel", info.GetIsolate()); - return; - } - - if (value->IsString()) { - String model = toCoreString(value.As<v8::String>()); - if (model == "linear" || model == "inverse" || model == "exponential") { - imp->setDistanceModel(model); - return; - } - } - - throwTypeError("Illegal distanceModel", info.GetIsolate()); -} - -} // namespace WebCore - -#endif // ENABLE(WEB_AUDIO) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PerformanceEntryCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PerformanceEntryCustom.cpp index 15197329bae..6e1d54e0b68 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PerformanceEntryCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PerformanceEntryCustom.cpp @@ -29,11 +29,11 @@ */ #include "config.h" -#include "V8PerformanceEntry.h" +#include "bindings/core/v8/V8PerformanceEntry.h" -#include "V8PerformanceMark.h" -#include "V8PerformanceMeasure.h" -#include "V8PerformanceResourceTiming.h" +#include "bindings/core/v8/V8PerformanceMark.h" +#include "bindings/core/v8/V8PerformanceMeasure.h" +#include "bindings/core/v8/V8PerformanceResourceTiming.h" #include "core/timing/Performance.h" #include "core/timing/PerformanceMark.h" #include "core/timing/PerformanceMeasure.h" diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PopStateEventCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PopStateEventCustom.cpp index 8a7b790822c..83385ca297f 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PopStateEventCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PopStateEventCustom.cpp @@ -29,11 +29,11 @@ */ #include "config.h" -#include "V8PopStateEvent.h" +#include "bindings/core/v8/V8PopStateEvent.h" -#include "V8History.h" +#include "bindings/core/v8/V8History.h" #include "bindings/v8/SerializedScriptValue.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "core/events/PopStateEvent.h" #include "core/frame/History.h" @@ -42,13 +42,13 @@ namespace WebCore { // Save the state value to a hidden attribute in the V8PopStateEvent, and return it, for convenience. static v8::Handle<v8::Value> cacheState(v8::Handle<v8::Object> popStateEvent, v8::Handle<v8::Value> state, v8::Isolate* isolate) { - popStateEvent->SetHiddenValue(V8HiddenPropertyName::state(isolate), state); + V8HiddenValue::setHiddenValue(isolate, popStateEvent, V8HiddenValue::state(isolate), state); return state; } void V8PopStateEvent::stateAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) { - v8::Handle<v8::Value> result = info.Holder()->GetHiddenValue(V8HiddenPropertyName::state(info.GetIsolate())); + v8::Handle<v8::Value> result = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder(), V8HiddenValue::state(info.GetIsolate())); if (!result.IsEmpty()) { v8SetReturnValue(info, result); @@ -61,7 +61,7 @@ void V8PopStateEvent::stateAttributeGetterCustom(const v8::PropertyCallbackInfo< if (!event->serializedState()) { // If we're in an isolated world and the event was created in the main world, // we need to find the 'state' property on the main world wrapper and clone it. - v8::Local<v8::Value> mainWorldState = getHiddenValueFromMainWorldWrapper(info.GetIsolate(), event, V8HiddenPropertyName::state(info.GetIsolate())); + v8::Local<v8::Value> mainWorldState = V8HiddenValue::getHiddenValueFromMainWorldWrapper(info.GetIsolate(), event, V8HiddenValue::state(info.GetIsolate())); if (!mainWorldState.IsEmpty()) event->setSerializedState(SerializedScriptValue::createAndSwallowExceptions(mainWorldState, info.GetIsolate())); } @@ -84,14 +84,14 @@ void V8PopStateEvent::stateAttributeGetterCustom(const v8::PropertyCallbackInfo< if (isSameState) { v8::Handle<v8::Object> v8History = toV8(history, info.Holder(), info.GetIsolate()).As<v8::Object>(); if (!history->stateChanged()) { - result = v8History->GetHiddenValue(V8HiddenPropertyName::state(info.GetIsolate())); + result = V8HiddenValue::getHiddenValue(info.GetIsolate(), v8History, V8HiddenValue::state(info.GetIsolate())); if (!result.IsEmpty()) { v8SetReturnValue(info, cacheState(info.Holder(), result, info.GetIsolate())); return; } } result = event->serializedState()->deserialize(info.GetIsolate()); - v8History->SetHiddenValue(V8HiddenPropertyName::state(info.GetIsolate()), result); + V8HiddenValue::setHiddenValue(info.GetIsolate(), v8History, V8HiddenValue::state(info.GetIsolate()), result); } else { result = event->serializedState()->deserialize(info.GetIsolate()); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PromiseCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PromiseCustom.cpp deleted file mode 100644 index 22580d70da8..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PromiseCustom.cpp +++ /dev/null @@ -1,794 +0,0 @@ -/* - * Copyright (C) 2013 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 "bindings/v8/custom/V8PromiseCustom.h" - -#include <v8.h> -#include "V8Promise.h" -#include "bindings/v8/DOMRequestState.h" -#include "bindings/v8/ScopedPersistent.h" -#include "bindings/v8/ScriptFunctionCall.h" -#include "bindings/v8/ScriptState.h" -#include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" -#include "bindings/v8/V8PerIsolateData.h" -#include "bindings/v8/V8ScriptRunner.h" -#include "bindings/v8/WrapperTypeInfo.h" -#include "core/dom/Document.h" -#include "core/dom/ExecutionContextTask.h" -#include "core/frame/DOMWindow.h" -#include "core/workers/WorkerGlobalScope.h" -#include "platform/Task.h" -#include "wtf/Deque.h" -#include "wtf/Functional.h" -#include "wtf/Noncopyable.h" -#include "wtf/PassOwnPtr.h" - -namespace WebCore { - -namespace { - -v8::Local<v8::ObjectTemplate> cachedObjectTemplate(void* privateTemplateUniqueKey, int internalFieldCount, v8::Isolate* isolate) -{ - V8PerIsolateData* data = V8PerIsolateData::from(isolate); - WrapperWorldType currentWorldType = worldType(isolate); - v8::Handle<v8::FunctionTemplate> functionDescriptor = data->privateTemplateIfExists(currentWorldType, privateTemplateUniqueKey); - if (!functionDescriptor.IsEmpty()) - return functionDescriptor->InstanceTemplate(); - - functionDescriptor = v8::FunctionTemplate::New(isolate); - v8::Local<v8::ObjectTemplate> instanceTemplate = functionDescriptor->InstanceTemplate(); - instanceTemplate->SetInternalFieldCount(internalFieldCount); - data->setPrivateTemplate(currentWorldType, privateTemplateUniqueKey, functionDescriptor); - return instanceTemplate; -} - -v8::Local<v8::ObjectTemplate> promiseAllEnvironmentObjectTemplate(v8::Isolate* isolate) -{ - // This is only for getting a unique pointer which we can pass to privateTemplate. - static int privateTemplateUniqueKey; - return cachedObjectTemplate(&privateTemplateUniqueKey, V8PromiseCustom::PromiseAllEnvironmentFieldCount, isolate); -} - -v8::Local<v8::ObjectTemplate> primitiveWrapperObjectTemplate(v8::Isolate* isolate) -{ - // This is only for getting a unique pointer which we can pass to privateTemplate. - static int privateTemplateUniqueKey; - return cachedObjectTemplate(&privateTemplateUniqueKey, V8PromiseCustom::PrimitiveWrapperFieldCount, isolate); -} - -v8::Local<v8::ObjectTemplate> internalObjectTemplate(v8::Isolate* isolate) -{ - // This is only for getting a unique pointer which we can pass to privateTemplate. - static int privateTemplateUniqueKey; - return cachedObjectTemplate(&privateTemplateUniqueKey, V8PromiseCustom::InternalFieldCount, isolate); -} - -void promiseResolveCallback(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - ASSERT(!info.Data().IsEmpty()); - v8::Local<v8::Object> promise = info.Data().As<v8::Object>(); - v8::Local<v8::Value> result = v8::Undefined(info.GetIsolate()); - if (info.Length() > 0) - result = info[0]; - - V8PromiseCustom::resolve(promise, result, info.GetIsolate()); -} - -void promiseRejectCallback(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - ASSERT(!info.Data().IsEmpty()); - v8::Local<v8::Object> promise = info.Data().As<v8::Object>(); - v8::Local<v8::Value> result = v8::Undefined(info.GetIsolate()); - if (info.Length() > 0) - result = info[0]; - - V8PromiseCustom::reject(promise, result, info.GetIsolate()); -} - -void promiseAllFulfillCallback(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - v8::Isolate* isolate = info.GetIsolate(); - ASSERT(!info.Data().IsEmpty()); - v8::Local<v8::Object> environment = info.Data().As<v8::Object>(); - v8::Local<v8::Value> result = v8::Undefined(isolate); - if (info.Length() > 0) - result = info[0]; - - v8::Local<v8::Object> promise = environment->GetInternalField(V8PromiseCustom::PromiseAllEnvironmentPromiseIndex).As<v8::Object>(); - v8::Local<v8::Object> countdownWrapper = environment->GetInternalField(V8PromiseCustom::PromiseAllEnvironmentCountdownIndex).As<v8::Object>(); - v8::Local<v8::Integer> index = environment->GetInternalField(V8PromiseCustom::PromiseAllEnvironmentIndexIndex).As<v8::Integer>(); - v8::Local<v8::Array> results = environment->GetInternalField(V8PromiseCustom::PromiseAllEnvironmentResultsIndex).As<v8::Array>(); - - results->Set(index->Value(), result); - - v8::Local<v8::Integer> countdown = countdownWrapper->GetInternalField(V8PromiseCustom::PrimitiveWrapperPrimitiveIndex).As<v8::Integer>(); - ASSERT(countdown->Value() >= 1); - if (countdown->Value() == 1) { - V8PromiseCustom::resolve(promise, results, isolate); - return; - } - countdownWrapper->SetInternalField(V8PromiseCustom::PrimitiveWrapperPrimitiveIndex, v8::Integer::New(countdown->Value() - 1, isolate)); -} - -v8::Local<v8::Object> promiseAllEnvironment(v8::Handle<v8::Object> promise, v8::Handle<v8::Object> countdownWrapper, int index, v8::Handle<v8::Array> results, v8::Isolate* isolate) -{ - v8::Local<v8::ObjectTemplate> objectTemplate = promiseAllEnvironmentObjectTemplate(isolate); - v8::Local<v8::Object> environment = objectTemplate->NewInstance(); - - environment->SetInternalField(V8PromiseCustom::PromiseAllEnvironmentPromiseIndex, promise); - environment->SetInternalField(V8PromiseCustom::PromiseAllEnvironmentCountdownIndex, countdownWrapper); - environment->SetInternalField(V8PromiseCustom::PromiseAllEnvironmentIndexIndex, v8::Integer::New(index, isolate)); - environment->SetInternalField(V8PromiseCustom::PromiseAllEnvironmentResultsIndex, results); - return environment; -} - -// Clear |internal|'s derived array. -void clearDerived(v8::Handle<v8::Object> internal, v8::Isolate* isolate) -{ - internal->SetInternalField(V8PromiseCustom::InternalFulfillCallbackIndex, v8::Array::New(isolate)); - internal->SetInternalField(V8PromiseCustom::InternalRejectCallbackIndex, v8::Array::New(isolate)); - internal->SetInternalField(V8PromiseCustom::InternalDerivedPromiseIndex, v8::Array::New(isolate)); -} - -// Add a tuple (|derivedPromise|, |onFulfilled|, |onRejected|) to -// |internal|'s derived array. -// |internal| must be a Promise internal object. -// |derivedPromise| must be a Promise instance. -// |onFulfilled| and |onRejected| can be an empty value respectively. -void addToDerived(v8::Handle<v8::Object> internal, v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Isolate* isolate) -{ - v8::Local<v8::Array> fulfillCallbacks = internal->GetInternalField(V8PromiseCustom::InternalFulfillCallbackIndex).As<v8::Array>(); - v8::Local<v8::Array> rejectCallbacks = internal->GetInternalField(V8PromiseCustom::InternalRejectCallbackIndex).As<v8::Array>(); - v8::Local<v8::Array> derivedPromises = internal->GetInternalField(V8PromiseCustom::InternalDerivedPromiseIndex).As<v8::Array>(); - - if (onFulfilled.IsEmpty()) { - fulfillCallbacks->Set(fulfillCallbacks->Length(), v8::Undefined(isolate)); - } else { - fulfillCallbacks->Set(fulfillCallbacks->Length(), onFulfilled); - } - - if (onRejected.IsEmpty()) { - rejectCallbacks->Set(rejectCallbacks->Length(), v8::Undefined(isolate)); - } else { - rejectCallbacks->Set(rejectCallbacks->Length(), onRejected); - } - - ASSERT(!derivedPromise.IsEmpty()); - derivedPromises->Set(derivedPromises->Length(), derivedPromise); - - // Since they are treated as a tuple, - // we need to guaranteed that the length of these arrays are same. - ASSERT(fulfillCallbacks->Length() == rejectCallbacks->Length() && rejectCallbacks->Length() == derivedPromises->Length()); -} - -class CallHandlerTask : public ExecutionContextTask { -public: - CallHandlerTask(v8::Handle<v8::Object> promise, v8::Handle<v8::Function> handler, v8::Handle<v8::Value> argument, v8::Isolate* isolate, ExecutionContext* context) - : m_promise(isolate, promise) - , m_handler(isolate, handler) - , m_argument(isolate, argument) - , m_requestState(context) - { - ASSERT(!m_promise.isEmpty()); - ASSERT(!m_handler.isEmpty()); - ASSERT(!m_argument.isEmpty()); - } - virtual ~CallHandlerTask() { } - - virtual void performTask(ExecutionContext*) OVERRIDE; - -private: - ScopedPersistent<v8::Object> m_promise; - ScopedPersistent<v8::Function> m_handler; - ScopedPersistent<v8::Value> m_argument; - DOMRequestState m_requestState; -}; - -void CallHandlerTask::performTask(ExecutionContext* context) -{ - ASSERT(context); - if (context->activeDOMObjectsAreStopped()) - return; - - DOMRequestState::Scope scope(m_requestState); - v8::Isolate* isolate = m_requestState.isolate(); - v8::Handle<v8::Value> info[] = { m_argument.newLocal(isolate) }; - v8::TryCatch trycatch; - v8::Local<v8::Value> value = V8ScriptRunner::callFunction(m_handler.newLocal(isolate), context, v8::Undefined(isolate), WTF_ARRAY_LENGTH(info), info, isolate); - if (value.IsEmpty()) { - V8PromiseCustom::reject(m_promise.newLocal(isolate), trycatch.Exception(), isolate); - } else { - V8PromiseCustom::resolve(m_promise.newLocal(isolate), value, isolate); - } -} - -class UpdateDerivedTask : public ExecutionContextTask { -public: - UpdateDerivedTask(v8::Handle<v8::Object> promise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> originatorValueObject, v8::Isolate* isolate, ExecutionContext* context) - : m_promise(isolate, promise) - , m_onFulfilled(isolate, onFulfilled) - , m_onRejected(isolate, onRejected) - , m_originatorValueObject(isolate, originatorValueObject) - , m_requestState(context) - { - ASSERT(!m_promise.isEmpty()); - ASSERT(!m_originatorValueObject.isEmpty()); - } - virtual ~UpdateDerivedTask() { } - - virtual void performTask(ExecutionContext*) OVERRIDE; - -private: - ScopedPersistent<v8::Object> m_promise; - ScopedPersistent<v8::Function> m_onFulfilled; - ScopedPersistent<v8::Function> m_onRejected; - ScopedPersistent<v8::Object> m_originatorValueObject; - DOMRequestState m_requestState; -}; - -void UpdateDerivedTask::performTask(ExecutionContext* context) -{ - ASSERT(context); - if (context->activeDOMObjectsAreStopped()) - return; - - DOMRequestState::Scope scope(m_requestState); - v8::Isolate* isolate = m_requestState.isolate(); - v8::Local<v8::Object> originatorValueObject = m_originatorValueObject.newLocal(isolate); - v8::Local<v8::Value> coercedAlready = originatorValueObject->GetHiddenValue(V8HiddenPropertyName::thenableHiddenPromise(isolate)); - if (!coercedAlready.IsEmpty() && coercedAlready->IsObject()) { - ASSERT(V8PromiseCustom::isPromise(coercedAlready.As<v8::Object>(), isolate)); - V8PromiseCustom::updateDerivedFromPromise(m_promise.newLocal(isolate), m_onFulfilled.newLocal(isolate), m_onRejected.newLocal(isolate), coercedAlready.As<v8::Object>(), isolate); - return; - } - - v8::Local<v8::Value> then; - v8::TryCatch trycatch; - then = originatorValueObject->Get(v8AtomicString(isolate, "then")); - if (then.IsEmpty()) { - // If calling the [[Get]] internal method threw an exception, catch it and run updateDerivedFromReason. - V8PromiseCustom::updateDerivedFromReason(m_promise.newLocal(isolate), m_onRejected.newLocal(isolate), trycatch.Exception(), isolate); - return; - } - - if (then->IsFunction()) { - ASSERT(then->IsObject()); - v8::Local<v8::Object> coerced = V8PromiseCustom::coerceThenable(originatorValueObject, then.As<v8::Function>(), isolate); - V8PromiseCustom::updateDerivedFromPromise(m_promise.newLocal(isolate), m_onFulfilled.newLocal(isolate), m_onRejected.newLocal(isolate), coerced, isolate); - return; - } - - V8PromiseCustom::updateDerivedFromValue(m_promise.newLocal(isolate), m_onFulfilled.newLocal(isolate), originatorValueObject, isolate); -} - -// Since Promises state propagation routines are executed recursively, they cause -// stack overflow. -// (e.g. UpdateDerived -> UpdateDerivedFromValue -> SetValue -> -// PropagateToDerived -> UpdateDerived) -// -// To fix that, we introduce PromisePropagator. It holds the stack. When -// propagating the result to the derived tuples, we append the derived tuples -// to the stack. After that, we drain the stack to propagate the result to -// the stored tuples. -// -// PromisePropagator should be held on the stack and should not be held -// as other object's member. PromisePropagator holds Derived tuples. Since -// Derived tuples hold persistent handles to JS objects, retaining -// PromisePropagator in the heap causes memory leaks. -// -class PromisePropagator { - WTF_MAKE_NONCOPYABLE(PromisePropagator); -public: - PromisePropagator() { } - - void performPropagation(v8::Isolate*); - - void setValue(v8::Handle<v8::Object> promise, v8::Handle<v8::Value>, v8::Isolate*); - void setReason(v8::Handle<v8::Object> promise, v8::Handle<v8::Value>, v8::Isolate*); - void propagateToDerived(v8::Handle<v8::Object> promise, v8::Isolate*); - void updateDerived(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> originator, v8::Isolate*); - void updateDerivedFromValue(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Value>, v8::Isolate*); - void updateDerivedFromReason(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Value>, v8::Isolate*); - void updateDerivedFromPromise(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> promise, v8::Isolate*); - -private: - class Derived { - WTF_MAKE_NONCOPYABLE(Derived); - public: - Derived(v8::Handle<v8::Object> promise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> originator, v8::Isolate* isolate) - : m_promise(isolate, promise) - , m_onFulfilled(isolate, onFulfilled) - , m_onRejected(isolate, onRejected) - , m_originator(isolate, originator) - { - ASSERT(!m_promise.isEmpty()); - ASSERT(!m_originator.isEmpty()); - } - - static PassOwnPtr<Derived> create(v8::Handle<v8::Object> promise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> originator, v8::Isolate* isolate) - { - return adoptPtr(new Derived(promise, onFulfilled, onRejected, originator, isolate)); - } - - v8::Local<v8::Object> promise(v8::Isolate* isolate) const { return m_promise.newLocal(isolate); } - v8::Local<v8::Function> onFulfilled(v8::Isolate* isolate) const { return m_onFulfilled.newLocal(isolate); } - v8::Local<v8::Function> onRejected(v8::Isolate* isolate) const { return m_onRejected.newLocal(isolate); } - v8::Local<v8::Object> originator(v8::Isolate* isolate) const { return m_originator.newLocal(isolate); } - - private: - ScopedPersistent<v8::Object> m_promise; - ScopedPersistent<v8::Function> m_onFulfilled; - ScopedPersistent<v8::Function> m_onRejected; - ScopedPersistent<v8::Object> m_originator; - }; - - Deque<OwnPtr<Derived> > m_derivedStack; -}; - -void PromisePropagator::performPropagation(v8::Isolate* isolate) -{ - while (!m_derivedStack.isEmpty()) { - v8::HandleScope handleScope(isolate); - OwnPtr<Derived> derived = m_derivedStack.takeLast(); - updateDerived(derived->promise(isolate), derived->onFulfilled(isolate), derived->onRejected(isolate), derived->originator(isolate), isolate); - } -} - -void PromisePropagator::setValue(v8::Handle<v8::Object> promise, v8::Handle<v8::Value> value, v8::Isolate* isolate) -{ - v8::Local<v8::Object> internal = V8PromiseCustom::getInternal(promise); - ASSERT(V8PromiseCustom::getState(internal) != V8PromiseCustom::Fulfilled && V8PromiseCustom::getState(internal) != V8PromiseCustom::Rejected); - V8PromiseCustom::setState(internal, V8PromiseCustom::Fulfilled, value, isolate); - propagateToDerived(promise, isolate); -} - -void PromisePropagator::setReason(v8::Handle<v8::Object> promise, v8::Handle<v8::Value> reason, v8::Isolate* isolate) -{ - v8::Local<v8::Object> internal = V8PromiseCustom::getInternal(promise); - ASSERT(V8PromiseCustom::getState(internal) != V8PromiseCustom::Fulfilled && V8PromiseCustom::getState(internal) != V8PromiseCustom::Rejected); - V8PromiseCustom::setState(internal, V8PromiseCustom::Rejected, reason, isolate); - propagateToDerived(promise, isolate); -} - -void PromisePropagator::propagateToDerived(v8::Handle<v8::Object> promise, v8::Isolate* isolate) -{ - v8::Local<v8::Object> internal = V8PromiseCustom::getInternal(promise); - ASSERT(V8PromiseCustom::getState(internal) == V8PromiseCustom::Fulfilled || V8PromiseCustom::getState(internal) == V8PromiseCustom::Rejected); - v8::Local<v8::Array> fulfillCallbacks = internal->GetInternalField(V8PromiseCustom::InternalFulfillCallbackIndex).As<v8::Array>(); - v8::Local<v8::Array> rejectCallbacks = internal->GetInternalField(V8PromiseCustom::InternalRejectCallbackIndex).As<v8::Array>(); - v8::Local<v8::Array> derivedPromises = internal->GetInternalField(V8PromiseCustom::InternalDerivedPromiseIndex).As<v8::Array>(); - // Since they are treated as a tuple, - // we need to guaranteed that the length of these arrays are same. - ASSERT(fulfillCallbacks->Length() == rejectCallbacks->Length() && rejectCallbacks->Length() == derivedPromises->Length()); - - // Append Derived tuple to the stack in reverse order. - for (uint32_t count = 0, length = derivedPromises->Length(); count < length; ++count) { - uint32_t i = length - count - 1; - v8::Local<v8::Object> derivedPromise = derivedPromises->Get(i).As<v8::Object>(); - - v8::Local<v8::Function> onFulfilled, onRejected; - v8::Local<v8::Value> onFulfilledValue = fulfillCallbacks->Get(i); - if (onFulfilledValue->IsFunction()) { - onFulfilled = onFulfilledValue.As<v8::Function>(); - } - v8::Local<v8::Value> onRejectedValue = rejectCallbacks->Get(i); - if (onRejectedValue->IsFunction()) { - onRejected = onRejectedValue.As<v8::Function>(); - } - - m_derivedStack.append(Derived::create(derivedPromise, onFulfilled, onRejected, promise, isolate)); - } - clearDerived(internal, isolate); -} - -void PromisePropagator::updateDerivedFromValue(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Value> value, v8::Isolate* isolate) -{ - if (!onFulfilled.IsEmpty()) { - V8PromiseCustom::callHandler(derivedPromise, onFulfilled, value, isolate); - } else { - setValue(derivedPromise, value, isolate); - } -} - -void PromisePropagator::updateDerivedFromReason(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Value> reason, v8::Isolate* isolate) -{ - if (!onRejected.IsEmpty()) { - V8PromiseCustom::callHandler(derivedPromise, onRejected, reason, isolate); - } else { - setReason(derivedPromise, reason, isolate); - } -} - -void PromisePropagator::updateDerived(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> originator, v8::Isolate* isolate) -{ - v8::Local<v8::Object> originatorInternal = V8PromiseCustom::getInternal(originator); - V8PromiseCustom::PromiseState originatorState = V8PromiseCustom::getState(originatorInternal); - ASSERT(originatorState == V8PromiseCustom::Fulfilled || originatorState == V8PromiseCustom::Rejected); - v8::Local<v8::Value> originatorValue = originatorInternal->GetInternalField(V8PromiseCustom::InternalResultIndex); - if (originatorState == V8PromiseCustom::Fulfilled) { - if (originatorValue->IsObject()) { - ExecutionContext* executionContext = getExecutionContext(); - ASSERT(executionContext && executionContext->isContextThread()); - executionContext->postTask(adoptPtr(new UpdateDerivedTask(derivedPromise, onFulfilled, onRejected, originatorValue.As<v8::Object>(), isolate, executionContext))); - } else { - updateDerivedFromValue(derivedPromise, onFulfilled, originatorValue, isolate); - } - } else { - updateDerivedFromReason(derivedPromise, onRejected, originatorValue, isolate); - } -} - -void PromisePropagator::updateDerivedFromPromise(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> promise, v8::Isolate* isolate) -{ - v8::Local<v8::Object> internal = V8PromiseCustom::getInternal(promise); - V8PromiseCustom::PromiseState state = V8PromiseCustom::getState(internal); - if (state == V8PromiseCustom::Fulfilled || state == V8PromiseCustom::Rejected) { - updateDerived(derivedPromise, onFulfilled, onRejected, promise, isolate); - } else { - addToDerived(internal, derivedPromise, onFulfilled, onRejected, isolate); - } -} - -} // namespace - -void V8Promise::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - v8SetReturnValue(info, v8::Local<v8::Value>()); - v8::Isolate* isolate = info.GetIsolate(); - if (!info.Length() || !info[0]->IsFunction()) { - throwTypeError("Promise constructor takes a function argument", isolate); - return; - } - v8::Local<v8::Function> init = info[0].As<v8::Function>(); - v8::Local<v8::Object> promise = V8PromiseCustom::createPromise(info.Holder(), isolate); - v8::Handle<v8::Value> argv[] = { - createClosure(promiseResolveCallback, promise, isolate), - createClosure(promiseRejectCallback, promise, isolate) - }; - v8::TryCatch trycatch; - if (V8ScriptRunner::callFunction(init, getExecutionContext(), v8::Undefined(isolate), WTF_ARRAY_LENGTH(argv), argv, isolate).IsEmpty()) { - // An exception is thrown. Reject the promise if its resolved flag is unset. - V8PromiseCustom::reject(promise, trycatch.Exception(), isolate); - } - v8SetReturnValue(info, promise); - return; -} - -void V8Promise::thenMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - v8::Isolate* isolate = info.GetIsolate(); - v8::Local<v8::Function> onFulfilled, onRejected; - if (info.Length() > 0 && info[0]->IsFunction()) - onFulfilled = info[0].As<v8::Function>(); - if (info.Length() > 1 && info[1]->IsFunction()) - onRejected = info[1].As<v8::Function>(); - v8SetReturnValue(info, V8PromiseCustom::then(info.Holder(), onFulfilled, onRejected, isolate)); -} - -void V8Promise::castMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - v8::Isolate* isolate = info.GetIsolate(); - v8::Local<v8::Value> result = v8::Undefined(isolate); - if (info.Length() > 0) - result = info[0]; - - v8SetReturnValue(info, V8PromiseCustom::toPromise(result, isolate)); -} - -void V8Promise::catchMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - v8::Isolate* isolate = info.GetIsolate(); - v8::Local<v8::Function> onFulfilled, onRejected; - - if (info.Length() > 0 && !info[0]->IsUndefined()) { - if (!info[0]->IsFunction()) { - v8SetReturnValue(info, throwTypeError("onRejected must be a function or undefined", isolate)); - return; - } - onRejected = info[0].As<v8::Function>(); - } - v8SetReturnValue(info, V8PromiseCustom::then(info.Holder(), onFulfilled, onRejected, isolate)); -} - -void V8Promise::resolveMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - v8::Isolate* isolate = info.GetIsolate(); - v8::Local<v8::Value> result = v8::Undefined(isolate); - if (info.Length() > 0) - result = info[0]; - - v8::Local<v8::Object> promise = V8PromiseCustom::createPromise(info.Holder(), isolate); - V8PromiseCustom::resolve(promise, result, isolate); - v8SetReturnValue(info, promise); -} - -void V8Promise::rejectMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - v8::Isolate* isolate = info.GetIsolate(); - v8::Local<v8::Value> result = v8::Undefined(isolate); - if (info.Length() > 0) - result = info[0]; - - v8::Local<v8::Object> promise = V8PromiseCustom::createPromise(info.Holder(), isolate); - V8PromiseCustom::reject(promise, result, isolate); - v8SetReturnValue(info, promise); -} - -void V8Promise::raceMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - v8::Isolate* isolate = info.GetIsolate(); - v8::Local<v8::Object> promise = V8PromiseCustom::createPromise(info.Holder(), isolate); - - if (!info.Length() || !info[0]->IsArray()) { - v8SetReturnValue(info, promise); - return; - } - - // FIXME: Now we limit the iterable type to the Array type. - v8::Local<v8::Array> iterable = info[0].As<v8::Array>(); - v8::Local<v8::Function> onFulfilled = createClosure(promiseResolveCallback, promise, isolate); - v8::Local<v8::Function> onRejected = createClosure(promiseRejectCallback, promise, isolate); - - for (unsigned i = 0, length = iterable->Length(); i < length; ++i) { - // Array-holes should not be skipped by for-of iteration semantics. - V8TRYCATCH_VOID(v8::Local<v8::Value>, nextValue, iterable->Get(i)); - v8::Local<v8::Object> nextPromise = V8PromiseCustom::toPromise(nextValue, isolate); - V8PromiseCustom::then(nextPromise, onFulfilled, onRejected, isolate); - } - v8SetReturnValue(info, promise); -} - -void V8Promise::allMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - v8::Isolate* isolate = info.GetIsolate(); - v8::Local<v8::Object> promise = V8PromiseCustom::createPromise(info.Holder(), isolate); - v8::Local<v8::Array> results = v8::Array::New(info.GetIsolate()); - - if (!info.Length() || !info[0]->IsArray()) { - V8PromiseCustom::resolve(promise, results, isolate); - v8SetReturnValue(info, promise); - return; - } - - // FIXME: Now we limit the iterable type to the Array type. - v8::Local<v8::Array> iterable = info[0].As<v8::Array>(); - - if (!iterable->Length()) { - V8PromiseCustom::resolve(promise, results, isolate); - v8SetReturnValue(info, promise); - return; - } - - v8::Local<v8::ObjectTemplate> objectTemplate = primitiveWrapperObjectTemplate(isolate); - v8::Local<v8::Object> countdownWrapper = objectTemplate->NewInstance(); - countdownWrapper->SetInternalField(V8PromiseCustom::PrimitiveWrapperPrimitiveIndex, v8::Integer::New(iterable->Length(), isolate)); - - v8::Local<v8::Function> onRejected = createClosure(promiseRejectCallback, promise, isolate); - for (unsigned i = 0, length = iterable->Length(); i < length; ++i) { - // Array-holes should not be skipped by for-of iteration semantics. - v8::Local<v8::Object> environment = promiseAllEnvironment(promise, countdownWrapper, i, results, isolate); - v8::Local<v8::Function> onFulfilled = createClosure(promiseAllFulfillCallback, environment, isolate); - V8TRYCATCH_VOID(v8::Local<v8::Value>, nextValue, iterable->Get(i)); - v8::Local<v8::Object> nextPromise = V8PromiseCustom::toPromise(nextValue, isolate); - V8PromiseCustom::then(nextPromise, onFulfilled, onRejected, isolate); - } - v8SetReturnValue(info, promise); -} - -// -// -- V8PromiseCustom -- -v8::Local<v8::Object> V8PromiseCustom::createPromise(v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) -{ - v8::Local<v8::ObjectTemplate> internalTemplate = internalObjectTemplate(isolate); - v8::Local<v8::Object> internal = internalTemplate->NewInstance(); - v8::Local<v8::Object> promise = V8DOMWrapper::createWrapper(creationContext, &V8Promise::wrapperTypeInfo, 0, isolate); - - clearDerived(internal, isolate); - setState(internal, Pending, v8::Undefined(isolate), isolate); - - promise->SetInternalField(v8DOMWrapperObjectIndex, internal); - return promise; -} - -v8::Local<v8::Object> V8PromiseCustom::getInternal(v8::Handle<v8::Object> promise) -{ - v8::Local<v8::Value> value = promise->GetInternalField(v8DOMWrapperObjectIndex); - return value.As<v8::Object>(); -} - -V8PromiseCustom::PromiseState V8PromiseCustom::getState(v8::Handle<v8::Object> internal) -{ - v8::Handle<v8::Value> value = internal->GetInternalField(V8PromiseCustom::InternalStateIndex); - bool ok = false; - uint32_t number = toInt32(value, ok); - ASSERT(ok && (number == Pending || number == Fulfilled || number == Rejected || number == Following)); - return static_cast<PromiseState>(number); -} - -void V8PromiseCustom::setState(v8::Handle<v8::Object> internal, PromiseState state, v8::Handle<v8::Value> value, v8::Isolate* isolate) -{ - ASSERT(!value.IsEmpty()); - ASSERT(state == Pending || state == Fulfilled || state == Rejected || state == Following); - internal->SetInternalField(InternalStateIndex, v8::Integer::New(state, isolate)); - internal->SetInternalField(InternalResultIndex, value); -} - -bool V8PromiseCustom::isPromise(v8::Handle<v8::Value> maybePromise, v8::Isolate* isolate) -{ - WrapperWorldType currentWorldType = worldType(isolate); - return V8Promise::domTemplate(isolate, currentWorldType)->HasInstance(maybePromise); -} - -v8::Local<v8::Object> V8PromiseCustom::toPromise(v8::Handle<v8::Value> maybePromise, v8::Isolate* isolate) -{ - // FIXME: Currently we don't check [[PromiseConstructor]] since we limit - // the creation of the promise objects only from the Blink Promise - // constructor. - if (isPromise(maybePromise, isolate)) - return maybePromise.As<v8::Object>(); - - v8::Local<v8::Object> promise = createPromise(v8::Handle<v8::Object>(), isolate); - resolve(promise, maybePromise, isolate); - return promise; -} - -void V8PromiseCustom::resolve(v8::Handle<v8::Object> promise, v8::Handle<v8::Value> result, v8::Isolate* isolate) -{ - ASSERT(!result.IsEmpty()); - v8::Local<v8::Object> internal = getInternal(promise); - PromiseState state = getState(internal); - if (state != Pending) - return; - - if (isPromise(result, isolate)) { - v8::Local<v8::Object> valuePromise = result.As<v8::Object>(); - v8::Local<v8::Object> valueInternal = getInternal(valuePromise); - PromiseState valueState = getState(valueInternal); - if (promise->SameValue(valuePromise)) { - v8::Local<v8::Value> reason = V8ThrowException::createTypeError("Resolve a promise with itself", isolate); - setReason(promise, reason, isolate); - } else if (valueState == Following) { - v8::Local<v8::Object> valuePromiseFollowing = valueInternal->GetInternalField(InternalResultIndex).As<v8::Object>(); - setState(internal, Following, valuePromiseFollowing, isolate); - addToDerived(getInternal(valuePromiseFollowing), promise, v8::Handle<v8::Function>(), v8::Handle<v8::Function>(), isolate); - } else if (valueState == Fulfilled) { - setValue(promise, valueInternal->GetInternalField(InternalResultIndex), isolate); - } else if (valueState == Rejected) { - setReason(promise, valueInternal->GetInternalField(InternalResultIndex), isolate); - } else { - ASSERT(valueState == Pending); - setState(internal, Following, valuePromise, isolate); - addToDerived(valueInternal, promise, v8::Handle<v8::Function>(), v8::Handle<v8::Function>(), isolate); - } - } else { - setValue(promise, result, isolate); - } -} - -void V8PromiseCustom::reject(v8::Handle<v8::Object> promise, v8::Handle<v8::Value> reason, v8::Isolate* isolate) -{ - v8::Local<v8::Object> internal = getInternal(promise); - PromiseState state = getState(internal); - if (state != Pending) - return; - setReason(promise, reason, isolate); -} - -v8::Local<v8::Object> V8PromiseCustom::then(v8::Handle<v8::Object> promise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Isolate* isolate) -{ - v8::Handle<v8::Object> internal = getInternal(promise); - while (getState(internal) == Following) { - promise = internal->GetInternalField(InternalResultIndex).As<v8::Object>(); - internal = getInternal(promise); - } - // FIXME: Currently we don't lookup "constructor" property since we limit - // the creation of the promise objects only from the Blink Promise - // constructor. - v8::Local<v8::Object> derivedPromise = createPromise(v8::Handle<v8::Object>(), isolate); - updateDerivedFromPromise(derivedPromise, onFulfilled, onRejected, promise, isolate); - return derivedPromise; -} - -void V8PromiseCustom::setValue(v8::Handle<v8::Object> promise, v8::Handle<v8::Value> value, v8::Isolate* isolate) -{ - PromisePropagator propagator; - propagator.setValue(promise, value, isolate); - propagator.performPropagation(isolate); -} - -void V8PromiseCustom::setReason(v8::Handle<v8::Object> promise, v8::Handle<v8::Value> reason, v8::Isolate* isolate) -{ - PromisePropagator propagator; - propagator.setReason(promise, reason, isolate); - propagator.performPropagation(isolate); -} - -void V8PromiseCustom::propagateToDerived(v8::Handle<v8::Object> promise, v8::Isolate* isolate) -{ - PromisePropagator propagator; - propagator.propagateToDerived(promise, isolate); - propagator.performPropagation(isolate); -} - -void V8PromiseCustom::updateDerived(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> originator, v8::Isolate* isolate) -{ - PromisePropagator propagator; - propagator.updateDerived(derivedPromise, onFulfilled, onRejected, originator, isolate); - propagator.performPropagation(isolate); -} - -void V8PromiseCustom::updateDerivedFromValue(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Value> value, v8::Isolate* isolate) -{ - PromisePropagator propagator; - propagator.updateDerivedFromValue(derivedPromise, onFulfilled, value, isolate); - propagator.performPropagation(isolate); -} - -void V8PromiseCustom::updateDerivedFromReason(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Value> reason, v8::Isolate* isolate) -{ - PromisePropagator propagator; - propagator.updateDerivedFromReason(derivedPromise, onRejected, reason, isolate); - propagator.performPropagation(isolate); -} - -void V8PromiseCustom::updateDerivedFromPromise(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> promise, v8::Isolate* isolate) -{ - PromisePropagator propagator; - propagator.updateDerivedFromPromise(derivedPromise, onFulfilled, onRejected, promise, isolate); - propagator.performPropagation(isolate); -} - -v8::Local<v8::Object> V8PromiseCustom::coerceThenable(v8::Handle<v8::Object> thenable, v8::Handle<v8::Function> then, v8::Isolate* isolate) -{ - ASSERT(!thenable.IsEmpty()); - ASSERT(!then.IsEmpty()); - v8::Local<v8::Object> promise = createPromise(v8::Handle<v8::Object>(), isolate); - v8::Handle<v8::Value> argv[] = { - createClosure(promiseResolveCallback, promise, isolate), - createClosure(promiseRejectCallback, promise, isolate) - }; - v8::TryCatch trycatch; - if (V8ScriptRunner::callFunction(then, getExecutionContext(), thenable, WTF_ARRAY_LENGTH(argv), argv, isolate).IsEmpty()) { - reject(promise, trycatch.Exception(), isolate); - } - thenable->SetHiddenValue(V8HiddenPropertyName::thenableHiddenPromise(isolate), promise); - return promise; -} - -void V8PromiseCustom::callHandler(v8::Handle<v8::Object> promise, v8::Handle<v8::Function> handler, v8::Handle<v8::Value> argument, v8::Isolate* isolate) -{ - ExecutionContext* executionContext = getExecutionContext(); - ASSERT(executionContext && executionContext->isContextThread()); - executionContext->postTask(adoptPtr(new CallHandlerTask(promise, handler, argument, isolate, executionContext))); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PromiseCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PromiseCustom.h deleted file mode 100644 index 1751c1e4ae3..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8PromiseCustom.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2013, 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. - */ - -#ifndef V8PromiseCustom_h -#define V8PromiseCustom_h - -#include "bindings/v8/WrapperTypeInfo.h" - -#include <v8.h> - -namespace WebCore { - -class V8PromiseCustom { -public: - enum InternalFieldIndex { - InternalStateIndex, - InternalResultIndex, - InternalFulfillCallbackIndex, - InternalRejectCallbackIndex, - InternalDerivedPromiseIndex, - InternalFieldCount, // This entry must always be at the bottom. - }; - - enum PromiseAllEnvironmentFieldIndex { - PromiseAllEnvironmentPromiseIndex, - PromiseAllEnvironmentCountdownIndex, - PromiseAllEnvironmentIndexIndex, - PromiseAllEnvironmentResultsIndex, - PromiseAllEnvironmentFieldCount, // This entry must always be at the bottom. - }; - - enum PrimitiveWrapperFieldIndex { - PrimitiveWrapperPrimitiveIndex, - PrimitiveWrapperFieldCount, // This entry must always be at the bottom. - }; - - enum PromiseState { - Pending, - Fulfilled, - Rejected, - Following, - }; - - static v8::Local<v8::Object> createPromise(v8::Handle<v8::Object> creationContext, v8::Isolate*); - - // |promise| must be a Promise instance. - static v8::Local<v8::Object> getInternal(v8::Handle<v8::Object> promise); - - // |internal| must be a Promise internal object. - static PromiseState getState(v8::Handle<v8::Object> internal); - - // |internal| must be a Promise internal object. - // Set a |promise|'s state and result that correspond to the state. - static void setState(v8::Handle<v8::Object> internal, PromiseState, v8::Handle<v8::Value>, v8::Isolate*); - - // Return true if |maybePromise| is a Promise instance. - static bool isPromise(v8::Handle<v8::Value> maybePromise, v8::Isolate*); - - // Coerces |maybePromise| to a Promise instance. - static v8::Local<v8::Object> toPromise(v8::Handle<v8::Value> maybePromise, v8::Isolate*); - - // |promise| must be a Promise instance. - static void resolve(v8::Handle<v8::Object> promise, v8::Handle<v8::Value> result, v8::Isolate*); - - // |promise| must be a Promise instance. - static void reject(v8::Handle<v8::Object> promise, v8::Handle<v8::Value> result, v8::Isolate*); - - // |promise| must be a Promise instance. - // |onFulfilled| and |onRejected| can be an empty value respectively. - // Appends |onFulfilled| and/or |onRejected| handlers to |promise|. - static v8::Local<v8::Object> then(v8::Handle<v8::Object> promise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Isolate*); - - // |promise| must be a Promise instance. - // Set a |promise|'s value and propagate it to derived promises. - static void setValue(v8::Handle<v8::Object> promise, v8::Handle<v8::Value>, v8::Isolate*); - - // |promise| must be a Promise instance. - // Set a |promise|'s failure reason and propagate it to derived promises. - static void setReason(v8::Handle<v8::Object> promise, v8::Handle<v8::Value>, v8::Isolate*); - - // |promise| must be a Promise instance. - // Propagate a |promise|'s value or reason to all of its derived promies. - static void propagateToDerived(v8::Handle<v8::Object> promise, v8::Isolate*); - - // |derivedPromise| and |originator| must be a Promise instance. - // |onFulfilled| and |onRejected| can be an empty value respectively. - // Propagate |originator|'s state to |derivedPromise|. - static void updateDerived(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> originator, v8::Isolate*); - - // |derivedPromise| must be a Promise instance. - // Propagate a value to |derivedPromise|. - static void updateDerivedFromValue(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Value>, v8::Isolate*); - - // |derivedPromise| must be a Promise instance. - // Propagate a failure reason to |derivedPromise|. - static void updateDerivedFromReason(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Value>, v8::Isolate*); - - // |derivedPromise| and |promise| must be a Promise instance. - // |onFulfilled| and |onRejected| can be an empty value respectively. - // Propagate |promise|'s state to |derivedPromise|. - static void updateDerivedFromPromise(v8::Handle<v8::Object> derivedPromise, v8::Handle<v8::Function> onFulfilled, v8::Handle<v8::Function> onRejected, v8::Handle<v8::Object> promise, v8::Isolate*); - - // Returns a Promise instance that will be fulfilled or rejected by - // |thenable|'s result. - static v8::Local<v8::Object> coerceThenable(v8::Handle<v8::Object> thenable, v8::Handle<v8::Function> then, v8::Isolate*); - - // |promise| must be a Promise instance. - // Applies a transformation to an argument and use it to update derived - // promies. - static void callHandler(v8::Handle<v8::Object> promise, v8::Handle<v8::Function> handler, v8::Handle<v8::Value> argument, v8::Isolate*); -}; - -} // namespace WebCore - -#endif // V8PromiseCustom_h diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLResultSetRowListCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLResultSetRowListCustom.cpp index 3c41cb7b9a6..a6fed441759 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLResultSetRowListCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLResultSetRowListCustom.cpp @@ -29,22 +29,28 @@ */ #include "config.h" -#include "V8SQLResultSetRowList.h" +#include "bindings/modules/v8/V8SQLResultSetRowList.h" +#include "bindings/v8/ExceptionMessages.h" +#include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" +#include "core/dom/ExceptionCode.h" #include "modules/webdatabase/SQLResultSetRowList.h" namespace WebCore { void V8SQLResultSetRowList::itemMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { + ExceptionState exceptionState(ExceptionState::ExecutionContext, "item", "SQLResultSetRowList", info.Holder(), info.GetIsolate()); if (!info.Length()) { - throwError(v8SyntaxError, "Item index is required.", info.GetIsolate()); + exceptionState.throwDOMException(SyntaxError, ExceptionMessages::notEnoughArguments(1, 0)); + exceptionState.throwIfNeeded(); return; } if (!info[0]->IsNumber()) { - throwTypeError("Item index must be a number.", info.GetIsolate()); + exceptionState.throwTypeError("The index provided is not a number."); + exceptionState.throwIfNeeded(); return; } @@ -52,11 +58,12 @@ void V8SQLResultSetRowList::itemMethodCustom(const v8::FunctionCallbackInfo<v8:: unsigned long index = info[0]->IntegerValue(); if (index >= rowList->length()) { - throwError(v8RangeError, "Item index is out of range.", info.GetIsolate()); + exceptionState.throwDOMException(IndexSizeError, ExceptionMessages::indexExceedsMaximumBound<unsigned>("index", index, rowList->length())); + exceptionState.throwIfNeeded(); return; } - v8::Local<v8::Object> item = v8::Object::New(); + v8::Local<v8::Object> item = v8::Object::New(info.GetIsolate()); unsigned numColumns = rowList->columnNames().size(); unsigned valuesIndex = index * numColumns; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLTransactionCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLTransactionCustom.cpp index 9a314b5f666..45a764ce042 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLTransactionCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLTransactionCustom.cpp @@ -29,10 +29,11 @@ */ #include "config.h" -#include "V8SQLTransaction.h" +#include "bindings/modules/v8/V8SQLTransaction.h" -#include "V8SQLStatementCallback.h" -#include "V8SQLStatementErrorCallback.h" +#include "bindings/modules/v8/V8SQLStatementCallback.h" +#include "bindings/modules/v8/V8SQLStatementErrorCallback.h" +#include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" #include "core/dom/ExceptionCode.h" @@ -46,69 +47,70 @@ namespace WebCore { void V8SQLTransaction::executeSqlMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { + ExceptionState exceptionState(ExceptionState::ExecutionContext, "executeSql", "SQLTransaction", info.Holder(), info.GetIsolate()); if (!info.Length()) { - setDOMException(SyntaxError, info.GetIsolate()); + exceptionState.throwDOMException(SyntaxError, ExceptionMessages::notEnoughArguments(1, 0)); + exceptionState.throwIfNeeded(); return; } - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, statement, info[0]); + TOSTRING_VOID(V8StringResource<>, statement, info[0]); Vector<SQLValue> sqlValues; if (info.Length() > 1 && !isUndefinedOrNull(info[1])) { if (!info[1]->IsObject()) { - setDOMException(TypeMismatchError, info.GetIsolate()); + exceptionState.throwDOMException(TypeMismatchError, "The 'arguments' (2nd) argument provided is not an object."); + exceptionState.throwIfNeeded(); return; } uint32_t sqlArgsLength = 0; v8::Local<v8::Object> sqlArgsObject = info[1]->ToObject(); - V8TRYCATCH_VOID(v8::Local<v8::Value>, length, sqlArgsObject->Get(v8AtomicString(info.GetIsolate(), "length"))); + TONATIVE_VOID(v8::Local<v8::Value>, length, sqlArgsObject->Get(v8AtomicString(info.GetIsolate(), "length"))); if (isUndefinedOrNull(length)) sqlArgsLength = sqlArgsObject->GetPropertyNames()->Length(); else sqlArgsLength = length->Uint32Value(); - for (unsigned int i = 0; i < sqlArgsLength; ++i) { - v8::Handle<v8::Integer> key = v8::Integer::New(i, info.GetIsolate()); - V8TRYCATCH_VOID(v8::Local<v8::Value>, value, sqlArgsObject->Get(key)); + for (unsigned i = 0; i < sqlArgsLength; ++i) { + v8::Handle<v8::Integer> key = v8::Integer::New(info.GetIsolate(), i); + TONATIVE_VOID(v8::Local<v8::Value>, value, sqlArgsObject->Get(key)); if (value.IsEmpty() || value->IsNull()) sqlValues.append(SQLValue()); else if (value->IsNumber()) { - V8TRYCATCH_VOID(double, sqlValue, value->NumberValue()); + TONATIVE_VOID(double, sqlValue, value->NumberValue()); sqlValues.append(SQLValue(sqlValue)); } else { - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, sqlValue, value); + TOSTRING_VOID(V8StringResource<>, sqlValue, value); sqlValues.append(SQLValue(sqlValue)); } } } SQLTransaction* transaction = V8SQLTransaction::toNative(info.Holder()); - - ExecutionContext* executionContext = getExecutionContext(); - OwnPtr<SQLStatementCallback> callback; if (info.Length() > 2 && !isUndefinedOrNull(info[2])) { if (!info[2]->IsFunction()) { - setDOMException(TypeMismatchError, info.GetIsolate()); + exceptionState.throwDOMException(TypeMismatchError, "The 'callback' (2nd) argument provided is not a function."); + exceptionState.throwIfNeeded(); return; } - callback = V8SQLStatementCallback::create(v8::Handle<v8::Function>::Cast(info[2]), executionContext); + callback = V8SQLStatementCallback::create(v8::Handle<v8::Function>::Cast(info[2]), ScriptState::current(info.GetIsolate())); } OwnPtr<SQLStatementErrorCallback> errorCallback; if (info.Length() > 3 && !isUndefinedOrNull(info[3])) { if (!info[3]->IsFunction()) { - setDOMException(TypeMismatchError, info.GetIsolate()); + exceptionState.throwDOMException(TypeMismatchError, "The 'errorCallback' (3rd) argument provided is not a function."); + exceptionState.throwIfNeeded(); return; } - errorCallback = V8SQLStatementErrorCallback::create(v8::Handle<v8::Function>::Cast(info[3]), executionContext); + errorCallback = V8SQLStatementErrorCallback::create(v8::Handle<v8::Function>::Cast(info[3]), ScriptState::current(info.GetIsolate())); } - ExceptionState exceptionState(info.Holder(), info.GetIsolate()); transaction->executeSQL(statement, sqlValues, callback.release(), errorCallback.release(), exceptionState); exceptionState.throwIfNeeded(); } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLTransactionSyncCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLTransactionSyncCustom.cpp index eaffffa0ca5..9b24721fa41 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLTransactionSyncCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SQLTransactionSyncCustom.cpp @@ -29,9 +29,9 @@ */ #include "config.h" -#include "V8SQLTransactionSync.h" +#include "bindings/modules/v8/V8SQLTransactionSync.h" -#include "V8SQLResultSet.h" +#include "bindings/modules/v8/V8SQLResultSet.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" #include "core/dom/ExceptionCode.h" @@ -46,41 +46,44 @@ namespace WebCore { void V8SQLTransactionSync::executeSqlMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { + ExceptionState exceptionState(ExceptionState::ExecutionContext, "executeSql", "SQLTransactionSync", info.Holder(), info.GetIsolate()); if (!info.Length()) { - setDOMException(SyntaxError, info.GetIsolate()); + exceptionState.throwDOMException(SyntaxError, ExceptionMessages::notEnoughArguments(1, 0)); + exceptionState.throwIfNeeded(); return; } - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, statement, info[0]); + TOSTRING_VOID(V8StringResource<>, statement, info[0]); Vector<SQLValue> sqlValues; if (info.Length() > 1 && !isUndefinedOrNull(info[1])) { if (!info[1]->IsObject()) { - setDOMException(TypeMismatchError, info.GetIsolate()); + exceptionState.throwDOMException(TypeMismatchError, ExceptionMessages::argumentNullOrIncorrectType(1, "DOMString")); + exceptionState.throwIfNeeded(); return; } uint32_t sqlArgsLength = 0; v8::Local<v8::Object> sqlArgsObject = info[1]->ToObject(); - V8TRYCATCH_VOID(v8::Local<v8::Value>, length, sqlArgsObject->Get(v8AtomicString(info.GetIsolate(), "length"))); + TONATIVE_VOID(v8::Local<v8::Value>, length, sqlArgsObject->Get(v8AtomicString(info.GetIsolate(), "length"))); if (isUndefinedOrNull(length)) sqlArgsLength = sqlArgsObject->GetPropertyNames()->Length(); else sqlArgsLength = length->Uint32Value(); - for (unsigned int i = 0; i < sqlArgsLength; ++i) { - v8::Handle<v8::Integer> key = v8::Integer::New(i, info.GetIsolate()); - V8TRYCATCH_VOID(v8::Local<v8::Value>, value, sqlArgsObject->Get(key)); + for (unsigned i = 0; i < sqlArgsLength; ++i) { + v8::Handle<v8::Integer> key = v8::Integer::New(info.GetIsolate(), i); + TONATIVE_VOID(v8::Local<v8::Value>, value, sqlArgsObject->Get(key)); if (value.IsEmpty() || value->IsNull()) sqlValues.append(SQLValue()); else if (value->IsNumber()) { - V8TRYCATCH_VOID(double, sqlValue, value->NumberValue()); + TONATIVE_VOID(double, sqlValue, value->NumberValue()); sqlValues.append(SQLValue(sqlValue)); } else { - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, sqlValue, value); + TOSTRING_VOID(V8StringResource<>, sqlValue, value); sqlValues.append(SQLValue(sqlValue)); } } @@ -88,7 +91,6 @@ void V8SQLTransactionSync::executeSqlMethodCustom(const v8::FunctionCallbackInfo SQLTransactionSync* transaction = V8SQLTransactionSync::toNative(info.Holder()); - ExceptionState exceptionState(info.Holder(), info.GetIsolate()); v8::Handle<v8::Value> result = toV8(transaction->executeSQL(statement, sqlValues, exceptionState), info.Holder(), info.GetIsolate()); if (exceptionState.throwIfNeeded()) return; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SVGElementCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SVGElementCustom.cpp index c21247e4d9a..abe89461fad 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SVGElementCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SVGElementCustom.cpp @@ -29,9 +29,9 @@ */ #include "config.h" -#include "V8SVGElement.h" +#include "bindings/core/v8/V8SVGElement.h" -#include "V8SVGElementWrapperFactory.h" +#include "core/V8SVGElementWrapperFactory.h" // FIXME: should be bindings/core/v8 namespace WebCore { diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SVGLengthCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SVGLengthCustom.cpp deleted file mode 100644 index a5a1cfef55b..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SVGLengthCustom.cpp +++ /dev/null @@ -1,102 +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" -#include "V8SVGLength.h" - -#include "bindings/v8/ExceptionMessages.h" -#include "bindings/v8/ExceptionState.h" -#include "bindings/v8/V8Binding.h" -#include "core/dom/ExceptionCode.h" -#include "core/svg/SVGLengthContext.h" -#include "core/svg/properties/SVGPropertyTearOff.h" - -namespace WebCore { - -void V8SVGLength::valueAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) -{ - SVGPropertyTearOff<SVGLength>* wrapper = V8SVGLength::toNative(info.Holder()); - SVGLength& imp = wrapper->propertyReference(); - ExceptionState exceptionState(info.Holder(), info.GetIsolate()); - SVGLengthContext lengthContext(wrapper->contextElement()); - float value = imp.value(lengthContext, exceptionState); - if (exceptionState.throwIfNeeded()) - return; - v8SetReturnValue(info, value); -} - -void V8SVGLength::valueAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) -{ - SVGPropertyTearOff<SVGLength>* wrapper = V8SVGLength::toNative(info.Holder()); - if (wrapper->isReadOnly()) { - setDOMException(NoModificationAllowedError, info.GetIsolate()); - return; - } - - if (!isUndefinedOrNull(value) && !value->IsNumber() && !value->IsBoolean()) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); - return; - } - - SVGLength& imp = wrapper->propertyReference(); - ExceptionState exceptionState(info.Holder(), info.GetIsolate()); - SVGLengthContext lengthContext(wrapper->contextElement()); - imp.setValue(static_cast<float>(value->NumberValue()), lengthContext, exceptionState); - if (exceptionState.throwIfNeeded()) - return; - wrapper->commitChange(); -} - -void V8SVGLength::convertToSpecifiedUnitsMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - ExceptionState exceptionState(ExceptionState::ExecutionContext, "convertToSpecifiedUnits", "SVGLength", info.Holder(), info.GetIsolate()); - SVGPropertyTearOff<SVGLength>* wrapper = V8SVGLength::toNative(info.Holder()); - if (wrapper->isReadOnly()) { - exceptionState.throwDOMException(NoModificationAllowedError, "The length is read only."); - exceptionState.throwIfNeeded(); - return; - } - - if (info.Length() < 1) { - exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(1, info.Length())); - exceptionState.throwIfNeeded(); - return; - } - - SVGLength& imp = wrapper->propertyReference(); - V8TRYCATCH_VOID(int, unitType, toUInt32(info[0])); - SVGLengthContext lengthContext(wrapper->contextElement()); - imp.convertToSpecifiedUnits(unitType, lengthContext, exceptionState); - if (exceptionState.throwIfNeeded()) - return; - wrapper->commitChange(); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SVGPathSegCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SVGPathSegCustom.cpp index 77bf679d4f8..8d159757c06 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SVGPathSegCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SVGPathSegCustom.cpp @@ -29,28 +29,28 @@ */ #include "config.h" -#include "V8SVGPathSeg.h" +#include "bindings/core/v8/V8SVGPathSeg.h" -#include "V8SVGPathSegArcAbs.h" -#include "V8SVGPathSegArcRel.h" -#include "V8SVGPathSegClosePath.h" -#include "V8SVGPathSegCurvetoCubicAbs.h" -#include "V8SVGPathSegCurvetoCubicRel.h" -#include "V8SVGPathSegCurvetoCubicSmoothAbs.h" -#include "V8SVGPathSegCurvetoCubicSmoothRel.h" -#include "V8SVGPathSegCurvetoQuadraticAbs.h" -#include "V8SVGPathSegCurvetoQuadraticRel.h" -#include "V8SVGPathSegCurvetoQuadraticSmoothAbs.h" -#include "V8SVGPathSegCurvetoQuadraticSmoothRel.h" -#include "V8SVGPathSegLinetoAbs.h" -#include "V8SVGPathSegLinetoHorizontalAbs.h" -#include "V8SVGPathSegLinetoHorizontalRel.h" -#include "V8SVGPathSegLinetoRel.h" -#include "V8SVGPathSegLinetoVerticalAbs.h" -#include "V8SVGPathSegLinetoVerticalRel.h" -#include "V8SVGPathSegMovetoAbs.h" -#include "V8SVGPathSegMovetoRel.h" -#include "V8Window.h" +#include "bindings/core/v8/V8SVGPathSegArcAbs.h" +#include "bindings/core/v8/V8SVGPathSegArcRel.h" +#include "bindings/core/v8/V8SVGPathSegClosePath.h" +#include "bindings/core/v8/V8SVGPathSegCurvetoCubicAbs.h" +#include "bindings/core/v8/V8SVGPathSegCurvetoCubicRel.h" +#include "bindings/core/v8/V8SVGPathSegCurvetoCubicSmoothAbs.h" +#include "bindings/core/v8/V8SVGPathSegCurvetoCubicSmoothRel.h" +#include "bindings/core/v8/V8SVGPathSegCurvetoQuadraticAbs.h" +#include "bindings/core/v8/V8SVGPathSegCurvetoQuadraticRel.h" +#include "bindings/core/v8/V8SVGPathSegCurvetoQuadraticSmoothAbs.h" +#include "bindings/core/v8/V8SVGPathSegCurvetoQuadraticSmoothRel.h" +#include "bindings/core/v8/V8SVGPathSegLinetoAbs.h" +#include "bindings/core/v8/V8SVGPathSegLinetoHorizontalAbs.h" +#include "bindings/core/v8/V8SVGPathSegLinetoHorizontalRel.h" +#include "bindings/core/v8/V8SVGPathSegLinetoRel.h" +#include "bindings/core/v8/V8SVGPathSegLinetoVerticalAbs.h" +#include "bindings/core/v8/V8SVGPathSegLinetoVerticalRel.h" +#include "bindings/core/v8/V8SVGPathSegMovetoAbs.h" +#include "bindings/core/v8/V8SVGPathSegMovetoRel.h" +#include "bindings/core/v8/V8Window.h" #include "bindings/v8/V8DOMWrapper.h" namespace WebCore { diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ServiceWorkerCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ServiceWorkerCustom.cpp new file mode 100644 index 00000000000..21337b4f437 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8ServiceWorkerCustom.cpp @@ -0,0 +1,38 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "bindings/modules/v8/V8ServiceWorker.h" + +#include "bindings/v8/ExceptionMessages.h" +#include "bindings/v8/ExceptionState.h" +#include "bindings/v8/SerializedScriptValue.h" +#include "bindings/v8/V8Binding.h" +#include "core/dom/MessagePort.h" +#include "modules/serviceworkers/ServiceWorker.h" +#include "wtf/ArrayBuffer.h" + +namespace WebCore { + +void V8ServiceWorker::postMessageMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + ExceptionState exceptionState(ExceptionState::ExecutionContext, "postMessage", "ServiceWorker", info.Holder(), info.GetIsolate()); + ServiceWorker* worker = V8ServiceWorker::toNative(info.Holder()); + MessagePortArray ports; + ArrayBufferArray arrayBuffers; + if (info.Length() > 1) { + const int transferablesArgIndex = 1; + if (!SerializedScriptValue::extractTransferables(info[transferablesArgIndex], transferablesArgIndex, ports, arrayBuffers, exceptionState, info.GetIsolate())) { + exceptionState.throwIfNeeded(); + return; + } + } + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(info[0], &ports, &arrayBuffers, exceptionState, info.GetIsolate()); + if (exceptionState.throwIfNeeded()) + return; + worker->postMessage(message.release(), &ports, exceptionState); + exceptionState.throwIfNeeded(); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8StyleSheetCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8StyleSheetCustom.cpp index 39d28a800c6..8705d0783be 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8StyleSheetCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8StyleSheetCustom.cpp @@ -29,10 +29,10 @@ */ #include "config.h" -#include "V8StyleSheet.h" +#include "bindings/core/v8/V8StyleSheet.h" -#include "V8CSSStyleSheet.h" -#include "V8Node.h" +#include "bindings/core/v8/V8CSSStyleSheet.h" +#include "bindings/core/v8/V8Node.h" #include "bindings/v8/V8DOMWrapper.h" namespace WebCore { diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SubtleCryptoCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SubtleCryptoCustom.cpp new file mode 100644 index 00000000000..943ad7666a0 --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8SubtleCryptoCustom.cpp @@ -0,0 +1,125 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" +#include "bindings/modules/v8/V8SubtleCrypto.h" + +#include "bindings/modules/v8/V8Key.h" +#include "bindings/v8/Dictionary.h" +#include "bindings/v8/custom/V8ArrayBufferCustom.h" +#include "bindings/v8/custom/V8ArrayBufferViewCustom.h" + +namespace WebCore { + +//////////////////////////////////////////////////////////////////////////////// +// Overload resolution for verify() +// FIXME: needs support for union types http://crbug.com/240176 +//////////////////////////////////////////////////////////////////////////////// + +// Promise verify(Dictionary algorithm, Key key, ArrayBuffer signature, ArrayBuffer data); +void verify1Method(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + SubtleCrypto* impl = V8SubtleCrypto::toNative(info.Holder()); + TONATIVE_VOID(Dictionary, algorithm, Dictionary(info[0], info.GetIsolate())); + if (!algorithm.isUndefinedOrNull() && !algorithm.isObject()) { + throwTypeError(ExceptionMessages::failedToExecute("verify", "SubtleCrypto", "parameter 1 ('algorithm') is not an object."), info.GetIsolate()); + return; + } + TONATIVE_VOID(Key*, key, V8Key::toNativeWithTypeCheck(info.GetIsolate(), info[1])); + TONATIVE_VOID(ArrayBuffer*, signature, info[2]->IsArrayBuffer() ? V8ArrayBuffer::toNative(v8::Handle<v8::ArrayBuffer>::Cast(info[2])) : 0); + TONATIVE_VOID(ArrayBuffer*, data, info[3]->IsArrayBuffer() ? V8ArrayBuffer::toNative(v8::Handle<v8::ArrayBuffer>::Cast(info[3])) : 0); + v8SetReturnValue(info, impl->verifySignature(ScriptState::current(info.GetIsolate()), algorithm, key, signature, data).v8Value()); +} + +// Promise verify(Dictionary algorithm, Key key, ArrayBuffer signature, ArrayBufferView data); +void verify2Method(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + SubtleCrypto* impl = V8SubtleCrypto::toNative(info.Holder()); + TONATIVE_VOID(Dictionary, algorithm, Dictionary(info[0], info.GetIsolate())); + if (!algorithm.isUndefinedOrNull() && !algorithm.isObject()) { + throwTypeError(ExceptionMessages::failedToExecute("verify", "SubtleCrypto", "parameter 1 ('algorithm') is not an object."), info.GetIsolate()); + return; + } + TONATIVE_VOID(Key*, key, V8Key::toNativeWithTypeCheck(info.GetIsolate(), info[1])); + TONATIVE_VOID(ArrayBuffer*, signature, info[2]->IsArrayBuffer() ? V8ArrayBuffer::toNative(v8::Handle<v8::ArrayBuffer>::Cast(info[2])) : 0); + TONATIVE_VOID(ArrayBufferView*, data, info[3]->IsArrayBufferView() ? V8ArrayBufferView::toNative(v8::Handle<v8::ArrayBufferView>::Cast(info[3])) : 0); + v8SetReturnValue(info, impl->verifySignature(ScriptState::current(info.GetIsolate()), algorithm, key, signature, data).v8Value()); +} + +// Promise verify(Dictionary algorithm, Key key, ArrayBufferView signature, ArrayBuffer data); +void verify3Method(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + SubtleCrypto* impl = V8SubtleCrypto::toNative(info.Holder()); + TONATIVE_VOID(Dictionary, algorithm, Dictionary(info[0], info.GetIsolate())); + if (!algorithm.isUndefinedOrNull() && !algorithm.isObject()) { + throwTypeError(ExceptionMessages::failedToExecute("verify", "SubtleCrypto", "parameter 1 ('algorithm') is not an object."), info.GetIsolate()); + return; + } + TONATIVE_VOID(Key*, key, V8Key::toNativeWithTypeCheck(info.GetIsolate(), info[1])); + TONATIVE_VOID(ArrayBufferView*, signature, info[2]->IsArrayBufferView() ? V8ArrayBufferView::toNative(v8::Handle<v8::ArrayBufferView>::Cast(info[2])) : 0); + TONATIVE_VOID(ArrayBuffer*, data, info[3]->IsArrayBuffer() ? V8ArrayBuffer::toNative(v8::Handle<v8::ArrayBuffer>::Cast(info[3])) : 0); + v8SetReturnValue(info, impl->verifySignature(ScriptState::current(info.GetIsolate()), algorithm, key, signature, data).v8Value()); +} + +// Promise verify(Dictionary algorithm, Key key, ArrayBufferView signature, ArrayBufferView data); +void verify4Method(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + SubtleCrypto* impl = V8SubtleCrypto::toNative(info.Holder()); + TONATIVE_VOID(Dictionary, algorithm, Dictionary(info[0], info.GetIsolate())); + if (!algorithm.isUndefinedOrNull() && !algorithm.isObject()) { + throwTypeError(ExceptionMessages::failedToExecute("verify", "SubtleCrypto", "parameter 1 ('algorithm') is not an object."), info.GetIsolate()); + return; + } + TONATIVE_VOID(Key*, key, V8Key::toNativeWithTypeCheck(info.GetIsolate(), info[1])); + TONATIVE_VOID(ArrayBufferView*, signature, info[2]->IsArrayBufferView() ? V8ArrayBufferView::toNative(v8::Handle<v8::ArrayBufferView>::Cast(info[2])) : 0); + TONATIVE_VOID(ArrayBufferView*, data, info[3]->IsArrayBufferView() ? V8ArrayBufferView::toNative(v8::Handle<v8::ArrayBufferView>::Cast(info[3])) : 0); + v8SetReturnValue(info, impl->verifySignature(ScriptState::current(info.GetIsolate()), algorithm, key, signature, data).v8Value()); +} + +void V8SubtleCrypto::verifyMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) +{ + v8::Isolate* isolate = info.GetIsolate(); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "verify", "SubtleCrypto", info.Holder(), isolate); + // typedef (ArrayBuffer or ArrayBufferView) CryptoOperationData; + // + // Promise verify(Dictionary algorithm, Key key, + // CryptoOperationData signature, + // CryptoOperationData data); + switch (info.Length()) { + case 4: + // Promise verify(Dictionary algorithm, Key key, ArrayBuffer signature, ArrayBuffer data); + if (V8ArrayBuffer::hasInstance(info[2], isolate) + && V8ArrayBuffer::hasInstance(info[3], isolate)) { + verify1Method(info); + return; + } + // Promise verify(Dictionary algorithm, Key key, ArrayBuffer signature, ArrayBufferView data); + if (V8ArrayBuffer::hasInstance(info[2], isolate) + && V8ArrayBufferView::hasInstance(info[3], isolate)) { + verify2Method(info); + return; + } + // Promise verify(Dictionary algorithm, Key key, ArrayBufferView signature, ArrayBuffer data); + if (V8ArrayBufferView::hasInstance(info[2], isolate) + && V8ArrayBuffer::hasInstance(info[3], isolate)) { + verify3Method(info); + return; + } + // Promise verify(Dictionary algorithm, Key key, ArrayBufferView signature, ArrayBufferView data); + if (V8ArrayBufferView::hasInstance(info[2], isolate) + && V8ArrayBufferView::hasInstance(info[3], isolate)) { + verify4Method(info); + return; + } + break; + default: + throwArityTypeError(exceptionState, "[4]", info.Length()); + return; + break; + } + exceptionState.throwTypeError("No function was found that matched the signature provided."); + exceptionState.throwIfNeeded(); +} + +} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TextCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TextCustom.cpp index 478537c3b9f..4ffbadc0d3d 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TextCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TextCustom.cpp @@ -29,9 +29,9 @@ */ #include "config.h" -#include "V8Text.h" +#include "bindings/core/v8/V8Text.h" -#include "V8CDATASection.h" +#include "bindings/core/v8/V8CDATASection.h" #include "core/dom/Node.h" #include "core/dom/Text.h" diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TextTrackCueCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TextTrackCueCustom.cpp index 3adef38297e..8d078eb91e9 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TextTrackCueCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TextTrackCueCustom.cpp @@ -28,13 +28,9 @@ */ #include "config.h" -#include "V8TextTrackCue.h" +#include "bindings/core/v8/V8TextTrackCue.h" -#include "V8VTTCue.h" - -#include "bindings/v8/ExceptionMessages.h" -#include "bindings/v8/ExceptionState.h" -#include "core/frame/UseCounter.h" +#include "bindings/core/v8/V8VTTCue.h" namespace WebCore { @@ -43,27 +39,4 @@ v8::Handle<v8::Value> toV8(TextTrackCue* impl, v8::Handle<v8::Object> creationCo return toV8(toVTTCue(impl), creationContext, isolate); } -// Custom constructor to make new TextTrackCue(...) return a VTTCue. This is legacy -// compat, not per spec, and should be removed at the earliest opportunity. -void V8TextTrackCue::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - ExceptionState exceptionState(ExceptionState::ConstructionContext, "TextTrackCue", info.Holder(), info.GetIsolate()); - if (UNLIKELY(info.Length() < 3)) { - exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(3, info.Length())); - exceptionState.throwIfNeeded(); - return; - } - V8TRYCATCH_VOID(double, startTime, static_cast<double>(info[0]->NumberValue())); - V8TRYCATCH_VOID(double, endTime, static_cast<double>(info[1]->NumberValue())); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, text, info[2]); - - Document& document = *toDocument(getExecutionContext()); - UseCounter::count(document, UseCounter::TextTrackCueConstructor); - - RefPtr<VTTCue> impl = VTTCue::create(document, startTime, endTime, text); - v8::Handle<v8::Object> wrapper = wrap(impl.get(), info.Holder(), info.GetIsolate()); - - v8SetReturnValue(info, wrapper); -} - } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TrackEventCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TrackEventCustom.cpp index aa76cc2c3fd..9c2b04e3c31 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TrackEventCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TrackEventCustom.cpp @@ -29,9 +29,11 @@ */ #include "config.h" -#include "V8TrackEvent.h" +#include "bindings/core/v8/V8TrackEvent.h" -#include "V8TextTrack.h" +#include "bindings/core/v8/V8AudioTrack.h" +#include "bindings/core/v8/V8TextTrack.h" +#include "bindings/core/v8/V8VideoTrack.h" #include "core/html/track/TrackBase.h" #include "core/html/track/TrackEvent.h" @@ -53,10 +55,12 @@ void V8TrackEvent::trackAttributeGetterCustom(const v8::PropertyCallbackInfo<v8: return; case TrackBase::AudioTrack: + v8SetReturnValueFast(info, static_cast<AudioTrack*>(track), trackEvent); + return; + case TrackBase::VideoTrack: - // This should not happen until VideoTrack and AudioTrack are implemented. - ASSERT_NOT_REACHED(); - break; + v8SetReturnValueFast(info, static_cast<VideoTrack*>(track), trackEvent); + return; } v8SetReturnValueNull(info); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TypedArrayCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TypedArrayCustom.h index f64f457f2f5..fac7a110e5e 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TypedArrayCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8TypedArrayCustom.h @@ -47,17 +47,13 @@ class TypedArrayTraits template<typename TypedArray> class V8TypedArray { public: - static bool hasInstance(v8::Handle<v8::Value> value, v8::Isolate*, WrapperWorldType) - { - return TypedArrayTraits<TypedArray>::IsInstance(value); - } - - static bool hasInstanceInAnyWorld(v8::Handle<v8::Value> value, v8::Isolate*) + static bool hasInstance(v8::Handle<v8::Value> value, v8::Isolate*) { return TypedArrayTraits<TypedArray>::IsInstance(value); } static TypedArray* toNative(v8::Handle<v8::Object>); + static TypedArray* toNativeWithTypeCheck(v8::Isolate*, v8::Handle<v8::Value>); static void derefObject(void*); static const WrapperTypeInfo wrapperTypeInfo; static const int internalFieldCount = v8DefaultWrapperInternalFieldCount; @@ -95,7 +91,7 @@ public: template<typename CallbackInfo> static void v8SetReturnValueForMainWorld(const CallbackInfo& info, TypedArray* impl) { - ASSERT(worldType(info.GetIsolate()) == MainWorld); + ASSERT(DOMWrapperWorld::current(info.GetIsolate()).isMainWorld()); if (UNLIKELY(!impl)) { v8SetReturnValueNull(info); return; @@ -174,12 +170,17 @@ TypedArray* V8TypedArray<TypedArray>::toNative(v8::Handle<v8::Object> object) return reinterpret_cast<TypedArray*>(typedarrayPtr); } +template <typename TypedArray> +TypedArray* V8TypedArray<TypedArray>::toNativeWithTypeCheck(v8::Isolate* isolate, v8::Handle<v8::Value> value) +{ + return V8TypedArray<TypedArray>::hasInstance(value, isolate) ? V8TypedArray<TypedArray>::toNative(v8::Handle<v8::Object>::Cast(value)) : 0; +} template <typename TypedArray> const WrapperTypeInfo V8TypedArray<TypedArray>::wrapperTypeInfo = { gin::kEmbedderBlink, 0, V8TypedArray<TypedArray>::derefObject, - 0, 0, 0, 0, 0, WrapperTypeObjectPrototype + 0, 0, 0, 0, 0, WrapperTypeObjectPrototype, RefCountedObject }; template <typename TypedArray> diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint16ArrayCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint16ArrayCustom.h index e692a9cb979..d819d228ece 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint16ArrayCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint16ArrayCustom.h @@ -59,10 +59,6 @@ public: typedef V8TypedArray<Uint16Array> V8Uint16Array; -template<> -class WrapperTypeTraits<Uint16Array> : public TypedArrayWrapperTraits<Uint16Array> { }; - - inline v8::Handle<v8::Object> wrap(Uint16Array* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { return V8TypedArray<Uint16Array>::wrap(impl, creationContext, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint32ArrayCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint32ArrayCustom.h index 09ee5e990ec..9218135ef73 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint32ArrayCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint32ArrayCustom.h @@ -59,10 +59,6 @@ public: typedef V8TypedArray<Uint32Array> V8Uint32Array; -template<> -class WrapperTypeTraits<Uint32Array> : public TypedArrayWrapperTraits<Uint32Array> { }; - - inline v8::Handle<v8::Object> wrap(Uint32Array* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { return V8TypedArray<Uint32Array>::wrap(impl, creationContext, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint8ArrayCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint8ArrayCustom.h index 5bcf0045731..7a37501dc64 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint8ArrayCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint8ArrayCustom.h @@ -59,10 +59,6 @@ public: typedef V8TypedArray<Uint8Array> V8Uint8Array; -template<> -class WrapperTypeTraits<Uint8Array> : public TypedArrayWrapperTraits<Uint8Array> { }; - - inline v8::Handle<v8::Object> wrap(Uint8Array* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { return V8TypedArray<Uint8Array>::wrap(impl, creationContext, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint8ClampedArrayCustom.h b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint8ClampedArrayCustom.h index 53d938ad4d4..7f936669b8d 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint8ClampedArrayCustom.h +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8Uint8ClampedArrayCustom.h @@ -59,10 +59,6 @@ public: typedef V8TypedArray<Uint8ClampedArray> V8Uint8ClampedArray; -template<> -class WrapperTypeTraits<Uint8ClampedArray> : public TypedArrayWrapperTraits<Uint8ClampedArray> { }; - - inline v8::Handle<v8::Object> wrap(Uint8ClampedArray* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { return V8TypedArray<Uint8ClampedArray>::wrap(impl, creationContext, isolate); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp index 8eb86e9ba86..faa45a3ce42 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WebGLRenderingContextCustom.cpp @@ -29,41 +29,44 @@ */ #include "config.h" -#include "V8WebGLRenderingContext.h" - -#include "V8ANGLEInstancedArrays.h" -#include "V8EXTFragDepth.h" -#include "V8EXTTextureFilterAnisotropic.h" -#include "V8HTMLCanvasElement.h" -#include "V8HTMLImageElement.h" -#include "V8HTMLVideoElement.h" -#include "V8ImageData.h" -#include "V8OESElementIndexUint.h" -#include "V8OESStandardDerivatives.h" -#include "V8OESTextureFloat.h" -#include "V8OESTextureFloatLinear.h" -#include "V8OESTextureHalfFloat.h" -#include "V8OESTextureHalfFloatLinear.h" -#include "V8OESVertexArrayObject.h" -#include "V8WebGLBuffer.h" -#include "V8WebGLCompressedTextureATC.h" -#include "V8WebGLCompressedTexturePVRTC.h" -#include "V8WebGLCompressedTextureS3TC.h" -#include "V8WebGLDebugRendererInfo.h" -#include "V8WebGLDebugShaders.h" -#include "V8WebGLDepthTexture.h" -#include "V8WebGLDrawBuffers.h" -#include "V8WebGLFramebuffer.h" -#include "V8WebGLLoseContext.h" -#include "V8WebGLProgram.h" -#include "V8WebGLRenderbuffer.h" -#include "V8WebGLShader.h" -#include "V8WebGLTexture.h" -#include "V8WebGLUniformLocation.h" -#include "V8WebGLVertexArrayObjectOES.h" +#include "bindings/core/v8/V8WebGLRenderingContext.h" + +#include "bindings/core/v8/V8ANGLEInstancedArrays.h" +#include "bindings/core/v8/V8EXTBlendMinMax.h" +#include "bindings/core/v8/V8EXTFragDepth.h" +#include "bindings/core/v8/V8EXTShaderTextureLOD.h" +#include "bindings/core/v8/V8EXTTextureFilterAnisotropic.h" +#include "bindings/core/v8/V8HTMLCanvasElement.h" +#include "bindings/core/v8/V8HTMLImageElement.h" +#include "bindings/core/v8/V8HTMLVideoElement.h" +#include "bindings/core/v8/V8ImageData.h" +#include "bindings/core/v8/V8OESElementIndexUint.h" +#include "bindings/core/v8/V8OESStandardDerivatives.h" +#include "bindings/core/v8/V8OESTextureFloat.h" +#include "bindings/core/v8/V8OESTextureFloatLinear.h" +#include "bindings/core/v8/V8OESTextureHalfFloat.h" +#include "bindings/core/v8/V8OESTextureHalfFloatLinear.h" +#include "bindings/core/v8/V8OESVertexArrayObject.h" +#include "bindings/core/v8/V8WebGLBuffer.h" +#include "bindings/core/v8/V8WebGLCompressedTextureATC.h" +#include "bindings/core/v8/V8WebGLCompressedTextureETC1.h" +#include "bindings/core/v8/V8WebGLCompressedTexturePVRTC.h" +#include "bindings/core/v8/V8WebGLCompressedTextureS3TC.h" +#include "bindings/core/v8/V8WebGLDebugRendererInfo.h" +#include "bindings/core/v8/V8WebGLDebugShaders.h" +#include "bindings/core/v8/V8WebGLDepthTexture.h" +#include "bindings/core/v8/V8WebGLDrawBuffers.h" +#include "bindings/core/v8/V8WebGLFramebuffer.h" +#include "bindings/core/v8/V8WebGLLoseContext.h" +#include "bindings/core/v8/V8WebGLProgram.h" +#include "bindings/core/v8/V8WebGLRenderbuffer.h" +#include "bindings/core/v8/V8WebGLShader.h" +#include "bindings/core/v8/V8WebGLTexture.h" +#include "bindings/core/v8/V8WebGLUniformLocation.h" +#include "bindings/core/v8/V8WebGLVertexArrayObjectOES.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8HiddenPropertyName.h" +#include "bindings/v8/V8HiddenValue.h" #include "bindings/v8/custom/V8ArrayBufferViewCustom.h" #include "bindings/v8/custom/V8Float32ArrayCustom.h" #include "bindings/v8/custom/V8Int16ArrayCustom.h" @@ -81,39 +84,43 @@ namespace WebCore { // Allocates new storage via fastMalloc. -// Returns NULL if array failed to convert for any reason. -static float* jsArrayToFloatArray(v8::Handle<v8::Array> array, uint32_t len) +// Returns 0 if array failed to convert for any reason. +static float* jsArrayToFloatArray(v8::Handle<v8::Array> array, uint32_t len, ExceptionState& exceptionState) { // Convert the data element-by-element. - if (len > std::numeric_limits<uint32_t>::max() / sizeof(float)) + if (len > std::numeric_limits<uint32_t>::max() / sizeof(float)) { + exceptionState.throwTypeError("Array length exceeds supported limit."); return 0; + } float* data = static_cast<float*>(fastMalloc(len * sizeof(float))); for (uint32_t i = 0; i < len; i++) { v8::Local<v8::Value> val = array->Get(i); - if (!val->IsNumber()) { + float value = toFloat(val, exceptionState); + if (exceptionState.hadException()) { fastFree(data); return 0; } - data[i] = toFloat(val); + data[i] = value; } return data; } // Allocates new storage via fastMalloc. -// Returns NULL if array failed to convert for any reason. -static int* jsArrayToIntArray(v8::Handle<v8::Array> array, uint32_t len) +// Returns 0 if array failed to convert for any reason. +static int* jsArrayToIntArray(v8::Handle<v8::Array> array, uint32_t len, ExceptionState& exceptionState) { // Convert the data element-by-element. - if (len > std::numeric_limits<uint32_t>::max() / sizeof(int)) + if (len > std::numeric_limits<uint32_t>::max() / sizeof(int)) { + exceptionState.throwTypeError("Array length exceeds supported limit."); return 0; + } int* data = static_cast<int*>(fastMalloc(len * sizeof(int))); for (uint32_t i = 0; i < len; i++) { v8::Local<v8::Value> val = array->Get(i); - bool ok; - int ival = toInt32(val, ok); - if (!ok) { + int ival = toInt32(val, exceptionState); + if (exceptionState.hadException()) { fastFree(data); return 0; } @@ -131,19 +138,19 @@ static v8::Handle<v8::Value> toV8Object(const WebGLGetInfo& args, v8::Handle<v8: const Vector<bool>& value = args.getBoolArray(); v8::Local<v8::Array> array = v8::Array::New(isolate, value.size()); for (size_t ii = 0; ii < value.size(); ++ii) - array->Set(v8::Integer::New(ii, isolate), v8Boolean(value[ii], isolate)); + array->Set(v8::Integer::New(isolate, ii), v8Boolean(value[ii], isolate)); return array; } case WebGLGetInfo::kTypeFloat: return v8::Number::New(isolate, args.getFloat()); case WebGLGetInfo::kTypeInt: - return v8::Integer::New(args.getInt(), isolate); + return v8::Integer::New(isolate, args.getInt()); case WebGLGetInfo::kTypeNull: return v8::Null(isolate); case WebGLGetInfo::kTypeString: return v8String(isolate, args.getString()); case WebGLGetInfo::kTypeUnsignedInt: - return v8::Integer::NewFromUnsigned(args.getUnsignedInt(), isolate); + return v8::Integer::NewFromUnsigned(isolate, args.getUnsignedInt()); case WebGLGetInfo::kTypeWebGLBuffer: return toV8(args.getWebGLBuffer(), creationContext, isolate); case WebGLGetInfo::kTypeWebGLFloatArray: @@ -179,81 +186,96 @@ static v8::Handle<v8::Value> toV8Object(WebGLExtension* extension, v8::Handle<v8 v8::Handle<v8::Value> extensionObject; const char* referenceName = 0; switch (extension->name()) { - case WebGLExtension::ANGLEInstancedArraysName: + case ANGLEInstancedArraysName: extensionObject = toV8(static_cast<ANGLEInstancedArrays*>(extension), contextObject, isolate); referenceName = "angleInstancedArraysName"; break; - case WebGLExtension::EXTFragDepthName: + case EXTBlendMinMaxName: + extensionObject = toV8(static_cast<EXTBlendMinMax*>(extension), contextObject, isolate); + referenceName = "extBlendMinMaxName"; + break; + case EXTFragDepthName: extensionObject = toV8(static_cast<EXTFragDepth*>(extension), contextObject, isolate); referenceName = "extFragDepthName"; break; - case WebGLExtension::EXTTextureFilterAnisotropicName: + case EXTShaderTextureLODName: + extensionObject = toV8(static_cast<EXTShaderTextureLOD*>(extension), contextObject, isolate); + referenceName = "extShaderTextureLODName"; + break; + case EXTTextureFilterAnisotropicName: extensionObject = toV8(static_cast<EXTTextureFilterAnisotropic*>(extension), contextObject, isolate); referenceName = "extTextureFilterAnisotropicName"; break; - case WebGLExtension::OESElementIndexUintName: + case OESElementIndexUintName: extensionObject = toV8(static_cast<OESElementIndexUint*>(extension), contextObject, isolate); referenceName = "oesElementIndexUintName"; break; - case WebGLExtension::OESStandardDerivativesName: + case OESStandardDerivativesName: extensionObject = toV8(static_cast<OESStandardDerivatives*>(extension), contextObject, isolate); referenceName = "oesStandardDerivativesName"; break; - case WebGLExtension::OESTextureFloatName: + case OESTextureFloatName: extensionObject = toV8(static_cast<OESTextureFloat*>(extension), contextObject, isolate); referenceName = "oesTextureFloatName"; break; - case WebGLExtension::OESTextureFloatLinearName: + case OESTextureFloatLinearName: extensionObject = toV8(static_cast<OESTextureFloatLinear*>(extension), contextObject, isolate); referenceName = "oesTextureFloatLinearName"; break; - case WebGLExtension::OESTextureHalfFloatName: + case OESTextureHalfFloatName: extensionObject = toV8(static_cast<OESTextureHalfFloat*>(extension), contextObject, isolate); referenceName = "oesTextureHalfFloatName"; break; - case WebGLExtension::OESTextureHalfFloatLinearName: + case OESTextureHalfFloatLinearName: extensionObject = toV8(static_cast<OESTextureHalfFloatLinear*>(extension), contextObject, isolate); referenceName = "oesTextureHalfFloatLinearName"; break; - case WebGLExtension::OESVertexArrayObjectName: + case OESVertexArrayObjectName: extensionObject = toV8(static_cast<OESVertexArrayObject*>(extension), contextObject, isolate); referenceName = "oesVertexArrayObjectName"; break; - case WebGLExtension::WebGLCompressedTextureATCName: + case WebGLCompressedTextureATCName: extensionObject = toV8(static_cast<WebGLCompressedTextureATC*>(extension), contextObject, isolate); referenceName = "webGLCompressedTextureATCName"; break; - case WebGLExtension::WebGLCompressedTexturePVRTCName: + case WebGLCompressedTextureETC1Name: + extensionObject = toV8(static_cast<WebGLCompressedTextureETC1*>(extension), contextObject, isolate); + referenceName = "webGLCompressedTextureETC1Name"; + break; + case WebGLCompressedTexturePVRTCName: extensionObject = toV8(static_cast<WebGLCompressedTexturePVRTC*>(extension), contextObject, isolate); referenceName = "webGLCompressedTexturePVRTCName"; break; - case WebGLExtension::WebGLCompressedTextureS3TCName: + case WebGLCompressedTextureS3TCName: extensionObject = toV8(static_cast<WebGLCompressedTextureS3TC*>(extension), contextObject, isolate); referenceName = "webGLCompressedTextureS3TCName"; break; - case WebGLExtension::WebGLDebugRendererInfoName: + case WebGLDebugRendererInfoName: extensionObject = toV8(static_cast<WebGLDebugRendererInfo*>(extension), contextObject, isolate); referenceName = "webGLDebugRendererInfoName"; break; - case WebGLExtension::WebGLDebugShadersName: + case WebGLDebugShadersName: extensionObject = toV8(static_cast<WebGLDebugShaders*>(extension), contextObject, isolate); referenceName = "webGLDebugShadersName"; break; - case WebGLExtension::WebGLDepthTextureName: + case WebGLDepthTextureName: extensionObject = toV8(static_cast<WebGLDepthTexture*>(extension), contextObject, isolate); referenceName = "webGLDepthTextureName"; break; - case WebGLExtension::WebGLDrawBuffersName: + case WebGLDrawBuffersName: extensionObject = toV8(static_cast<WebGLDrawBuffers*>(extension), contextObject, isolate); referenceName = "webGLDrawBuffersName"; break; - case WebGLExtension::WebGLLoseContextName: + case WebGLLoseContextName: extensionObject = toV8(static_cast<WebGLLoseContext*>(extension), contextObject, isolate); referenceName = "webGLLoseContextName"; break; + case WebGLExtensionNameCount: + notImplemented(); + return v8::Undefined(isolate); } ASSERT(!extensionObject.IsEmpty()); - V8HiddenPropertyName::setNamedHiddenReference(contextObject, referenceName, extensionObject); + V8HiddenValue::setHiddenValue(isolate, contextObject, v8AtomicString(isolate, referenceName), extensionObject); return extensionObject; } @@ -261,16 +283,21 @@ enum ObjectType { kBuffer, kRenderbuffer, kTexture, kVertexAttrib }; -static void getObjectParameter(const v8::FunctionCallbackInfo<v8::Value>& info, ObjectType objectType, const char* method) +static void getObjectParameter(const v8::FunctionCallbackInfo<v8::Value>& info, ObjectType objectType, ExceptionState& exceptionState) { if (info.Length() != 2) { - throwTypeError(ExceptionMessages::failedToExecute(method, "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(2, info.Length())), info.GetIsolate()); + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(2, info.Length())); + exceptionState.throwIfNeeded(); return; } WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); - unsigned target = toInt32(info[0]); - unsigned pname = toInt32(info[1]); + unsigned target = toInt32(info[0], exceptionState); + if (exceptionState.throwIfNeeded()) + return; + unsigned pname = toInt32(info[1], exceptionState); + if (exceptionState.throwIfNeeded()) + return; WebGLGetInfo args; switch (objectType) { case kBuffer: @@ -293,15 +320,9 @@ static void getObjectParameter(const v8::FunctionCallbackInfo<v8::Value>& info, v8SetReturnValue(info, toV8Object(args, info.Holder(), info.GetIsolate())); } -static WebGLUniformLocation* toWebGLUniformLocation(v8::Handle<v8::Value> value, bool& ok, v8::Isolate* isolate) +static WebGLUniformLocation* toWebGLUniformLocation(v8::Handle<v8::Value> value, v8::Isolate* isolate) { - ok = false; - WebGLUniformLocation* location = 0; - if (V8WebGLUniformLocation::hasInstance(value, isolate, worldType(isolate))) { - location = V8WebGLUniformLocation::toNative(value->ToObject()); - ok = true; - } - return location; + return V8WebGLUniformLocation::toNativeWithTypeCheck(isolate, value); } enum WhichProgramCall { @@ -310,17 +331,21 @@ enum WhichProgramCall { void V8WebGLRenderingContext::getAttachedShadersMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getAttachedShaders", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); if (info.Length() < 1) { - throwTypeError(ExceptionMessages::failedToExecute("getAttachedShaders", "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(1, info.Length())), info.GetIsolate()); + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(1, info.Length())); + exceptionState.throwIfNeeded(); return; } + const int programArgumentIndex = 0; WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); - if (info.Length() > 0 && !isUndefinedOrNull(info[0]) && !V8WebGLProgram::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + if (info.Length() > 0 && !isUndefinedOrNull(info[programArgumentIndex]) && !V8WebGLProgram::hasInstance(info[programArgumentIndex], info.GetIsolate())) { + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(programArgumentIndex + 1, "WebGLProgram")); + exceptionState.throwIfNeeded(); return; } - WebGLProgram* program = V8WebGLProgram::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate())) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(info[0])) : 0; + WebGLProgram* program = V8WebGLProgram::toNativeWithTypeCheck(info.GetIsolate(), info[programArgumentIndex]); Vector<RefPtr<WebGLShader> > shaders; bool succeed = context->getAttachedShaders(program, shaders); if (!succeed) { @@ -329,136 +354,169 @@ void V8WebGLRenderingContext::getAttachedShadersMethodCustom(const v8::FunctionC } v8::Local<v8::Array> array = v8::Array::New(info.GetIsolate(), shaders.size()); for (size_t ii = 0; ii < shaders.size(); ++ii) - array->Set(v8::Integer::New(ii, info.GetIsolate()), toV8(shaders[ii].get(), info.Holder(), info.GetIsolate())); + array->Set(v8::Integer::New(info.GetIsolate(), ii), toV8(shaders[ii].get(), info.Holder(), info.GetIsolate())); v8SetReturnValue(info, array); } void V8WebGLRenderingContext::getBufferParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - getObjectParameter(info, kBuffer, "getBufferParameter"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getBufferParameter", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + getObjectParameter(info, kBuffer, exceptionState); } void V8WebGLRenderingContext::getExtensionMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - WebGLRenderingContext* imp = V8WebGLRenderingContext::toNative(info.Holder()); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getExtension", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + WebGLRenderingContext* impl = V8WebGLRenderingContext::toNative(info.Holder()); if (info.Length() < 1) { - throwTypeError(ExceptionMessages::failedToExecute("getExtension", "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(1, info.Length())), info.GetIsolate()); + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(1, info.Length())); + exceptionState.throwIfNeeded(); return; } - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, name, info[0]); - RefPtr<WebGLExtension> extension(imp->getExtension(name)); + TOSTRING_VOID(V8StringResource<>, name, info[0]); + RefPtr<WebGLExtension> extension(impl->getExtension(name)); v8SetReturnValue(info, toV8Object(extension.get(), info.Holder(), info.GetIsolate())); } void V8WebGLRenderingContext::getFramebufferAttachmentParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getFramebufferAttachmentParameter", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); if (info.Length() != 3) { - throwTypeError(ExceptionMessages::failedToExecute("getFramebufferAttachmentParameter", "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(3, info.Length())), info.GetIsolate()); + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(3, info.Length())); + exceptionState.throwIfNeeded(); return; } WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); unsigned target = toInt32(info[0]); - unsigned attachment = toInt32(info[1]); - unsigned pname = toInt32(info[2]); + unsigned attachment = toInt32(info[1], exceptionState); + if (exceptionState.throwIfNeeded()) + return; + unsigned pname = toInt32(info[2], exceptionState); + if (exceptionState.throwIfNeeded()) + return; WebGLGetInfo args = context->getFramebufferAttachmentParameter(target, attachment, pname); v8SetReturnValue(info, toV8Object(args, info.Holder(), info.GetIsolate())); } void V8WebGLRenderingContext::getParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getParameter", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); if (info.Length() != 1) { - throwTypeError(ExceptionMessages::failedToExecute("getParameter", "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(1, info.Length())), info.GetIsolate()); + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(1, info.Length())); + exceptionState.throwIfNeeded(); return; } WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); - unsigned pname = toInt32(info[0]); + unsigned pname = toInt32(info[0], exceptionState); + if (exceptionState.throwIfNeeded()) + return; WebGLGetInfo args = context->getParameter(pname); v8SetReturnValue(info, toV8Object(args, info.Holder(), info.GetIsolate())); } void V8WebGLRenderingContext::getProgramParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getProgramParameter", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); if (info.Length() != 2) { - throwTypeError(ExceptionMessages::failedToExecute("getProgramParameter", "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(2, info.Length())), info.GetIsolate()); + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(2, info.Length())); + exceptionState.throwIfNeeded(); return; } + const int programArgumentIndex = 0; WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); - if (info.Length() > 0 && !isUndefinedOrNull(info[0]) && !V8WebGLProgram::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + if (info.Length() > 0 && !isUndefinedOrNull(info[programArgumentIndex]) && !V8WebGLProgram::hasInstance(info[programArgumentIndex], info.GetIsolate())) { + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(programArgumentIndex + 1, "WebGLProgram")); + exceptionState.throwIfNeeded(); return; } - WebGLProgram* program = V8WebGLProgram::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate())) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(info[0])) : 0; - unsigned pname = toInt32(info[1]); + WebGLProgram* program = V8WebGLProgram::toNativeWithTypeCheck(info.GetIsolate(), info[programArgumentIndex]); + unsigned pname = toInt32(info[1], exceptionState); + if (exceptionState.throwIfNeeded()) + return; WebGLGetInfo args = context->getProgramParameter(program, pname); v8SetReturnValue(info, toV8Object(args, info.Holder(), info.GetIsolate())); } void V8WebGLRenderingContext::getRenderbufferParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - getObjectParameter(info, kRenderbuffer, "getRenderbufferParameter"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getRenderbufferParameter", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + getObjectParameter(info, kRenderbuffer, exceptionState); } void V8WebGLRenderingContext::getShaderParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getShaderParameter", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); if (info.Length() != 2) { - throwTypeError(ExceptionMessages::failedToExecute("getShaderParameter", "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(2, info.Length())), info.GetIsolate()); + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(2, info.Length())); + exceptionState.throwIfNeeded(); return; } + const int shaderArgumentIndex = 0; WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); - if (info.Length() > 0 && !isUndefinedOrNull(info[0]) && !V8WebGLShader::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + if (info.Length() > 0 && !isUndefinedOrNull(info[shaderArgumentIndex]) && !V8WebGLShader::hasInstance(info[shaderArgumentIndex], info.GetIsolate())) { + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(shaderArgumentIndex + 1, "WebGLShader")); + exceptionState.throwIfNeeded(); return; } - WebGLShader* shader = V8WebGLShader::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate())) ? V8WebGLShader::toNative(v8::Handle<v8::Object>::Cast(info[0])) : 0; - unsigned pname = toInt32(info[1]); + WebGLShader* shader = V8WebGLShader::toNativeWithTypeCheck(info.GetIsolate(), info[shaderArgumentIndex]); + unsigned pname = toInt32(info[1], exceptionState); + if (exceptionState.throwIfNeeded()) + return; WebGLGetInfo args = context->getShaderParameter(shader, pname); v8SetReturnValue(info, toV8Object(args, info.Holder(), info.GetIsolate())); } void V8WebGLRenderingContext::getSupportedExtensionsMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - WebGLRenderingContext* imp = V8WebGLRenderingContext::toNative(info.Holder()); - if (imp->isContextLost()) { + WebGLRenderingContext* impl = V8WebGLRenderingContext::toNative(info.Holder()); + if (impl->isContextLost()) { v8SetReturnValueNull(info); return; } - Vector<String> value = imp->getSupportedExtensions(); + Vector<String> value = impl->getSupportedExtensions(); v8::Local<v8::Array> array = v8::Array::New(info.GetIsolate(), value.size()); for (size_t ii = 0; ii < value.size(); ++ii) - array->Set(v8::Integer::New(ii, info.GetIsolate()), v8String(info.GetIsolate(), value[ii])); + array->Set(v8::Integer::New(info.GetIsolate(), ii), v8String(info.GetIsolate(), value[ii])); v8SetReturnValue(info, array); } void V8WebGLRenderingContext::getTexParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - getObjectParameter(info, kTexture, "getTexParameter"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getTexParameter", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + getObjectParameter(info, kTexture, exceptionState); } void V8WebGLRenderingContext::getUniformMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getUniform", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); if (info.Length() != 2) { - throwTypeError(ExceptionMessages::failedToExecute("getUniform", "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(2, info.Length())), info.GetIsolate()); + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(2, info.Length())); + exceptionState.throwIfNeeded(); return; } + const int programArgumentIndex = 0; WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); - if (info.Length() > 0 && !isUndefinedOrNull(info[0]) && !V8WebGLProgram::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + if (info.Length() > 0 && !isUndefinedOrNull(info[programArgumentIndex]) && !V8WebGLProgram::hasInstance(info[programArgumentIndex], info.GetIsolate())) { + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(programArgumentIndex + 1, "WebGLProgram")); + exceptionState.throwIfNeeded(); return; } - WebGLProgram* program = V8WebGLProgram::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate())) ? V8WebGLProgram::toNative(v8::Handle<v8::Object>::Cast(info[0])) : 0; + WebGLProgram* program = V8WebGLProgram::toNativeWithTypeCheck(info.GetIsolate(), info[programArgumentIndex]); - if (info.Length() > 1 && !isUndefinedOrNull(info[1]) && !V8WebGLUniformLocation::hasInstance(info[1], info.GetIsolate(), worldType(info.GetIsolate()))) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + const int uniformArgumentIndex = 1; + if (info.Length() > 1 && !isUndefinedOrNull(info[uniformArgumentIndex]) && !V8WebGLUniformLocation::hasInstance(info[uniformArgumentIndex], info.GetIsolate())) { + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(uniformArgumentIndex + 1, "WebGLUniformLocation")); + exceptionState.throwIfNeeded(); return; } - bool ok = false; - WebGLUniformLocation* location = toWebGLUniformLocation(info[1], ok, info.GetIsolate()); + const int uniformLocationArgumentIndex = 1; + WebGLUniformLocation* location = toWebGLUniformLocation(info[uniformLocationArgumentIndex], info.GetIsolate()); WebGLGetInfo args = context->getUniform(program, location); v8SetReturnValue(info, toV8Object(args, info.Holder(), info.GetIsolate())); @@ -466,7 +524,8 @@ void V8WebGLRenderingContext::getUniformMethodCustom(const v8::FunctionCallbackI void V8WebGLRenderingContext::getVertexAttribMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - getObjectParameter(info, kVertexAttrib, "getVertexAttrib"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "getVertexAttrib", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + getObjectParameter(info, kVertexAttrib, exceptionState); } enum FunctionToCall { @@ -488,7 +547,7 @@ bool isFunctionToCallForAttribute(FunctionToCall functionToCall) return false; } -static void vertexAttribAndUniformHelperf(const v8::FunctionCallbackInfo<v8::Value>& info, FunctionToCall functionToCall, const char* method) +static void vertexAttribAndUniformHelperf(const v8::FunctionCallbackInfo<v8::Value>& info, FunctionToCall functionToCall, ExceptionState& exceptionState) { // Forms: // * glUniform1fv(WebGLUniformLocation location, Array data); @@ -509,29 +568,34 @@ static void vertexAttribAndUniformHelperf(const v8::FunctionCallbackInfo<v8::Val // * glVertexAttrib4fv(GLint index, Float32Array data); if (info.Length() != 2) { - throwTypeError(ExceptionMessages::failedToExecute(method, "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(2, info.Length())), info.GetIsolate()); + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(2, info.Length())); + exceptionState.throwIfNeeded(); return; } - bool ok = false; int index = -1; WebGLUniformLocation* location = 0; - if (isFunctionToCallForAttribute(functionToCall)) - index = toInt32(info[0]); - else { - if (info.Length() > 0 && !isUndefinedOrNull(info[0]) && !V8WebGLUniformLocation::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + if (isFunctionToCallForAttribute(functionToCall)) { + index = toInt32(info[0], exceptionState); + if (exceptionState.throwIfNeeded()) + return; + } else { + const int uniformLocationArgumentIndex = 0; + if (info.Length() > 0 && !isUndefinedOrNull(info[uniformLocationArgumentIndex]) && !V8WebGLUniformLocation::hasInstance(info[uniformLocationArgumentIndex], info.GetIsolate())) { + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(uniformLocationArgumentIndex + 1, "WebGLUniformLocation")); + exceptionState.throwIfNeeded(); return; } - location = toWebGLUniformLocation(info[0], ok, info.GetIsolate()); + location = toWebGLUniformLocation(info[uniformLocationArgumentIndex], info.GetIsolate()); } WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); - if (V8Float32Array::hasInstance(info[1], info.GetIsolate(), worldType(info.GetIsolate()))) { - Float32Array* array = V8Float32Array::toNative(info[1]->ToObject()); - ASSERT(array != NULL); + const int indexArrayArgument = 1; + if (V8Float32Array::hasInstance(info[indexArrayArgument], info.GetIsolate())) { + Float32Array* array = V8Float32Array::toNative(info[indexArrayArgument]->ToObject()); + ASSERT(array); switch (functionToCall) { case kUniform1v: context->uniform1fv(location, array); break; case kUniform2v: context->uniform2fv(location, array); break; @@ -546,16 +610,20 @@ static void vertexAttribAndUniformHelperf(const v8::FunctionCallbackInfo<v8::Val return; } - if (info[1].IsEmpty() || !info[1]->IsArray()) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + if (info[indexArrayArgument].IsEmpty() || !info[indexArrayArgument]->IsArray()) { + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(indexArrayArgument + 1, "Array")); + exceptionState.throwIfNeeded(); return; } v8::Handle<v8::Array> array = v8::Local<v8::Array>::Cast(info[1]); uint32_t len = array->Length(); - float* data = jsArrayToFloatArray(array, len); + float* data = jsArrayToFloatArray(array, len, exceptionState); + if (exceptionState.throwIfNeeded()) + return; if (!data) { // FIXME: consider different / better exception type. - setDOMException(SyntaxError, info.GetIsolate()); + exceptionState.throwDOMException(SyntaxError, "Failed to convert array argument"); + exceptionState.throwIfNeeded(); return; } switch (functionToCall) { @@ -572,7 +640,7 @@ static void vertexAttribAndUniformHelperf(const v8::FunctionCallbackInfo<v8::Val fastFree(data); } -static void uniformHelperi(const v8::FunctionCallbackInfo<v8::Value>& info, FunctionToCall functionToCall, const char* method) +static void uniformHelperi(const v8::FunctionCallbackInfo<v8::Value>& info, FunctionToCall functionToCall, ExceptionState& exceptionState) { // Forms: // * glUniform1iv(GLUniformLocation location, Array data); @@ -585,21 +653,24 @@ static void uniformHelperi(const v8::FunctionCallbackInfo<v8::Value>& info, Func // * glUniform4iv(GLUniformLocation location, Int32Array data); if (info.Length() != 2) { - throwTypeError(ExceptionMessages::failedToExecute(method, "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(2, info.Length())), info.GetIsolate()); + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(2, info.Length())); + exceptionState.throwIfNeeded(); return; } + const int uniformLocationArgumentIndex = 0; WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); - if (info.Length() > 0 && !isUndefinedOrNull(info[0]) && !V8WebGLUniformLocation::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + if (info.Length() > 0 && !isUndefinedOrNull(info[uniformLocationArgumentIndex]) && !V8WebGLUniformLocation::hasInstance(info[uniformLocationArgumentIndex], info.GetIsolate())) { + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(uniformLocationArgumentIndex + 1, "WebGLUniformLocation")); + exceptionState.throwIfNeeded(); return; } - bool ok = false; - WebGLUniformLocation* location = toWebGLUniformLocation(info[0], ok, info.GetIsolate()); + WebGLUniformLocation* location = toWebGLUniformLocation(info[uniformLocationArgumentIndex], info.GetIsolate()); - if (V8Int32Array::hasInstance(info[1], info.GetIsolate(), worldType(info.GetIsolate()))) { - Int32Array* array = V8Int32Array::toNative(info[1]->ToObject()); - ASSERT(array != NULL); + const int indexArrayArgumentIndex = 1; + if (V8Int32Array::hasInstance(info[indexArrayArgumentIndex], info.GetIsolate())) { + Int32Array* array = V8Int32Array::toNative(info[indexArrayArgumentIndex]->ToObject()); + ASSERT(array); switch (functionToCall) { case kUniform1v: context->uniform1iv(location, array); break; case kUniform2v: context->uniform2iv(location, array); break; @@ -610,16 +681,20 @@ static void uniformHelperi(const v8::FunctionCallbackInfo<v8::Value>& info, Func return; } - if (info[1].IsEmpty() || !info[1]->IsArray()) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + if (info[indexArrayArgumentIndex].IsEmpty() || !info[indexArrayArgumentIndex]->IsArray()) { + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(indexArrayArgumentIndex + 1, "Array")); + exceptionState.throwIfNeeded(); return; } - v8::Handle<v8::Array> array = v8::Local<v8::Array>::Cast(info[1]); + v8::Handle<v8::Array> array = v8::Local<v8::Array>::Cast(info[indexArrayArgumentIndex]); uint32_t len = array->Length(); - int* data = jsArrayToIntArray(array, len); + int* data = jsArrayToIntArray(array, len, exceptionState); + if (exceptionState.throwIfNeeded()) + return; if (!data) { // FIXME: consider different / better exception type. - setDOMException(SyntaxError, info.GetIsolate()); + exceptionState.throwDOMException(SyntaxError, "Failed to convert array argument"); + exceptionState.throwIfNeeded(); return; } switch (functionToCall) { @@ -634,45 +709,53 @@ static void uniformHelperi(const v8::FunctionCallbackInfo<v8::Value>& info, Func void V8WebGLRenderingContext::uniform1fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - vertexAttribAndUniformHelperf(info, kUniform1v, "uniform1fv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "uniform1fv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + vertexAttribAndUniformHelperf(info, kUniform1v, exceptionState); } void V8WebGLRenderingContext::uniform1ivMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - uniformHelperi(info, kUniform1v, "uniform1iv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "uniform1iv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + uniformHelperi(info, kUniform1v, exceptionState); } void V8WebGLRenderingContext::uniform2fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - vertexAttribAndUniformHelperf(info, kUniform2v, "uniform2fv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "uniform2fv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + vertexAttribAndUniformHelperf(info, kUniform2v, exceptionState); } void V8WebGLRenderingContext::uniform2ivMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - uniformHelperi(info, kUniform2v, "uniform2iv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "uniform2iv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + uniformHelperi(info, kUniform2v, exceptionState); } void V8WebGLRenderingContext::uniform3fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - vertexAttribAndUniformHelperf(info, kUniform3v, "uniform3fv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "uniform3fv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + vertexAttribAndUniformHelperf(info, kUniform3v, exceptionState); } void V8WebGLRenderingContext::uniform3ivMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - uniformHelperi(info, kUniform3v, "uniform3iv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "uniform3iv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + uniformHelperi(info, kUniform3v, exceptionState); } void V8WebGLRenderingContext::uniform4fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - vertexAttribAndUniformHelperf(info, kUniform4v, "uniform4fv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "uniform4fv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + vertexAttribAndUniformHelperf(info, kUniform4v, exceptionState); } void V8WebGLRenderingContext::uniform4ivMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - uniformHelperi(info, kUniform4v, "uniform4iv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "uniform4iv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + uniformHelperi(info, kUniform4v, exceptionState); } -static void uniformMatrixHelper(const v8::FunctionCallbackInfo<v8::Value>& info, int matrixSize, const char* method) +static void uniformMatrixHelper(const v8::FunctionCallbackInfo<v8::Value>& info, int matrixSize, ExceptionState& exceptionState) { // Forms: // * glUniformMatrix2fv(GLint location, GLboolean transpose, Array data); @@ -684,23 +767,26 @@ static void uniformMatrixHelper(const v8::FunctionCallbackInfo<v8::Value>& info, // // FIXME: need to change to accept Float32Array as well. if (info.Length() != 3) { - throwTypeError(ExceptionMessages::failedToExecute(method, "WebGLRenderingContext", ExceptionMessages::notEnoughArguments(3, info.Length())), info.GetIsolate()); + exceptionState.throwTypeError(ExceptionMessages::notEnoughArguments(3, info.Length())); + exceptionState.throwIfNeeded(); return; } WebGLRenderingContext* context = V8WebGLRenderingContext::toNative(info.Holder()); - if (info.Length() > 0 && !isUndefinedOrNull(info[0]) && !V8WebGLUniformLocation::hasInstance(info[0], info.GetIsolate(), worldType(info.GetIsolate()))) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + const int uniformLocationArgumentIndex = 0; + if (info.Length() > 0 && !isUndefinedOrNull(info[uniformLocationArgumentIndex]) && !V8WebGLUniformLocation::hasInstance(info[uniformLocationArgumentIndex], info.GetIsolate())) { + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(uniformLocationArgumentIndex + 1, "WebGLUniformLocation")); + exceptionState.throwIfNeeded(); return; } - bool ok = false; - WebGLUniformLocation* location = toWebGLUniformLocation(info[0], ok, info.GetIsolate()); + WebGLUniformLocation* location = toWebGLUniformLocation(info[uniformLocationArgumentIndex], info.GetIsolate()); bool transpose = info[1]->BooleanValue(); - if (V8Float32Array::hasInstance(info[2], info.GetIsolate(), worldType(info.GetIsolate()))) { - Float32Array* array = V8Float32Array::toNative(info[2]->ToObject()); - ASSERT(array != NULL); + const int arrayArgumentIndex = 2; + if (V8Float32Array::hasInstance(info[arrayArgumentIndex], info.GetIsolate())) { + Float32Array* array = V8Float32Array::toNative(info[arrayArgumentIndex]->ToObject()); + ASSERT(array); switch (matrixSize) { case 2: context->uniformMatrix2fv(location, transpose, array); break; case 3: context->uniformMatrix3fv(location, transpose, array); break; @@ -710,16 +796,20 @@ static void uniformMatrixHelper(const v8::FunctionCallbackInfo<v8::Value>& info, return; } - if (info[2].IsEmpty() || !info[2]->IsArray()) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + if (info[arrayArgumentIndex].IsEmpty() || !info[arrayArgumentIndex]->IsArray()) { + exceptionState.throwTypeError(ExceptionMessages::argumentNullOrIncorrectType(arrayArgumentIndex + 1, "Array")); + exceptionState.throwIfNeeded(); return; } v8::Handle<v8::Array> array = v8::Local<v8::Array>::Cast(info[2]); uint32_t len = array->Length(); - float* data = jsArrayToFloatArray(array, len); + float* data = jsArrayToFloatArray(array, len, exceptionState); + if (exceptionState.throwIfNeeded()) + return; if (!data) { // FIXME: consider different / better exception type. - setDOMException(SyntaxError, info.GetIsolate()); + exceptionState.throwDOMException(SyntaxError, "failed to convert Array value"); + exceptionState.throwIfNeeded(); return; } switch (matrixSize) { @@ -733,37 +823,44 @@ static void uniformMatrixHelper(const v8::FunctionCallbackInfo<v8::Value>& info, void V8WebGLRenderingContext::uniformMatrix2fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - uniformMatrixHelper(info, 2, "uniformMatrix2fv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "uniformMatrix2fv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + uniformMatrixHelper(info, 2, exceptionState); } void V8WebGLRenderingContext::uniformMatrix3fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - uniformMatrixHelper(info, 3, "uniformMatrix3fv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "uniformMatrix3fv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + uniformMatrixHelper(info, 3, exceptionState); } void V8WebGLRenderingContext::uniformMatrix4fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - uniformMatrixHelper(info, 4, "uniformMatrix4fv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "uniformMatrix4fv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + uniformMatrixHelper(info, 4, exceptionState); } void V8WebGLRenderingContext::vertexAttrib1fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - vertexAttribAndUniformHelperf(info, kVertexAttrib1v, "vertexAttrib1fv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "vertexAttrib1fv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + vertexAttribAndUniformHelperf(info, kVertexAttrib1v, exceptionState); } void V8WebGLRenderingContext::vertexAttrib2fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - vertexAttribAndUniformHelperf(info, kVertexAttrib2v, "vertexAttrib2fv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "vertexAttrib2fv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + vertexAttribAndUniformHelperf(info, kVertexAttrib2v, exceptionState); } void V8WebGLRenderingContext::vertexAttrib3fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - vertexAttribAndUniformHelperf(info, kVertexAttrib3v, "vertexAttrib3fv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "vertexAttrib3fv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + vertexAttribAndUniformHelperf(info, kVertexAttrib3v, exceptionState); } void V8WebGLRenderingContext::vertexAttrib4fvMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - vertexAttribAndUniformHelperf(info, kVertexAttrib4v, "vertexAttrib4fv"); + ExceptionState exceptionState(ExceptionState::ExecutionContext, "vertexAttrib4fv", "WebGLRenderingContext", info.Holder(), info.GetIsolate()); + vertexAttribAndUniformHelperf(info, kVertexAttrib4v, exceptionState); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WebKitPointCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WebKitPointCustom.cpp index 35429f91ffd..e87549ec81f 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WebKitPointCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WebKitPointCustom.cpp @@ -29,7 +29,7 @@ */ #include "config.h" -#include "V8WebKitPoint.h" +#include "bindings/core/v8/V8WebKitPoint.h" #include "bindings/v8/V8Binding.h" #include "bindings/v8/V8DOMWrapper.h" @@ -54,7 +54,7 @@ void V8WebKitPoint::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& y = 0; } } - RefPtr<DOMPoint> point = DOMPoint::create(x, y); + RefPtrWillBeRawPtr<DOMPoint> point = DOMPoint::create(x, y); v8::Handle<v8::Object> wrapper = info.Holder(); V8DOMWrapper::associateObjectWithWrapper<V8WebKitPoint>(point.release(), &wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent); info.GetReturnValue().Set(wrapper); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WindowCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WindowCustom.cpp index 24f19e4fd10..7ab9e529d00 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WindowCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WindowCustom.cpp @@ -29,10 +29,10 @@ */ #include "config.h" -#include "V8Window.h" +#include "bindings/core/v8/V8Window.h" -#include "V8HTMLCollection.h" -#include "V8Node.h" +#include "bindings/core/v8/V8HTMLCollection.h" +#include "bindings/core/v8/V8Node.h" #include "bindings/v8/BindingSecurity.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" @@ -44,8 +44,7 @@ #include "bindings/v8/V8EventListener.h" #include "bindings/v8/V8EventListenerList.h" #include "bindings/v8/V8GCForContextDispose.h" -#include "bindings/v8/V8HiddenPropertyName.h" -#include "bindings/v8/V8Utilities.h" +#include "bindings/v8/V8HiddenValue.h" #include "core/dom/ExceptionCode.h" #include "core/dom/MessagePort.h" #include "core/html/HTMLCollection.h" @@ -53,13 +52,13 @@ #include "core/inspector/ScriptCallStack.h" #include "core/loader/FrameLoadRequest.h" #include "core/loader/FrameLoader.h" -#include "core/frame/ContentSecurityPolicy.h" #include "core/frame/DOMTimer.h" -#include "core/frame/DOMWindow.h" +#include "core/frame/LocalDOMWindow.h" #include "core/frame/DOMWindowTimers.h" -#include "core/frame/Frame.h" #include "core/frame/FrameView.h" +#include "core/frame/LocalFrame.h" #include "core/frame/Settings.h" +#include "core/frame/csp/ContentSecurityPolicy.h" #include "core/storage/Storage.h" #include "platform/PlatformScreen.h" #include "platform/graphics/media/MediaPlayer.h" @@ -71,19 +70,19 @@ namespace WebCore { // FIXME: There is a lot of duplication with SetTimeoutOrInterval() in V8WorkerGlobalScopeCustom.cpp. // We should refactor this. -void WindowSetTimeoutImpl(const v8::FunctionCallbackInfo<v8::Value>& info, bool singleShot, ExceptionState& exceptionState) +static void windowSetTimeoutImpl(const v8::FunctionCallbackInfo<v8::Value>& info, bool singleShot, ExceptionState& exceptionState) { int argumentCount = info.Length(); if (argumentCount < 1) return; - DOMWindow* imp = V8Window::toNative(info.Holder()); - if (!imp->document()) { + LocalDOMWindow* impl = V8Window::toNative(info.Holder()); + if (!impl->frame() || !impl->document()) { exceptionState.throwDOMException(InvalidAccessError, "No script context is available in which to execute the script."); return; } - + ScriptState* scriptState = ScriptState::current(info.GetIsolate()); v8::Handle<v8::Value> function = info[0]; String functionString; if (!function->IsFunction()) { @@ -105,7 +104,7 @@ void WindowSetTimeoutImpl(const v8::FunctionCallbackInfo<v8::Value>& info, bool return; } - if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame(), exceptionState)) + if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), impl->frame(), exceptionState)) return; OwnPtr<ScheduledAction> action; @@ -121,23 +120,23 @@ void WindowSetTimeoutImpl(const v8::FunctionCallbackInfo<v8::Value>& info, bool } // params is passed to action, and released in action's destructor - ASSERT(imp->frame()); - action = adoptPtr(new ScheduledAction(imp->frame()->script().currentWorldContext(), v8::Handle<v8::Function>::Cast(function), paramCount, params.get(), info.GetIsolate())); + ASSERT(impl->frame()); + action = adoptPtr(new ScheduledAction(scriptState, v8::Handle<v8::Function>::Cast(function), paramCount, params.get(), info.GetIsolate())); } else { - if (imp->document() && !imp->document()->contentSecurityPolicy()->allowEval()) { + if (impl->document() && !impl->document()->contentSecurityPolicy()->allowEval()) { v8SetReturnValue(info, 0); return; } - ASSERT(imp->frame()); - action = adoptPtr(new ScheduledAction(imp->frame()->script().currentWorldContext(), functionString, KURL(), info.GetIsolate())); + ASSERT(impl->frame()); + action = adoptPtr(new ScheduledAction(scriptState, functionString, KURL(), info.GetIsolate())); } int32_t timeout = argumentCount >= 2 ? info[1]->Int32Value() : 0; int timerId; if (singleShot) - timerId = DOMWindowTimers::setTimeout(imp, action.release(), timeout); + timerId = DOMWindowTimers::setTimeout(*impl, action.release(), timeout); else - timerId = DOMWindowTimers::setInterval(imp, action.release(), timeout); + timerId = DOMWindowTimers::setInterval(*impl, action.release(), timeout); // Try to do the idle notification before the timeout expires to get better // use of any idle time. Aim for the middle of the interval for simplicity. @@ -151,24 +150,14 @@ void WindowSetTimeoutImpl(const v8::FunctionCallbackInfo<v8::Value>& info, bool void V8Window::eventAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) { - v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(V8Window::domTemplate(info.GetIsolate(), worldTypeInMainThread(info.GetIsolate()))); - if (holder.IsEmpty()) - return; - - Frame* frame = V8Window::toNative(holder)->frame(); + LocalFrame* frame = V8Window::toNative(info.Holder())->frame(); ExceptionState exceptionState(ExceptionState::GetterContext, "event", "Window", info.Holder(), info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToFrame(frame, exceptionState)) { + if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), frame, exceptionState)) { exceptionState.throwIfNeeded(); return; } - ASSERT(frame); - v8::Local<v8::Context> context = frame->script().currentWorldContext(); - if (context.IsEmpty()) - return; - - v8::Handle<v8::String> eventSymbol = V8HiddenPropertyName::event(info.GetIsolate()); - v8::Handle<v8::Value> jsEvent = context->Global()->GetHiddenValue(eventSymbol); + v8::Handle<v8::Value> jsEvent = V8HiddenValue::getHiddenValue(info.GetIsolate(), info.Holder()->CreationContext()->Global(), V8HiddenValue::event(info.GetIsolate())); if (jsEvent.IsEmpty()) return; v8SetReturnValue(info, jsEvent); @@ -176,31 +165,21 @@ void V8Window::eventAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Val void V8Window::eventAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) { - v8::Handle<v8::Object> holder = info.This()->FindInstanceInPrototypeChain(V8Window::domTemplate(info.GetIsolate(), worldTypeInMainThread(info.GetIsolate()))); - if (holder.IsEmpty()) - return; - - Frame* frame = V8Window::toNative(holder)->frame(); + LocalFrame* frame = V8Window::toNative(info.Holder())->frame(); ExceptionState exceptionState(ExceptionState::SetterContext, "event", "Window", info.Holder(), info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToFrame(frame, exceptionState)) { + if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), frame, exceptionState)) { exceptionState.throwIfNeeded(); return; } - ASSERT(frame); - v8::Local<v8::Context> context = frame->script().currentWorldContext(); - if (context.IsEmpty()) - return; - - v8::Handle<v8::String> eventSymbol = V8HiddenPropertyName::event(info.GetIsolate()); - context->Global()->SetHiddenValue(eventSymbol, value); + V8HiddenValue::setHiddenValue(info.GetIsolate(), info.Holder()->CreationContext()->Global(), V8HiddenValue::event(info.GetIsolate()), value); } void V8Window::frameElementAttributeGetterCustom(const v8::PropertyCallbackInfo<v8::Value>& info) { - DOMWindow* imp = V8Window::toNative(info.Holder()); + LocalDOMWindow* impl = V8Window::toNative(info.Holder()); ExceptionState exceptionState(ExceptionState::GetterContext, "frame", "Window", info.Holder(), info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToNode(imp->frameElement(), exceptionState)) { + if (!BindingSecurity::shouldAllowAccessToNode(info.GetIsolate(), impl->frameElement(), exceptionState)) { v8SetReturnValueNull(info); exceptionState.throwIfNeeded(); return; @@ -208,17 +187,17 @@ void V8Window::frameElementAttributeGetterCustom(const v8::PropertyCallbackInfo< // The wrapper for an <iframe> should get its prototype from the context of the frame it's in, rather than its own frame. // So, use its containing document as the creation context when wrapping. - v8::Handle<v8::Value> creationContext = toV8(&imp->frameElement()->document(), v8::Handle<v8::Object>(), info.GetIsolate()); + v8::Handle<v8::Value> creationContext = toV8(&impl->frameElement()->document(), info.Holder(), info.GetIsolate()); RELEASE_ASSERT(!creationContext.IsEmpty()); - v8::Handle<v8::Value> wrapper = toV8(imp->frameElement(), v8::Handle<v8::Object>::Cast(creationContext), info.GetIsolate()); + v8::Handle<v8::Value> wrapper = toV8(impl->frameElement(), v8::Handle<v8::Object>::Cast(creationContext), info.GetIsolate()); v8SetReturnValue(info, wrapper); } void V8Window::openerAttributeSetterCustom(v8::Local<v8::Value> value, const v8::PropertyCallbackInfo<void>& info) { - DOMWindow* imp = V8Window::toNative(info.Holder()); + LocalDOMWindow* impl = V8Window::toNative(info.Holder()); ExceptionState exceptionState(ExceptionState::SetterContext, "opener", "Window", info.Holder(), info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToFrame(imp->frame(), exceptionState)) { + if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), impl->frame(), exceptionState)) { exceptionState.throwIfNeeded(); return; } @@ -227,17 +206,18 @@ void V8Window::openerAttributeSetterCustom(v8::Local<v8::Value> value, const v8: // Have a special handling of null value to behave // like Firefox. See bug http://b/1224887 & http://b/791706. if (value->IsNull()) { - // imp->frame() cannot be null, + // impl->frame() cannot be null, // otherwise, SameOrigin check would have failed. - ASSERT(imp->frame()); - imp->frame()->loader().setOpener(0); + ASSERT(impl->frame()); + impl->frame()->loader().setOpener(0); } // Delete the accessor from this object. info.Holder()->Delete(v8AtomicString(info.GetIsolate(), "opener")); // Put property on the front (this) object. - info.This()->Set(v8AtomicString(info.GetIsolate(), "opener"), value); + if (info.This()->IsObject()) + v8::Handle<v8::Object>::Cast(info.This())->Set(v8AtomicString(info.GetIsolate(), "opener"), value); } static bool isLegacyTargetOriginDesignation(v8::Handle<v8::Value> value) @@ -252,12 +232,15 @@ void V8Window::postMessageMethodCustom(const v8::FunctionCallbackInfo<v8::Value> { // None of these need to be RefPtr because info and context are guaranteed // to hold on to them. - DOMWindow* window = V8Window::toNative(info.Holder()); - DOMWindow* source = activeDOMWindow(); + LocalDOMWindow* window = V8Window::toNative(info.Holder()); + LocalDOMWindow* source = callingDOMWindow(info.GetIsolate()); + + ExceptionState exceptionState(ExceptionState::ExecutionContext, "postMessage", "Window", info.Holder(), info.GetIsolate()); // If called directly by WebCore we don't have a calling context. if (!source) { - throwUninformativeAndGenericTypeError(info.GetIsolate()); + exceptionState.throwTypeError("No active calling context exists."); + exceptionState.throwIfNeeded(); return; } @@ -276,22 +259,17 @@ void V8Window::postMessageMethodCustom(const v8::FunctionCallbackInfo<v8::Value> targetOriginArgIndex = 2; transferablesArgIndex = 1; } - bool notASequence = false; - if (!extractTransferables(info[transferablesArgIndex], portArray, arrayBufferArray, notASequence, info.GetIsolate())) { - if (notASequence) - throwTypeError(ExceptionMessages::failedToExecute("postMessage", "Window", ExceptionMessages::notAnArrayTypeArgumentOrValue(transferablesArgIndex + 1)), info.GetIsolate()); + if (!SerializedScriptValue::extractTransferables(info[transferablesArgIndex], transferablesArgIndex, portArray, arrayBufferArray, exceptionState, info.GetIsolate())) { + exceptionState.throwIfNeeded(); return; } } - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, targetOrigin, info[targetOriginArgIndex]); + TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, targetOrigin, info[targetOriginArgIndex]); - bool didThrow = false; - RefPtr<SerializedScriptValue> message = - SerializedScriptValue::create(info[0], &portArray, &arrayBufferArray, didThrow, info.GetIsolate()); - if (didThrow) + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(info[0], &portArray, &arrayBufferArray, exceptionState, info.GetIsolate()); + if (exceptionState.throwIfNeeded()) return; - ExceptionState exceptionState(ExceptionState::ExecutionContext, "postMessage", "Window", info.Holder(), info.GetIsolate()); window->postMessage(message.release(), &portArray, targetOrigin, source, exceptionState); exceptionState.throwIfNeeded(); } @@ -302,7 +280,7 @@ void V8Window::postMessageMethodCustom(const v8::FunctionCallbackInfo<v8::Value> // switching context of receiver. I consider it is dangerous. void V8Window::toStringMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - v8::Handle<v8::Object> domWrapper = info.This()->FindInstanceInPrototypeChain(V8Window::domTemplate(info.GetIsolate(), worldTypeInMainThread(info.GetIsolate()))); + v8::Handle<v8::Object> domWrapper = V8Window::findInstanceInPrototypeChain(info.This(), info.GetIsolate()); if (domWrapper.IsEmpty()) { v8SetReturnValue(info, info.This()->ObjectProtoToString()); return; @@ -312,84 +290,92 @@ void V8Window::toStringMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& i class DialogHandler { public: - explicit DialogHandler(v8::Handle<v8::Value> dialogArguments) - : m_dialogArguments(dialogArguments) + explicit DialogHandler(v8::Handle<v8::Value> dialogArguments, ScriptState* scriptState) + : m_scriptState(scriptState) + , m_dialogArguments(dialogArguments) { } - void dialogCreated(DOMWindow*, v8::Isolate*); - v8::Handle<v8::Value> returnValue(v8::Isolate*) const; + void dialogCreated(LocalDOMWindow*); + v8::Handle<v8::Value> returnValue() const; private: + RefPtr<ScriptState> m_scriptState; + RefPtr<ScriptState> m_scriptStateForDialogFrame; v8::Handle<v8::Value> m_dialogArguments; - v8::Handle<v8::Context> m_dialogContext; }; -inline void DialogHandler::dialogCreated(DOMWindow* dialogFrame, v8::Isolate* isolate) +void DialogHandler::dialogCreated(LocalDOMWindow* dialogFrame) { - m_dialogContext = dialogFrame->frame() ? dialogFrame->frame()->script().currentWorldContext() : v8::Local<v8::Context>(); - if (m_dialogContext.IsEmpty()) - return; if (m_dialogArguments.IsEmpty()) return; - v8::Context::Scope scope(m_dialogContext); - m_dialogContext->Global()->Set(v8AtomicString(isolate, "dialogArguments"), m_dialogArguments); + v8::Handle<v8::Context> context = toV8Context(dialogFrame->frame(), m_scriptState->world()); + if (context.IsEmpty()) + return; + m_scriptStateForDialogFrame = ScriptState::from(context); + + ScriptState::Scope scope(m_scriptStateForDialogFrame.get()); + m_scriptStateForDialogFrame->context()->Global()->Set(v8AtomicString(m_scriptState->isolate(), "dialogArguments"), m_dialogArguments); } -inline v8::Handle<v8::Value> DialogHandler::returnValue(v8::Isolate* isolate) const +v8::Handle<v8::Value> DialogHandler::returnValue() const { - if (m_dialogContext.IsEmpty()) - return v8::Undefined(isolate); - v8::Context::Scope scope(m_dialogContext); - v8::Handle<v8::Value> returnValue = m_dialogContext->Global()->Get(v8AtomicString(isolate, "returnValue")); + if (!m_scriptStateForDialogFrame) + return v8Undefined(); + ASSERT(!m_scriptStateForDialogFrame->contextIsEmpty()); + + v8::Isolate* isolate = m_scriptStateForDialogFrame->isolate(); + v8::EscapableHandleScope handleScope(isolate); + ScriptState::Scope scope(m_scriptStateForDialogFrame.get()); + v8::Local<v8::Value> returnValue = m_scriptStateForDialogFrame->context()->Global()->Get(v8AtomicString(isolate, "returnValue")); if (returnValue.IsEmpty()) - return v8::Undefined(isolate); - return returnValue; + return v8Undefined(); + return handleScope.Escape(returnValue); } -static void setUpDialog(DOMWindow* dialog, void* handler) +static void setUpDialog(LocalDOMWindow* dialog, void* handler) { - static_cast<DialogHandler*>(handler)->dialogCreated(dialog, v8::Isolate::GetCurrent()); + static_cast<DialogHandler*>(handler)->dialogCreated(dialog); } void V8Window::showModalDialogMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - DOMWindow* impl = V8Window::toNative(info.Holder()); + LocalDOMWindow* impl = V8Window::toNative(info.Holder()); ExceptionState exceptionState(ExceptionState::ExecutionContext, "showModalDialog", "Window", info.Holder(), info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToFrame(impl->frame(), exceptionState)) { + if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), impl->frame(), exceptionState)) { exceptionState.throwIfNeeded(); return; } - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, urlString, info[0]); - DialogHandler handler(info[1]); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, dialogFeaturesString, info[2]); + TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, urlString, info[0]); + DialogHandler handler(info[1], ScriptState::current(info.GetIsolate())); + TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, dialogFeaturesString, info[2]); - impl->showModalDialog(urlString, dialogFeaturesString, activeDOMWindow(), firstDOMWindow(), setUpDialog, &handler); + impl->showModalDialog(urlString, dialogFeaturesString, callingDOMWindow(info.GetIsolate()), enteredDOMWindow(info.GetIsolate()), setUpDialog, &handler); - v8SetReturnValue(info, handler.returnValue(info.GetIsolate())); + v8SetReturnValue(info, handler.returnValue()); } void V8Window::openMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - DOMWindow* impl = V8Window::toNative(info.Holder()); + LocalDOMWindow* impl = V8Window::toNative(info.Holder()); ExceptionState exceptionState(ExceptionState::ExecutionContext, "open", "Window", info.Holder(), info.GetIsolate()); - if (!BindingSecurity::shouldAllowAccessToFrame(impl->frame(), exceptionState)) { + if (!BindingSecurity::shouldAllowAccessToFrame(info.GetIsolate(), impl->frame(), exceptionState)) { exceptionState.throwIfNeeded(); return; } - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, urlString, info[0]); + TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, urlString, info[0]); AtomicString frameName; if (info[1]->IsUndefined() || info[1]->IsNull()) { frameName = "_blank"; } else { - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, frameNameResource, info[1]); + TOSTRING_VOID(V8StringResource<>, frameNameResource, info[1]); frameName = frameNameResource; } - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithUndefinedOrNullCheck>, windowFeaturesString, info[2]); + TOSTRING_VOID(V8StringResource<WithUndefinedOrNullCheck>, windowFeaturesString, info[2]); - RefPtr<DOMWindow> openedWindow = impl->open(urlString, frameName, windowFeaturesString, activeDOMWindow(), firstDOMWindow()); + RefPtrWillBeRawPtr<LocalDOMWindow> openedWindow = impl->open(urlString, frameName, windowFeaturesString, callingDOMWindow(info.GetIsolate()), enteredDOMWindow(info.GetIsolate())); if (!openedWindow) return; @@ -399,11 +385,11 @@ void V8Window::openMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) void V8Window::namedPropertyGetterCustom(v8::Local<v8::String> name, const v8::PropertyCallbackInfo<v8::Value>& info) { - DOMWindow* window = V8Window::toNative(info.Holder()); + LocalDOMWindow* window = V8Window::toNative(info.Holder()); if (!window) return; - Frame* frame = window->frame(); + LocalFrame* frame = window->frame(); // window is detached from a frame. if (!frame) return; @@ -425,7 +411,7 @@ void V8Window::namedPropertyGetterCustom(v8::Local<v8::String> name, const v8::P if (doc && doc->isHTMLDocument()) { if (toHTMLDocument(doc)->hasNamedItem(propName) || doc->hasElementWithId(propName.impl())) { - RefPtr<HTMLCollection> items = doc->windowNamedItems(propName); + RefPtrWillBeRawPtr<HTMLCollection> items = doc->windowNamedItems(propName); if (!items->isEmpty()) { if (items->hasExactlyOneItem()) { v8SetReturnValueFast(info, items->item(0), window); @@ -442,7 +428,7 @@ void V8Window::namedPropertyGetterCustom(v8::Local<v8::String> name, const v8::P void V8Window::setTimeoutMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { ExceptionState exceptionState(ExceptionState::ExecutionContext, "setTimeout", "Window", info.Holder(), info.GetIsolate()); - WindowSetTimeoutImpl(info, true, exceptionState); + windowSetTimeoutImpl(info, true, exceptionState); exceptionState.throwIfNeeded(); } @@ -450,22 +436,22 @@ void V8Window::setTimeoutMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& void V8Window::setIntervalMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { ExceptionState exceptionState(ExceptionState::ExecutionContext, "setInterval", "Window", info.Holder(), info.GetIsolate()); - WindowSetTimeoutImpl(info, false, exceptionState); + windowSetTimeoutImpl(info, false, exceptionState); exceptionState.throwIfNeeded(); } bool V8Window::namedSecurityCheckCustom(v8::Local<v8::Object> host, v8::Local<v8::Value> key, v8::AccessType type, v8::Local<v8::Value>) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::Handle<v8::Object> window = host->FindInstanceInPrototypeChain(V8Window::domTemplate(isolate, worldTypeInMainThread(isolate))); + v8::Handle<v8::Object> window = V8Window::findInstanceInPrototypeChain(host, isolate); if (window.IsEmpty()) return false; // the frame is gone. - DOMWindow* targetWindow = V8Window::toNative(window); + LocalDOMWindow* targetWindow = V8Window::toNative(window); ASSERT(targetWindow); - Frame* target = targetWindow->frame(); + LocalFrame* target = targetWindow->frame(); if (!target) return false; @@ -494,21 +480,21 @@ bool V8Window::namedSecurityCheckCustom(v8::Local<v8::Object> host, v8::Local<v8 return true; } - return BindingSecurity::shouldAllowAccessToFrame(target, DoNotReportSecurityError); + return BindingSecurity::shouldAllowAccessToFrame(isolate, target, DoNotReportSecurityError); } bool V8Window::indexedSecurityCheckCustom(v8::Local<v8::Object> host, uint32_t index, v8::AccessType type, v8::Local<v8::Value>) { v8::Isolate* isolate = v8::Isolate::GetCurrent(); - v8::Handle<v8::Object> window = host->FindInstanceInPrototypeChain(V8Window::domTemplate(isolate, worldTypeInMainThread(isolate))); + v8::Handle<v8::Object> window = V8Window::findInstanceInPrototypeChain(host, isolate); if (window.IsEmpty()) return false; - DOMWindow* targetWindow = V8Window::toNative(window); + LocalDOMWindow* targetWindow = V8Window::toNative(window); ASSERT(targetWindow); - Frame* target = targetWindow->frame(); + LocalFrame* target = targetWindow->frame(); if (!target) return false; @@ -516,7 +502,7 @@ bool V8Window::indexedSecurityCheckCustom(v8::Local<v8::Object> host, uint32_t i if (target->loader().stateMachine()->isDisplayingInitialEmptyDocument()) target->loader().didAccessInitialDocument(); - Frame* childFrame = target->tree().scopedChild(index); + Frame* childFrame = target->tree().scopedChild(index); // Notice that we can't call HasRealNamedProperty for ACCESS_HAS // because that would generate infinite recursion. @@ -528,36 +514,22 @@ bool V8Window::indexedSecurityCheckCustom(v8::Local<v8::Object> host, uint32_t i && !window->HasRealIndexedProperty(index)) return true; - return BindingSecurity::shouldAllowAccessToFrame(target, DoNotReportSecurityError); + return BindingSecurity::shouldAllowAccessToFrame(isolate, target, DoNotReportSecurityError); } -v8::Handle<v8::Value> toV8(DOMWindow* window, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) +v8::Handle<v8::Value> toV8(LocalDOMWindow* window, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) { - // Notice that we explicitly ignore creationContext because the DOMWindow is its own creationContext. + // Notice that we explicitly ignore creationContext because the LocalDOMWindow is its own creationContext. if (!window) return v8::Null(isolate); // Initializes environment of a frame, and return the global object // of the frame. - Frame* frame = window->frame(); + LocalFrame* frame = window->frame(); if (!frame) return v8Undefined(); - // Special case: Because of executeScriptInIsolatedWorld() one DOMWindow can have - // multiple contexts and multiple global objects associated with it. When - // code running in one of those contexts accesses the window object, we - // want to return the global object associated with that context, not - // necessarily the first global object associated with that DOMWindow. - v8::Handle<v8::Context> currentContext = isolate->GetCurrentContext(); - v8::Handle<v8::Object> currentGlobal = currentContext->Global(); - v8::Handle<v8::Object> windowWrapper = currentGlobal->FindInstanceInPrototypeChain(V8Window::domTemplate(isolate, worldTypeInMainThread(isolate))); - if (!windowWrapper.IsEmpty()) { - if (V8Window::toNative(windowWrapper) == window) - return currentGlobal; - } - - // Otherwise, return the global object associated with this frame. - v8::Handle<v8::Context> context = frame->script().currentWorldContext(); + v8::Handle<v8::Context> context = toV8Context(frame, DOMWrapperWorld::current(isolate)); if (context.IsEmpty()) return v8Undefined(); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WorkerCryptoCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WorkerCryptoCustom.cpp deleted file mode 100644 index acf7a114d5a..00000000000 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WorkerCryptoCustom.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2013 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 "V8WorkerCrypto.h" - -#include "V8Crypto.h" - -namespace WebCore { - -void V8WorkerCrypto::getRandomValuesMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) -{ - V8Crypto::getRandomValuesMethodCustom(info); -} - -} // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WorkerCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WorkerCustom.cpp index 19440578be3..01a4a822546 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WorkerCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WorkerCustom.cpp @@ -29,13 +29,12 @@ */ #include "config.h" -#include "V8Worker.h" +#include "bindings/core/v8/V8Worker.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/SerializedScriptValue.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "core/workers/Worker.h" #include "core/workers/WorkerGlobalScope.h" #include "wtf/ArrayBuffer.h" @@ -50,18 +49,13 @@ void V8Worker::postMessageMethodCustom(const v8::FunctionCallbackInfo<v8::Value> ArrayBufferArray arrayBuffers; if (info.Length() > 1) { const int transferablesArgIndex = 1; - bool notASequence = false; - if (!extractTransferables(info[transferablesArgIndex], ports, arrayBuffers, notASequence, info.GetIsolate())) { - if (notASequence) { - exceptionState.throwTypeError(ExceptionMessages::notAnArrayTypeArgumentOrValue(transferablesArgIndex + 1)); - exceptionState.throwIfNeeded(); - } + if (!SerializedScriptValue::extractTransferables(info[transferablesArgIndex], transferablesArgIndex, ports, arrayBuffers, exceptionState, info.GetIsolate())) { + exceptionState.throwIfNeeded(); return; } } - bool didThrow = false; - RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(info[0], &ports, &arrayBuffers, didThrow, info.GetIsolate()); - if (didThrow) + RefPtr<SerializedScriptValue> message = SerializedScriptValue::create(info[0], &ports, &arrayBuffers, exceptionState, info.GetIsolate()); + if (exceptionState.throwIfNeeded()) return; worker->postMessage(message.release(), &ports, exceptionState); exceptionState.throwIfNeeded(); diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WorkerGlobalScopeCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WorkerGlobalScopeCustom.cpp index 1863af5992c..ca43934106b 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WorkerGlobalScopeCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8WorkerGlobalScopeCustom.cpp @@ -29,27 +29,27 @@ */ #include "config.h" -#include "V8WorkerGlobalScope.h" +#include "bindings/core/v8/V8WorkerGlobalScope.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/ScheduledAction.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "bindings/v8/V8WorkerGlobalScopeEventListener.h" #include "bindings/v8/WorkerScriptController.h" #include "core/inspector/ScriptCallStack.h" -#include "core/frame/ContentSecurityPolicy.h" #include "core/frame/DOMTimer.h" #include "core/frame/DOMWindowTimers.h" +#include "core/frame/csp/ContentSecurityPolicy.h" #include "core/workers/WorkerGlobalScope.h" #include "modules/websockets/WebSocket.h" #include "wtf/OwnPtr.h" namespace WebCore { -void SetTimeoutOrInterval(const v8::FunctionCallbackInfo<v8::Value>& info, bool singleShot) +static void setTimeoutOrInterval(const v8::FunctionCallbackInfo<v8::Value>& info, bool singleShot) { WorkerGlobalScope* workerGlobalScope = V8WorkerGlobalScope::toNative(info.Holder()); + ASSERT(workerGlobalScope); int argumentCount = info.Length(); if (argumentCount < 1) @@ -61,8 +61,8 @@ void SetTimeoutOrInterval(const v8::FunctionCallbackInfo<v8::Value>& info, bool if (!script) return; + ScriptState* scriptState = ScriptState::current(info.GetIsolate()); OwnPtr<ScheduledAction> action; - v8::Handle<v8::Context> v8Context = script->context(); if (function->IsString()) { if (ContentSecurityPolicy* policy = workerGlobalScope->contentSecurityPolicy()) { if (!policy->allowEval()) { @@ -70,7 +70,7 @@ void SetTimeoutOrInterval(const v8::FunctionCallbackInfo<v8::Value>& info, bool return; } } - action = adoptPtr(new ScheduledAction(v8Context, toCoreString(function.As<v8::String>()), workerGlobalScope->url(), info.GetIsolate())); + action = adoptPtr(new ScheduledAction(scriptState, toCoreString(function.As<v8::String>()), workerGlobalScope->url(), info.GetIsolate())); } else if (function->IsFunction()) { size_t paramCount = argumentCount >= 2 ? argumentCount - 2 : 0; OwnPtr<v8::Local<v8::Value>[]> params; @@ -80,28 +80,28 @@ void SetTimeoutOrInterval(const v8::FunctionCallbackInfo<v8::Value>& info, bool params[i] = info[i+2]; } // ScheduledAction takes ownership of actual params and releases them in its destructor. - action = adoptPtr(new ScheduledAction(v8Context, v8::Handle<v8::Function>::Cast(function), paramCount, params.get(), info.GetIsolate())); + action = adoptPtr(new ScheduledAction(scriptState, v8::Handle<v8::Function>::Cast(function), paramCount, params.get(), info.GetIsolate())); } else return; int32_t timeout = argumentCount >= 2 ? info[1]->Int32Value() : 0; int timerId; if (singleShot) - timerId = DOMWindowTimers::setTimeout(workerGlobalScope, action.release(), timeout); + timerId = DOMWindowTimers::setTimeout(*workerGlobalScope, action.release(), timeout); else - timerId = DOMWindowTimers::setInterval(workerGlobalScope, action.release(), timeout); + timerId = DOMWindowTimers::setInterval(*workerGlobalScope, action.release(), timeout); v8SetReturnValue(info, timerId); } void V8WorkerGlobalScope::setTimeoutMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - return SetTimeoutOrInterval(info, true); + return setTimeoutOrInterval(info, true); } void V8WorkerGlobalScope::setIntervalMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - return SetTimeoutOrInterval(info, false); + return setTimeoutOrInterval(info, false); } v8::Handle<v8::Value> toV8(WorkerGlobalScope* impl, v8::Handle<v8::Object> creationContext, v8::Isolate* isolate) diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8XMLHttpRequestCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8XMLHttpRequestCustom.cpp index 855f64e16bf..8659b65bcff 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8XMLHttpRequestCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8XMLHttpRequestCustom.cpp @@ -29,17 +29,16 @@ */ #include "config.h" -#include "V8XMLHttpRequest.h" +#include "bindings/core/v8/V8XMLHttpRequest.h" -#include "V8Blob.h" -#include "V8Document.h" -#include "V8FormData.h" -#include "V8HTMLDocument.h" -#include "V8Stream.h" +#include "bindings/core/v8/V8Blob.h" +#include "bindings/core/v8/V8Document.h" +#include "bindings/core/v8/V8FormData.h" +#include "bindings/core/v8/V8HTMLDocument.h" +#include "bindings/core/v8/V8Stream.h" #include "bindings/v8/ExceptionMessages.h" #include "bindings/v8/ExceptionState.h" #include "bindings/v8/V8Binding.h" -#include "bindings/v8/V8Utilities.h" #include "bindings/v8/custom/V8ArrayBufferCustom.h" #include "bindings/v8/custom/V8ArrayBufferViewCustom.h" #include "core/dom/Document.h" @@ -54,15 +53,16 @@ namespace WebCore { void V8XMLHttpRequest::constructorCustom(const v8::FunctionCallbackInfo<v8::Value>& info) { - ExecutionContext* context = getExecutionContext(); + ExecutionContext* context = currentExecutionContext(info.GetIsolate()); RefPtr<SecurityOrigin> securityOrigin; if (context->isDocument()) { - if (DOMWrapperWorld* world = isolatedWorldForEnteredContext(info.GetIsolate())) - securityOrigin = world->isolatedWorldSecurityOrigin(); + DOMWrapperWorld& world = DOMWrapperWorld::current(info.GetIsolate()); + if (world.isIsolatedWorld()) + securityOrigin = world.isolatedWorldSecurityOrigin(); } - RefPtr<XMLHttpRequest> xmlHttpRequest = XMLHttpRequest::create(context, securityOrigin); + RefPtrWillBeRawPtr<XMLHttpRequest> xmlHttpRequest = XMLHttpRequest::create(context, securityOrigin); v8::Handle<v8::Object> wrapper = info.Holder(); V8DOMWrapper::associateObjectWithWrapper<V8XMLHttpRequest>(xmlHttpRequest.release(), &wrapperTypeInfo, wrapper, info.GetIsolate(), WrapperConfiguration::Dependent); @@ -73,10 +73,10 @@ void V8XMLHttpRequest::responseTextAttributeGetterCustom(const v8::PropertyCallb { XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toNative(info.Holder()); ExceptionState exceptionState(ExceptionState::GetterContext, "responseText", "XMLHttpRequest", info.Holder(), info.GetIsolate()); - ScriptValue text = xmlHttpRequest->responseText(exceptionState); + ScriptString text = xmlHttpRequest->responseText(exceptionState); if (exceptionState.throwIfNeeded()) return; - if (text.hasNoValue()) { + if (text.isEmpty()) { v8SetReturnValueString(info, emptyString(), info.GetIsolate()); return; } @@ -98,21 +98,18 @@ void V8XMLHttpRequest::responseAttributeGetterCustom(const v8::PropertyCallbackI v8::Isolate* isolate = info.GetIsolate(); ScriptString jsonSource = xmlHttpRequest->responseJSONSource(); - if (jsonSource.hasNoValue() || !jsonSource.v8Value()->IsString()) { + if (jsonSource.isEmpty()) { v8SetReturnValue(info, v8::Null(isolate)); return; } // Catch syntax error. v8::TryCatch exceptionCatcher; - - v8::Handle<v8::Value> json = v8::JSON::Parse(jsonSource.v8Value().As<v8::String>()); - + v8::Handle<v8::Value> json = v8::JSON::Parse(jsonSource.v8Value()); if (exceptionCatcher.HasCaught() || json.IsEmpty()) v8SetReturnValue(info, v8::Null(isolate)); else v8SetReturnValue(info, json); - return; } @@ -170,20 +167,20 @@ void V8XMLHttpRequest::openMethodCustom(const v8::FunctionCallbackInfo<v8::Value XMLHttpRequest* xmlHttpRequest = V8XMLHttpRequest::toNative(info.Holder()); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, method, info[0]); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, urlstring, info[1]); + TOSTRING_VOID(V8StringResource<>, method, info[0]); + TOSTRING_VOID(V8StringResource<>, urlstring, info[1]); - ExecutionContext* context = getExecutionContext(); + ExecutionContext* context = currentExecutionContext(info.GetIsolate()); KURL url = context->completeURL(urlstring); if (info.Length() >= 3) { bool async = info[2]->BooleanValue(); if (info.Length() >= 4 && !info[3]->IsUndefined()) { - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, user, info[3]); + TOSTRING_VOID(V8StringResource<WithNullCheck>, user, info[3]); if (info.Length() >= 5 && !info[4]->IsUndefined()) { - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, password, info[4]); + TOSTRING_VOID(V8StringResource<WithNullCheck>, password, info[4]); xmlHttpRequest->open(method, url, async, user, password, exceptionState); } else { xmlHttpRequest->open(method, url, async, user, exceptionState); @@ -198,10 +195,10 @@ void V8XMLHttpRequest::openMethodCustom(const v8::FunctionCallbackInfo<v8::Value exceptionState.throwIfNeeded(); } -static bool isDocumentType(v8::Handle<v8::Value> value, v8::Isolate* isolate, WrapperWorldType currentWorldType) +static bool isDocumentType(v8::Handle<v8::Value> value, v8::Isolate* isolate) { // FIXME: add other document types. - return V8Document::hasInstance(value, isolate, currentWorldType) || V8HTMLDocument::hasInstance(value, isolate, currentWorldType); + return V8Document::hasInstance(value, isolate) || V8HTMLDocument::hasInstance(value, isolate); } void V8XMLHttpRequest::sendMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) @@ -215,36 +212,35 @@ void V8XMLHttpRequest::sendMethodCustom(const v8::FunctionCallbackInfo<v8::Value xmlHttpRequest->send(exceptionState); else { v8::Handle<v8::Value> arg = info[0]; - WrapperWorldType currentWorldType = worldType(info.GetIsolate()); if (isUndefinedOrNull(arg)) { xmlHttpRequest->send(exceptionState); - } else if (isDocumentType(arg, info.GetIsolate(), currentWorldType)) { + } else if (isDocumentType(arg, info.GetIsolate())) { v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); Document* document = V8Document::toNative(object); ASSERT(document); xmlHttpRequest->send(document, exceptionState); - } else if (V8Blob::hasInstance(arg, info.GetIsolate(), currentWorldType)) { + } else if (V8Blob::hasInstance(arg, info.GetIsolate())) { v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); Blob* blob = V8Blob::toNative(object); ASSERT(blob); xmlHttpRequest->send(blob, exceptionState); - } else if (V8FormData::hasInstance(arg, info.GetIsolate(), currentWorldType)) { + } else if (V8FormData::hasInstance(arg, info.GetIsolate())) { v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); DOMFormData* domFormData = V8FormData::toNative(object); ASSERT(domFormData); xmlHttpRequest->send(domFormData, exceptionState); - } else if (V8ArrayBuffer::hasInstance(arg, info.GetIsolate(), currentWorldType)) { + } else if (V8ArrayBuffer::hasInstance(arg, info.GetIsolate())) { v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); ArrayBuffer* arrayBuffer = V8ArrayBuffer::toNative(object); ASSERT(arrayBuffer); xmlHttpRequest->send(arrayBuffer, exceptionState); - } else if (V8ArrayBufferView::hasInstance(arg, info.GetIsolate(), currentWorldType)) { + } else if (V8ArrayBufferView::hasInstance(arg, info.GetIsolate())) { v8::Handle<v8::Object> object = v8::Handle<v8::Object>::Cast(arg); ArrayBufferView* arrayBufferView = V8ArrayBufferView::toNative(object); ASSERT(arrayBufferView); xmlHttpRequest->send(arrayBufferView, exceptionState); } else { - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<WithNullCheck>, argString, arg); + TOSTRING_VOID(V8StringResource<WithNullCheck>, argString, arg); xmlHttpRequest->send(argString, exceptionState); } } diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8XSLTProcessorCustom.cpp b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8XSLTProcessorCustom.cpp index 7835310a652..2c7591f1dde 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/custom/V8XSLTProcessorCustom.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/V8XSLTProcessorCustom.cpp @@ -29,11 +29,11 @@ */ #include "config.h" -#include "V8XSLTProcessor.h" +#include "bindings/core/v8/V8XSLTProcessor.h" -#include "V8Document.h" -#include "V8DocumentFragment.h" -#include "V8Node.h" +#include "bindings/core/v8/V8Document.h" +#include "bindings/core/v8/V8DocumentFragment.h" +#include "bindings/core/v8/V8Node.h" #include "bindings/v8/V8Binding.h" #include "core/dom/Document.h" #include "core/dom/DocumentFragment.h" @@ -48,12 +48,12 @@ void V8XSLTProcessor::setParameterMethodCustom(const v8::FunctionCallbackInfo<v8 if (isUndefinedOrNull(info[1]) || isUndefinedOrNull(info[2])) return; - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, namespaceURI, info[0]); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, localName, info[1]); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, value, info[2]); + TOSTRING_VOID(V8StringResource<>, namespaceURI, info[0]); + TOSTRING_VOID(V8StringResource<>, localName, info[1]); + TOSTRING_VOID(V8StringResource<>, value, info[2]); - XSLTProcessor* imp = V8XSLTProcessor::toNative(info.Holder()); - imp->setParameter(namespaceURI, localName, value); + XSLTProcessor* impl = V8XSLTProcessor::toNative(info.Holder()); + impl->setParameter(namespaceURI, localName, value); } void V8XSLTProcessor::getParameterMethodCustom(const v8::FunctionCallbackInfo<v8::Value>& info) @@ -61,11 +61,11 @@ void V8XSLTProcessor::getParameterMethodCustom(const v8::FunctionCallbackInfo<v8 if (isUndefinedOrNull(info[1])) return; - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, namespaceURI, info[0]); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, localName, info[1]); + TOSTRING_VOID(V8StringResource<>, namespaceURI, info[0]); + TOSTRING_VOID(V8StringResource<>, localName, info[1]); - XSLTProcessor* imp = V8XSLTProcessor::toNative(info.Holder()); - String result = imp->getParameter(namespaceURI, localName); + XSLTProcessor* impl = V8XSLTProcessor::toNative(info.Holder()); + String result = impl->getParameter(namespaceURI, localName); if (result.isNull()) return; @@ -77,11 +77,11 @@ void V8XSLTProcessor::removeParameterMethodCustom(const v8::FunctionCallbackInfo if (isUndefinedOrNull(info[1])) return; - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, namespaceURI, info[0]); - V8TRYCATCH_FOR_V8STRINGRESOURCE_VOID(V8StringResource<>, localName, info[1]); + TOSTRING_VOID(V8StringResource<>, namespaceURI, info[0]); + TOSTRING_VOID(V8StringResource<>, localName, info[1]); - XSLTProcessor* imp = V8XSLTProcessor::toNative(info.Holder()); - imp->removeParameter(namespaceURI, localName); + XSLTProcessor* impl = V8XSLTProcessor::toNative(info.Holder()); + impl->removeParameter(namespaceURI, localName); } } // namespace WebCore diff --git a/chromium/third_party/WebKit/Source/bindings/v8/custom/custom.gypi b/chromium/third_party/WebKit/Source/bindings/v8/custom/custom.gypi new file mode 100644 index 00000000000..9d76a6e41ad --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/custom/custom.gypi @@ -0,0 +1,92 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'variables': { + 'bindings_v8_custom_files': [ + 'V8ArrayBufferCustom.cpp', + 'V8ArrayBufferCustom.h', + 'V8ArrayBufferViewCustom.cpp', + 'V8ArrayBufferViewCustom.h', + 'V8AudioNodeCustom.cpp', + 'V8BlobCustom.cpp', + 'V8BlobCustomHelpers.cpp', + 'V8BlobCustomHelpers.h', + 'V8CSSRuleCustom.cpp', + 'V8CSSStyleDeclarationCustom.cpp', + 'V8CSSValueCustom.cpp', + 'V8CanvasRenderingContext2DCustom.cpp', + 'V8ClientCustom.cpp', + 'V8CryptoCustom.cpp', + 'V8CustomEventCustom.cpp', + 'V8CustomSQLStatementErrorCallback.cpp', + 'V8CustomXPathNSResolver.cpp', + 'V8CustomXPathNSResolver.h', + 'V8DataViewCustom.cpp', + 'V8DataViewCustom.h', + 'V8DedicatedWorkerGlobalScopeCustom.cpp', + 'V8DeviceMotionEventCustom.cpp', + 'V8DeviceOrientationEventCustom.cpp', + 'V8DocumentCustom.cpp', + 'V8ElementCustom.cpp', + 'V8EntryCustom.cpp', + 'V8EntrySyncCustom.cpp', + 'V8ErrorEventCustom.cpp', + 'V8EventCustom.cpp', + 'V8EventTargetCustom.cpp', + 'V8FileCustom.cpp', + 'V8FileReaderCustom.cpp', + 'V8Float32ArrayCustom.h', + 'V8Float64ArrayCustom.h', + 'V8GeolocationCustom.cpp', + 'V8HTMLAllCollectionCustom.cpp', + 'V8HTMLCanvasElementCustom.cpp', + 'V8HTMLCollectionCustom.cpp', + 'V8HTMLDocumentCustom.cpp', + 'V8HTMLElementCustom.cpp', + 'V8HTMLOptionsCollectionCustom.cpp', + 'V8HTMLPlugInElementCustom.cpp', + 'V8HistoryCustom.cpp', + 'V8ImageDataCustom.cpp', + 'V8InjectedScriptHostCustom.cpp', + 'V8InjectedScriptManager.cpp', + 'V8InspectorFrontendHostCustom.cpp', + 'V8Int16ArrayCustom.h', + 'V8Int32ArrayCustom.h', + 'V8Int8ArrayCustom.h', + 'V8JavaScriptCallFrameCustom.cpp', + 'V8LocationCustom.cpp', + 'V8MessageChannelCustom.cpp', + 'V8MessageEventCustom.cpp', + 'V8MessagePortCustom.cpp', + 'V8MutationObserverCustom.cpp', + 'V8NodeCustom.cpp', + 'V8PerformanceEntryCustom.cpp', + 'V8PopStateEventCustom.cpp', + 'V8SQLResultSetRowListCustom.cpp', + 'V8SQLTransactionCustom.cpp', + 'V8SQLTransactionSyncCustom.cpp', + 'V8SVGElementCustom.cpp', + 'V8SVGPathSegCustom.cpp', + 'V8ServiceWorkerCustom.cpp', + 'V8StyleSheetCustom.cpp', + 'V8SubtleCryptoCustom.cpp', + 'V8TextCustom.cpp', + 'V8TextTrackCueCustom.cpp', + 'V8TrackEventCustom.cpp', + 'V8TypedArrayCustom.h', + 'V8Uint16ArrayCustom.h', + 'V8Uint32ArrayCustom.h', + 'V8Uint8ArrayCustom.h', + 'V8Uint8ClampedArrayCustom.h', + 'V8WebGLRenderingContextCustom.cpp', + 'V8WebKitPointCustom.cpp', + 'V8WindowCustom.cpp', + 'V8WorkerCustom.cpp', + 'V8WorkerGlobalScopeCustom.cpp', + 'V8XMLHttpRequestCustom.cpp', + 'V8XSLTProcessorCustom.cpp', + ], + }, +} diff --git a/chromium/third_party/WebKit/Source/bindings/v8/npruntime.cpp b/chromium/third_party/WebKit/Source/bindings/v8/npruntime.cpp index d3e1755f100..182845e8810 100644 --- a/chromium/third_party/WebKit/Source/bindings/v8/npruntime.cpp +++ b/chromium/third_party/WebKit/Source/bindings/v8/npruntime.cpp @@ -352,7 +352,7 @@ void _NPN_InitializeVariantWithStringCopy(NPVariant* variant, const NPString* va // The rootObjectMap is a hash table of root objects to a set of // objects that should be deactivated in sync with the root. A // root is defined as a top-level owner object. This is used on -// Frame teardown to deactivate all objects associated +// LocalFrame teardown to deactivate all objects associated // with a particular plugin. typedef WTF::HashSet<NPObject*> NPObjectSet; @@ -432,7 +432,7 @@ void _NPN_UnregisterObject(NPObject* npObject) set->remove(sub_object); liveObjectMap().remove(sub_object); - // Script objects hold a refernce to their DOMWindow*, which is going away if + // Script objects hold a refernce to their LocalDOMWindow*, which is going away if // we're unregistering the associated owner NPObject. Clear it out. if (V8NPObject* v8npObject = npObjectToV8NPObject(sub_object)) v8npObject->rootObject = 0; diff --git a/chromium/third_party/WebKit/Source/bindings/v8/v8.gypi b/chromium/third_party/WebKit/Source/bindings/v8/v8.gypi new file mode 100644 index 00000000000..a220a63087e --- /dev/null +++ b/chromium/third_party/WebKit/Source/bindings/v8/v8.gypi @@ -0,0 +1,165 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +{ + 'includes': [ + 'custom/custom.gypi', + ], + 'variables': { + 'bindings_v8_dir': '.', + 'bindings_v8_files': [ + '<@(bindings_v8_custom_files)', + 'ActiveDOMCallback.cpp', + 'ActiveDOMCallback.h', + 'ArrayValue.cpp', + 'ArrayValue.h', + 'BindingSecurity.cpp', + 'BindingSecurity.h', + 'CallbackPromiseAdapter.h', + 'CustomElementBinding.cpp', + 'CustomElementBinding.h', + 'CustomElementConstructorBuilder.cpp', + 'CustomElementConstructorBuilder.h', + 'CustomElementWrapper.cpp', + 'CustomElementWrapper.h', + 'DOMDataStore.cpp', + 'DOMDataStore.h', + 'DOMWrapperMap.h', + 'DOMWrapperWorld.cpp', + 'DOMWrapperWorld.h', + 'Dictionary.cpp', + 'Dictionary.h', + 'ExceptionMessages.cpp', + 'ExceptionMessages.h', + 'ExceptionState.cpp', + 'ExceptionState.h', + 'ExceptionStatePlaceholder.cpp', + 'ExceptionStatePlaceholder.h', + 'IDBBindingUtilities.cpp', + 'IDBBindingUtilities.h', + 'NPV8Object.cpp', + 'NPV8Object.h', + 'Nullable.h', + 'PageScriptDebugServer.cpp', + 'PageScriptDebugServer.h', + 'RetainedDOMInfo.cpp', + 'RetainedDOMInfo.h', + 'RetainedObjectInfo.h', + 'ScheduledAction.cpp', + 'ScheduledAction.h', + 'ScopedPersistent.h', + 'ScriptCallStackFactory.cpp', + 'ScriptCallStackFactory.h', + 'ScriptController.cpp', + 'ScriptController.h', + 'ScriptDebugServer.cpp', + 'ScriptDebugServer.h', + 'ScriptEventListener.cpp', + 'ScriptEventListener.h', + 'ScriptFunction.cpp', + 'ScriptFunction.h', + 'ScriptFunctionCall.cpp', + 'ScriptFunctionCall.h', + 'ScriptGCEvent.cpp', + 'ScriptGCEvent.h', + 'ScriptHeapSnapshot.cpp', + 'ScriptHeapSnapshot.h', + 'ScriptPreprocessor.cpp', + 'ScriptPreprocessor.h', + 'ScriptProfiler.cpp', + 'ScriptProfiler.h', + 'ScriptPromise.cpp', + 'ScriptPromise.h', + 'ScriptPromiseResolver.cpp', + 'ScriptPromiseResolver.h', + 'ScriptPromiseResolverWithContext.cpp', + 'ScriptPromiseResolverWithContext.h', + 'ScriptRegexp.cpp', + 'ScriptRegexp.h', + 'ScriptSourceCode.h', + 'ScriptState.cpp', + 'ScriptState.h', + 'ScriptString.cpp', + 'ScriptString.h', + 'ScriptValue.cpp', + 'ScriptValue.h', + 'ScriptWrappable.h', + 'SerializedScriptValue.cpp', + 'SerializedScriptValue.h', + 'SharedPersistent.h', + 'V8AbstractEventListener.cpp', + 'V8AbstractEventListener.h', + 'V8Binding.cpp', + 'V8Binding.h', + 'V8BindingMacros.h', + 'V8Callback.cpp', + 'V8Callback.h', + 'V8CustomElementLifecycleCallbacks.cpp', + 'V8CustomElementLifecycleCallbacks.h', + 'V8DOMActivityLogger.cpp', + 'V8DOMActivityLogger.h', + 'V8DOMConfiguration.cpp', + 'V8DOMConfiguration.h', + 'V8DOMWrapper.cpp', + 'V8DOMWrapper.h', + 'V8ErrorHandler.cpp', + 'V8ErrorHandler.h', + 'V8EventListener.cpp', + 'V8EventListener.h', + 'V8EventListenerList.cpp', + 'V8EventListenerList.h', + 'V8GCController.cpp', + 'V8GCController.h', + 'V8GCForContextDispose.cpp', + 'V8GCForContextDispose.h', + 'V8HiddenValue.cpp', + 'V8HiddenValue.h', + 'V8Initializer.cpp', + 'V8Initializer.h', + 'V8LazyEventListener.cpp', + 'V8LazyEventListener.h', + 'V8MutationCallback.cpp', + 'V8MutationCallback.h', + 'V8NPObject.cpp', + 'V8NPObject.h', + 'V8NPUtils.cpp', + 'V8NPUtils.h', + 'V8NodeFilterCondition.cpp', + 'V8NodeFilterCondition.h', + 'V8ObjectConstructor.cpp', + 'V8ObjectConstructor.h', + 'V8PerContextData.cpp', + 'V8PerContextData.h', + 'V8PerIsolateData.cpp', + 'V8PerIsolateData.h', + 'V8RecursionScope.cpp', + 'V8RecursionScope.h', + 'V8ScriptRunner.cpp', + 'V8ScriptRunner.h', + 'V8StringResource.cpp', + 'V8StringResource.h', + 'V8ThrowException.cpp', + 'V8ThrowException.h', + 'V8ValueCache.cpp', + 'V8ValueCache.h', + 'V8WindowShell.cpp', + 'V8WindowShell.h', + 'V8WorkerGlobalScopeEventListener.cpp', + 'V8WorkerGlobalScopeEventListener.h', + 'WorkerScriptController.cpp', + 'WorkerScriptController.h', + 'WorkerScriptDebugServer.cpp', + 'WorkerScriptDebugServer.h', + 'WrapperTypeInfo.h', + 'npruntime.cpp', + 'npruntime_impl.h', + 'npruntime_priv.h', + ], + 'bindings_v8_unittest_files': [ + 'IDBBindingUtilitiesTest.cpp', + 'ScriptPromiseResolverTest.cpp', + 'ScriptPromiseTest.cpp', + ], + }, +} |