[WebIDL] Add support for generating timer bindings
authorweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 25 Jul 2017 18:02:57 +0000 (18:02 +0000)
committerweinig@apple.com <weinig@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 25 Jul 2017 18:02:57 +0000 (18:02 +0000)
https://bugs.webkit.org/show_bug.cgi?id=174766

Reviewed by Darin Adler.

Adds a new non-standard type, ScheduledAction, which stands in for the
standard (DOMString or Function). It would be good to move to that in
future, but for now, this allows for forward momentum on removing custom
bindings.

* WebCore.xcodeproj/project.pbxproj:
Add JSDOMConvertScheduledAction.h.

* bindings/IDLTypes.h:
Add IDLScheduledAction.

* bindings/js/JSDOMConvertScheduledAction.h: Added.
(WebCore::Converter<IDLScheduledAction>::convert):
Add conversion from JSValue -> ScheduledAction. This is moved from the old ScheduledAction
create function.

* bindings/js/JSDOMConvertVariadic.h:
(WebCore::convertVariadicArguments):
(WebCore::Detail::VariadicConverterBase::convert): Deleted.
(WebCore::Detail::VariadicConverterBase<IDLInterface<T>>::convert): Deleted.
* bindings/js/JSDOMConvertBase.h:
* bindings/js/JSDOMConvertAny.h:
(WebCore::VariadicConverter<IDLAny>::convert):
* bindings/js/JSDOMConvertInterface.h:
(WebCore::VariadicConverter<IDLInterface<T>>::convert):
Rename VariadicConverter to VariadicConverterDetails, and remove base class. Rename
VariadicConverterBase to VariadicConverter, and move specializations to the file
containing the base converter for that IDL type

* bindings/js/JSDOMWindowCustom.cpp:
(WebCore::JSDOMWindow::setTimeout): Deleted.
(WebCore::JSDOMWindow::setInterval): Deleted.
* bindings/js/JSWorkerGlobalScopeCustom.cpp:
(WebCore::JSWorkerGlobalScope::setTimeout): Deleted.
(WebCore::JSWorkerGlobalScope::setInterval): Deleted.
Remove custom implementations of setTimeout and setInterval.

* bindings/js/ScheduledAction.cpp:
(WebCore::ScheduledAction::create):
(WebCore::ScheduledAction::ScheduledAction):
(WebCore::ScheduledAction::~ScheduledAction):
(WebCore::ScheduledAction::addArguments):
(WebCore::ScheduledAction::executeFunctionInContext):
* bindings/js/ScheduledAction.h:
(WebCore::ScheduledAction::ScheduledAction): Deleted.
Rework ScheduledAction. Now has two create functions, one for the function
form, one for the string form. These are now called by the Converter. Also,
rather than extracting the arguments directly from the ExecState, allow the
bindings to work as designed, and have the arguments come in as variadic
arguments to setTimeout/setInterval and get added to the ScheduledAction if
needed. Also, move ContentSecurityPolicy check out of construction, and into
setTimeout/setInterval.

* bindings/scripts/CodeGenerator.pm:
(IsBuiltinType):
Add ScheduledAction to the builtin list.

* bindings/scripts/CodeGeneratorJS.pm:
(AddToIncludesForIDLType):
Add the correct include when ScheduledAction is used.

(GenerateParametersCheck):
Remove rule disallowing optional arguments before variadic arguments. That works
just fine.

(GetBaseIDLType):
Add mapping of ScheduledAction -> IDLScheduledAction.

(JSValueToNativeDOMConvertNeedsGlobalObject):
Add ScheduledAction to the list of types that need a global object
for conversion.

* page/WindowOrWorkerGlobalScope.idl:
Update interface to match spec and add FIXMEs for moving to TimerHandler.

* page/DOMWindow.cpp:
(WebCore::DOMWindow::setTimeout):
(WebCore::DOMWindow::setInterval):
* page/DOMWindow.h:
* workers/WorkerGlobalScope.cpp:
(WebCore::WorkerGlobalScope::setTimeout):
(WebCore::WorkerGlobalScope::setInterval):
* workers/WorkerGlobalScope.h:
Update for new signatures. WorkerGlobalScope now has to return ExceptionOr<int>
even though it never throws, due to having one IDL file defining these. This is
unfortunate and something we should look at addressing the future.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@219873 268f45cc-cd09-0410-ab3c-d52691b4dbfc

21 files changed:
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/bindings/IDLTypes.h
Source/WebCore/bindings/js/JSDOMConvertAny.h
Source/WebCore/bindings/js/JSDOMConvertBase.h
Source/WebCore/bindings/js/JSDOMConvertInterface.h
Source/WebCore/bindings/js/JSDOMConvertScheduledAction.h [new file with mode: 0644]
Source/WebCore/bindings/js/JSDOMConvertVariadic.h
Source/WebCore/bindings/js/JSDOMWindowCustom.cpp
Source/WebCore/bindings/js/JSWorkerGlobalScopeCustom.cpp
Source/WebCore/bindings/js/ScheduledAction.cpp
Source/WebCore/bindings/js/ScheduledAction.h
Source/WebCore/bindings/scripts/CodeGenerator.pm
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
Source/WebCore/bindings/scripts/test/JS/JSTestObj.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestOverloadedConstructors.cpp
Source/WebCore/page/DOMWindow.cpp
Source/WebCore/page/DOMWindow.h
Source/WebCore/page/WindowOrWorkerGlobalScope.idl
Source/WebCore/workers/WorkerGlobalScope.cpp
Source/WebCore/workers/WorkerGlobalScope.h

index 2af3274..f98d6b4 100644 (file)
@@ -1,3 +1,97 @@
+2017-07-23  Sam Weinig  <sam@webkit.org>
+
+        [WebIDL] Add support for generating timer bindings
+        https://bugs.webkit.org/show_bug.cgi?id=174766
+
+        Reviewed by Darin Adler.
+
+        Adds a new non-standard type, ScheduledAction, which stands in for the
+        standard (DOMString or Function). It would be good to move to that in
+        future, but for now, this allows for forward momentum on removing custom
+        bindings.
+
+        * WebCore.xcodeproj/project.pbxproj:
+        Add JSDOMConvertScheduledAction.h.
+
+        * bindings/IDLTypes.h:
+        Add IDLScheduledAction.
+
+        * bindings/js/JSDOMConvertScheduledAction.h: Added.
+        (WebCore::Converter<IDLScheduledAction>::convert):
+        Add conversion from JSValue -> ScheduledAction. This is moved from the old ScheduledAction
+        create function.
+
+        * bindings/js/JSDOMConvertVariadic.h:
+        (WebCore::convertVariadicArguments):
+        (WebCore::Detail::VariadicConverterBase::convert): Deleted.
+        (WebCore::Detail::VariadicConverterBase<IDLInterface<T>>::convert): Deleted.
+        * bindings/js/JSDOMConvertBase.h:
+        * bindings/js/JSDOMConvertAny.h:
+        (WebCore::VariadicConverter<IDLAny>::convert):
+        * bindings/js/JSDOMConvertInterface.h:
+        (WebCore::VariadicConverter<IDLInterface<T>>::convert):
+        Rename VariadicConverter to VariadicConverterDetails, and remove base class. Rename 
+        VariadicConverterBase to VariadicConverter, and move specializations to the file
+        containing the base converter for that IDL type 
+
+        * bindings/js/JSDOMWindowCustom.cpp:
+        (WebCore::JSDOMWindow::setTimeout): Deleted.
+        (WebCore::JSDOMWindow::setInterval): Deleted.
+        * bindings/js/JSWorkerGlobalScopeCustom.cpp:
+        (WebCore::JSWorkerGlobalScope::setTimeout): Deleted.
+        (WebCore::JSWorkerGlobalScope::setInterval): Deleted.
+        Remove custom implementations of setTimeout and setInterval.
+
+        * bindings/js/ScheduledAction.cpp:
+        (WebCore::ScheduledAction::create):
+        (WebCore::ScheduledAction::ScheduledAction):
+        (WebCore::ScheduledAction::~ScheduledAction):
+        (WebCore::ScheduledAction::addArguments):
+        (WebCore::ScheduledAction::executeFunctionInContext):
+        * bindings/js/ScheduledAction.h:
+        (WebCore::ScheduledAction::ScheduledAction): Deleted.
+        Rework ScheduledAction. Now has two create functions, one for the function
+        form, one for the string form. These are now called by the Converter. Also,
+        rather than extracting the arguments directly from the ExecState, allow the
+        bindings to work as designed, and have the arguments come in as variadic 
+        arguments to setTimeout/setInterval and get added to the ScheduledAction if
+        needed. Also, move ContentSecurityPolicy check out of construction, and into
+        setTimeout/setInterval.
+
+        * bindings/scripts/CodeGenerator.pm:
+        (IsBuiltinType):
+        Add ScheduledAction to the builtin list.
+
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (AddToIncludesForIDLType):
+        Add the correct include when ScheduledAction is used.
+
+        (GenerateParametersCheck):
+        Remove rule disallowing optional arguments before variadic arguments. That works
+        just fine.
+
+        (GetBaseIDLType):
+        Add mapping of ScheduledAction -> IDLScheduledAction.
+
+        (JSValueToNativeDOMConvertNeedsGlobalObject):
+        Add ScheduledAction to the list of types that need a global object
+        for conversion.
+
+        * page/WindowOrWorkerGlobalScope.idl:
+        Update interface to match spec and add FIXMEs for moving to TimerHandler.
+
+        * page/DOMWindow.cpp:
+        (WebCore::DOMWindow::setTimeout):
+        (WebCore::DOMWindow::setInterval):
+        * page/DOMWindow.h:
+        * workers/WorkerGlobalScope.cpp:
+        (WebCore::WorkerGlobalScope::setTimeout):
+        (WebCore::WorkerGlobalScope::setInterval):
+        * workers/WorkerGlobalScope.h:
+        Update for new signatures. WorkerGlobalScope now has to return ExceptionOr<int>
+        even though it never throws, due to having one IDL file defining these. This is 
+        unfortunate and something we should look at addressing the future.
+
 2017-07-25  Yoshiaki Jitsukawa  <Yoshiaki.Jitsukawa@sony.com>
 
         [WinCairo] Fix build with AllInOnes disabled
index 3390dbd..348e3e0 100644 (file)
                7C1E8D011ED0C2DA00B1D983 /* CallbackResult.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C1E8D001ED0C2BE00B1D983 /* CallbackResult.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7C1E97271A9F9834007BF0FB /* AutoFillButtonElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C1E97251A9F9834007BF0FB /* AutoFillButtonElement.cpp */; };
                7C1E97281A9F9834007BF0FB /* AutoFillButtonElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C1E97261A9F9834007BF0FB /* AutoFillButtonElement.h */; };
+               7C1F5D591F22FF7300A8874F /* JSDOMConvertScheduledAction.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C1F5D581F22FF7300A8874F /* JSDOMConvertScheduledAction.h */; };
                7C2BDD3D17C7F98C0038FF15 /* JSDOMGlobalObjectTask.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C2BDD3B17C7F98B0038FF15 /* JSDOMGlobalObjectTask.cpp */; };
                7C2BDD3E17C7F98C0038FF15 /* JSDOMGlobalObjectTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C2BDD3C17C7F98B0038FF15 /* JSDOMGlobalObjectTask.h */; };
                7C2FA6111EA95A3900A03108 /* ResourceCryptographicDigest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C2FA60F1EA95A3200A03108 /* ResourceCryptographicDigest.cpp */; };
                7C1E8D001ED0C2BE00B1D983 /* CallbackResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CallbackResult.h; sourceTree = "<group>"; };
                7C1E97251A9F9834007BF0FB /* AutoFillButtonElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AutoFillButtonElement.cpp; sourceTree = "<group>"; };
                7C1E97261A9F9834007BF0FB /* AutoFillButtonElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AutoFillButtonElement.h; sourceTree = "<group>"; };
+               7C1F5D581F22FF7300A8874F /* JSDOMConvertScheduledAction.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = JSDOMConvertScheduledAction.h; sourceTree = "<group>"; };
                7C2BDD3B17C7F98B0038FF15 /* JSDOMGlobalObjectTask.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDOMGlobalObjectTask.cpp; sourceTree = "<group>"; };
                7C2BDD3C17C7F98B0038FF15 /* JSDOMGlobalObjectTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDOMGlobalObjectTask.h; sourceTree = "<group>"; };
                7C2FA60F1EA95A3200A03108 /* ResourceCryptographicDigest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ResourceCryptographicDigest.cpp; sourceTree = "<group>"; };
                                BC46C1ED0C0DDBDF0020CFC3 /* JSCSSRuleCustom.cpp */,
                                AD726FE916D9F40A003A4E6D /* JSCSSRuleCustom.h */,
                                9392262E10321084006E7D5D /* JSCSSRuleListCustom.cpp */,
+                               BC5825F20C0B89380053F1B5 /* JSCSSStyleDeclarationCustom.cpp */,
+                               AD726FEA16D9F40B003A4E6D /* JSCSSStyleDeclarationCustom.h */,
                                BC20FB7E0C0E8E6C00D1447F /* JSDeprecatedCSSOMValueCustom.cpp */,
                                49C7BA8C1042F5B10009D447 /* JSDocumentCustom.cpp */,
                                ADDA94BF19686F8000453029 /* JSDocumentCustom.h */,
                                49EED14C1051971A00099FAB /* JSWebGLRenderingContextCustom.cpp */,
                                31A088C41E737B2C003B6609 /* JSWebGPURenderingContextCustom.cpp */,
                                31A088C51E737B2C003B6609 /* JSWebGPURenderPassAttachmentDescriptorCustom.cpp */,
+                               E18258AB0EF3CD7000933242 /* JSWorkerGlobalScopeCustom.cpp */,
                                83A4A9F81CE7FD7E00709B00 /* JSXMLDocumentCustom.cpp */,
                                836C14421CDEAFCA0073493F /* JSXPathNSResolverCustom.cpp */,
                                A1C7FAA1133A5D3500D6732D /* JSXPathResultCustom.cpp */,
                                7C8E34A31E4A338E0054CE23 /* JSDOMConvertObject.h */,
                                E323CFF91E5AF6A500F0B4A0 /* JSDOMConvertPromise.h */,
                                7C8E34A41E4A338E0054CE23 /* JSDOMConvertRecord.h */,
+                               7C1F5D581F22FF7300A8874F /* JSDOMConvertScheduledAction.h */,
                                7C8E34A51E4A338E0054CE23 /* JSDOMConvertSequences.h */,
                                7C8E34A61E4A338E0054CE23 /* JSDOMConvertSerializedScriptValue.h */,
                                7C8E34A71E4A338E0054CE23 /* JSDOMConvertStrings.cpp */,
                                7C8E34A81E4A338E0054CE23 /* JSDOMConvertStrings.h */,
                                7C8E34A91E4A338E0054CE23 /* JSDOMConvertUnion.h */,
                                7C8E34AA1E4A338E0054CE23 /* JSDOMConvertVariadic.h */,
-                               7C8E34AB1E4A338E0054CE23 /* JSDOMConvertWebGL.h */,
                                7CBA5BA61F0B4BDE0034D745 /* JSDOMConvertWebGL.cpp */,
+                               7C8E34AB1E4A338E0054CE23 /* JSDOMConvertWebGL.h */,
                                7C8E34AC1E4A338E0054CE23 /* JSDOMConvertXPathNSResolver.h */,
                        );
                        name = Conversions;
                                7C3D8EE41E08BABE0023B084 /* GC / Wrapping Only */,
                                7CBA5BA91F0B51480034D745 /* Promises Only */,
                                E157A8E618184C67009F821D /* JSCryptoKeyCustom.cpp */,
-                               BC5825F20C0B89380053F1B5 /* JSCSSStyleDeclarationCustom.cpp */,
-                               AD726FEA16D9F40B003A4E6D /* JSCSSStyleDeclarationCustom.h */,
                                9BC5F9DF1D5AAF6A002B749D /* JSCustomElementRegistryCustom.cpp */,
                                DEC2975D1B4DEB2A005F5945 /* JSCustomEventCustom.cpp */,
                                BCD9C25E0C17AA67005C90A2 /* JSDOMWindowCustom.cpp */,
                                51D0C5150DAA90B7003B3831 /* JSStorageCustom.cpp */,
                                57A9C88D1DA70BF800BC7305 /* JSSubtleCryptoCustom.cpp */,
                                E1FF8F661807460800132674 /* JSWebKitSubtleCryptoCustom.cpp */,
-                               E18258AB0EF3CD7000933242 /* JSWorkerGlobalScopeCustom.cpp */,
                                BC348BBD0DB7F531004ABAB9 /* JSXMLHttpRequestCustom.cpp */,
                        );
                        name = Custom;
                                BC23F0DB0DAFF4A4009FDC91 /* GeneratedImage.h in Headers */,
                                830030F61B7D33B500ED3AAC /* GenericCachedHTMLCollection.h in Headers */,
                                0720B0A114D3323500642955 /* GenericEventQueue.h in Headers */,
+                               7C1F5D591F22FF7300A8874F /* JSDOMConvertScheduledAction.h in Headers */,
                                CD62FB961AF018E70012ED7D /* GenericTaskQueue.h in Headers */,
                                9746AF2414F4DDE6003E7A70 /* Geolocation.h in Headers */,
                                9746AF2514F4DDE6003E7A71 /* GeolocationClient.h in Headers */,
index 838e5f8..8bc8834 100644 (file)
@@ -51,6 +51,7 @@ class IDBKey;
 class IDBKeyData;
 class IDBValue;
 class DOMPromise;
+class ScheduledAction;
 
 #if ENABLE(WEBGL)
 class WebGLExtension;
@@ -255,6 +256,7 @@ struct IDLJSON : IDLType<String> {
     template <typename U> static U&& extractValueFromNullable(U&& value) { return std::forward<U>(value); }
 };
 
+struct IDLScheduledAction : IDLType<std::unique_ptr<ScheduledAction>> { };
 template<typename T> struct IDLSerializedScriptValue : IDLWrapper<T> { };
 template<typename T> struct IDLEventListener : IDLWrapper<T> { };
 template<typename T> struct IDLXPathNSResolver : IDLWrapper<T> { };
index 4980fa0..3734a8b 100644 (file)
@@ -61,4 +61,19 @@ template<> struct JSConverter<IDLAny> {
     }
 };
 
+template<> struct VariadicConverter<IDLAny> {
+    using Item = typename IDLAny::ImplementationType;
+
+    static std::optional<Item> convert(JSC::ExecState& state, JSC::JSValue value)
+    {
+        auto& vm = state.vm();
+        auto scope = DECLARE_THROW_SCOPE(vm);
+
+        auto result = Converter<IDLAny>::convert(state, value);
+        RETURN_IF_EXCEPTION(scope, std::nullopt);
+
+        return Item { vm, result };
+    }
+};
+
 } // namespace WebCore
index 3353268..c50f28a 100644 (file)
@@ -199,4 +199,7 @@ template<typename T> struct DefaultConverter {
     static constexpr bool conversionHasSideEffects = true;
 };
 
+// Conversion from JSValue -> Implementation for variadic arguments
+template<typename IDLType> struct VariadicConverter;
+
 } // namespace WebCore
index aafed02..77b9a98 100644 (file)
@@ -66,5 +66,16 @@ template<typename T> struct JSConverter<IDLInterface<T>> {
     }
 };
 
+template<typename T> struct VariadicConverter<IDLInterface<T>> {
+    using Item = std::reference_wrapper<T>;
+
+    static std::optional<Item> convert(JSC::ExecState& state, JSC::JSValue value)
+    {
+        auto* result = Converter<IDLInterface<T>>::convert(state, value);
+        if (!result)
+            return std::nullopt;
+        return std::optional<Item> { *result };
+    }
+};
 
 } // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSDOMConvertScheduledAction.h b/Source/WebCore/bindings/js/JSDOMConvertScheduledAction.h
new file mode 100644 (file)
index 0000000..2eff93a
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "IDLTypes.h"
+#include "JSDOMConvertBase.h"
+#include "JSDOMConvertStrings.h"
+#include "ScheduledAction.h"
+
+namespace WebCore {
+
+template<> struct Converter<IDLScheduledAction> : DefaultConverter<IDLScheduledAction> {
+    static std::unique_ptr<ScheduledAction> convert(JSC::ExecState& state, JSC::JSValue value, JSDOMGlobalObject& globalObject)
+    {
+        JSC::VM& vm = state.vm();
+        auto scope = DECLARE_THROW_SCOPE(vm);
+
+        JSC::CallData callData;
+        if (getCallData(value, callData) == JSC::CallType::None) {
+            auto code = Converter<IDLDOMString>::convert(state, value);
+            RETURN_IF_EXCEPTION(scope, nullptr);
+            return ScheduledAction::create(globalObject.world(), WTFMove(code));
+        }
+
+        // The value must be an object at this point because no non-object values are callable.
+        ASSERT(value.isObject());
+        return ScheduledAction::create(globalObject.world(), JSC::Strong<JSC::Unknown> { vm, JSC::asObject(value) });
+    }
+};
+
+}
+
index 47ea962..18bd11f 100644 (file)
 #pragma once
 
 #include "IDLTypes.h"
+#include "JSDOMConvertBase.h"
 
 namespace WebCore {
 
-namespace Detail {
-
 template<typename IDLType>
-struct VariadicConverterBase;
-
-template<typename IDLType> 
-struct VariadicConverterBase {
+struct VariadicConverter {
     using Item = typename IDLType::ImplementationType;
 
     static std::optional<Item> convert(JSC::ExecState& state, JSC::JSValue value)
@@ -50,49 +46,23 @@ struct VariadicConverterBase {
     }
 };
 
-template<typename T>
-struct VariadicConverterBase<IDLInterface<T>> {
-    using Item = std::reference_wrapper<T>;
-
-    static std::optional<Item> convert(JSC::ExecState& state, JSC::JSValue value)
-    {
-        auto* result = Converter<IDLInterface<T>>::convert(state, value);
-        if (!result)
-            return std::nullopt;
-        return std::optional<Item>(*result);
-    }
-};
-
-template<typename IDLType>
-struct VariadicConverter : VariadicConverterBase<IDLType> {
-    using Item = typename VariadicConverterBase<IDLType>::Item;
-    using Container = Vector<Item>;
-
-    struct Result {
-        size_t argumentIndex;
-        std::optional<Container> arguments;
-    };
-};
-
-}
-
-template<typename IDLType> typename Detail::VariadicConverter<IDLType>::Result convertVariadicArguments(JSC::ExecState& state, size_t startIndex)
+template<typename IDLType> Vector<typename VariadicConverter<IDLType>::Item> convertVariadicArguments(JSC::ExecState& state, size_t startIndex)
 {
     size_t length = state.argumentCount();
-    if (startIndex > length)
-        return { 0, std::nullopt };
+    if (startIndex >= length)
+        return { };
 
-    typename Detail::VariadicConverter<IDLType>::Container result;
+    Vector<typename VariadicConverter<IDLType>::Item> result;
     result.reserveInitialCapacity(length - startIndex);
 
     for (size_t i = startIndex; i < length; ++i) {
-        auto value = Detail::VariadicConverter<IDLType>::convert(state, state.uncheckedArgument(i));
+        auto value = VariadicConverter<IDLType>::convert(state, state.uncheckedArgument(i));
         if (!value)
-            return { i, std::nullopt };
+            return { };
         result.uncheckedAppend(WTFMove(*value));
     }
 
-    return { length, WTFMove(result) };
+    return WTFMove(result);
 }
 
 } // namespace WebCore
index fd7f885..074c070 100644 (file)
@@ -459,42 +459,6 @@ JSValue JSDOMWindow::showModalDialog(ExecState& state)
     return handler.returnValue();
 }
 
-JSValue JSDOMWindow::setTimeout(ExecState& state)
-{
-    VM& vm = state.vm();
-    auto scope = DECLARE_THROW_SCOPE(vm);
-
-    if (UNLIKELY(state.argumentCount() < 1))
-        return throwException(&state, scope, createNotEnoughArgumentsError(&state));
-
-    auto* contentSecurityPolicy = wrapped().document() ? wrapped().document()->contentSecurityPolicy() : nullptr;
-    auto action = ScheduledAction::create(&state, globalObject()->world(), contentSecurityPolicy);
-    RETURN_IF_EXCEPTION(scope, JSValue());
-    if (!action)
-        return jsNumber(0);
-
-    int delay = state.argument(1).toInt32(&state);
-    return toJS<IDLLong>(state, scope, wrapped().setTimeout(WTFMove(action), delay));
-}
-
-JSValue JSDOMWindow::setInterval(ExecState& state)
-{
-    VM& vm = state.vm();
-    auto scope = DECLARE_THROW_SCOPE(vm);
-
-    if (UNLIKELY(state.argumentCount() < 1))
-        return throwException(&state, scope, createNotEnoughArgumentsError(&state));
-
-    auto* contentSecurityPolicy = wrapped().document() ? wrapped().document()->contentSecurityPolicy() : nullptr;
-    auto action = ScheduledAction::create(&state, globalObject()->world(), contentSecurityPolicy);
-    RETURN_IF_EXCEPTION(scope, JSValue());
-    if (!action)
-        return jsNumber(0);
-
-    int delay = state.argument(1).toInt32(&state);
-    return toJS<IDLLong>(state, scope, wrapped().setInterval(WTFMove(action), delay));
-}
-
 DOMWindow* JSDOMWindow::toWrapped(VM& vm, JSValue value)
 {
     if (!value.isObject())
index 6663dfb..4081a33 100644 (file)
@@ -26,8 +26,6 @@
 #include "config.h"
 #include "JSWorkerGlobalScope.h"
 
-#include "JSDOMConvert.h"
-#include "ScheduledAction.h"
 #include "WorkerGlobalScope.h"
 
 using namespace JSC;
@@ -49,36 +47,4 @@ void JSWorkerGlobalScope::visitAdditionalChildren(SlotVisitor& visitor)
     wrapped().visitJSEventListeners(visitor);
 }
 
-JSValue JSWorkerGlobalScope::setTimeout(ExecState& state)
-{
-    VM& vm = state.vm();
-    auto scope = DECLARE_THROW_SCOPE(vm);
-
-    if (UNLIKELY(state.argumentCount() < 1))
-        return throwException(&state, scope, createNotEnoughArgumentsError(&state));
-
-    std::unique_ptr<ScheduledAction> action = ScheduledAction::create(&state, globalObject()->world(), wrapped().contentSecurityPolicy());
-    RETURN_IF_EXCEPTION(scope, JSValue());
-    if (!action)
-        return jsNumber(0);
-    int delay = state.argument(1).toInt32(&state);
-    return jsNumber(wrapped().setTimeout(WTFMove(action), delay));
-}
-
-JSValue JSWorkerGlobalScope::setInterval(ExecState& state)
-{
-    VM& vm = state.vm();
-    auto scope = DECLARE_THROW_SCOPE(vm);
-
-    if (UNLIKELY(state.argumentCount() < 1))
-        return throwException(&state, scope, createNotEnoughArgumentsError(&state));
-
-    std::unique_ptr<ScheduledAction> action = ScheduledAction::create(&state, globalObject()->world(), wrapped().contentSecurityPolicy());
-    RETURN_IF_EXCEPTION(scope, JSValue());
-    if (!action)
-        return jsNumber(0);
-    int delay = state.argument(1).toInt32(&state);
-    return jsNumber(wrapped().setInterval(WTFMove(action), delay));
-}
-
 } // namespace WebCore
index d144796..5ed0474 100644 (file)
@@ -26,6 +26,7 @@
 
 #include "ContentSecurityPolicy.h"
 #include "DOMWindow.h"
+#include "DOMWrapperWorld.h"
 #include "Document.h"
 #include "Frame.h"
 #include "FrameLoader.h"
@@ -45,32 +46,41 @@ using namespace JSC;
 
 namespace WebCore {
 
-std::unique_ptr<ScheduledAction> ScheduledAction::create(ExecState* exec, DOMWrapperWorld& isolatedWorld, ContentSecurityPolicy* policy)
+std::unique_ptr<ScheduledAction> ScheduledAction::create(DOMWrapperWorld& isolatedWorld, JSC::Strong<JSC::Unknown>&& function)
 {
-    VM& vm = exec->vm();
-    auto scope = DECLARE_THROW_SCOPE(vm);
+    return std::unique_ptr<ScheduledAction>(new ScheduledAction(isolatedWorld, WTFMove(function)));
+}
 
-    JSValue v = exec->argument(0);
-    CallData callData;
-    if (getCallData(v, callData) == CallType::None) {
-        if (policy && !policy->allowEval(exec))
-            return nullptr;
-        String string = v.toWTFString(exec);
-        RETURN_IF_EXCEPTION(scope, nullptr);
-        return std::unique_ptr<ScheduledAction>(new ScheduledAction(string, isolatedWorld));
-    }
+std::unique_ptr<ScheduledAction> ScheduledAction::create(DOMWrapperWorld& isolatedWorld, String&& code)
+{
+    return std::unique_ptr<ScheduledAction>(new ScheduledAction(isolatedWorld, WTFMove(code)));
+}
+
+ScheduledAction::ScheduledAction(DOMWrapperWorld& isolatedWorld, JSC::Strong<JSC::Unknown>&& function)
+    : m_isolatedWorld(isolatedWorld)
+    , m_function(WTFMove(function))
+{
+}
 
-    return std::unique_ptr<ScheduledAction>(new ScheduledAction(exec, v, isolatedWorld));
+ScheduledAction::ScheduledAction(DOMWrapperWorld& isolatedWorld, String&& code)
+    : m_isolatedWorld(isolatedWorld)
+    , m_function(isolatedWorld.vm())
+    , m_code(WTFMove(code))
+{
+}
+
+ScheduledAction::~ScheduledAction()
+{
+}
+
+void ScheduledAction::addArguments(Vector<JSC::Strong<JSC::Unknown>>&& arguments)
+{
+    m_arguments = WTFMove(arguments);
 }
 
-ScheduledAction::ScheduledAction(ExecState* exec, JSValue function, DOMWrapperWorld& isolatedWorld)
-    : m_function(exec->vm(), function)
-    , m_isolatedWorld(isolatedWorld)
+auto ScheduledAction::type() const -> Type
 {
-    // setTimeout(function, interval, arg0, arg1...).
-    // Start at 2 to skip function and interval.
-    for (size_t i = 2; i < exec->argumentCount(); ++i)
-        m_args.append(Strong<JSC::Unknown>(exec->vm(), exec->uncheckedArgument(i)));
+    return m_function ? Type::Function : Type::Code;
 }
 
 void ScheduledAction::execute(ScriptExecutionContext& context)
@@ -93,18 +103,17 @@ void ScheduledAction::executeFunctionInContext(JSGlobalObject* globalObject, JSV
 
     ExecState* exec = globalObject->globalExec();
 
-    MarkedArgumentBuffer args;
-    size_t size = m_args.size();
-    for (size_t i = 0; i < size; ++i)
-        args.append(m_args[i].get());
+    MarkedArgumentBuffer arguments;
+    for (auto& argument : m_arguments)
+        arguments.append(argument.get());
 
     InspectorInstrumentationCookie cookie = JSMainThreadExecState::instrumentFunctionCall(&context, callType, callData);
 
     NakedPtr<JSC::Exception> exception;
     if (is<Document>(context))
-        JSMainThreadExecState::profiledCall(exec, JSC::ProfilingReason::Other, m_function.get(), callType, callData, thisValue, args, exception);
+        JSMainThreadExecState::profiledCall(exec, JSC::ProfilingReason::Other, m_function.get(), callType, callData, thisValue, arguments, exception);
     else
-        JSC::profiledCall(exec, JSC::ProfilingReason::Other, m_function.get(), callType, callData, thisValue, args, exception);
+        JSC::profiledCall(exec, JSC::ProfilingReason::Other, m_function.get(), callType, callData, thisValue, arguments, exception);
 
     InspectorInstrumentation::didCallFunction(cookie, &context);
 
index b7710d9..4e77e58 100644 (file)
@@ -19,7 +19,6 @@
 
 #pragma once
 
-#include "JSDOMBinding.h"
 #include <heap/Strong.h>
 #include <heap/StrongInlines.h>
 #include <memory>
 #include <wtf/text/WTFString.h>
 
 namespace JSC {
-    class JSGlobalObject;
+class JSGlobalObject;
 }
 
 namespace WebCore {
 
-    class Document;
-    class ContentSecurityPolicy;
-    class ScriptExecutionContext;
-    class WorkerGlobalScope;
+class DOMWrapperWorld;
+class Document;
+class ScriptExecutionContext;
+class WorkerGlobalScope;
 
-   /* An action (either function or string) to be executed after a specified
-    * time interval, either once or repeatedly. Used for window.setTimeout()
-    * and window.setInterval()
-    */
-    class ScheduledAction {
-        WTF_MAKE_NONCOPYABLE(ScheduledAction); WTF_MAKE_FAST_ALLOCATED;
-    public:
-        static std::unique_ptr<ScheduledAction> create(JSC::ExecState*, DOMWrapperWorld& isolatedWorld, ContentSecurityPolicy*);
+class ScheduledAction {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static std::unique_ptr<ScheduledAction> create(DOMWrapperWorld&, JSC::Strong<JSC::Unknown>&&);
+    static std::unique_ptr<ScheduledAction> create(DOMWrapperWorld&, String&&);
+    ~ScheduledAction();
 
-        void execute(ScriptExecutionContext&);
+    void addArguments(Vector<JSC::Strong<JSC::Unknown>>&&);
 
-    private:
-        ScheduledAction(JSC::ExecState*, JSC::JSValue function, DOMWrapperWorld& isolatedWorld);
-        ScheduledAction(const String& code, DOMWrapperWorld& isolatedWorld)
-            : m_function(isolatedWorld.vm())
-            , m_code(code)
-            , m_isolatedWorld(isolatedWorld)
-        {
-        }
+    enum class Type { Code, Function };
+    Type type() const;
 
-        void executeFunctionInContext(JSC::JSGlobalObject*, JSC::JSValue thisValue, ScriptExecutionContext&);
-        void execute(Document&);
-        void execute(WorkerGlobalScope&);
+    void execute(ScriptExecutionContext&);
 
-        JSC::Strong<JSC::Unknown> m_function;
-        Vector<JSC::Strong<JSC::Unknown>> m_args;
-        String m_code;
-        Ref<DOMWrapperWorld> m_isolatedWorld;
-    };
+private:
+    ScheduledAction(DOMWrapperWorld&, JSC::Strong<JSC::Unknown>&&);
+    ScheduledAction(DOMWrapperWorld&, String&&);
+
+    void executeFunctionInContext(JSC::JSGlobalObject*, JSC::JSValue thisValue, ScriptExecutionContext&);
+    void execute(Document&);
+    void execute(WorkerGlobalScope&);
+
+    Ref<DOMWrapperWorld> m_isolatedWorld;
+    JSC::Strong<JSC::Unknown> m_function;
+    Vector<JSC::Strong<JSC::Unknown>> m_arguments;
+    String m_code;
+};
 
 } // namespace WebCore
index 70dd3d5..62484f7 100644 (file)
@@ -870,6 +870,7 @@ sub IsBuiltinType
     return 1 if $type->name eq "EventListener";
     return 1 if $type->name eq "JSON";
     return 1 if $type->name eq "Promise";
+    return 1 if $type->name eq "ScheduledAction";
     return 1 if $type->name eq "SerializedScriptValue";
     return 1 if $type->name eq "XPathNSResolver";
     return 1 if $type->name eq "any";
index db23369..567a0b1 100644 (file)
@@ -417,6 +417,11 @@ sub AddToIncludesForIDLType
         return;
     }
 
+    if ($type->name eq "ScheduledAction") {
+        AddToIncludes("JSDOMConvertScheduledAction.h", $includesRef, $conditional);
+        return;
+    }
+
     if ($type->name eq "SerializedScriptValue") {
         AddToIncludes("SerializedScriptValue.h", $includesRef, $conditional);
         AddToIncludes("JSDOMConvertSerializedScriptValue.h", $includesRef, $conditional);
@@ -5524,7 +5529,6 @@ sub GenerateParametersCheck
         my $type = $argument->type;
 
         die "Optional arguments of non-nullable wrapper types are not supported" if $argument->isOptional && !$type->isNullable && $codeGenerator->IsWrapperType($type);
-        die "Optional arguments preceding variadic arguments are not supported" if ($argument->isOptional &&  @{$operation->arguments}[$numArguments - 1]->isVariadic);
 
         if ($argument->isOptional && !defined($argument->default)) {
             # As per Web IDL, optional dictionary arguments are always considered to have a default value of an empty dictionary, unless otherwise specified.
@@ -5559,7 +5563,7 @@ sub GenerateParametersCheck
             push(@$outputArray, $indent . "auto ${name} = convertVariadicArguments<${IDLType}>(*state, ${argumentIndex});\n");
             push(@$outputArray, $indent . "RETURN_IF_EXCEPTION(throwScope, encodedJSValue());\n");
 
-            $value = "WTFMove(${name}.arguments.value())";
+            $value = "WTFMove(${name})";
         } else {
             my $argumentLookupForConversion;
             my $optionalCheck;
@@ -6251,6 +6255,7 @@ sub GetBaseIDLType
         "Date" => "IDLDate",
         "EventListener" => "IDLEventListener<JSEventListener>",
         "JSON" => "IDLJSON",
+        "ScheduledAction" => "IDLScheduledAction",
         "SerializedScriptValue" => "IDLSerializedScriptValue<SerializedScriptValue>",
         "XPathNSResolver" => "IDLXPathNSResolver<XPathNSResolver>",
     );
@@ -6316,6 +6321,7 @@ sub JSValueToNativeDOMConvertNeedsGlobalObject
 
     return 1 if $codeGenerator->IsCallbackInterface($type);
     return 1 if $codeGenerator->IsCallbackFunction($type);
+    return 1 if $type->name eq "ScheduledAction";
     return 0;
 }
 
index 476ab74..c18f3e4 100644 (file)
@@ -6740,7 +6740,7 @@ static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionOverloadedMethod13Bo
     auto& impl = castedThis->wrapped();
     auto blobArgs = convertVariadicArguments<IDLInterface<Blob>>(*state, 0);
     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
-    impl.overloadedMethod(WTFMove(blobArgs.arguments.value()));
+    impl.overloadedMethod(WTFMove(blobArgs));
     return JSValue::encode(jsUndefined());
 }
 
@@ -7539,7 +7539,7 @@ static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionVariadicStringMethod
     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
     auto tail = convertVariadicArguments<IDLDOMString>(*state, 1);
     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
-    impl.variadicStringMethod(WTFMove(head), WTFMove(tail.arguments.value()));
+    impl.variadicStringMethod(WTFMove(head), WTFMove(tail));
     return JSValue::encode(jsUndefined());
 }
 
@@ -7559,7 +7559,7 @@ static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionVariadicDoubleMethod
     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
     auto tail = convertVariadicArguments<IDLUnrestrictedDouble>(*state, 1);
     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
-    impl.variadicDoubleMethod(WTFMove(head), WTFMove(tail.arguments.value()));
+    impl.variadicDoubleMethod(WTFMove(head), WTFMove(tail));
     return JSValue::encode(jsUndefined());
 }
 
@@ -7579,7 +7579,7 @@ static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionVariadicNodeMethodBo
     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
     auto tail = convertVariadicArguments<IDLInterface<Node>>(*state, 1);
     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
-    impl.variadicNodeMethod(*head, WTFMove(tail.arguments.value()));
+    impl.variadicNodeMethod(*head, WTFMove(tail));
     return JSValue::encode(jsUndefined());
 }
 
@@ -7599,7 +7599,7 @@ static inline JSC::EncodedJSValue jsTestObjPrototypeFunctionVariadicUnionMethodB
     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
     auto tail = convertVariadicArguments<IDLUnion<IDLInterface<Node>, IDLDOMString>>(*state, 1);
     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
-    impl.variadicUnionMethod(WTFMove(head), WTFMove(tail.arguments.value()));
+    impl.variadicUnionMethod(WTFMove(head), WTFMove(tail));
     return JSValue::encode(jsUndefined());
 }
 
index 56a5b21..97b36ba 100644 (file)
@@ -132,7 +132,7 @@ static inline EncodedJSValue constructJSTestOverloadedConstructors5(ExecState* s
     ASSERT(castedThis);
     auto longArgs = convertVariadicArguments<IDLLong>(*state, 0);
     RETURN_IF_EXCEPTION(throwScope, encodedJSValue());
-    auto object = TestOverloadedConstructors::create(WTFMove(longArgs.arguments.value()));
+    auto object = TestOverloadedConstructors::create(WTFMove(longArgs));
     return JSValue::encode(toJSNewlyCreated<IDLInterface<TestOverloadedConstructors>>(*state, *castedThis->globalObject(), WTFMove(object)));
 }
 
index ed74f5f..38222fa 100644 (file)
@@ -1666,11 +1666,20 @@ void DOMWindow::resizeTo(float width, float height) const
     page->chrome().setWindowRect(adjustWindowRect(*page, update));
 }
 
-ExceptionOr<int> DOMWindow::setTimeout(std::unique_ptr<ScheduledAction> action, int timeout)
+ExceptionOr<int> DOMWindow::setTimeout(JSC::ExecState& state, std::unique_ptr<ScheduledAction> action, int timeout, Vector<JSC::Strong<JSC::Unknown>>&& arguments)
 {
     auto* context = scriptExecutionContext();
     if (!context)
         return Exception { InvalidAccessError };
+
+    // FIXME: Should this check really happen here? Or should it happen when code is about to eval?
+    if (action->type() == ScheduledAction::Type::Code) {
+        if (!context->contentSecurityPolicy()->allowEval(&state))
+            return 0;
+    }
+
+    action->addArguments(WTFMove(arguments));
+
     return DOMTimer::install(*context, WTFMove(action), Seconds::fromMilliseconds(timeout), true);
 }
 
@@ -1698,11 +1707,20 @@ void DOMWindow::clearTimeout(int timeoutId)
     DOMTimer::removeById(*context, timeoutId);
 }
 
-ExceptionOr<int> DOMWindow::setInterval(std::unique_ptr<ScheduledAction> action, int timeout)
+ExceptionOr<int> DOMWindow::setInterval(JSC::ExecState& state, std::unique_ptr<ScheduledAction> action, int timeout, Vector<JSC::Strong<JSC::Unknown>>&& arguments)
 {
     auto* context = scriptExecutionContext();
     if (!context)
         return Exception { InvalidAccessError };
+
+    // FIXME: Should this check really happen here? Or should it happen when code is about to eval?
+    if (action->type() == ScheduledAction::Type::Code) {
+        if (!context->contentSecurityPolicy()->allowEval(&state))
+            return 0;
+    }
+
+    action->addArguments(WTFMove(arguments));
+
     return DOMTimer::install(*context, WTFMove(action), Seconds::fromMilliseconds(timeout), false);
 }
 
index 92a12af..4bd6dca 100644 (file)
@@ -33,6 +33,7 @@
 #include "FrameDestructionObserver.h"
 #include "ScrollToOptions.h"
 #include "Supplementable.h"
+#include <heap/HandleTypes.h>
 #include <wtf/Function.h>
 #include <wtf/HashSet.h>
 #include <wtf/WeakPtr.h>
@@ -239,9 +240,9 @@ public:
     void resizeTo(float width, float height) const;
 
     // Timers
-    ExceptionOr<int> setTimeout(std::unique_ptr<ScheduledAction>, int timeout);
+    ExceptionOr<int> setTimeout(JSC::ExecState&, std::unique_ptr<ScheduledAction>, int timeout, Vector<JSC::Strong<JSC::Unknown>>&& arguments);
     void clearTimeout(int timeoutId);
-    ExceptionOr<int> setInterval(std::unique_ptr<ScheduledAction>, int timeout);
+    ExceptionOr<int> setInterval(JSC::ExecState&, std::unique_ptr<ScheduledAction>, int timeout, Vector<JSC::Strong<JSC::Unknown>>&& arguments);
     void clearInterval(int timeoutId);
 
     int requestAnimationFrame(Ref<RequestAnimationFrameCallback>&&);
index 8f1f6e8..f6d6e4e 100644 (file)
     [Replaceable] readonly attribute USVString origin;
 
     // Timers
-    [Custom] long setTimeout(any handler, optional long timeout = 0);
+    // FIXME: This should take a TimerHandler (a.k.a. (DOMString or Function)) rather than a ScheduledAction.
+    [CallWith=ScriptState, MayThrowException] long setTimeout(ScheduledAction handler, optional long timeout = 0, any... arguments);
     void clearTimeout(optional long handle = 0);
-    [Custom] long setInterval(any handler, optional long timeout = 0);
+    // FIXME: This should take a TimerHandler (a.k.a. (DOMString or Function)) rather than a ScheduledAction.
+    [CallWith=ScriptState, MayThrowException] long setInterval(ScheduledAction handler, optional long timeout = 0, any... arguments);
     void clearInterval(optional long handle = 0);
 
     // Base64 utility methods.
index 5fd51dd..5e0eaf8 100644 (file)
@@ -222,8 +222,16 @@ void WorkerGlobalScope::postTask(Task&& task)
     thread().runLoop().postTask(WTFMove(task));
 }
 
-int WorkerGlobalScope::setTimeout(std::unique_ptr<ScheduledAction> action, int timeout)
+ExceptionOr<int> WorkerGlobalScope::setTimeout(JSC::ExecState& state, std::unique_ptr<ScheduledAction> action, int timeout, Vector<JSC::Strong<JSC::Unknown>>&& arguments)
 {
+    // FIXME: Should this check really happen here? Or should it happen when code is about to eval?
+    if (action->type() == ScheduledAction::Type::Code) {
+        if (!contentSecurityPolicy()->allowEval(&state))
+            return 0;
+    }
+
+    action->addArguments(WTFMove(arguments));
+
     return DOMTimer::install(*this, WTFMove(action), Seconds::fromMilliseconds(timeout), true);
 }
 
@@ -232,8 +240,16 @@ void WorkerGlobalScope::clearTimeout(int timeoutId)
     DOMTimer::removeById(*this, timeoutId);
 }
 
-int WorkerGlobalScope::setInterval(std::unique_ptr<ScheduledAction> action, int timeout)
+ExceptionOr<int> WorkerGlobalScope::setInterval(JSC::ExecState& state, std::unique_ptr<ScheduledAction> action, int timeout, Vector<JSC::Strong<JSC::Unknown>>&& arguments)
 {
+    // FIXME: Should this check really happen here? Or should it happen when code is about to eval?
+    if (action->type() == ScheduledAction::Type::Code) {
+        if (!contentSecurityPolicy()->allowEval(&state))
+            return 0;
+    }
+
+    action->addArguments(WTFMove(arguments));
+
     return DOMTimer::install(*this, WTFMove(action), Seconds::fromMilliseconds(timeout), false);
 }
 
index b2f69e9..904d364 100644 (file)
@@ -83,9 +83,9 @@ public:
     virtual ExceptionOr<void> importScripts(const Vector<String>& urls);
     WorkerNavigator& navigator() const;
 
-    int setTimeout(std::unique_ptr<ScheduledAction>, int timeout);
+    ExceptionOr<int> setTimeout(JSC::ExecState&, std::unique_ptr<ScheduledAction>, int timeout, Vector<JSC::Strong<JSC::Unknown>>&& arguments);
     void clearTimeout(int timeoutId);
-    int setInterval(std::unique_ptr<ScheduledAction>, int timeout);
+    ExceptionOr<int> setInterval(JSC::ExecState&, std::unique_ptr<ScheduledAction>, int timeout, Vector<JSC::Strong<JSC::Unknown>>&& arguments);
     void clearInterval(int timeoutId);
 
     bool isContextThread() const final;