[WebIDL] Support callbacks with arbitrary return types
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 22 May 2017 19:27:43 +0000 (19:27 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 22 May 2017 19:27:43 +0000 (19:27 +0000)
https://bugs.webkit.org/show_bug.cgi?id=172407

Patch by Sam Weinig <sam@webkit.org> on 2017-05-22
Reviewed by Chris Dumez.

Source/WebCore:

- Adds and adopts CallbackResult<> template class that encapsulates a return value
  and status from a javascript callback.
- Updates NodeIterator/TreeWalker to explicitly propagate exceptions thrown from
  a JSNodeFilter, rather than relying on the JSNodeFilter to catch them (seemingly
  accidentally).

* CMakeLists.txt:
* WebCore.xcodeproj/project.pbxproj:
* bindings/js/JSBindingsAllInOne.cpp:
Update file lists.

* Modules/geolocation/PositionCallback.h:
* Modules/geolocation/PositionErrorCallback.h:
* Modules/notifications/NotificationPermissionCallback.h:
* Modules/webaudio/AudioBufferCallback.h:
* Modules/webdatabase/DatabaseCallback.h:
* dom/RequestAnimationFrameCallback.h:
* dom/StringCallback.h:
* dom/Traversal.cpp:
* fileapi/BlobCallback.h:
* html/VoidCallback.h:
* page/IntersectionObserverCallback.h:
* page/PerformanceObserverCallback.h:
* css/MediaQueryListListener.h:
* Modules/webdatabase/SQLStatement.h:
* Modules/webdatabase/SQLStatementCallback.h:
* Modules/webdatabase/SQLStatementErrorCallback.h:
* Modules/webdatabase/SQLTransaction.cpp:
* Modules/webdatabase/SQLTransactionCallback.h:
* Modules/webdatabase/SQLTransactionErrorCallback.h:
* inspector/InspectorDatabaseAgent.cpp:
Adopt CallbackResult.

* Modules/webdatabase/SQLStatementErrorCallback.idl:
Remove Custom extended attribute annotation.

* Modules/webdatabase/SQLStatement.cpp:
(WebCore::SQLStatement::performCallback):
Adopt CallbackResult, migrating logic from JSSQLStatementErrorCallbackCustom
into the implementation, by way of the status enum.

* bindings/IDLTypes.h:
Add IDLVoid type.

* bindings/js/JSNodeFilterCustom.cpp: Removed.
* bindings/js/JSSQLStatementErrorCallbackCustom.cpp: Removed.
Remove now unneeded custom bindings.

* bindings/scripts/CodeGeneratorJS.pm:
(GenerateIndexedGetter):
(GenerateNamedGetter):
(GenerateImplementation):
(GenerateImplementationFunctionCall):
Update for new NativeToJSValue arguments.

(GenerateCallbackHeaderContent):
(GenerateCallbackImplementationContent):
Remove requirement of only void return types and update return type to use CallbackFunction.
Also adds necessary conversion of return value.

(GetBaseIDLType):
Add void IDL type mapping.

(IsValidContextForJSValueToNative):
Add operation as valid context, as that is what the callback return type's context is.

(NativeToJSValueUsingReferences):
(NativeToJSValueUsingPointers):
(NativeToJSValue):
Rework NativeToJSValueUsingReferences/NativeToJSValueUsingPointers to take a global object reference
accessor rather than a thisObject accessor, as a thisObject is not always available, and what the function
actually wants is the global object.

* bindings/scripts/IDLAttributes.json:
Add new RethrowException attribute to instruct the callback function to re-throw, rather than
just report, exceptions thrown in the callback and SkipCallbackInvokeCheck which instructs the
callback function to not check canInvokeCallback() before calling. These will both be needed to retain
the behavior of NodeFilter, and should be investigated further.

* bindings/scripts/test/JS/JSTestCallbackFunction.cpp:
* bindings/scripts/test/JS/JSTestCallbackFunction.h:
* bindings/scripts/test/JS/JSTestCallbackFunctionRethrow.cpp: Added.
* bindings/scripts/test/JS/JSTestCallbackFunctionRethrow.h: Added.
* bindings/scripts/test/JS/JSTestCallbackFunctionWithTypedefs.cpp:
* bindings/scripts/test/JS/JSTestCallbackFunctionWithTypedefs.h:
* bindings/scripts/test/JS/JSTestCallbackInterface.cpp:
* bindings/scripts/test/JS/JSTestCallbackInterface.h:
* bindings/scripts/test/JS/JSTestVoidCallbackFunction.cpp: Added.
* bindings/scripts/test/JS/JSTestVoidCallbackFunction.h: Added.
* bindings/scripts/test/TestCallbackFunction.idl:
* bindings/scripts/test/TestCallbackInterface.idl:
* bindings/scripts/test/TestVoidCallbackFunction.idl: Copied from Source/WebCore/bindings/scripts/test/TestCallbackFunction.idl.
Update test results and add some additional test cases for callback functions and callback interface functions that return
non-void and use the RethrowExceptions.

* dom/CallbackResult.h: Added.
(WebCore::CallbackResult<ReturnType>::CallbackResult):
(WebCore::CallbackResult<ReturnType>::type):
(WebCore::CallbackResult<void>::CallbackResult):
(WebCore::CallbackResult<void>::type):
New class to encapsulate the return value and status of a callback function. Modeled loosely on
ExceptionOr, but is simpler since it does not need to handle complex exception objects.

* dom/NativeNodeFilter.cpp:
* dom/NativeNodeFilter.h:
Adopt CallbackResult, matching other NodeFiltering code by using
unsigned short rather than short, remove unused functions, and convert
condition member to a Ref, allowing us to get rid of the branch acceptNode.

* dom/NodeFilter.h:
Adopt CallbackResult.

* dom/NodeFilter.idl:
Replace Custom extended attribute with SkipCallbackInvokeCheck and RethrowException.

* dom/NodeFilterCondition.cpp:
* dom/NodeFilterCondition.h:
Modernize to take a Node reference and match other filtering code
by returning an unsigned short.

* dom/Traversal.cpp:
* dom/Traversal.h:
Adopt CallbackResult and match other node filtering code by using unsigned short
rather than short.

* dom/NodeIterator.cpp:
* dom/NodeIterator.h:
* dom/NodeIterator.idl:
* dom/TreeWalker.cpp:
* dom/TreeWalker.h:
* dom/TreeWalker.idl:
Change functions that callout to javascript via the NodeFilter to
return ExceptionOr<Node>. Check the result of CallbackResult for a
thrown exception, and bail, returning Exception { ExistingExceptionError }
which acts as an indicator to the bindings that an exception was thrown.
(In actuality, the specific exception code does not matter. All that matters
is that an ExceptionOr<> is returned, which triggers, via overload, a path
in toJS() that calls propagateException(), which in turn, checks to see if
an exception is on the stack. But, having an explicit code here helps debugging).

Source/WebKit/mac:

* DOM/DOM.mm:
(-[DOMNodeFilter acceptNode:]):
Update for CallbackResult adoption in the base class.

* DOM/DOMNodeIterator.mm:
* DOM/DOMTreeWalker.mm:
Update to account for new WebCore implementation return types. We return nil
if there was an exception, since retains the existing behavior if a javascript
NodeFilter had been used (an exception would cause all nodes to be rejected,
thus returning nullptr).

* DOM/ObjCNodeFilterCondition.h:
* DOM/ObjCNodeFilterCondition.mm:
Update to match new interface of NodeFilterCondition.

Source/WebKit2:

* WebProcess/InjectedBundle/API/gtk/DOM/GObjectNodeFilterCondition.cpp:
* WebProcess/InjectedBundle/API/gtk/DOM/GObjectNodeFilterCondition.h:
Update to match new interface of NodeFilterCondition.

* WebProcess/InjectedBundle/API/gtk/DOM/WebKitDOMNodeIterator.cpp:
* WebProcess/InjectedBundle/API/gtk/DOM/WebKitDOMTreeWalker.cpp:
Update to account for new WebCore implementation return types.

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

70 files changed:
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/Modules/geolocation/PositionCallback.h
Source/WebCore/Modules/geolocation/PositionErrorCallback.h
Source/WebCore/Modules/notifications/NotificationPermissionCallback.h
Source/WebCore/Modules/webaudio/AudioBufferCallback.h
Source/WebCore/Modules/webdatabase/DatabaseCallback.h
Source/WebCore/Modules/webdatabase/SQLStatement.cpp
Source/WebCore/Modules/webdatabase/SQLStatement.h
Source/WebCore/Modules/webdatabase/SQLStatementCallback.h
Source/WebCore/Modules/webdatabase/SQLStatementErrorCallback.h
Source/WebCore/Modules/webdatabase/SQLStatementErrorCallback.idl
Source/WebCore/Modules/webdatabase/SQLTransaction.cpp
Source/WebCore/Modules/webdatabase/SQLTransactionCallback.h
Source/WebCore/Modules/webdatabase/SQLTransactionErrorCallback.h
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/bindings/IDLTypes.h
Source/WebCore/bindings/js/JSBindingsAllInOne.cpp
Source/WebCore/bindings/js/JSNodeFilterCustom.cpp [deleted file]
Source/WebCore/bindings/js/JSSQLStatementErrorCallbackCustom.cpp [deleted file]
Source/WebCore/bindings/scripts/CodeGeneratorJS.pm
Source/WebCore/bindings/scripts/IDLAttributes.json
Source/WebCore/bindings/scripts/test/JS/JSTestCallbackFunction.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestCallbackFunction.h
Source/WebCore/bindings/scripts/test/JS/JSTestCallbackFunctionRethrow.cpp [new file with mode: 0644]
Source/WebCore/bindings/scripts/test/JS/JSTestCallbackFunctionRethrow.h [new file with mode: 0644]
Source/WebCore/bindings/scripts/test/JS/JSTestCallbackFunctionWithTypedefs.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestCallbackFunctionWithTypedefs.h
Source/WebCore/bindings/scripts/test/JS/JSTestCallbackInterface.cpp
Source/WebCore/bindings/scripts/test/JS/JSTestCallbackInterface.h
Source/WebCore/bindings/scripts/test/JS/JSTestVoidCallbackFunction.cpp [new file with mode: 0644]
Source/WebCore/bindings/scripts/test/JS/JSTestVoidCallbackFunction.h [new file with mode: 0644]
Source/WebCore/bindings/scripts/test/TestCallbackFunction.idl
Source/WebCore/bindings/scripts/test/TestCallbackFunctionRethrow.idl [new file with mode: 0644]
Source/WebCore/bindings/scripts/test/TestCallbackInterface.idl
Source/WebCore/bindings/scripts/test/TestVoidCallbackFunction.idl [new file with mode: 0644]
Source/WebCore/css/MediaQueryListListener.h
Source/WebCore/dom/CallbackResult.h [new file with mode: 0644]
Source/WebCore/dom/NativeNodeFilter.cpp
Source/WebCore/dom/NativeNodeFilter.h
Source/WebCore/dom/NodeFilter.h
Source/WebCore/dom/NodeFilter.idl
Source/WebCore/dom/NodeFilterCondition.cpp
Source/WebCore/dom/NodeFilterCondition.h
Source/WebCore/dom/NodeIterator.cpp
Source/WebCore/dom/NodeIterator.h
Source/WebCore/dom/NodeIterator.idl
Source/WebCore/dom/RequestAnimationFrameCallback.h
Source/WebCore/dom/StringCallback.h
Source/WebCore/dom/Traversal.cpp
Source/WebCore/dom/Traversal.h
Source/WebCore/dom/TreeWalker.cpp
Source/WebCore/dom/TreeWalker.h
Source/WebCore/dom/TreeWalker.idl
Source/WebCore/fileapi/BlobCallback.h
Source/WebCore/html/VoidCallback.h
Source/WebCore/inspector/InspectorDatabaseAgent.cpp
Source/WebCore/page/IntersectionObserverCallback.h
Source/WebCore/page/PerformanceObserverCallback.h
Source/WebKit/mac/ChangeLog
Source/WebKit/mac/DOM/DOM.mm
Source/WebKit/mac/DOM/DOMNodeIterator.mm
Source/WebKit/mac/DOM/DOMTreeWalker.mm
Source/WebKit/mac/DOM/ObjCNodeFilterCondition.h
Source/WebKit/mac/DOM/ObjCNodeFilterCondition.mm
Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/InjectedBundle/API/gtk/DOM/GObjectNodeFilterCondition.cpp
Source/WebKit2/WebProcess/InjectedBundle/API/gtk/DOM/GObjectNodeFilterCondition.h
Source/WebKit2/WebProcess/InjectedBundle/API/gtk/DOM/WebKitDOMNodeIterator.cpp
Source/WebKit2/WebProcess/InjectedBundle/API/gtk/DOM/WebKitDOMTreeWalker.cpp

index 57049c6..f828482 100644 (file)
@@ -1201,7 +1201,6 @@ set(WebCore_SOURCES
     bindings/js/JSMutationCallback.cpp
     bindings/js/JSMutationObserverCustom.cpp
     bindings/js/JSNodeCustom.cpp
-    bindings/js/JSNodeFilterCustom.cpp
     bindings/js/JSNodeIteratorCustom.cpp
     bindings/js/JSNodeListCustom.cpp
     bindings/js/JSPerformanceEntryCustom.cpp
@@ -1209,7 +1208,6 @@ set(WebCore_SOURCES
     bindings/js/JSPopStateEventCustom.cpp
     bindings/js/JSReadableStreamPrivateConstructors.cpp
     bindings/js/JSReadableStreamSourceCustom.cpp
-    bindings/js/JSSQLStatementErrorCallbackCustom.cpp
     bindings/js/JSSVGPathSegCustom.cpp
     bindings/js/JSStorageCustom.cpp
     bindings/js/JSStyleSheetCustom.cpp
index 8400ea0..01e7154 100644 (file)
@@ -1,3 +1,150 @@
+2017-05-22  Sam Weinig  <sam@webkit.org>
+
+        [WebIDL] Support callbacks with arbitrary return types
+        https://bugs.webkit.org/show_bug.cgi?id=172407
+
+        Reviewed by Chris Dumez.
+
+        - Adds and adopts CallbackResult<> template class that encapsulates a return value
+          and status from a javascript callback.
+        - Updates NodeIterator/TreeWalker to explicitly propagate exceptions thrown from
+          a JSNodeFilter, rather than relying on the JSNodeFilter to catch them (seemingly
+          accidentally).
+
+        * CMakeLists.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * bindings/js/JSBindingsAllInOne.cpp:
+        Update file lists.
+
+        * Modules/geolocation/PositionCallback.h:
+        * Modules/geolocation/PositionErrorCallback.h:
+        * Modules/notifications/NotificationPermissionCallback.h:
+        * Modules/webaudio/AudioBufferCallback.h:
+        * Modules/webdatabase/DatabaseCallback.h:
+        * dom/RequestAnimationFrameCallback.h:
+        * dom/StringCallback.h:
+        * dom/Traversal.cpp:
+        * fileapi/BlobCallback.h:
+        * html/VoidCallback.h:
+        * page/IntersectionObserverCallback.h:
+        * page/PerformanceObserverCallback.h:
+        * css/MediaQueryListListener.h:
+        * Modules/webdatabase/SQLStatement.h:
+        * Modules/webdatabase/SQLStatementCallback.h:
+        * Modules/webdatabase/SQLStatementErrorCallback.h:
+        * Modules/webdatabase/SQLTransaction.cpp:
+        * Modules/webdatabase/SQLTransactionCallback.h:
+        * Modules/webdatabase/SQLTransactionErrorCallback.h:
+        * inspector/InspectorDatabaseAgent.cpp:
+        Adopt CallbackResult.
+
+        * Modules/webdatabase/SQLStatementErrorCallback.idl:
+        Remove Custom extended attribute annotation.
+
+        * Modules/webdatabase/SQLStatement.cpp:
+        (WebCore::SQLStatement::performCallback):
+        Adopt CallbackResult, migrating logic from JSSQLStatementErrorCallbackCustom
+        into the implementation, by way of the status enum.
+
+        * bindings/IDLTypes.h:
+        Add IDLVoid type.
+
+        * bindings/js/JSNodeFilterCustom.cpp: Removed.
+        * bindings/js/JSSQLStatementErrorCallbackCustom.cpp: Removed.
+        Remove now unneeded custom bindings.
+
+        * bindings/scripts/CodeGeneratorJS.pm:
+        (GenerateIndexedGetter):
+        (GenerateNamedGetter):
+        (GenerateImplementation):
+        (GenerateImplementationFunctionCall):
+        Update for new NativeToJSValue arguments.
+
+        (GenerateCallbackHeaderContent):
+        (GenerateCallbackImplementationContent):
+        Remove requirement of only void return types and update return type to use CallbackFunction.
+        Also adds necessary conversion of return value.
+
+        (GetBaseIDLType):
+        Add void IDL type mapping.
+
+        (IsValidContextForJSValueToNative):
+        Add operation as valid context, as that is what the callback return type's context is.
+
+        (NativeToJSValueUsingReferences):
+        (NativeToJSValueUsingPointers):
+        (NativeToJSValue):
+        Rework NativeToJSValueUsingReferences/NativeToJSValueUsingPointers to take a global object reference
+        accessor rather than a thisObject accessor, as a thisObject is not always available, and what the function
+        actually wants is the global object.
+
+        * bindings/scripts/IDLAttributes.json:
+        Add new RethrowException attribute to instruct the callback function to re-throw, rather than
+        just report, exceptions thrown in the callback and SkipCallbackInvokeCheck which instructs the
+        callback function to not check canInvokeCallback() before calling. These will both be needed to retain
+        the behavior of NodeFilter, and should be investigated further.
+
+        * bindings/scripts/test/JS/JSTestCallbackFunction.cpp:
+        * bindings/scripts/test/JS/JSTestCallbackFunction.h:
+        * bindings/scripts/test/JS/JSTestCallbackFunctionRethrow.cpp: Added.
+        * bindings/scripts/test/JS/JSTestCallbackFunctionRethrow.h: Added.
+        * bindings/scripts/test/JS/JSTestCallbackFunctionWithTypedefs.cpp:
+        * bindings/scripts/test/JS/JSTestCallbackFunctionWithTypedefs.h:
+        * bindings/scripts/test/JS/JSTestCallbackInterface.cpp:
+        * bindings/scripts/test/JS/JSTestCallbackInterface.h:
+        * bindings/scripts/test/JS/JSTestVoidCallbackFunction.cpp: Added.
+        * bindings/scripts/test/JS/JSTestVoidCallbackFunction.h: Added.
+        * bindings/scripts/test/TestCallbackFunction.idl:
+        * bindings/scripts/test/TestCallbackInterface.idl:
+        * bindings/scripts/test/TestVoidCallbackFunction.idl: Copied from Source/WebCore/bindings/scripts/test/TestCallbackFunction.idl.
+        Update test results and add some additional test cases for callback functions and callback interface functions that return
+        non-void and use the RethrowExceptions.
+
+        * dom/CallbackResult.h: Added.
+        (WebCore::CallbackResult<ReturnType>::CallbackResult):
+        (WebCore::CallbackResult<ReturnType>::type):
+        (WebCore::CallbackResult<void>::CallbackResult):
+        (WebCore::CallbackResult<void>::type):
+        New class to encapsulate the return value and status of a callback function. Modeled loosely on
+        ExceptionOr, but is simpler since it does not need to handle complex exception objects.
+
+        * dom/NativeNodeFilter.cpp:
+        * dom/NativeNodeFilter.h:
+        Adopt CallbackResult, matching other NodeFiltering code by using
+        unsigned short rather than short, remove unused functions, and convert 
+        condition member to a Ref, allowing us to get rid of the branch acceptNode.
+
+        * dom/NodeFilter.h:
+        Adopt CallbackResult.
+
+        * dom/NodeFilter.idl:
+        Replace Custom extended attribute with SkipCallbackInvokeCheck and RethrowException.
+
+        * dom/NodeFilterCondition.cpp:
+        * dom/NodeFilterCondition.h:
+        Modernize to take a Node reference and match other filtering code
+        by returning an unsigned short.
+
+        * dom/Traversal.cpp:
+        * dom/Traversal.h:
+        Adopt CallbackResult and match other node filtering code by using unsigned short 
+        rather than short.
+
+        * dom/NodeIterator.cpp:
+        * dom/NodeIterator.h:
+        * dom/NodeIterator.idl:
+        * dom/TreeWalker.cpp:
+        * dom/TreeWalker.h:
+        * dom/TreeWalker.idl:
+        Change functions that callout to javascript via the NodeFilter to 
+        return ExceptionOr<Node>. Check the result of CallbackResult for a
+        thrown exception, and bail, returning Exception { ExistingExceptionError }
+        which acts as an indicator to the bindings that an exception was thrown.
+        (In actuality, the specific exception code does not matter. All that matters
+        is that an ExceptionOr<> is returned, which triggers, via overload, a path
+        in toJS() that calls propagateException(), which in turn, checks to see if
+        an exception is on the stack. But, having an explicit code here helps debugging).
+
 2017-05-22  Simon Fraser  <simon.fraser@apple.com>
 
         Support transform-box to switch sizing box in SVG
index 32ca1bc..b6e8870 100644 (file)
 
 #pragma once
 
+#include "CallbackResult.h"
 #include <wtf/RefCounted.h>
 
 namespace WebCore {
 
-    class Geoposition;
+class Geoposition;
 
-    class PositionCallback : public RefCounted<PositionCallback> {
-    public:
-        virtual ~PositionCallback() { }
-        virtual bool handleEvent(Geoposition*) = 0;
-    };
+class PositionCallback : public RefCounted<PositionCallback> {
+public:
+    virtual ~PositionCallback() { }
+    virtual CallbackResult<void> handleEvent(Geoposition*) = 0;
+};
 
 } // namespace WebCore
index 4eab9a1..3fda16a 100644 (file)
 
 #pragma once
 
+#include "CallbackResult.h"
 #include <wtf/RefCounted.h>
 
 namespace WebCore {
 
-    class PositionError;
+class PositionError;
 
-    class PositionErrorCallback : public RefCounted<PositionErrorCallback> {
-    public:
-        virtual ~PositionErrorCallback() { }
-        virtual bool handleEvent(PositionError&) = 0;
-    };
+class PositionErrorCallback : public RefCounted<PositionErrorCallback> {
+public:
+    virtual ~PositionErrorCallback() { }
+    virtual CallbackResult<void> handleEvent(PositionError&) = 0;
+};
 
 } // namespace WebCore
index 7250a3a..31d54c1 100644 (file)
@@ -27,6 +27,7 @@
 
 #if ENABLE(NOTIFICATIONS)
 
+#include "CallbackResult.h"
 #include "Notification.h"
 #include <wtf/Forward.h>
 #include <wtf/RefCounted.h>
@@ -36,7 +37,7 @@ namespace WebCore {
 class NotificationPermissionCallback : public RefCounted<NotificationPermissionCallback> {
 public:
     virtual ~NotificationPermissionCallback() { }
-    virtual bool handleEvent(Notification::Permission) = 0;
+    virtual CallbackResult<void> handleEvent(Notification::Permission) = 0;
 };
 
 } // namespace WebCore
index 27cc6ac..4f91fb9 100644 (file)
@@ -26,6 +26,7 @@
 
 #if ENABLE(WEB_AUDIO)
 
+#include "CallbackResult.h"
 #include <wtf/RefCounted.h>
 
 namespace WebCore {
@@ -35,7 +36,7 @@ class AudioBuffer;
 class AudioBufferCallback : public RefCounted<AudioBufferCallback> {
 public:
     virtual ~AudioBufferCallback() { }
-    virtual bool handleEvent(AudioBuffer*) = 0;
+    virtual CallbackResult<void> handleEvent(AudioBuffer*) = 0;
 };
 
 } // namespace WebCore
index ee4fd28..18ab418 100644 (file)
@@ -30,6 +30,7 @@
 
 #pragma once
 
+#include "CallbackResult.h"
 #include <wtf/ThreadSafeRefCounted.h>
 
 namespace WebCore {
@@ -39,7 +40,7 @@ class Database;
 class DatabaseCallback : public ThreadSafeRefCounted<DatabaseCallback> {
 public:
     virtual ~DatabaseCallback() { }
-    virtual bool handleEvent(Database&) = 0;
+    virtual CallbackResult<void> handleEvent(Database&) = 0;
 };
 
 } // namespace WebCore
index 8438130..e243f8e 100644 (file)
@@ -199,27 +199,39 @@ bool SQLStatement::execute(Database& db)
     return true;
 }
 
-bool SQLStatement::performCallback(SQLTransaction* transaction)
+bool SQLStatement::performCallback(SQLTransaction& transaction)
 {
-    ASSERT(transaction);
-
-    bool callbackError = false;
-
-    RefPtr<SQLStatementCallback> callback = m_statementCallbackWrapper.unwrap();
-    RefPtr<SQLStatementErrorCallback> errorCallback = m_statementErrorCallbackWrapper.unwrap();
-    RefPtr<SQLError> error = sqlError();
-
     // Call the appropriate statement callback and track if it resulted in an error,
     // because then we need to jump to the transaction error callback.
-    if (error) {
-        if (errorCallback)
-            callbackError = errorCallback->handleEvent(*transaction, *error);
-    } else if (callback) {
-        RefPtr<SQLResultSet> resultSet = sqlResultSet();
-        callbackError = !callback->handleEvent(*transaction, *resultSet);
+
+    if (m_error) {
+        if (auto errorCallback = m_statementErrorCallbackWrapper.unwrap()) {
+            auto result = errorCallback->handleEvent(transaction, *m_error);
+
+            // The spec says:
+            // "If the error callback returns false, then move on to the next statement..."
+            // "Otherwise, the error callback did not return false, or there was no error callback"
+            // Therefore an exception and returning true are the same thing - so, return true on an exception
+
+            switch (result.type()) {
+            case CallbackResultType::Success:
+                return result.releaseReturnValue();
+            case CallbackResultType::ExceptionThrown:
+            case CallbackResultType::UnableToExecute:
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    if (auto callback = m_statementCallbackWrapper.unwrap()) {
+        ASSERT(m_resultSet);
+
+        auto result = callback->handleEvent(transaction, *m_resultSet);
+        return result.type() == CallbackResultType::ExceptionThrown;
     }
 
-    return callbackError;
+    return false;
 }
 
 void SQLStatement::setDatabaseDeletedError()
index 239ea93..85f1b63 100644 (file)
@@ -53,7 +53,7 @@ public:
 
     bool hasStatementCallback() const { return m_statementCallbackWrapper.hasCallback(); }
     bool hasStatementErrorCallback() const { return m_statementErrorCallbackWrapper.hasCallback(); }
-    bool performCallback(SQLTransaction*);
+    bool performCallback(SQLTransaction&);
 
     void setDatabaseDeletedError();
     void setVersionMismatchedError();
index 41568cf..18733ba 100644 (file)
@@ -28,6 +28,7 @@
 
 #pragma once
 
+#include "CallbackResult.h"
 #include <wtf/ThreadSafeRefCounted.h>
 
 namespace WebCore {
@@ -38,7 +39,7 @@ class SQLResultSet;
 class SQLStatementCallback : public ThreadSafeRefCounted<SQLStatementCallback> {
 public:
     virtual ~SQLStatementCallback() { }
-    virtual bool handleEvent(SQLTransaction&, SQLResultSet&) = 0;
+    virtual CallbackResult<void> handleEvent(SQLTransaction&, SQLResultSet&) = 0;
 };
 
 } // namespace WebCore
index 013fba2..fc9bb72 100644 (file)
@@ -28,6 +28,7 @@
 
 #pragma once
 
+#include "CallbackResult.h"
 #include <wtf/ThreadSafeRefCounted.h>
 
 namespace WebCore {
@@ -38,7 +39,7 @@ class SQLError;
 class SQLStatementErrorCallback : public ThreadSafeRefCounted<SQLStatementErrorCallback> {
 public:
     virtual ~SQLStatementErrorCallback() { }
-    virtual bool handleEvent(SQLTransaction&, SQLError&) = 0;
+    virtual CallbackResult<bool> handleEvent(SQLTransaction&, SQLError&) = 0;
 };
 
 } // namespace WebCore
index c684823..c3fce7c 100644 (file)
@@ -26,6 +26,4 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-[
-    Custom
-] callback SQLStatementErrorCallback = boolean (SQLTransaction transaction, SQLError error);
+callback SQLStatementErrorCallback = boolean (SQLTransaction transaction, SQLError error);
index 7cb233f..75c700e 100644 (file)
@@ -371,7 +371,10 @@ void SQLTransaction::deliverTransactionCallback()
     RefPtr<SQLTransactionCallback> callback = m_callbackWrapper.unwrap();
     if (callback) {
         m_executeSqlAllowed = true;
-        shouldDeliverErrorCallback = !callback->handleEvent(*this);
+
+        auto result = callback->handleEvent(*this);
+        shouldDeliverErrorCallback = result.type() == CallbackResultType::ExceptionThrown;
+
         m_executeSqlAllowed = false;
     }
 
@@ -407,7 +410,7 @@ void SQLTransaction::deliverStatementCallback()
     // Spec 4.3.2.6.6 and 4.3.2.6.3: If the statement callback went wrong, jump to the transaction error callback
     // Otherwise, continue to loop through the statement queue
     m_executeSqlAllowed = true;
-    bool result = m_currentStatement->performCallback(this);
+    bool result = m_currentStatement->performCallback(*this);
     m_executeSqlAllowed = false;
 
     if (result) {
index f70287c..0cf8872 100644 (file)
@@ -28,6 +28,7 @@
 
 #pragma once
 
+#include "CallbackResult.h"
 #include <wtf/ThreadSafeRefCounted.h>
 
 namespace WebCore {
@@ -37,7 +38,7 @@ class SQLTransaction;
 class SQLTransactionCallback : public ThreadSafeRefCounted<SQLTransactionCallback> {
 public:
     virtual ~SQLTransactionCallback() { }
-    virtual bool handleEvent(SQLTransaction&) = 0;
+    virtual CallbackResult<void> handleEvent(SQLTransaction&) = 0;
 };
 
 } // namespace WebCore
index 7ee8274..c692437 100644 (file)
@@ -28,6 +28,7 @@
 
 #pragma once
 
+#include "CallbackResult.h"
 #include <wtf/ThreadSafeRefCounted.h>
 
 namespace WebCore {
@@ -37,7 +38,7 @@ class SQLError;
 class SQLTransactionErrorCallback : public ThreadSafeRefCounted<SQLTransactionErrorCallback> {
 public:
     virtual ~SQLTransactionErrorCallback() { }
-    virtual bool handleEvent(SQLError&) = 0;
+    virtual CallbackResult<void> handleEvent(SQLError&) = 0;
 };
 
 } // namespace WebCore
index bc25b68..1eef36d 100644 (file)
                51E3F9D60DA05E1D00250911 /* JSStorage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51E3F9D40DA05E1D00250911 /* JSStorage.cpp */; };
                51E4143416A6596300C633C7 /* ResourceHandleTypes.h in Headers */ = {isa = PBXBuildFile; fileRef = 51E4143216A6595100C633C7 /* ResourceHandleTypes.h */; settings = {ATTRIBUTES = (Private, ); }; };
                51E6821016387302003BBF3C /* LoaderStrategy.h in Headers */ = {isa = PBXBuildFile; fileRef = 51E6820F16387302003BBF3C /* LoaderStrategy.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               51EC92650CE90DD400F90308 /* JSSQLStatementErrorCallbackCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51EC925D0CE90DD400F90308 /* JSSQLStatementErrorCallbackCustom.cpp */; };
                51EE7B381AA50B0500F92B21 /* ResourceLoadInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 51EE7B371AA50B0500F92B21 /* ResourceLoadInfo.h */; settings = {ATTRIBUTES = (Private, ); }; };
                51EE7B3A1AA5123100F92B21 /* ResourceLoadInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51EE7B391AA5123100F92B21 /* ResourceLoadInfo.cpp */; };
                51EEAA731BEFFAB100218008 /* IndexValueEntry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 51EEAA711BEFFA7900218008 /* IndexValueEntry.cpp */; };
                7BE7427381FA906FBB4F0F2C /* JSSVGGraphicsElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 950C4C02BED8936F818E2F99 /* JSSVGGraphicsElement.h */; };
                7C1843FD1C8B7283002EB973 /* Autofill.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C1843FB1C8B7283002EB973 /* Autofill.cpp */; };
                7C1843FE1C8B7283002EB973 /* Autofill.h in Headers */ = {isa = PBXBuildFile; fileRef = 7C1843FC1C8B7283002EB973 /* Autofill.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               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 */; };
                7C2BDD3D17C7F98C0038FF15 /* JSDOMGlobalObjectTask.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C2BDD3B17C7F98B0038FF15 /* JSDOMGlobalObjectTask.cpp */; };
                83D35AF21C718D9000F70D5A /* JSXMLHttpRequestEventTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 83D35AF01C718D8400F70D5A /* JSXMLHttpRequestEventTarget.h */; };
                83E359A21BB1031D002CEB98 /* JSHTMLTimeElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 83E359A01BB1031D002CEB98 /* JSHTMLTimeElement.h */; };
                83E359A31BB1031D002CEB98 /* JSHTMLTimeElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83E359A11BB1031D002CEB98 /* JSHTMLTimeElement.cpp */; };
-               83F1206B1B8C104700D75F63 /* JSNodeFilterCustom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 83F1206A1B8C103600D75F63 /* JSNodeFilterCustom.cpp */; };
                83FE7CA71DA9F1A70037237C /* UIEventInit.h in Headers */ = {isa = PBXBuildFile; fileRef = 83FE7CA41DA9F1660037237C /* UIEventInit.h */; settings = {ATTRIBUTES = (Private, ); }; };
                83FE7CA81DA9F1B60037237C /* EventModifierInit.h in Headers */ = {isa = PBXBuildFile; fileRef = 83FE7CA31DA9F1650037237C /* EventModifierInit.h */; settings = {ATTRIBUTES = (Private, ); }; };
                83FE90271E307C30003E9199 /* PerformanceMonitor.h in Headers */ = {isa = PBXBuildFile; fileRef = 83FE90261E307C1C003E9199 /* PerformanceMonitor.h */; };
                51E4143216A6595100C633C7 /* ResourceHandleTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResourceHandleTypes.h; sourceTree = "<group>"; };
                51E6820F16387302003BBF3C /* LoaderStrategy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoaderStrategy.h; sourceTree = "<group>"; };
                51EAC5B018163F4E004F1BA4 /* IDBRecordIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IDBRecordIdentifier.h; sourceTree = "<group>"; };
-               51EC925D0CE90DD400F90308 /* JSSQLStatementErrorCallbackCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSSQLStatementErrorCallbackCustom.cpp; sourceTree = "<group>"; };
                51EE7B371AA50B0500F92B21 /* ResourceLoadInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ResourceLoadInfo.h; sourceTree = "<group>"; };
                51EE7B391AA5123100F92B21 /* ResourceLoadInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ResourceLoadInfo.cpp; sourceTree = "<group>"; };
                51EEAA711BEFFA7900218008 /* IndexValueEntry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = IndexValueEntry.cpp; sourceTree = "<group>"; };
                7C0CEF301E4A58F1008DEB80 /* JSDOMConstructorWithDocument.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDOMConstructorWithDocument.cpp; sourceTree = "<group>"; };
                7C1843FB1C8B7283002EB973 /* Autofill.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Autofill.cpp; sourceTree = "<group>"; };
                7C1843FC1C8B7283002EB973 /* Autofill.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Autofill.h; sourceTree = "<group>"; };
+               7C1E8CFF1ED0C2BE00B1D983 /* BeforeUnloadEvent.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = BeforeUnloadEvent.idl; sourceTree = "<group>"; };
+               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>"; };
                7C2BDD3B17C7F98B0038FF15 /* JSDOMGlobalObjectTask.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDOMGlobalObjectTask.cpp; sourceTree = "<group>"; };
                83E959E11B8BC22B004D9385 /* NativeNodeFilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeNodeFilter.h; sourceTree = "<group>"; };
                83E9B3001DA5A51E00FFE8F6 /* JSScrollToOptions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSScrollToOptions.cpp; sourceTree = "<group>"; };
                83E9B3011DA5A51E00FFE8F6 /* JSScrollToOptions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSScrollToOptions.h; sourceTree = "<group>"; };
-               83F1206A1B8C103600D75F63 /* JSNodeFilterCustom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSNodeFilterCustom.cpp; sourceTree = "<group>"; };
                83F570AD1C53268E007FD6CB /* JSXMLDocument.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSXMLDocument.h; sourceTree = "<group>"; };
                83F570AE1C53268E007FD6CB /* JSXMLDocument.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSXMLDocument.cpp; sourceTree = "<group>"; };
                83FE7CA31DA9F1650037237C /* EventModifierInit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EventModifierInit.h; sourceTree = "<group>"; };
                                C6F0917E143A2BB900685849 /* JSMutationObserverCustom.cpp */,
                                BCD9C2600C17AA67005C90A2 /* JSNodeCustom.cpp */,
                                BC9439C2116CF4940048C750 /* JSNodeCustom.h */,
-                               83F1206A1B8C103600D75F63 /* JSNodeFilterCustom.cpp */,
                                A85F22081430377D007CC884 /* JSPopStateEventCustom.cpp */,
                                418C395D1C8F0AAB0051C8A3 /* JSReadableStreamSourceCustom.cpp */,
                                51D0C5150DAA90B7003B3831 /* JSStorageCustom.cpp */,
                                935F45410F7C3B5F00D7C1FB /* JSLazyEventListener.h */,
                                C6F420A016B7164E0052A9F2 /* JSMutationCallback.cpp */,
                                C6F420A116B7164E0052A9F2 /* JSMutationCallback.h */,
-                               51EC925D0CE90DD400F90308 /* JSSQLStatementErrorCallbackCustom.cpp */,
                                BCA378BA0D15F64200B793D6 /* ScheduledAction.cpp */,
                                BCA378BB0D15F64200B793D6 /* ScheduledAction.h */,
                        );
                                AB23A32609BBA7D00067CC53 /* BeforeTextInsertedEvent.h */,
                                85031B260A44EFC700F992E0 /* BeforeUnloadEvent.cpp */,
                                85031B270A44EFC700F992E0 /* BeforeUnloadEvent.h */,
+                               7C1E8CFF1ED0C2BE00B1D983 /* BeforeUnloadEvent.idl */,
+                               7C1E8D001ED0C2BE00B1D983 /* CallbackResult.h */,
                                6550B693099DF0270090D781 /* CDATASection.cpp */,
                                6550B694099DF0270090D781 /* CDATASection.h */,
                                85089CC90A98C2AB00A275AA /* CDATASection.idl */,
                                9746AF2A14F4DDE6003E7A70 /* Geoposition.h in Headers */,
                                086BBD0F136039C2008B15D8 /* Glyph.h in Headers */,
                                B2C3DA6C0D006CD600EF6F26 /* GlyphBuffer.h in Headers */,
+                               7C1E8D011ED0C2DA00B1D983 /* CallbackResult.h in Headers */,
                                C5D4AA7A116BAFB60069CA93 /* GlyphMetricsMap.h in Headers */,
                                0873B86B136064EA00A522C2 /* GlyphPage.h in Headers */,
                                311518FC1E78C15F00EC514A /* GPUBasedCanvasRenderingContext.h in Headers */,
                                BCD9C2640C17AA67005C90A2 /* JSNodeCustom.cpp in Sources */,
                                E3150EA61DA7219000194012 /* JSNodeDOMJIT.cpp in Sources */,
                                14115B7209F84CD600CA4FC1 /* JSNodeFilter.cpp in Sources */,
-                               83F1206B1B8C104700D75F63 /* JSNodeFilterCustom.cpp in Sources */,
                                1A750D8D0A90E521000FF215 /* JSNodeIterator.cpp in Sources */,
                                1A750DD40A90E729000FF215 /* JSNodeIteratorCustom.cpp in Sources */,
                                BCD9C2C20C17B69E005C90A2 /* JSNodeList.cpp in Sources */,
                                1AFE11990CBFFCC4003017FA /* JSSQLResultSetRowList.cpp in Sources */,
                                B59DD6A611902A62007E9684 /* JSSQLStatementCallback.cpp in Sources */,
                                B59DD6AA11902A71007E9684 /* JSSQLStatementErrorCallback.cpp in Sources */,
-                               51EC92650CE90DD400F90308 /* JSSQLStatementErrorCallbackCustom.cpp in Sources */,
                                514C76380CE9225E007EF3CD /* JSSQLTransaction.cpp in Sources */,
                                B59DD69E11902A42007E9684 /* JSSQLTransactionCallback.cpp in Sources */,
                                B59DD6A211902A52007E9684 /* JSSQLTransactionErrorCallback.cpp in Sources */,
index 8d75766..68853d3 100644 (file)
@@ -79,6 +79,8 @@ struct IDLAny : IDLType<JSC::Strong<JSC::Unknown>> {
     template<typename U> static inline U&& extractValueFromNullable(U&& value) { return std::forward<U>(value); }
 };
 
+struct IDLVoid : IDLType<void> { };
+
 struct IDLBoolean : IDLType<bool> { };
 
 template<typename NumericType> struct IDLNumber : IDLType<NumericType> { };
index e3bc775..8a606de 100644 (file)
@@ -42,7 +42,6 @@
 #include "JSCommandLineAPIHostCustom.cpp"
 #include "JSCryptoCustom.cpp"
 #include "JSCustomEventCustom.cpp"
-#include "JSSQLStatementErrorCallbackCustom.cpp"
 #include "JSCustomXPathNSResolver.cpp"
 #include "JSDOMBindingSecurity.cpp"
 #include "JSDOMBuiltinConstructorBase.cpp"
@@ -91,7 +90,6 @@
 #include "JSMutationCallback.cpp"
 #include "JSMutationObserverCustom.cpp"
 #include "JSNodeCustom.cpp"
-#include "JSNodeFilterCustom.cpp"
 #include "JSNodeIteratorCustom.cpp"
 #include "JSNodeListCustom.cpp"
 #include "JSPluginElementFunctions.cpp"
diff --git a/Source/WebCore/bindings/js/JSNodeFilterCustom.cpp b/Source/WebCore/bindings/js/JSNodeFilterCustom.cpp
deleted file mode 100644 (file)
index 141f2b7..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2015-2016 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
- * THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "JSNodeFilter.h"
-
-#include "JSCallbackData.h"
-#include "JSDOMConvert.h"
-#include "JSNode.h"
-#include "NodeFilter.h"
-
-namespace WebCore {
-
-using namespace JSC;
-
-// FIXME: The bindings generator is currently not able to generate
-// callback function calls if they return something other than a
-// boolean.
-unsigned short JSNodeFilter::acceptNode(Node& node)
-{
-    Ref<JSNodeFilter> protectedThis(*this);
-
-    VM& vm = m_data->globalObject()->vm();
-    JSLockHolder lock(vm);
-    auto scope = DECLARE_THROW_SCOPE(vm);
-
-    ExecState* state = m_data->globalObject()->globalExec();
-    MarkedArgumentBuffer args;
-    args.append(toJS(state, m_data->globalObject(), node));
-    RETURN_IF_EXCEPTION(scope, NodeFilter::FILTER_REJECT);
-
-    NakedPtr<JSC::Exception> returnedException;
-    JSValue value = m_data->invokeCallback(args, JSCallbackData::CallbackType::FunctionOrObject, Identifier::fromString(state, "acceptNode"), returnedException);
-    ASSERT(!scope.exception() || returnedException);
-    if (returnedException) {
-        // Rethrow exception.
-        throwException(state, scope, returnedException);
-
-        return NodeFilter::FILTER_REJECT;
-    }
-
-    auto result = convert<IDLUnsignedShort>(*state, value);
-    RETURN_IF_EXCEPTION(scope, NodeFilter::FILTER_REJECT);
-
-    return result;
-}
-
-} // namespace WebCore
diff --git a/Source/WebCore/bindings/js/JSSQLStatementErrorCallbackCustom.cpp b/Source/WebCore/bindings/js/JSSQLStatementErrorCallbackCustom.cpp
deleted file mode 100644 (file)
index 4c8517f..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2007 Apple Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include "config.h"
-#include "JSSQLStatementErrorCallback.h"
-
-#include "JSDOMConvertInterface.h"
-#include "JSDOMExceptionHandling.h"
-#include "JSSQLError.h"
-#include "JSSQLTransaction.h"
-#include "ScriptExecutionContext.h"
-#include <runtime/Exception.h>
-#include <runtime/JSLock.h>
-#include <wtf/Ref.h>
-
-namespace WebCore {
-
-using namespace JSC;
-
-bool JSSQLStatementErrorCallback::handleEvent(SQLTransaction& transaction, SQLError& error)
-{
-    if (!m_data || !m_data->globalObject() || !canInvokeCallback())
-        return true;
-
-    Ref<JSSQLStatementErrorCallback> protectedThis(*this);
-
-    JSC::JSLockHolder lock(m_data->globalObject()->vm());
-
-    ExecState* exec = m_data->globalObject()->globalExec();
-    MarkedArgumentBuffer args;
-    args.append(toJS<IDLInterface<SQLTransaction>>(*exec, *m_data->globalObject(), transaction));
-    args.append(toJS<IDLInterface<SQLError>>(*exec, *m_data->globalObject(), error));
-
-    NakedPtr<JSC::Exception> returnedException;
-    JSValue result = m_data->invokeCallback(args, JSCallbackData::CallbackType::Function, Identifier(), returnedException);
-    if (returnedException) {
-        reportException(exec, returnedException);
-
-        // The spec says:
-        // "If the error callback returns false, then move on to the next statement..."
-        // "Otherwise, the error callback did not return false, or there was no error callback"
-        // Therefore an exception and returning true are the same thing - so, return true on an exception
-        return true;
-    }
-    return result.toBoolean(exec);
-}
-
-}
index 9125a0e..3fc6fc1 100644 (file)
@@ -416,7 +416,7 @@ sub GenerateIndexedGetter
     my $attributeString = ((@attributes > 0) ? join(" | ", @attributes) : "0");
 
     my $indexedGetterFunctionName = $indexedGetterFunction->name || "item";
-    my $nativeToJSConversion = NativeToJSValueUsingPointers($indexedGetterFunction, $interface, "thisObject->wrapped().${indexedGetterFunctionName}(index)", "thisObject");
+    my $nativeToJSConversion = NativeToJSValueUsingPointers($indexedGetterFunction, $interface, "thisObject->wrapped().${indexedGetterFunctionName}(index)", "*thisObject->globalObject()");
 
     push(@output, "        slot.setValue(thisObject, ${attributeString}, ${nativeToJSConversion});\n");
     push(@output, "        return true;\n");
@@ -459,7 +459,7 @@ sub GenerateNamedGetter
         my $IDLType = GetIDLType($interface, $namedGetterFunction->type);
         push(@output, "        if (!${IDLType}::isNullValue(${itemVariable})) {\n");
 
-        my $nativeToJSConversion = NativeToJSValueUsingPointers($namedGetterFunction, $interface, $itemVariable, "thisObject", 1);
+        my $nativeToJSConversion = NativeToJSValueUsingPointers($namedGetterFunction, $interface, $itemVariable, "*thisObject->globalObject()", 1);
         push(@output, "            slot.setValue(thisObject, ${attributeString}, ${nativeToJSConversion});\n");
     }
     
@@ -3825,7 +3825,7 @@ sub GenerateImplementation
                 }
 
                 unshift(@arguments, @callWithArgs);
-                my $jsType = NativeToJSValueUsingReferences($attribute, $interface, "${functionName}(" . join(", ", @arguments) . ")", "thisObject");
+                my $jsType = NativeToJSValueUsingReferences($attribute, $interface, "${functionName}(" . join(", ", @arguments) . ")", "*thisObject.globalObject()");
                 push(@implContent, "    auto& impl = thisObject.wrapped();\n") unless $attribute->isStatic or $attribute->isMapLike;
                 push(@implContent, "    JSValue result = $jsType;\n");
 
@@ -4270,7 +4270,7 @@ END
                 }
                 my $functionString = "$implFunctionName(" . join(", ", @arguments) . ")";
                 $functionString = "propagateException(*state, throwScope, $functionString)" if NeedsExplicitPropagateExceptionCall($function);
-                push(@implContent, "    return JSValue::encode(" . NativeToJSValueUsingPointers($function, $interface, $functionString, "castedThis") . ");\n");
+                push(@implContent, "    return JSValue::encode(" . NativeToJSValueUsingPointers($function, $interface, $functionString, "*castedThis->globalObject()") . ");\n");
                 push(@implContent, "}\n\n");
             }
 
@@ -5169,8 +5169,7 @@ sub GenerateCallbackHeaderContent
                 push(@arguments, "typename ${IDLType}::ParameterType " . $argument->name);
             }
 
-            # FIXME: Add support for non-void return types (the bool actually is returning exception state), for non-custom functions.
-            my $nativeReturnType = $function->extendedAttributes->{Custom} ? "typename " . GetIDLType($interfaceOrCallback, $function->type) . "::ImplementationType" : "bool";
+            my $nativeReturnType = "CallbackResult<typename " . GetIDLType($interfaceOrCallback, $function->type) . "::ImplementationType>";
             
             # FIXME: Change the default name (used for callback functions) to something other than handleEvent. It makes little sense.
             my $functionName = $function->name ? $function->name : "handleEvent";
@@ -5288,16 +5287,13 @@ sub GenerateCallbackImplementationContent
         foreach my $function (@{$functions}) {
             next if $function->extendedAttributes->{Custom};
         
-            assert("Unsupport return type: " . $function->type->name . ".") unless $function->type->name eq "void";
-
             AddToIncludesForIDLType($function->type, $includesRef);
+
+            my $nativeReturnType = "CallbackResult<typename " . GetIDLType($interfaceOrCallback, $function->type) . "::ImplementationType>";
             
             # FIXME: Change the default name (used for callback functions) to something other than handleEvent. It makes little sense.
             my $functionName = $function->name ? $function->name : "handleEvent";
 
-            # FIXME: Add support for non-void return types (the bool actually is returning exception state), for non-custom functions.
-            my $nativeReturnType = "bool";
-
             my @args = ();
             foreach my $argument (@{$function->arguments}) {
                 AddToIncludesForIDLType($argument->type, $includesRef, 1);
@@ -5308,32 +5304,68 @@ sub GenerateCallbackImplementationContent
             
             push(@$contentRef, "${nativeReturnType} ${className}::${functionName}(" . join(", ", @args) . ")\n");
             push(@$contentRef, "{\n");
-            push(@$contentRef, "    if (!canInvokeCallback())\n");
-            push(@$contentRef, "        return true;\n\n");
+
+            # FIXME: This is needed for NodeFilter, which works even for disconnected iframes. We should investigate
+            # if that behavior is needed for other callbacks.
+            if (!$function->extendedAttributes->{SkipCallbackInvokeCheck}) {
+                push(@$contentRef, "    if (!canInvokeCallback())\n");
+                push(@$contentRef, "        return CallbackResultType::UnableToExecute;\n\n");
+            }
+
             push(@$contentRef, "    Ref<$className> protectedThis(*this);\n\n");
-            push(@$contentRef, "    JSLockHolder lock(m_data->globalObject()->vm());\n\n");
-            push(@$contentRef, "    ExecState* state = m_data->globalObject()->globalExec();\n");
+            push(@$contentRef, "    auto& globalObject = *m_data->globalObject();\n");
+            push(@$contentRef, "    auto& vm = globalObject.vm();\n\n");
+            push(@$contentRef, "    JSLockHolder lock(vm);\n");
+
+            push(@$contentRef, "    auto& state = *globalObject.globalExec();\n");
             push(@$contentRef, "    MarkedArgumentBuffer args;\n");
 
             foreach my $argument (@{$function->arguments}) {
-                push(@$contentRef, "    args.append(" . NativeToJSValueUsingPointers($argument, $interfaceOrCallback, $argument->name, "m_data") . ");\n");
+                push(@$contentRef, "    args.append(" . NativeToJSValueUsingReferences($argument, $interfaceOrCallback, $argument->name, "globalObject") . ");\n");
             }
 
             push(@$contentRef, "\n    NakedPtr<JSC::Exception> returnedException;\n");
 
+            my $callbackInvocation;
             if (ref($interfaceOrCallback) eq "IDLCallbackFunction") {
-                push(@$contentRef, "    m_data->invokeCallback(args, JSCallbackData::CallbackType::Function, Identifier(), returnedException);\n");
+                $callbackInvocation = "m_data->invokeCallback(args, JSCallbackData::CallbackType::Function, Identifier(), returnedException)";
             } else {
                 my $callbackType = $numFunctions > 1 ? "Object" : "FunctionOrObject";
-                push(@$contentRef, "    m_data->invokeCallback(args, JSCallbackData::CallbackType::${callbackType}, Identifier::fromString(state, \"${functionName}\"), returnedException);\n");
+                $callbackInvocation = "m_data->invokeCallback(args, JSCallbackData::CallbackType::${callbackType}, Identifier::fromString(&vm, \"${functionName}\"), returnedException)";
+            }
+
+            if ($function->type->name eq "void") {
+                push(@$contentRef, "    ${callbackInvocation};\n");
+            } else {
+                push(@$contentRef, "    auto jsResult = ${callbackInvocation};\n");
             }
 
-            # FIXME: We currently just report the exception. We should probably add an extended attribute to indicate when
-            # we want the exception to be rethrown instead.
             $includesRef->{"JSDOMExceptionHandling.h"} = 1;
-            push(@$contentRef, "    if (returnedException)\n");
-            push(@$contentRef, "        reportException(state, returnedException);\n");
-            push(@$contentRef, "    return !returnedException;\n");
+            push(@$contentRef, "    if (returnedException) {\n");
+            if ($function->extendedAttributes->{RethrowException}) {
+                push(@$contentRef, "        auto throwScope = DECLARE_THROW_SCOPE(vm);\n");
+                push(@$contentRef, "        throwException(&state, throwScope, returnedException);\n");
+            } else {
+                push(@$contentRef, "        reportException(&state, returnedException);\n");
+            }
+            push(@$contentRef, "        return CallbackResultType::ExceptionThrown;\n");
+            push(@$contentRef, "     }\n\n");
+
+            if ($function->type->name eq "void") {
+                push(@$contentRef, "    return { };\n");
+            } else {
+                my ($nativeValue, $mayThrowException) = JSValueToNative($interfaceOrCallback, $function, "jsResult", "", "&state", "state");
+            
+                if ($mayThrowException) {
+                    push(@$contentRef, "    auto throwScope = DECLARE_THROW_SCOPE(vm);\n");
+                    push(@$contentRef, "    auto returnValue = ${nativeValue};\n");
+                    push(@$contentRef, "    RETURN_IF_EXCEPTION(throwScope, CallbackResultType::ExceptionThrown);\n");
+                    push(@$contentRef, "    return WTFMove(returnValue);\n");
+                } else {
+                    push(@$contentRef, "    return ${nativeValue};\n");
+                }
+            }
+
             push(@$contentRef, "}\n\n");
         }
     }
@@ -5355,8 +5387,8 @@ sub GenerateImplementationFunctionCall
         push(@implContent, $indent . "$functionString;\n");
         push(@implContent, $indent . "return JSValue::encode(jsUndefined());\n");
     } else {
-        my $thisObject = $function->isStatic ? 0 : "castedThis";
-        push(@implContent, $indent . "return JSValue::encode(" . NativeToJSValueUsingPointers($function, $interface, $functionString, $thisObject) . ");\n");
+        my $globalObjectReference = $function->isStatic ? "*jsCast<JSDOMGlobalObject*>(state->lexicalGlobalObject())" : "*castedThis->globalObject()";
+        push(@implContent, $indent . "return JSValue::encode(" . NativeToJSValueUsingPointers($function, $interface, $functionString, $globalObjectReference) . ");\n");
     }
 }
 
@@ -5537,6 +5569,7 @@ sub GetBaseIDLType
     }
 
     my %IDLTypes = (
+        "void" => "IDLVoid",
         "any" => "IDLAny",
         "boolean" => "IDLBoolean",
         "byte" => "IDLByte",
@@ -5634,7 +5667,7 @@ sub JSValueToNativeDOMConvertNeedsGlobalObject
 sub IsValidContextForJSValueToNative
 {
     my $context = shift;
-    return ref($context) eq "IDLAttribute" || ref($context) eq "IDLArgument" || ref($context) eq "IDLDictionaryMember";
+    return ref($context) eq "IDLAttribute" || ref($context) eq "IDLArgument" || ref($context) eq "IDLDictionaryMember" || ref($context) eq "IDLOperation";
 }
 
 # Returns (convertString, mayThrowException).
@@ -5764,23 +5797,17 @@ sub NativeToJSValueDOMConvertNeedsGlobalObject
 
 sub NativeToJSValueUsingReferences
 {
-    my ($context, $interface, $value, $thisValue, $suppressExceptionCheck) = @_;
-    my $stateReference = "state";
-    my $wrapped = "$thisValue.wrapped()";
-    my $globalObjectReference = $thisValue ? "*$thisValue.globalObject()" : "*jsCast<JSDOMGlobalObject*>(state.lexicalGlobalObject())";
+    my ($context, $interface, $value, $globalObjectReference, $suppressExceptionCheck) = @_;
 
-    return NativeToJSValue($context, $interface, $value, $stateReference, $wrapped, $globalObjectReference, $suppressExceptionCheck);
+    return NativeToJSValue($context, $interface, $value, "state", $globalObjectReference, $suppressExceptionCheck);
 }
 
 # FIXME: We should remove NativeToJSValueUsingPointers and combine NativeToJSValueUsingReferences and NativeToJSValue
 sub NativeToJSValueUsingPointers
 {
-    my ($context, $interface, $value, $thisValue, $suppressExceptionCheck) = @_;
-    my $stateReference = "*state";
-    my $wrapped = "$thisValue->wrapped()";
-    my $globalObjectReference = $thisValue ? "*$thisValue->globalObject()" : "*jsCast<JSDOMGlobalObject*>(state->lexicalGlobalObject())";
+    my ($context, $interface, $value, $globalObjectReference, $suppressExceptionCheck) = @_;
 
-    return NativeToJSValue($context, $interface, $value, $stateReference, $wrapped, $globalObjectReference, $suppressExceptionCheck);
+    return NativeToJSValue($context, $interface, $value, "*state", $globalObjectReference, $suppressExceptionCheck);
 }
 
 sub IsValidContextForNativeToJSValue
@@ -5792,7 +5819,7 @@ sub IsValidContextForNativeToJSValue
 
 sub NativeToJSValue
 {
-    my ($context, $interface, $value, $stateReference, $wrapped, $globalObjectReference, $suppressExceptionCheck) = @_;
+    my ($context, $interface, $value, $stateReference, $globalObjectReference, $suppressExceptionCheck) = @_;
 
     assert("Invalid context type") if !IsValidContextForNativeToJSValue($context);
 
index 2219504..94c9db6 100644 (file)
         "RequiresExistingAtomicString": {
             "contextsAllowed": ["type"]
         },
+        "RethrowException": {
+            "contextsAllowed": ["operation", "callback-function"]
+        },
         "SameObject": {
             "contextsAllowed": ["attribute"],
             "standard": {
         "SetterMayThrowException": {
             "contextsAllowed": ["attribute"]
         },
+        "SkipCallbackInvokeCheck": {
+            "contextsAllowed": ["operation", "callback-function"]
+        },
         "SkipVTableValidation": {
             "contextsAllowed": ["interface"]
         },
index 822675e..55f70a5 100644 (file)
 */
 
 #include "config.h"
-
-#if ENABLE(SPEECH_SYNTHESIS)
-
 #include "JSTestCallbackFunction.h"
 
 #include "JSDOMConvert.h"
 #include "JSDOMExceptionHandling.h"
-#include "JSTestNode.h"
 #include "ScriptExecutionContext.h"
-#include "SerializedScriptValue.h"
 #include <runtime/JSLock.h>
 
 using namespace JSC;
@@ -56,29 +51,32 @@ JSTestCallbackFunction::~JSTestCallbackFunction()
 #endif
 }
 
-bool JSTestCallbackFunction::handleEvent(typename IDLInterface<Float32Array>::ParameterType arrayParam, typename IDLSerializedScriptValue<SerializedScriptValue>::ParameterType srzParam, typename IDLDOMString::ParameterType strArg, typename IDLBoolean::ParameterType boolParam, typename IDLLong::ParameterType longParam, typename IDLInterface<TestNode>::ParameterType testNodeParam)
+CallbackResult<typename IDLDOMString::ImplementationType> JSTestCallbackFunction::handleEvent(typename IDLLong::ParameterType argument)
 {
     if (!canInvokeCallback())
-        return true;
+        return CallbackResultType::UnableToExecute;
 
     Ref<JSTestCallbackFunction> protectedThis(*this);
 
-    JSLockHolder lock(m_data->globalObject()->vm());
+    auto& globalObject = *m_data->globalObject();
+    auto& vm = globalObject.vm();
 
-    ExecState* state = m_data->globalObject()->globalExec();
+    JSLockHolder lock(vm);
+    auto& state = *globalObject.globalExec();
     MarkedArgumentBuffer args;
-    args.append(toJS<IDLInterface<Float32Array>>(*state, *m_data->globalObject(), arrayParam));
-    args.append(toJS<IDLSerializedScriptValue<SerializedScriptValue>>(*state, *m_data->globalObject(), srzParam));
-    args.append(toJS<IDLDOMString>(*state, strArg));
-    args.append(toJS<IDLBoolean>(boolParam));
-    args.append(toJS<IDLLong>(longParam));
-    args.append(toJS<IDLInterface<TestNode>>(*state, *m_data->globalObject(), testNodeParam));
+    args.append(toJS<IDLLong>(argument));
 
     NakedPtr<JSC::Exception> returnedException;
-    m_data->invokeCallback(args, JSCallbackData::CallbackType::Function, Identifier(), returnedException);
-    if (returnedException)
-        reportException(state, returnedException);
-    return !returnedException;
+    auto jsResult = m_data->invokeCallback(args, JSCallbackData::CallbackType::Function, Identifier(), returnedException);
+    if (returnedException) {
+        reportException(&state, returnedException);
+        return CallbackResultType::ExceptionThrown;
+     }
+
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    auto returnValue = convert<IDLDOMString>(state, jsResult);
+    RETURN_IF_EXCEPTION(throwScope, CallbackResultType::ExceptionThrown);
+    return WTFMove(returnValue);
 }
 
 JSC::JSValue toJS(TestCallbackFunction& impl)
@@ -91,5 +89,3 @@ JSC::JSValue toJS(TestCallbackFunction& impl)
 }
 
 } // namespace WebCore
-
-#endif // ENABLE(SPEECH_SYNTHESIS)
index 7975f5b..bfcfd97 100644 (file)
@@ -20,8 +20,6 @@
 
 #pragma once
 
-#if ENABLE(SPEECH_SYNTHESIS)
-
 #include "ActiveDOMCallback.h"
 #include "IDLTypes.h"
 #include "JSCallbackData.h"
@@ -43,7 +41,7 @@ public:
     JSCallbackDataStrong* callbackData() { return m_data; }
 
     // Functions
-    virtual bool handleEvent(typename IDLInterface<Float32Array>::ParameterType arrayParam, typename IDLSerializedScriptValue<SerializedScriptValue>::ParameterType srzParam, typename IDLDOMString::ParameterType strArg, typename IDLBoolean::ParameterType boolParam, typename IDLLong::ParameterType longParam, typename IDLInterface<TestNode>::ParameterType testNodeParam) override;
+    virtual CallbackResult<typename IDLDOMString::ImplementationType> handleEvent(typename IDLLong::ParameterType argument) override;
 
 private:
     JSTestCallbackFunction(JSC::JSObject*, JSDOMGlobalObject*);
@@ -55,5 +53,3 @@ JSC::JSValue toJS(TestCallbackFunction&);
 inline JSC::JSValue toJS(TestCallbackFunction* impl) { return impl ? toJS(*impl) : JSC::jsNull(); }
 
 } // namespace WebCore
-
-#endif // ENABLE(SPEECH_SYNTHESIS)
diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestCallbackFunctionRethrow.cpp b/Source/WebCore/bindings/scripts/test/JS/JSTestCallbackFunctionRethrow.cpp
new file mode 100644 (file)
index 0000000..563360b
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+    This file is part of the WebKit open source project.
+    This file has been generated by generate-bindings.pl. DO NOT MODIFY!
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+#include "JSTestCallbackFunctionRethrow.h"
+
+#include "JSDOMConvert.h"
+#include "JSDOMExceptionHandling.h"
+#include "ScriptExecutionContext.h"
+#include <runtime/JSArray.h>
+#include <runtime/JSLock.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSTestCallbackFunctionRethrow::JSTestCallbackFunctionRethrow(JSObject* callback, JSDOMGlobalObject* globalObject)
+    : TestCallbackFunctionRethrow()
+    , ActiveDOMCallback(globalObject->scriptExecutionContext())
+    , m_data(new JSCallbackDataStrong(callback, globalObject, this))
+{
+}
+
+JSTestCallbackFunctionRethrow::~JSTestCallbackFunctionRethrow()
+{
+    ScriptExecutionContext* context = scriptExecutionContext();
+    // When the context is destroyed, all tasks with a reference to a callback
+    // should be deleted. So if the context is 0, we are on the context thread.
+    if (!context || context->isContextThread())
+        delete m_data;
+    else
+        context->postTask(DeleteCallbackDataTask(m_data));
+#ifndef NDEBUG
+    m_data = nullptr;
+#endif
+}
+
+CallbackResult<typename IDLDOMString::ImplementationType> JSTestCallbackFunctionRethrow::handleEvent(typename IDLSequence<IDLLong>::ParameterType argument)
+{
+    if (!canInvokeCallback())
+        return CallbackResultType::UnableToExecute;
+
+    Ref<JSTestCallbackFunctionRethrow> protectedThis(*this);
+
+    auto& globalObject = *m_data->globalObject();
+    auto& vm = globalObject.vm();
+
+    JSLockHolder lock(vm);
+    auto& state = *globalObject.globalExec();
+    MarkedArgumentBuffer args;
+    args.append(toJS<IDLSequence<IDLLong>>(state, globalObject, argument));
+
+    NakedPtr<JSC::Exception> returnedException;
+    auto jsResult = m_data->invokeCallback(args, JSCallbackData::CallbackType::Function, Identifier(), returnedException);
+    if (returnedException) {
+        auto throwScope = DECLARE_THROW_SCOPE(vm);
+        throwException(&state, throwScope, returnedException);
+        return CallbackResultType::ExceptionThrown;
+     }
+
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    auto returnValue = convert<IDLDOMString>(state, jsResult);
+    RETURN_IF_EXCEPTION(throwScope, CallbackResultType::ExceptionThrown);
+    return WTFMove(returnValue);
+}
+
+JSC::JSValue toJS(TestCallbackFunctionRethrow& impl)
+{
+    if (!static_cast<JSTestCallbackFunctionRethrow&>(impl).callbackData())
+        return jsNull();
+
+    return static_cast<JSTestCallbackFunctionRethrow&>(impl).callbackData()->callback();
+
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestCallbackFunctionRethrow.h b/Source/WebCore/bindings/scripts/test/JS/JSTestCallbackFunctionRethrow.h
new file mode 100644 (file)
index 0000000..99c100f
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+    This file is part of the WebKit open source project.
+    This file has been generated by generate-bindings.pl. DO NOT MODIFY!
+
+    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.
+*/
+
+#pragma once
+
+#include "ActiveDOMCallback.h"
+#include "IDLTypes.h"
+#include "JSCallbackData.h"
+#include "TestCallbackFunctionRethrow.h"
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class JSTestCallbackFunctionRethrow final : public TestCallbackFunctionRethrow, public ActiveDOMCallback {
+public:
+    static Ref<JSTestCallbackFunctionRethrow> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)
+    {
+        return adoptRef(*new JSTestCallbackFunctionRethrow(callback, globalObject));
+    }
+
+    virtual ScriptExecutionContext* scriptExecutionContext() const { return ContextDestructionObserver::scriptExecutionContext(); }
+
+    virtual ~JSTestCallbackFunctionRethrow();
+    JSCallbackDataStrong* callbackData() { return m_data; }
+
+    // Functions
+    virtual CallbackResult<typename IDLDOMString::ImplementationType> handleEvent(typename IDLSequence<IDLLong>::ParameterType argument) override;
+
+private:
+    JSTestCallbackFunctionRethrow(JSC::JSObject*, JSDOMGlobalObject*);
+
+    JSCallbackDataStrong* m_data;
+};
+
+JSC::JSValue toJS(TestCallbackFunctionRethrow&);
+inline JSC::JSValue toJS(TestCallbackFunctionRethrow* impl) { return impl ? toJS(*impl) : JSC::jsNull(); }
+
+} // namespace WebCore
index 3740d7a..e26600f 100644 (file)
@@ -52,25 +52,30 @@ JSTestCallbackFunctionWithTypedefs::~JSTestCallbackFunctionWithTypedefs()
 #endif
 }
 
-bool JSTestCallbackFunctionWithTypedefs::handleEvent(typename IDLSequence<IDLNullable<IDLLong>>::ParameterType sequenceArg, typename IDLLong::ParameterType longArg)
+CallbackResult<typename IDLVoid::ImplementationType> JSTestCallbackFunctionWithTypedefs::handleEvent(typename IDLSequence<IDLNullable<IDLLong>>::ParameterType sequenceArg, typename IDLLong::ParameterType longArg)
 {
     if (!canInvokeCallback())
-        return true;
+        return CallbackResultType::UnableToExecute;
 
     Ref<JSTestCallbackFunctionWithTypedefs> protectedThis(*this);
 
-    JSLockHolder lock(m_data->globalObject()->vm());
+    auto& globalObject = *m_data->globalObject();
+    auto& vm = globalObject.vm();
 
-    ExecState* state = m_data->globalObject()->globalExec();
+    JSLockHolder lock(vm);
+    auto& state = *globalObject.globalExec();
     MarkedArgumentBuffer args;
-    args.append(toJS<IDLSequence<IDLNullable<IDLLong>>>(*state, *m_data->globalObject(), sequenceArg));
+    args.append(toJS<IDLSequence<IDLNullable<IDLLong>>>(state, globalObject, sequenceArg));
     args.append(toJS<IDLLong>(longArg));
 
     NakedPtr<JSC::Exception> returnedException;
     m_data->invokeCallback(args, JSCallbackData::CallbackType::Function, Identifier(), returnedException);
-    if (returnedException)
-        reportException(state, returnedException);
-    return !returnedException;
+    if (returnedException) {
+        reportException(&state, returnedException);
+        return CallbackResultType::ExceptionThrown;
+     }
+
+    return { };
 }
 
 JSC::JSValue toJS(TestCallbackFunctionWithTypedefs& impl)
index 2452929..ad5ad5f 100644 (file)
@@ -41,7 +41,7 @@ public:
     JSCallbackDataStrong* callbackData() { return m_data; }
 
     // Functions
-    virtual bool handleEvent(typename IDLSequence<IDLNullable<IDLLong>>::ParameterType sequenceArg, typename IDLLong::ParameterType longArg) override;
+    virtual CallbackResult<typename IDLVoid::ImplementationType> handleEvent(typename IDLSequence<IDLNullable<IDLLong>>::ParameterType sequenceArg, typename IDLLong::ParameterType longArg) override;
 
 private:
     JSTestCallbackFunctionWithTypedefs(JSC::JSObject*, JSDOMGlobalObject*);
index b0c0188..d90aa1a 100644 (file)
 
 #include "config.h"
 
-#if ENABLE(SPEECH_SYNTHESIS)
+#if ENABLE(TEST_CONDITIONAL)
 
 #include "JSTestCallbackInterface.h"
 
 #include "JSDOMConstructorNotConstructable.h"
-#include "JSDOMConvert.h"
 #include "JSDOMExceptionHandling.h"
 #include "JSDOMStringList.h"
 #include "JSTestNode.h"
 #include "SerializedScriptValue.h"
 #include <runtime/FunctionPrototype.h>
 #include <runtime/JSLock.h>
+#include <runtime/JSString.h>
+#include <wtf/NeverDestroyed.h>
 
 using namespace JSC;
 
 namespace WebCore {
 
+template<> JSString* convertEnumerationToJS(ExecState& state, TestCallbackInterface::Enum enumerationValue)
+{
+    static NeverDestroyed<const String> values[] = {
+        ASCIILiteral("value1"),
+        ASCIILiteral("value2"),
+    };
+    static_assert(static_cast<size_t>(TestCallbackInterface::Enum::Value1) == 0, "TestCallbackInterface::Enum::Value1 is not 0 as expected");
+    static_assert(static_cast<size_t>(TestCallbackInterface::Enum::Value2) == 1, "TestCallbackInterface::Enum::Value2 is not 1 as expected");
+    ASSERT(static_cast<size_t>(enumerationValue) < WTF_ARRAY_LENGTH(values));
+    return jsStringWithCache(&state, values[static_cast<size_t>(enumerationValue)]);
+}
+
+template<> std::optional<TestCallbackInterface::Enum> parseEnumeration<TestCallbackInterface::Enum>(ExecState& state, JSValue value)
+{
+    auto stringValue = value.toWTFString(&state);
+    if (stringValue == "value1")
+        return TestCallbackInterface::Enum::Value1;
+    if (stringValue == "value2")
+        return TestCallbackInterface::Enum::Value2;
+    return std::nullopt;
+}
+
+template<> TestCallbackInterface::Enum convertEnumeration<TestCallbackInterface::Enum>(ExecState& state, JSValue value)
+{
+    VM& vm = state.vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    auto result = parseEnumeration<TestCallbackInterface::Enum>(state, value);
+    if (UNLIKELY(!result)) {
+        throwTypeError(&state, throwScope);
+        return { };
+    }
+    return result.value();
+}
+
+template<> const char* expectedEnumerationValues<TestCallbackInterface::Enum>()
+{
+    return "\"value1\", \"value2\"";
+}
+
+template<> TestCallbackInterface::Dictionary convertDictionary<TestCallbackInterface::Dictionary>(ExecState& state, JSValue value)
+{
+    VM& vm = state.vm();
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    bool isNullOrUndefined = value.isUndefinedOrNull();
+    auto* object = isNullOrUndefined ? nullptr : value.getObject();
+    if (UNLIKELY(!isNullOrUndefined && !object)) {
+        throwTypeError(&state, throwScope);
+        return { };
+    }
+    if (UNLIKELY(object && object->type() == RegExpObjectType)) {
+        throwTypeError(&state, throwScope);
+        return { };
+    }
+    TestCallbackInterface::Dictionary result;
+    JSValue optionalMemberValue = isNullOrUndefined ? jsUndefined() : object->get(&state, Identifier::fromString(&state, "optionalMember"));
+    if (!optionalMemberValue.isUndefined()) {
+        result.optionalMember = convert<IDLLong>(state, optionalMemberValue);
+        RETURN_IF_EXCEPTION(throwScope, { });
+    }
+    JSValue requiredMemberValue = isNullOrUndefined ? jsUndefined() : object->get(&state, Identifier::fromString(&state, "requiredMember"));
+    if (!requiredMemberValue.isUndefined()) {
+        result.requiredMember = convert<IDLUSVString>(state, requiredMemberValue);
+        RETURN_IF_EXCEPTION(throwScope, { });
+    } else {
+        throwRequiredMemberTypeError(state, throwScope, "requiredMember", "TestCallbackInterfaceDictionary", "USVString");
+        return { };
+    }
+    return result;
+}
+
 JSTestCallbackInterface::JSTestCallbackInterface(JSObject* callback, JSDOMGlobalObject* globalObject)
     : TestCallbackInterface()
     , ActiveDOMCallback(globalObject->scriptExecutionContext())
@@ -93,125 +164,236 @@ JSValue JSTestCallbackInterface::getConstructor(VM& vm, const JSGlobalObject* gl
     return getDOMConstructor<JSTestCallbackInterfaceConstructor>(vm, *jsCast<const JSDOMGlobalObject*>(globalObject));
 }
 
-bool JSTestCallbackInterface::callbackWithNoParam()
+CallbackResult<typename IDLVoid::ImplementationType> JSTestCallbackInterface::callbackWithNoParam()
 {
     if (!canInvokeCallback())
-        return true;
+        return CallbackResultType::UnableToExecute;
 
     Ref<JSTestCallbackInterface> protectedThis(*this);
 
-    JSLockHolder lock(m_data->globalObject()->vm());
+    auto& globalObject = *m_data->globalObject();
+    auto& vm = globalObject.vm();
 
-    ExecState* state = m_data->globalObject()->globalExec();
+    JSLockHolder lock(vm);
+    auto& state = *globalObject.globalExec();
     MarkedArgumentBuffer args;
 
     NakedPtr<JSC::Exception> returnedException;
-    m_data->invokeCallback(args, JSCallbackData::CallbackType::Object, Identifier::fromString(state, "callbackWithNoParam"), returnedException);
-    if (returnedException)
-        reportException(state, returnedException);
-    return !returnedException;
+    m_data->invokeCallback(args, JSCallbackData::CallbackType::Object, Identifier::fromString(&vm, "callbackWithNoParam"), returnedException);
+    if (returnedException) {
+        reportException(&state, returnedException);
+        return CallbackResultType::ExceptionThrown;
+     }
+
+    return { };
 }
 
-bool JSTestCallbackInterface::callbackWithArrayParam(typename IDLInterface<Float32Array>::ParameterType arrayParam)
+CallbackResult<typename IDLVoid::ImplementationType> JSTestCallbackInterface::callbackWithArrayParam(typename IDLInterface<Float32Array>::ParameterType arrayParam)
 {
     if (!canInvokeCallback())
-        return true;
+        return CallbackResultType::UnableToExecute;
 
     Ref<JSTestCallbackInterface> protectedThis(*this);
 
-    JSLockHolder lock(m_data->globalObject()->vm());
+    auto& globalObject = *m_data->globalObject();
+    auto& vm = globalObject.vm();
 
-    ExecState* state = m_data->globalObject()->globalExec();
+    JSLockHolder lock(vm);
+    auto& state = *globalObject.globalExec();
     MarkedArgumentBuffer args;
-    args.append(toJS<IDLInterface<Float32Array>>(*state, *m_data->globalObject(), arrayParam));
+    args.append(toJS<IDLInterface<Float32Array>>(state, globalObject, arrayParam));
 
     NakedPtr<JSC::Exception> returnedException;
-    m_data->invokeCallback(args, JSCallbackData::CallbackType::Object, Identifier::fromString(state, "callbackWithArrayParam"), returnedException);
-    if (returnedException)
-        reportException(state, returnedException);
-    return !returnedException;
+    m_data->invokeCallback(args, JSCallbackData::CallbackType::Object, Identifier::fromString(&vm, "callbackWithArrayParam"), returnedException);
+    if (returnedException) {
+        reportException(&state, returnedException);
+        return CallbackResultType::ExceptionThrown;
+     }
+
+    return { };
 }
 
-bool JSTestCallbackInterface::callbackWithSerializedScriptValueParam(typename IDLSerializedScriptValue<SerializedScriptValue>::ParameterType srzParam, typename IDLDOMString::ParameterType strParam)
+CallbackResult<typename IDLVoid::ImplementationType> JSTestCallbackInterface::callbackWithSerializedScriptValueParam(typename IDLSerializedScriptValue<SerializedScriptValue>::ParameterType srzParam, typename IDLDOMString::ParameterType strParam)
 {
     if (!canInvokeCallback())
-        return true;
+        return CallbackResultType::UnableToExecute;
 
     Ref<JSTestCallbackInterface> protectedThis(*this);
 
-    JSLockHolder lock(m_data->globalObject()->vm());
+    auto& globalObject = *m_data->globalObject();
+    auto& vm = globalObject.vm();
 
-    ExecState* state = m_data->globalObject()->globalExec();
+    JSLockHolder lock(vm);
+    auto& state = *globalObject.globalExec();
     MarkedArgumentBuffer args;
-    args.append(toJS<IDLSerializedScriptValue<SerializedScriptValue>>(*state, *m_data->globalObject(), srzParam));
-    args.append(toJS<IDLDOMString>(*state, strParam));
+    args.append(toJS<IDLSerializedScriptValue<SerializedScriptValue>>(state, globalObject, srzParam));
+    args.append(toJS<IDLDOMString>(state, strParam));
 
     NakedPtr<JSC::Exception> returnedException;
-    m_data->invokeCallback(args, JSCallbackData::CallbackType::Object, Identifier::fromString(state, "callbackWithSerializedScriptValueParam"), returnedException);
-    if (returnedException)
-        reportException(state, returnedException);
-    return !returnedException;
+    m_data->invokeCallback(args, JSCallbackData::CallbackType::Object, Identifier::fromString(&vm, "callbackWithSerializedScriptValueParam"), returnedException);
+    if (returnedException) {
+        reportException(&state, returnedException);
+        return CallbackResultType::ExceptionThrown;
+     }
+
+    return { };
 }
 
-bool JSTestCallbackInterface::callbackWithStringList(typename IDLInterface<DOMStringList>::ParameterType listParam)
+CallbackResult<typename IDLVoid::ImplementationType> JSTestCallbackInterface::callbackWithStringList(typename IDLInterface<DOMStringList>::ParameterType listParam)
 {
     if (!canInvokeCallback())
-        return true;
+        return CallbackResultType::UnableToExecute;
 
     Ref<JSTestCallbackInterface> protectedThis(*this);
 
-    JSLockHolder lock(m_data->globalObject()->vm());
+    auto& globalObject = *m_data->globalObject();
+    auto& vm = globalObject.vm();
 
-    ExecState* state = m_data->globalObject()->globalExec();
+    JSLockHolder lock(vm);
+    auto& state = *globalObject.globalExec();
     MarkedArgumentBuffer args;
-    args.append(toJS<IDLInterface<DOMStringList>>(*state, *m_data->globalObject(), listParam));
+    args.append(toJS<IDLInterface<DOMStringList>>(state, globalObject, listParam));
 
     NakedPtr<JSC::Exception> returnedException;
-    m_data->invokeCallback(args, JSCallbackData::CallbackType::Object, Identifier::fromString(state, "callbackWithStringList"), returnedException);
-    if (returnedException)
-        reportException(state, returnedException);
-    return !returnedException;
+    m_data->invokeCallback(args, JSCallbackData::CallbackType::Object, Identifier::fromString(&vm, "callbackWithStringList"), returnedException);
+    if (returnedException) {
+        reportException(&state, returnedException);
+        return CallbackResultType::ExceptionThrown;
+     }
+
+    return { };
 }
 
-bool JSTestCallbackInterface::callbackWithBoolean(typename IDLBoolean::ParameterType boolParam)
+CallbackResult<typename IDLVoid::ImplementationType> JSTestCallbackInterface::callbackWithBoolean(typename IDLBoolean::ParameterType boolParam)
 {
     if (!canInvokeCallback())
-        return true;
+        return CallbackResultType::UnableToExecute;
 
     Ref<JSTestCallbackInterface> protectedThis(*this);
 
-    JSLockHolder lock(m_data->globalObject()->vm());
+    auto& globalObject = *m_data->globalObject();
+    auto& vm = globalObject.vm();
 
-    ExecState* state = m_data->globalObject()->globalExec();
+    JSLockHolder lock(vm);
+    auto& state = *globalObject.globalExec();
     MarkedArgumentBuffer args;
     args.append(toJS<IDLBoolean>(boolParam));
 
     NakedPtr<JSC::Exception> returnedException;
-    m_data->invokeCallback(args, JSCallbackData::CallbackType::Object, Identifier::fromString(state, "callbackWithBoolean"), returnedException);
-    if (returnedException)
-        reportException(state, returnedException);
-    return !returnedException;
+    m_data->invokeCallback(args, JSCallbackData::CallbackType::Object, Identifier::fromString(&vm, "callbackWithBoolean"), returnedException);
+    if (returnedException) {
+        reportException(&state, returnedException);
+        return CallbackResultType::ExceptionThrown;
+     }
+
+    return { };
 }
 
-bool JSTestCallbackInterface::callbackRequiresThisToPass(typename IDLLong::ParameterType longParam, typename IDLInterface<TestNode>::ParameterType testNodeParam)
+CallbackResult<typename IDLVoid::ImplementationType> JSTestCallbackInterface::callbackRequiresThisToPass(typename IDLLong::ParameterType longParam, typename IDLInterface<TestNode>::ParameterType testNodeParam)
 {
     if (!canInvokeCallback())
-        return true;
+        return CallbackResultType::UnableToExecute;
 
     Ref<JSTestCallbackInterface> protectedThis(*this);
 
-    JSLockHolder lock(m_data->globalObject()->vm());
+    auto& globalObject = *m_data->globalObject();
+    auto& vm = globalObject.vm();
 
-    ExecState* state = m_data->globalObject()->globalExec();
+    JSLockHolder lock(vm);
+    auto& state = *globalObject.globalExec();
     MarkedArgumentBuffer args;
     args.append(toJS<IDLLong>(longParam));
-    args.append(toJS<IDLInterface<TestNode>>(*state, *m_data->globalObject(), testNodeParam));
+    args.append(toJS<IDLInterface<TestNode>>(state, globalObject, testNodeParam));
+
+    NakedPtr<JSC::Exception> returnedException;
+    m_data->invokeCallback(args, JSCallbackData::CallbackType::Object, Identifier::fromString(&vm, "callbackRequiresThisToPass"), returnedException);
+    if (returnedException) {
+        reportException(&state, returnedException);
+        return CallbackResultType::ExceptionThrown;
+     }
+
+    return { };
+}
+
+CallbackResult<typename IDLDOMString::ImplementationType> JSTestCallbackInterface::callbackWithAReturnValue()
+{
+    if (!canInvokeCallback())
+        return CallbackResultType::UnableToExecute;
+
+    Ref<JSTestCallbackInterface> protectedThis(*this);
+
+    auto& globalObject = *m_data->globalObject();
+    auto& vm = globalObject.vm();
+
+    JSLockHolder lock(vm);
+    auto& state = *globalObject.globalExec();
+    MarkedArgumentBuffer args;
+
+    NakedPtr<JSC::Exception> returnedException;
+    auto jsResult = m_data->invokeCallback(args, JSCallbackData::CallbackType::Object, Identifier::fromString(&vm, "callbackWithAReturnValue"), returnedException);
+    if (returnedException) {
+        reportException(&state, returnedException);
+        return CallbackResultType::ExceptionThrown;
+     }
+
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    auto returnValue = convert<IDLDOMString>(state, jsResult);
+    RETURN_IF_EXCEPTION(throwScope, CallbackResultType::ExceptionThrown);
+    return WTFMove(returnValue);
+}
+
+CallbackResult<typename IDLDOMString::ImplementationType> JSTestCallbackInterface::callbackThatRethrowsExceptions(typename IDLEnumeration<TestCallbackInterface::Enum>::ParameterType enumParam)
+{
+    if (!canInvokeCallback())
+        return CallbackResultType::UnableToExecute;
+
+    Ref<JSTestCallbackInterface> protectedThis(*this);
+
+    auto& globalObject = *m_data->globalObject();
+    auto& vm = globalObject.vm();
+
+    JSLockHolder lock(vm);
+    auto& state = *globalObject.globalExec();
+    MarkedArgumentBuffer args;
+    args.append(toJS<IDLEnumeration<TestCallbackInterface::Enum>>(state, enumParam));
+
+    NakedPtr<JSC::Exception> returnedException;
+    auto jsResult = m_data->invokeCallback(args, JSCallbackData::CallbackType::Object, Identifier::fromString(&vm, "callbackThatRethrowsExceptions"), returnedException);
+    if (returnedException) {
+        auto throwScope = DECLARE_THROW_SCOPE(vm);
+        throwException(&state, throwScope, returnedException);
+        return CallbackResultType::ExceptionThrown;
+     }
+
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    auto returnValue = convert<IDLDOMString>(state, jsResult);
+    RETURN_IF_EXCEPTION(throwScope, CallbackResultType::ExceptionThrown);
+    return WTFMove(returnValue);
+}
+
+CallbackResult<typename IDLDOMString::ImplementationType> JSTestCallbackInterface::callbackThatSkipsInvokeCheck(typename IDLDictionary<TestCallbackInterface::Dictionary>::ParameterType dictionaryParam)
+{
+    Ref<JSTestCallbackInterface> protectedThis(*this);
+
+    auto& globalObject = *m_data->globalObject();
+    auto& vm = globalObject.vm();
+
+    JSLockHolder lock(vm);
+    auto& state = *globalObject.globalExec();
+    MarkedArgumentBuffer args;
+    args.append(toJS<IDLDictionary<TestCallbackInterface::Dictionary>>(state, globalObject, dictionaryParam));
 
     NakedPtr<JSC::Exception> returnedException;
-    m_data->invokeCallback(args, JSCallbackData::CallbackType::Object, Identifier::fromString(state, "callbackRequiresThisToPass"), returnedException);
-    if (returnedException)
-        reportException(state, returnedException);
-    return !returnedException;
+    auto jsResult = m_data->invokeCallback(args, JSCallbackData::CallbackType::Object, Identifier::fromString(&vm, "callbackThatSkipsInvokeCheck"), returnedException);
+    if (returnedException) {
+        reportException(&state, returnedException);
+        return CallbackResultType::ExceptionThrown;
+     }
+
+    auto throwScope = DECLARE_THROW_SCOPE(vm);
+    auto returnValue = convert<IDLDOMString>(state, jsResult);
+    RETURN_IF_EXCEPTION(throwScope, CallbackResultType::ExceptionThrown);
+    return WTFMove(returnValue);
 }
 
 JSC::JSValue toJS(TestCallbackInterface& impl)
@@ -225,4 +407,4 @@ JSC::JSValue toJS(TestCallbackInterface& impl)
 
 } // namespace WebCore
 
-#endif // ENABLE(SPEECH_SYNTHESIS)
+#endif // ENABLE(TEST_CONDITIONAL)
index 6922006..33bad26 100644 (file)
 
 #pragma once
 
-#if ENABLE(SPEECH_SYNTHESIS)
+#if ENABLE(TEST_CONDITIONAL)
 
 #include "ActiveDOMCallback.h"
 #include "IDLTypes.h"
 #include "JSCallbackData.h"
+#include "JSDOMConvert.h"
 #include "TestCallbackInterface.h"
 #include <wtf/Forward.h>
 
@@ -44,13 +45,16 @@ public:
     static JSC::JSValue getConstructor(JSC::VM&, const JSC::JSGlobalObject*);
 
     // Functions
-    virtual bool callbackWithNoParam() override;
-    virtual bool callbackWithArrayParam(typename IDLInterface<Float32Array>::ParameterType arrayParam) override;
-    virtual bool callbackWithSerializedScriptValueParam(typename IDLSerializedScriptValue<SerializedScriptValue>::ParameterType srzParam, typename IDLDOMString::ParameterType strParam) override;
-    virtual typename IDLLong::ImplementationType customCallback(typename IDLInterface<TestObj>::ParameterType testObjParam, typename IDLInterface<TestNode>::ParameterType testNodeParam) override;
-    virtual bool callbackWithStringList(typename IDLInterface<DOMStringList>::ParameterType listParam) override;
-    virtual bool callbackWithBoolean(typename IDLBoolean::ParameterType boolParam) override;
-    virtual bool callbackRequiresThisToPass(typename IDLLong::ParameterType longParam, typename IDLInterface<TestNode>::ParameterType testNodeParam) override;
+    virtual CallbackResult<typename IDLVoid::ImplementationType> callbackWithNoParam() override;
+    virtual CallbackResult<typename IDLVoid::ImplementationType> callbackWithArrayParam(typename IDLInterface<Float32Array>::ParameterType arrayParam) override;
+    virtual CallbackResult<typename IDLVoid::ImplementationType> callbackWithSerializedScriptValueParam(typename IDLSerializedScriptValue<SerializedScriptValue>::ParameterType srzParam, typename IDLDOMString::ParameterType strParam) override;
+    virtual CallbackResult<typename IDLLong::ImplementationType> customCallback(typename IDLInterface<TestObj>::ParameterType testObjParam, typename IDLInterface<TestNode>::ParameterType testNodeParam) override;
+    virtual CallbackResult<typename IDLVoid::ImplementationType> callbackWithStringList(typename IDLInterface<DOMStringList>::ParameterType listParam) override;
+    virtual CallbackResult<typename IDLVoid::ImplementationType> callbackWithBoolean(typename IDLBoolean::ParameterType boolParam) override;
+    virtual CallbackResult<typename IDLVoid::ImplementationType> callbackRequiresThisToPass(typename IDLLong::ParameterType longParam, typename IDLInterface<TestNode>::ParameterType testNodeParam) override;
+    virtual CallbackResult<typename IDLDOMString::ImplementationType> callbackWithAReturnValue() override;
+    virtual CallbackResult<typename IDLDOMString::ImplementationType> callbackThatRethrowsExceptions(typename IDLEnumeration<TestCallbackInterface::Enum>::ParameterType enumParam) override;
+    virtual CallbackResult<typename IDLDOMString::ImplementationType> callbackThatSkipsInvokeCheck(typename IDLDictionary<TestCallbackInterface::Dictionary>::ParameterType dictionaryParam) override;
 
 private:
     JSTestCallbackInterface(JSC::JSObject*, JSDOMGlobalObject*);
@@ -61,6 +65,14 @@ private:
 JSC::JSValue toJS(TestCallbackInterface&);
 inline JSC::JSValue toJS(TestCallbackInterface* impl) { return impl ? toJS(*impl) : JSC::jsNull(); }
 
+template<> JSC::JSString* convertEnumerationToJS(JSC::ExecState&, TestCallbackInterface::Enum);
+
+template<> std::optional<TestCallbackInterface::Enum> parseEnumeration<TestCallbackInterface::Enum>(JSC::ExecState&, JSC::JSValue);
+template<> TestCallbackInterface::Enum convertEnumeration<TestCallbackInterface::Enum>(JSC::ExecState&, JSC::JSValue);
+template<> const char* expectedEnumerationValues<TestCallbackInterface::Enum>();
+
+template<> TestCallbackInterface::Dictionary convertDictionary<TestCallbackInterface::Dictionary>(JSC::ExecState&, JSC::JSValue);
+
 } // namespace WebCore
 
-#endif // ENABLE(SPEECH_SYNTHESIS)
+#endif // ENABLE(TEST_CONDITIONAL)
diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestVoidCallbackFunction.cpp b/Source/WebCore/bindings/scripts/test/JS/JSTestVoidCallbackFunction.cpp
new file mode 100644 (file)
index 0000000..e30c35d
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+    This file is part of the WebKit open source project.
+    This file has been generated by generate-bindings.pl. DO NOT MODIFY!
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+    Boston, MA 02110-1301, USA.
+*/
+
+#include "config.h"
+
+#if ENABLE(TEST_CONDITIONAL)
+
+#include "JSTestVoidCallbackFunction.h"
+
+#include "JSDOMConvert.h"
+#include "JSDOMExceptionHandling.h"
+#include "JSTestNode.h"
+#include "ScriptExecutionContext.h"
+#include "SerializedScriptValue.h"
+#include <runtime/JSLock.h>
+
+using namespace JSC;
+
+namespace WebCore {
+
+JSTestVoidCallbackFunction::JSTestVoidCallbackFunction(JSObject* callback, JSDOMGlobalObject* globalObject)
+    : TestVoidCallbackFunction()
+    , ActiveDOMCallback(globalObject->scriptExecutionContext())
+    , m_data(new JSCallbackDataStrong(callback, globalObject, this))
+{
+}
+
+JSTestVoidCallbackFunction::~JSTestVoidCallbackFunction()
+{
+    ScriptExecutionContext* context = scriptExecutionContext();
+    // When the context is destroyed, all tasks with a reference to a callback
+    // should be deleted. So if the context is 0, we are on the context thread.
+    if (!context || context->isContextThread())
+        delete m_data;
+    else
+        context->postTask(DeleteCallbackDataTask(m_data));
+#ifndef NDEBUG
+    m_data = nullptr;
+#endif
+}
+
+CallbackResult<typename IDLVoid::ImplementationType> JSTestVoidCallbackFunction::handleEvent(typename IDLInterface<Float32Array>::ParameterType arrayParam, typename IDLSerializedScriptValue<SerializedScriptValue>::ParameterType srzParam, typename IDLDOMString::ParameterType strArg, typename IDLBoolean::ParameterType boolParam, typename IDLLong::ParameterType longParam, typename IDLInterface<TestNode>::ParameterType testNodeParam)
+{
+    if (!canInvokeCallback())
+        return CallbackResultType::UnableToExecute;
+
+    Ref<JSTestVoidCallbackFunction> protectedThis(*this);
+
+    auto& globalObject = *m_data->globalObject();
+    auto& vm = globalObject.vm();
+
+    JSLockHolder lock(vm);
+    auto& state = *globalObject.globalExec();
+    MarkedArgumentBuffer args;
+    args.append(toJS<IDLInterface<Float32Array>>(state, globalObject, arrayParam));
+    args.append(toJS<IDLSerializedScriptValue<SerializedScriptValue>>(state, globalObject, srzParam));
+    args.append(toJS<IDLDOMString>(state, strArg));
+    args.append(toJS<IDLBoolean>(boolParam));
+    args.append(toJS<IDLLong>(longParam));
+    args.append(toJS<IDLInterface<TestNode>>(state, globalObject, testNodeParam));
+
+    NakedPtr<JSC::Exception> returnedException;
+    m_data->invokeCallback(args, JSCallbackData::CallbackType::Function, Identifier(), returnedException);
+    if (returnedException) {
+        reportException(&state, returnedException);
+        return CallbackResultType::ExceptionThrown;
+     }
+
+    return { };
+}
+
+JSC::JSValue toJS(TestVoidCallbackFunction& impl)
+{
+    if (!static_cast<JSTestVoidCallbackFunction&>(impl).callbackData())
+        return jsNull();
+
+    return static_cast<JSTestVoidCallbackFunction&>(impl).callbackData()->callback();
+
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(TEST_CONDITIONAL)
diff --git a/Source/WebCore/bindings/scripts/test/JS/JSTestVoidCallbackFunction.h b/Source/WebCore/bindings/scripts/test/JS/JSTestVoidCallbackFunction.h
new file mode 100644 (file)
index 0000000..30e5156
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+    This file is part of the WebKit open source project.
+    This file has been generated by generate-bindings.pl. DO NOT MODIFY!
+
+    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.
+*/
+
+#pragma once
+
+#if ENABLE(TEST_CONDITIONAL)
+
+#include "ActiveDOMCallback.h"
+#include "IDLTypes.h"
+#include "JSCallbackData.h"
+#include "TestVoidCallbackFunction.h"
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class JSTestVoidCallbackFunction final : public TestVoidCallbackFunction, public ActiveDOMCallback {
+public:
+    static Ref<JSTestVoidCallbackFunction> create(JSC::JSObject* callback, JSDOMGlobalObject* globalObject)
+    {
+        return adoptRef(*new JSTestVoidCallbackFunction(callback, globalObject));
+    }
+
+    virtual ScriptExecutionContext* scriptExecutionContext() const { return ContextDestructionObserver::scriptExecutionContext(); }
+
+    virtual ~JSTestVoidCallbackFunction();
+    JSCallbackDataStrong* callbackData() { return m_data; }
+
+    // Functions
+    virtual CallbackResult<typename IDLVoid::ImplementationType> handleEvent(typename IDLInterface<Float32Array>::ParameterType arrayParam, typename IDLSerializedScriptValue<SerializedScriptValue>::ParameterType srzParam, typename IDLDOMString::ParameterType strArg, typename IDLBoolean::ParameterType boolParam, typename IDLLong::ParameterType longParam, typename IDLInterface<TestNode>::ParameterType testNodeParam) override;
+
+private:
+    JSTestVoidCallbackFunction(JSC::JSObject*, JSDOMGlobalObject*);
+
+    JSCallbackDataStrong* m_data;
+};
+
+JSC::JSValue toJS(TestVoidCallbackFunction&);
+inline JSC::JSValue toJS(TestVoidCallbackFunction* impl) { return impl ? toJS(*impl) : JSC::jsNull(); }
+
+} // namespace WebCore
+
+#endif // ENABLE(TEST_CONDITIONAL)
index 2b24ad2..1b88302 100644 (file)
@@ -1,31 +1,26 @@
 /*
- * Copyright (C) 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
  *
- * Redistribution and use in source and binary formstrArg, with or without
+ * 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.
  *
- * 1.  Redistributions of source code must retain the above copyright
- *     notice, this list of conditions and the following disclaimer.
- * 2.  Redistributions in binary form must reproduce the above copyright
- *     notice, this list of conditions and the following disclaimer in the
- *     documentation and/or other materials provided with the distribution.
- * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
- *     its contributors may be used to endorse or promote products derived
- *     from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIEstrArg, 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.
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
  */
 
-[
-    Conditional=SPEECH_SYNTHESIS,
-] callback TestCallbackFunction = void (Float32Array arrayParam, SerializedScriptValue srzParam, DOMString strArg, boolean boolParam, long longParam, TestNode testNodeParam);
+callback TestCallbackFunction = DOMString (long argument);
diff --git a/Source/WebCore/bindings/scripts/test/TestCallbackFunctionRethrow.idl b/Source/WebCore/bindings/scripts/test/TestCallbackFunctionRethrow.idl
new file mode 100644 (file)
index 0000000..c9db1d0
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2017 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+ */
+
+[
+    RethrowException
+] callback TestCallbackFunctionRethrow = DOMString (sequence<long> argument);
index c95d4eb..6380eef 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2009 Google Inc. All rights reserved.
+ * 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
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+enum TestCallbackInterfaceEnum { "value1", "value2" };
+
+dictionary TestCallbackInterfaceDictionary { 
+    required USVString requiredMember;
+    long optionalMember;
+};
+
 [
-    Conditional=SPEECH_SYNTHESIS,
+    Conditional=TEST_CONDITIONAL,
 ] callback interface TestCallbackInterface {
     // Constants
     const unsigned short CONSTANT1 = 1;
@@ -41,4 +49,7 @@
     void callbackWithStringList(DOMStringList listParam);
     void callbackWithBoolean(boolean boolParam);
     void callbackRequiresThisToPass(long longParam, TestNode testNodeParam);
+    DOMString callbackWithAReturnValue();
+    [RethrowException] DOMString callbackThatRethrowsExceptions(TestCallbackInterfaceEnum enumParam);
+    [SkipCallbackInvokeCheck] DOMString callbackThatSkipsInvokeCheck(TestCallbackInterfaceDictionary dictionaryParam);
 };
diff --git a/Source/WebCore/bindings/scripts/test/TestVoidCallbackFunction.idl b/Source/WebCore/bindings/scripts/test/TestVoidCallbackFunction.idl
new file mode 100644 (file)
index 0000000..4dd0e36
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2015 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1.  Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ * 2.  Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in the
+ *     documentation and/or other materials provided with the distribution.
+ * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
+ *     its contributors may be used to endorse or promote products derived
+ *     from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+[
+    Conditional=TEST_CONDITIONAL,
+] callback TestVoidCallbackFunction = void (Float32Array arrayParam, SerializedScriptValue srzParam, DOMString strArg, boolean boolParam, long longParam, TestNode testNodeParam);
index e7a7626..af51ef8 100644 (file)
@@ -19,6 +19,7 @@
 
 #pragma once
 
+#include "CallbackResult.h"
 #include <wtf/RefCounted.h>
 
 namespace WebCore {
@@ -31,7 +32,7 @@ public:
         JSMediaQueryListListenerType
     };
 
-    virtual bool handleEvent(MediaQueryList&) = 0;
+    virtual CallbackResult<void> handleEvent(MediaQueryList&) = 0;
     virtual bool operator==(const MediaQueryListListener&) const = 0;
     virtual ~MediaQueryListListener() { }
 
diff --git a/Source/WebCore/dom/CallbackResult.h b/Source/WebCore/dom/CallbackResult.h
new file mode 100644 (file)
index 0000000..3bebfe1
--- /dev/null
@@ -0,0 +1,96 @@
+/*
+ * 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 <wtf/Expected.h>
+
+namespace WebCore {
+
+enum class CallbackResultType {
+    Success,
+    ExceptionThrown,
+    UnableToExecute
+};
+
+template<typename ReturnType> class CallbackResult {
+public:
+    CallbackResult(CallbackResultType);
+    CallbackResult(ReturnType&&);
+
+    CallbackResultType type() const;
+    ReturnType&& releaseReturnValue();
+
+private:
+    Expected<ReturnType, CallbackResultType> m_value;
+};
+
+template<> class CallbackResult<void> {
+public:
+    CallbackResult() = default;
+    CallbackResult(CallbackResultType);
+
+    CallbackResultType type() const;
+
+private:
+    CallbackResultType m_type = CallbackResultType::Success;
+};
+
+
+template<typename ReturnType> inline CallbackResult<ReturnType>::CallbackResult(CallbackResultType type)
+    : m_value(makeUnexpected(type))
+{
+}
+
+template<typename ReturnType> inline CallbackResult<ReturnType>::CallbackResult(ReturnType&& returnValue)
+    : m_value(WTFMove(returnValue))
+{
+}
+
+template<typename ReturnType> inline CallbackResultType CallbackResult<ReturnType>::type() const
+{
+    return m_value.hasValue() ? CallbackResultType::Success : m_value.error();
+}
+
+template<typename ReturnType> inline auto CallbackResult<ReturnType>::releaseReturnValue() -> ReturnType&&
+{
+    ASSERT(m_value.hasValue());
+    return WTFMove(m_value.value());
+}
+
+
+// Void specialization
+
+inline CallbackResult<void>::CallbackResult(CallbackResultType type)
+    : m_type(type)
+{
+}
+
+inline CallbackResultType CallbackResult<void>::type() const
+{
+    return m_type;
+}
+
+}
index efd3e6e..86326eb 100644 (file)
 
 namespace WebCore {
 
-NativeNodeFilter::NativeNodeFilter(RefPtr<NodeFilterCondition>&& condition)
-    : m_condition(condition)
+NativeNodeFilter::NativeNodeFilter(Ref<NodeFilterCondition>&& condition)
+    : m_condition(WTFMove(condition))
 {
 }
 
-unsigned short NativeNodeFilter::acceptNode(Node& node)
+CallbackResult<unsigned short> NativeNodeFilter::acceptNode(Node& node)
 {
-    // cast to short silences "enumeral and non-enumeral types in return" warning
-    return m_condition ? m_condition->acceptNode(&node) : static_cast<unsigned short>(FILTER_ACCEPT);
+    return m_condition->acceptNode(node);
 }
 
 } // namespace WebCore
index b132832..c3d9167 100644 (file)
@@ -33,26 +33,17 @@ namespace WebCore {
 
 class NativeNodeFilter final : public NodeFilter {
 public:
-    static Ref<NativeNodeFilter> create(RefPtr<NodeFilterCondition>&& condition)
+    static Ref<NativeNodeFilter> create(Ref<NodeFilterCondition>&& condition)
     {
         return adoptRef(*new NativeNodeFilter(WTFMove(condition)));
     }
 
-    static Ref<NativeNodeFilter> create()
-    {
-        return adoptRef(*new NativeNodeFilter());
-    }
-
-    unsigned short acceptNode(Node&) override;
-
-    void setCondition(RefPtr<NodeFilterCondition>&& condition) { ASSERT(!m_condition); m_condition = condition; }
+    CallbackResult<unsigned short> acceptNode(Node&) override;
 
 private:
-    WEBCORE_EXPORT explicit NativeNodeFilter(RefPtr<NodeFilterCondition>&&);
-
-    NativeNodeFilter() { }
+    WEBCORE_EXPORT explicit NativeNodeFilter(Ref<NodeFilterCondition>&&);
 
-    RefPtr<NodeFilterCondition> m_condition;
+    Ref<NodeFilterCondition> m_condition;
 };
 
 } // namespace WebCore
index add08f2..9810a92 100644 (file)
@@ -24,6 +24,7 @@
 
 #pragma once
 
+#include "CallbackResult.h"
 #include <wtf/RefCounted.h>
 
 namespace WebCore {
@@ -33,7 +34,7 @@ class Node;
 class NodeFilter : public RefCounted<NodeFilter> {
 public:
     virtual ~NodeFilter() { }
-    virtual unsigned short acceptNode(Node&) = 0;
+    virtual CallbackResult<unsigned short> acceptNode(Node&) = 0;
 
     /*
      * The following constants are returned by the acceptNode()
index 9f5e373..67733a4 100644 (file)
@@ -41,5 +41,5 @@
     const unsigned long SHOW_DOCUMENT_FRAGMENT = 0x00000400;
     const unsigned long SHOW_NOTATION = 0x00000800; // Historical.
 
-    [Custom] unsigned short acceptNode(Node node);
+    [SkipCallbackInvokeCheck, RethrowException] unsigned short acceptNode(Node node);
 };
index 72c9ee1..8d50870 100644 (file)
@@ -29,7 +29,7 @@
 
 namespace WebCore {
 
-short NodeFilterCondition::acceptNode(Node*) const
+unsigned short NodeFilterCondition::acceptNode(Node&) const
 {
     return NodeFilter::FILTER_ACCEPT;
 }
index 8ccebe3..903f151 100644 (file)
@@ -37,7 +37,7 @@ class Node;
 class NodeFilterCondition : public RefCounted<NodeFilterCondition> {
 public:
     virtual ~NodeFilterCondition() { }
-    virtual short acceptNode(Node*) const = 0;
+    virtual unsigned short acceptNode(Node&) const = 0;
     virtual void visitAggregate(JSC::SlotVisitor&) { }
 };
 
index 9108ea5..882e803 100644 (file)
@@ -26,8 +26,8 @@
 #include "NodeIterator.h"
 
 #include "Document.h"
+#include "ExceptionCode.h"
 #include "NodeTraversal.h"
-#include <runtime/JSCJSValueInlines.h>
 
 namespace WebCore {
 
@@ -87,7 +87,7 @@ NodeIterator::~NodeIterator()
     root().document().detachNodeIterator(this);
 }
 
-RefPtr<Node> NodeIterator::nextNode()
+ExceptionOr<RefPtr<Node>> NodeIterator::nextNode()
 {
     RefPtr<Node> result;
 
@@ -97,7 +97,14 @@ RefPtr<Node> NodeIterator::nextNode()
         // In other words, FILTER_REJECT does not pass over descendants
         // of the rejected node. Hence, FILTER_REJECT is the same as FILTER_SKIP.
         RefPtr<Node> provisionalResult = m_candidateNode.node;
-        bool nodeWasAccepted = acceptNode(*provisionalResult) == NodeFilter::FILTER_ACCEPT;
+
+        auto callbackResult = acceptNode(*provisionalResult);
+        if (callbackResult.type() == CallbackResultType::ExceptionThrown)
+            return Exception { ExistingExceptionError };
+
+        ASSERT(callbackResult.type() == CallbackResultType::Success);
+
+        bool nodeWasAccepted = callbackResult.releaseReturnValue() == NodeFilter::FILTER_ACCEPT;
         if (nodeWasAccepted) {
             m_referenceNode = m_candidateNode;
             result = WTFMove(provisionalResult);
@@ -106,10 +113,10 @@ RefPtr<Node> NodeIterator::nextNode()
     }
 
     m_candidateNode.clear();
-    return result;
+    return WTFMove(result);
 }
 
-RefPtr<Node> NodeIterator::previousNode()
+ExceptionOr<RefPtr<Node>> NodeIterator::previousNode()
 {
     RefPtr<Node> result;
 
@@ -119,7 +126,14 @@ RefPtr<Node> NodeIterator::previousNode()
         // In other words, FILTER_REJECT does not pass over descendants
         // of the rejected node. Hence, FILTER_REJECT is the same as FILTER_SKIP.
         RefPtr<Node> provisionalResult = m_candidateNode.node;
-        bool nodeWasAccepted = acceptNode(*provisionalResult) == NodeFilter::FILTER_ACCEPT;
+
+        auto callbackResult = acceptNode(*provisionalResult);
+        if (callbackResult.type() == CallbackResultType::ExceptionThrown)
+            return Exception { ExistingExceptionError };
+
+        ASSERT(callbackResult.type() == CallbackResultType::Success);
+
+        bool nodeWasAccepted = callbackResult.releaseReturnValue() == NodeFilter::FILTER_ACCEPT;
         if (nodeWasAccepted) {
             m_referenceNode = m_candidateNode;
             result = WTFMove(provisionalResult);
@@ -128,7 +142,7 @@ RefPtr<Node> NodeIterator::previousNode()
     }
 
     m_candidateNode.clear();
-    return result;
+    return WTFMove(result);
 }
 
 void NodeIterator::nodeWillBeRemoved(Node& removedNode)
index 28bcaf0..e7b566a 100644 (file)
@@ -24,6 +24,7 @@
 
 #pragma once
 
+#include "ExceptionOr.h"
 #include "NodeFilter.h"
 #include "ScriptWrappable.h"
 #include "Traversal.h"
@@ -35,8 +36,8 @@ public:
     static Ref<NodeIterator> create(Node&, unsigned whatToShow, RefPtr<NodeFilter>&&);
     WEBCORE_EXPORT ~NodeIterator();
 
-    WEBCORE_EXPORT RefPtr<Node> nextNode();
-    WEBCORE_EXPORT RefPtr<Node> previousNode();
+    WEBCORE_EXPORT ExceptionOr<RefPtr<Node>> nextNode();
+    WEBCORE_EXPORT ExceptionOr<RefPtr<Node>> previousNode();
     void detach() { } // This is now a no-op as per the DOM specification.
 
     Node* referenceNode() const { return m_referenceNode.node.get(); }
index 5b244e6..b3aab6c 100644 (file)
@@ -29,8 +29,8 @@
     readonly attribute unsigned long whatToShow;
     readonly attribute NodeFilter? filter;
 
-    Node? nextNode();
-    Node? previousNode();
+    [MayThrowException] Node? nextNode();
+    [MayThrowException] Node? previousNode();
 
     void detach();
 };
index 86690b0..683a110 100644 (file)
@@ -30,6 +30,7 @@
 
 #pragma once
 
+#include "CallbackResult.h"
 #include <wtf/RefCounted.h>
 
 namespace WebCore {
@@ -37,7 +38,7 @@ namespace WebCore {
 class RequestAnimationFrameCallback : public RefCounted<RequestAnimationFrameCallback> {
 public:
     virtual ~RequestAnimationFrameCallback() { }
-    virtual bool handleEvent(double highResTimeMs) = 0;
+    virtual CallbackResult<void> handleEvent(double highResTimeMs) = 0;
 
     int m_id;
     bool m_firedOrCancelled;
index 72771e1..6eee72e 100644 (file)
@@ -30,6 +30,7 @@
 
 #pragma once
 
+#include "CallbackResult.h"
 #include <wtf/Forward.h>
 #include <wtf/RefCounted.h>
 
@@ -40,7 +41,7 @@ class ScriptExecutionContext;
 class StringCallback : public RefCounted<StringCallback> {
 public:
     virtual ~StringCallback() { }
-    virtual bool handleEvent(const String& data) = 0;
+    virtual CallbackResult<void> handleEvent(const String& data) = 0;
 
     // Helper to post callback task.
     void scheduleCallback(ScriptExecutionContext&, const String& data);
index 3759a5b..3209e52 100644 (file)
@@ -37,7 +37,7 @@ NodeIteratorBase::NodeIteratorBase(Node& rootNode, unsigned whatToShow, RefPtr<N
 {
 }
 
-short NodeIteratorBase::acceptNode(Node& node) const
+CallbackResult<unsigned short> NodeIteratorBase::acceptNode(Node& node) const
 {
     // The bit twiddling here is done to map DOM node types, which are given as integers from
     // 1 through 14, to whatToShow bit masks.
@@ -45,6 +45,7 @@ short NodeIteratorBase::acceptNode(Node& node) const
         return NodeFilter::FILTER_SKIP;
     if (!m_filter)
         return NodeFilter::FILTER_ACCEPT;
+
     return m_filter->acceptNode(node);
 }
 
index cf13149..96f2fef 100644 (file)
@@ -24,6 +24,7 @@
 
 #pragma once
 
+#include "CallbackResult.h"
 #include <wtf/RefPtr.h>
 
 namespace WebCore {
@@ -41,7 +42,7 @@ public:
 
 protected:
     NodeIteratorBase(Node&, unsigned whatToShow, RefPtr<NodeFilter>&&);
-    short acceptNode(Node&) const;
+    CallbackResult<unsigned short> acceptNode(Node&) const;
 
 private:
     Ref<Node> m_root;
index 8927114..d96a85c 100644 (file)
@@ -26,8 +26,8 @@
 #include "TreeWalker.h"
 
 #include "ContainerNode.h"
+#include "ExceptionCode.h"
 #include "NodeTraversal.h"
-#include <runtime/JSCJSValueInlines.h>
 
 namespace WebCore {
 
@@ -48,24 +48,37 @@ inline Node* TreeWalker::setCurrent(Ref<Node>&& node)
     return m_current.ptr();
 }
 
-Node* TreeWalker::parentNode()
+ExceptionOr<Node*> TreeWalker::parentNode()
 {
     RefPtr<Node> node = m_current.ptr();
     while (node != &root()) {
         node = node->parentNode();
         if (!node)
             return nullptr;
-        short acceptNodeResult = acceptNode(*node);
+
+        auto callbackResult = acceptNode(*node);
+        if (callbackResult.type() == CallbackResultType::ExceptionThrown)
+            return Exception { ExistingExceptionError };
+
+        ASSERT(callbackResult.type() == CallbackResultType::Success);
+
+        auto acceptNodeResult = callbackResult.releaseReturnValue();
         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
             return setCurrent(node.releaseNonNull());
     }
     return nullptr;
 }
 
-Node* TreeWalker::firstChild()
+ExceptionOr<Node*> TreeWalker::firstChild()
 {
     for (RefPtr<Node> node = m_current->firstChild(); node; ) {
-        short acceptNodeResult = acceptNode(*node);
+        auto callbackResult = acceptNode(*node);
+        if (callbackResult.type() == CallbackResultType::ExceptionThrown)
+            return Exception { ExistingExceptionError };
+
+        ASSERT(callbackResult.type() == CallbackResultType::Success);
+
+        auto acceptNodeResult = callbackResult.releaseReturnValue();
         switch (acceptNodeResult) {
             case NodeFilter::FILTER_ACCEPT:
                 m_current = node.releaseNonNull();
@@ -93,10 +106,16 @@ Node* TreeWalker::firstChild()
     return nullptr;
 }
 
-Node* TreeWalker::lastChild()
+ExceptionOr<Node*> TreeWalker::lastChild()
 {
     for (RefPtr<Node> node = m_current->lastChild(); node; ) {
-        short acceptNodeResult = acceptNode(*node);
+        auto callbackResult = acceptNode(*node);
+        if (callbackResult.type() == CallbackResultType::ExceptionThrown)
+            return Exception { ExistingExceptionError };
+
+        ASSERT(callbackResult.type() == CallbackResultType::Success);
+
+        auto acceptNodeResult = callbackResult.releaseReturnValue();
         switch (acceptNodeResult) {
             case NodeFilter::FILTER_ACCEPT:
                 m_current = node.releaseNonNull();
@@ -124,7 +143,7 @@ Node* TreeWalker::lastChild()
     return nullptr;
 }
 
-template<TreeWalker::SiblingTraversalType type> Node* TreeWalker::traverseSiblings()
+template<TreeWalker::SiblingTraversalType type> ExceptionOr<Node*> TreeWalker::traverseSiblings()
 {
     RefPtr<Node> node = m_current.ptr();
     if (node == &root())
@@ -133,7 +152,13 @@ template<TreeWalker::SiblingTraversalType type> Node* TreeWalker::traverseSiblin
     auto isNext = type == SiblingTraversalType::Next;
     while (true) {
         for (RefPtr<Node> sibling = isNext ? node->nextSibling() : node->previousSibling(); sibling; ) {
-            short acceptNodeResult = acceptNode(*sibling);
+            auto callbackResult = acceptNode(*sibling);
+            if (callbackResult.type() == CallbackResultType::ExceptionThrown)
+                return Exception { ExistingExceptionError };
+
+            ASSERT(callbackResult.type() == CallbackResultType::Success);
+
+            auto acceptNodeResult = callbackResult.releaseReturnValue();
             if (acceptNodeResult == NodeFilter::FILTER_ACCEPT) {
                 m_current = sibling.releaseNonNull();
                 return m_current.ptr();
@@ -146,34 +171,55 @@ template<TreeWalker::SiblingTraversalType type> Node* TreeWalker::traverseSiblin
         node = node->parentNode();
         if (!node || node == &root())
             return nullptr;
-        short acceptNodeResult = acceptNode(*node);
+
+        auto callbackResult = acceptNode(*node);
+        if (callbackResult.type() == CallbackResultType::ExceptionThrown)
+            return Exception { ExistingExceptionError };
+
+        ASSERT(callbackResult.type() == CallbackResultType::Success);
+
+        auto acceptNodeResult = callbackResult.releaseReturnValue();
         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
             return nullptr;
     }
 }
 
-Node* TreeWalker::previousSibling()
+ExceptionOr<Node*> TreeWalker::previousSibling()
 {
     return traverseSiblings<SiblingTraversalType::Previous>();
 }
 
-Node* TreeWalker::nextSibling()
+ExceptionOr<Node*> TreeWalker::nextSibling()
 {
     return traverseSiblings<SiblingTraversalType::Next>();
 }
 
-Node* TreeWalker::previousNode()
+ExceptionOr<Node*> TreeWalker::previousNode()
 {
     RefPtr<Node> node = m_current.ptr();
     while (node != &root()) {
         while (Node* previousSibling = node->previousSibling()) {
             node = previousSibling;
-            short acceptNodeResult = acceptNode(*node);
+
+            auto callbackResult = acceptNode(*node);
+            if (callbackResult.type() == CallbackResultType::ExceptionThrown)
+                return Exception { ExistingExceptionError };
+
+            ASSERT(callbackResult.type() == CallbackResultType::Success);
+
+            auto acceptNodeResult = callbackResult.releaseReturnValue();
             if (acceptNodeResult == NodeFilter::FILTER_REJECT)
                 continue;
             while (Node* lastChild = node->lastChild()) {
                 node = lastChild;
-                acceptNodeResult = acceptNode(*node);
+
+                auto callbackResult = acceptNode(*node);
+                if (callbackResult.type() == CallbackResultType::ExceptionThrown)
+                    return Exception { ExistingExceptionError };
+
+                ASSERT(callbackResult.type() == CallbackResultType::Success);
+
+                acceptNodeResult = callbackResult.releaseReturnValue();
                 if (acceptNodeResult == NodeFilter::FILTER_REJECT)
                     break;
             }
@@ -188,20 +234,34 @@ Node* TreeWalker::previousNode()
         if (!parent)
             return nullptr;
         node = parent;
-        short acceptNodeResult = acceptNode(*node);
+
+        auto callbackResult = acceptNode(*node);
+        if (callbackResult.type() == CallbackResultType::ExceptionThrown)
+            return Exception { ExistingExceptionError };
+
+        ASSERT(callbackResult.type() == CallbackResultType::Success);
+
+        auto acceptNodeResult = callbackResult.releaseReturnValue();
         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
             return setCurrent(node.releaseNonNull());
     }
     return nullptr;
 }
 
-Node* TreeWalker::nextNode()
+ExceptionOr<Node*> TreeWalker::nextNode()
 {
     RefPtr<Node> node = m_current.ptr();
 Children:
     while (Node* firstChild = node->firstChild()) {
         node = firstChild;
-        short acceptNodeResult = acceptNode(*node);
+
+        auto callbackResult = acceptNode(*node);
+        if (callbackResult.type() == CallbackResultType::ExceptionThrown)
+            return Exception { ExistingExceptionError };
+
+        ASSERT(callbackResult.type() == CallbackResultType::Success);
+
+        auto acceptNodeResult = callbackResult.releaseReturnValue();
         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
             return setCurrent(node.releaseNonNull());
         if (acceptNodeResult == NodeFilter::FILTER_REJECT)
@@ -209,7 +269,14 @@ Children:
     }
     while (Node* nextSibling = NodeTraversal::nextSkippingChildren(*node, &root())) {
         node = nextSibling;
-        short acceptNodeResult = acceptNode(*node);
+
+        auto callbackResult = acceptNode(*node);
+        if (callbackResult.type() == CallbackResultType::ExceptionThrown)
+            return Exception { ExistingExceptionError };
+
+        ASSERT(callbackResult.type() == CallbackResultType::Success);
+
+        auto acceptNodeResult = callbackResult.releaseReturnValue();
         if (acceptNodeResult == NodeFilter::FILTER_ACCEPT)
             return setCurrent(node.releaseNonNull());
         if (acceptNodeResult == NodeFilter::FILTER_SKIP)
index 7270f2d..e1eec74 100644 (file)
@@ -24,6 +24,7 @@
 
 #pragma once
 
+#include "ExceptionOr.h"
 #include "NodeFilter.h"
 #include "ScriptWrappable.h"
 #include "Traversal.h"
 
 namespace WebCore {
 
-    class TreeWalker : public ScriptWrappable, public RefCounted<TreeWalker>, public NodeIteratorBase {
-    public:
-        static Ref<TreeWalker> create(Node& rootNode, unsigned long whatToShow, RefPtr<NodeFilter>&& filter)
-        {
-            return adoptRef(*new TreeWalker(rootNode, whatToShow, WTFMove(filter)));
-        }                            
+class TreeWalker : public ScriptWrappable, public RefCounted<TreeWalker>, public NodeIteratorBase {
+public:
+    static Ref<TreeWalker> create(Node& rootNode, unsigned long whatToShow, RefPtr<NodeFilter>&& filter)
+    {
+        return adoptRef(*new TreeWalker(rootNode, whatToShow, WTFMove(filter)));
+    }                            
 
-        Node& currentNode() { return m_current.get(); }
-        const Node& currentNode() const { return m_current.get(); }
+    Node& currentNode() { return m_current.get(); }
+    const Node& currentNode() const { return m_current.get(); }
 
-        WEBCORE_EXPORT void setCurrentNode(Node&);
+    WEBCORE_EXPORT void setCurrentNode(Node&);
 
-        WEBCORE_EXPORT Node* parentNode();
-        WEBCORE_EXPORT Node* firstChild();
-        WEBCORE_EXPORT Node* lastChild();
-        WEBCORE_EXPORT Node* previousSibling();
-        WEBCORE_EXPORT Node* nextSibling();
-        WEBCORE_EXPORT Node* previousNode();
-        WEBCORE_EXPORT Node* nextNode();
+    WEBCORE_EXPORT ExceptionOr<Node*> parentNode();
+    WEBCORE_EXPORT ExceptionOr<Node*> firstChild();
+    WEBCORE_EXPORT ExceptionOr<Node*> lastChild();
+    WEBCORE_EXPORT ExceptionOr<Node*> previousSibling();
+    WEBCORE_EXPORT ExceptionOr<Node*> nextSibling();
+    WEBCORE_EXPORT ExceptionOr<Node*> previousNode();
+    WEBCORE_EXPORT ExceptionOr<Node*> nextNode();
 
-    private:
-        TreeWalker(Node&, unsigned long whatToShow, RefPtr<NodeFilter>&&);
-        enum class SiblingTraversalType { Previous, Next };
-        template<SiblingTraversalType> Node* traverseSiblings();
-        
-        Node* setCurrent(Ref<Node>&&);
+private:
+    TreeWalker(Node&, unsigned long whatToShow, RefPtr<NodeFilter>&&);
 
-        Ref<Node> m_current;
-    };
+    enum class SiblingTraversalType { Previous, Next };
+    template<SiblingTraversalType> ExceptionOr<Node*> traverseSiblings();
+    
+    Node* setCurrent(Ref<Node>&&);
+
+    Ref<Node> m_current;
+};
 
 } // namespace WebCore
index f3ad1dc..e2bb376 100644 (file)
     readonly attribute NodeFilter? filter;
     attribute Node currentNode;
 
-    Node? parentNode();
-    Node? firstChild();
-    Node? lastChild();
-    Node? previousSibling();
-    Node? nextSibling();
-    Node? previousNode();
-    Node? nextNode();
+    [MayThrowException] Node? parentNode();
+    [MayThrowException] Node? firstChild();
+    [MayThrowException] Node? lastChild();
+    [MayThrowException] Node? previousSibling();
+    [MayThrowException] Node? nextSibling();
+    [MayThrowException] Node? previousNode();
+    [MayThrowException] Node? nextNode();
 };
index 23c6fc2..59f28dd 100644 (file)
@@ -25,6 +25,7 @@
 
 #pragma once
 
+#include "CallbackResult.h"
 #include <wtf/RefCounted.h>
 #include <wtf/RefPtr.h>
 
@@ -36,7 +37,7 @@ class ScriptExecutionContext;
 class BlobCallback : public RefCounted<BlobCallback> {
 public:
     virtual ~BlobCallback() { }
-    virtual bool handleEvent(Blob*) = 0;
+    virtual CallbackResult<void> handleEvent(Blob*) = 0;
 
     void scheduleCallback(ScriptExecutionContext&, RefPtr<Blob>&&);
 };
index 4d498b9..5e71633 100644 (file)
@@ -25,6 +25,7 @@
 
 #pragma once
 
+#include "CallbackResult.h"
 #include <wtf/RefCounted.h>
 
 namespace WebCore {
@@ -32,7 +33,7 @@ namespace WebCore {
 class VoidCallback : public RefCounted<VoidCallback> {
 public:
     virtual ~VoidCallback() { }
-    virtual bool handleEvent() = 0;
+    virtual CallbackResult<void> handleEvent() = 0;
 };
 
 } // namespace WebCore
index aa18653..bf38b5a 100644 (file)
@@ -75,7 +75,7 @@ private:
     StatementCallback(Ref<ExecuteSQLCallback>&& requestCallback)
         : m_requestCallback(WTFMove(requestCallback)) { }
 
-    bool handleEvent(SQLTransaction&, SQLResultSet& resultSet) final
+    CallbackResult<void> handleEvent(SQLTransaction&, SQLResultSet& resultSet) final
     {
         auto& rowList = resultSet.rows();
 
@@ -93,7 +93,7 @@ private:
             values->addItem(WTFMove(inspectorValue));
         }
         m_requestCallback->sendSuccess(WTFMove(columnNames), WTFMove(values), nullptr);
-        return true;
+        return { };
     }
 
     Ref<ExecuteSQLCallback> m_requestCallback;
@@ -110,7 +110,7 @@ private:
     StatementErrorCallback(Ref<ExecuteSQLCallback>&& requestCallback)
         : m_requestCallback(WTFMove(requestCallback)) { }
 
-    bool handleEvent(SQLTransaction&, SQLError& error) final
+    CallbackResult<bool> handleEvent(SQLTransaction&, SQLError& error) final
     {
         reportTransactionFailed(m_requestCallback.copyRef(), error);
         return true;
@@ -131,15 +131,15 @@ private:
         : m_sqlStatement(sqlStatement)
         , m_requestCallback(WTFMove(requestCallback)) { }
 
-    bool handleEvent(SQLTransaction& transaction) final
+    CallbackResult<void> handleEvent(SQLTransaction& transaction) final
     {
         if (!m_requestCallback->isActive())
-            return true;
+            return { };
 
         Ref<SQLStatementCallback> callback(StatementCallback::create(m_requestCallback.copyRef()));
         Ref<SQLStatementErrorCallback> errorCallback(StatementErrorCallback::create(m_requestCallback.copyRef()));
         transaction.executeSql(m_sqlStatement, { }, WTFMove(callback), WTFMove(errorCallback));
-        return true;
+        return { };
     }
 
     String m_sqlStatement;
@@ -157,10 +157,10 @@ private:
     TransactionErrorCallback(Ref<ExecuteSQLCallback>&& requestCallback)
         : m_requestCallback(WTFMove(requestCallback)) { }
 
-    bool handleEvent(SQLError& error) final
+    CallbackResult<void> handleEvent(SQLError& error) final
     {
         reportTransactionFailed(m_requestCallback.get(), error);
-        return true;
+        return { };
     }
 
     Ref<ExecuteSQLCallback> m_requestCallback;
@@ -173,7 +173,7 @@ public:
         return adoptRef(*new TransactionSuccessCallback());
     }
 
-    bool handleEvent() final { return false; }
+    CallbackResult<void> handleEvent() final { return { }; }
 
 private:
     TransactionSuccessCallback() { }
index e6e96f2..59ba7b0 100644 (file)
@@ -27,6 +27,7 @@
 
 #if ENABLE(INTERSECTION_OBSERVER)
 
+#include "CallbackResult.h"
 #include <wtf/RefCounted.h>
 #include <wtf/Vector.h>
 
@@ -38,7 +39,7 @@ class IntersectionObserverEntry;
 class IntersectionObserverCallback : public RefCounted<IntersectionObserverCallback> {
 public:
     virtual ~IntersectionObserverCallback() { }
-    virtual bool handleEvent(const Vector<RefPtr<IntersectionObserverEntry>>&, IntersectionObserver&) = 0;
+    virtual CallbackResult<void> handleEvent(const Vector<RefPtr<IntersectionObserverEntry>>&, IntersectionObserver&) = 0;
 };
 
 } // namespace WebCore
index 1b3a396..3c62d68 100644 (file)
@@ -27,6 +27,7 @@
 
 #if ENABLE(WEB_TIMING)
 
+#include "CallbackResult.h"
 #include <wtf/RefCounted.h>
 
 namespace WebCore {
@@ -37,7 +38,7 @@ class PerformanceObserverEntryList;
 class PerformanceObserverCallback : public RefCounted<PerformanceObserverCallback> {
 public:
     virtual ~PerformanceObserverCallback() { }
-    virtual bool handleEvent(PerformanceObserverEntryList&, PerformanceObserver&) = 0;
+    virtual CallbackResult<void> handleEvent(PerformanceObserverEntryList&, PerformanceObserver&) = 0;
 };
 
 } // namespace WebCore
index 341740d..3115f8d 100644 (file)
@@ -1,3 +1,25 @@
+2017-05-22  Sam Weinig  <sam@webkit.org>
+
+        [WebIDL] Support callbacks with arbitrary return types
+        https://bugs.webkit.org/show_bug.cgi?id=172407
+
+        Reviewed by Chris Dumez.
+
+        * DOM/DOM.mm:
+        (-[DOMNodeFilter acceptNode:]):
+        Update for CallbackResult adoption in the base class.
+
+        * DOM/DOMNodeIterator.mm:
+        * DOM/DOMTreeWalker.mm:
+        Update to account for new WebCore implementation return types. We return nil
+        if there was an exception, since retains the existing behavior if a javascript
+        NodeFilter had been used (an exception would cause all nodes to be rejected,
+        thus returning nullptr).
+
+        * DOM/ObjCNodeFilterCondition.h:
+        * DOM/ObjCNodeFilterCondition.mm:
+        Update to match new interface of NodeFilterCondition.
+
 2017-05-18  Sam Weinig  <sam@webkit.org>
 
         [WebIDL] Remove the need for the generator to know about native type mapping
index 33dbe7f..0ffa197 100644 (file)
@@ -861,7 +861,9 @@ WebCore::NodeFilter* core(DOMNodeFilter *wrapper)
 {
     if (!node)
         raiseTypeErrorException();
-    return core(self)->acceptNode(*core(node));
+    
+    auto result = core(self)->acceptNode(*core(node));
+    return result.type() == CallbackResultType::Success ? result.releaseReturnValue() : NodeFilter::FILTER_REJECT;
 }
 
 @end
index 1591fb0..6cb2b24 100644 (file)
 - (DOMNode *)nextNode
 {
     WebCore::JSMainThreadNullState state;
-    return kit(WTF::getPtr(IMPL->nextNode()));
+    
+    auto result = IMPL->nextNode();
+    if (result.hasException())
+        return nil;
+    
+    return kit(WTF::getPtr(result.releaseReturnValue()));
 }
 
 - (DOMNode *)previousNode
 {
     WebCore::JSMainThreadNullState state;
-    return kit(WTF::getPtr(IMPL->previousNode()));
+
+    auto result = IMPL->previousNode();
+    if (result.hasException())
+        return nil;
+    
+    return kit(WTF::getPtr(result.releaseReturnValue()));
 }
 
 - (void)detach
index fd7f5e2..de0419f 100644 (file)
 - (DOMNode *)parentNode
 {
     WebCore::JSMainThreadNullState state;
-    return kit(WTF::getPtr(IMPL->parentNode()));
+
+    auto result = IMPL->parentNode();
+    if (result.hasException())
+        return nil;
+    
+    return kit(WTF::getPtr(result.releaseReturnValue()));
 }
 
 - (DOMNode *)firstChild
 {
     WebCore::JSMainThreadNullState state;
-    return kit(WTF::getPtr(IMPL->firstChild()));
+
+    auto result = IMPL->firstChild();
+    if (result.hasException())
+        return nil;
+    
+    return kit(WTF::getPtr(result.releaseReturnValue()));
 }
 
 - (DOMNode *)lastChild
 {
     WebCore::JSMainThreadNullState state;
-    return kit(WTF::getPtr(IMPL->lastChild()));
+
+    auto result = IMPL->lastChild();
+    if (result.hasException())
+        return nil;
+    
+    return kit(WTF::getPtr(result.releaseReturnValue()));
 }
 
 - (DOMNode *)previousSibling
 {
     WebCore::JSMainThreadNullState state;
-    return kit(WTF::getPtr(IMPL->previousSibling()));
+
+    auto result = IMPL->previousSibling();
+    if (result.hasException())
+        return nil;
+    
+    return kit(WTF::getPtr(result.releaseReturnValue()));
 }
 
 - (DOMNode *)nextSibling
 {
     WebCore::JSMainThreadNullState state;
-    return kit(WTF::getPtr(IMPL->nextSibling()));
+
+    auto result = IMPL->nextSibling();
+    if (result.hasException())
+        return nil;
+    
+    return kit(WTF::getPtr(result.releaseReturnValue()));
 }
 
 - (DOMNode *)previousNode
 {
     WebCore::JSMainThreadNullState state;
-    return kit(WTF::getPtr(IMPL->previousNode()));
+
+    auto result = IMPL->previousNode();
+    if (result.hasException())
+        return nil;
+    
+    return kit(WTF::getPtr(result.releaseReturnValue()));
 }
 
 - (DOMNode *)nextNode
 {
     WebCore::JSMainThreadNullState state;
-    return kit(WTF::getPtr(IMPL->nextNode()));
+
+    auto result = IMPL->nextNode();
+    if (result.hasException())
+        return nil;
+    
+    return kit(WTF::getPtr(result.releaseReturnValue()));
 }
 
 @end
index 00ed114..5cca9d4 100644 (file)
 
 namespace WebCore {
 
-    class Node;
+class Node;
 
-    class ObjCNodeFilterCondition : public NodeFilterCondition {
-    public:
-        static Ref<ObjCNodeFilterCondition> create(id <DOMNodeFilter> filter)
-        {
-            return adoptRef(*new ObjCNodeFilterCondition(filter));
-        }
+class ObjCNodeFilterCondition final : public NodeFilterCondition {
+public:
+    static Ref<ObjCNodeFilterCondition> create(id <DOMNodeFilter> filter)
+    {
+        return adoptRef(*new ObjCNodeFilterCondition(filter));
+    }
 
-        virtual short acceptNode(Node*) const;
+    unsigned short acceptNode(Node&) const override;
 
-    private:
-        ObjCNodeFilterCondition(id <DOMNodeFilter> filter)
-            : m_filter(filter)
-        {
-        }
+private:
+    ObjCNodeFilterCondition(id <DOMNodeFilter> filter)
+        : m_filter(filter)
+    {
+    }
 
-        RetainPtr<id <DOMNodeFilter> > m_filter;
-    };
+    RetainPtr<id <DOMNodeFilter> > m_filter;
+};
 
 } // namespace WebCore
index 0b5f1d2..e686d80 100644 (file)
 
 namespace WebCore {
 
-short ObjCNodeFilterCondition::acceptNode(Node* node) const
+unsigned short ObjCNodeFilterCondition::acceptNode(Node& node) const
 {
-    if (!node)
-        return NodeFilter::FILTER_REJECT;
-    return [m_filter.get() acceptNode:kit(node)];
+    return [m_filter.get() acceptNode:kit(&node)];
 }
 
 } // namespace WebCore
index 7227979..6767419 100644 (file)
@@ -1,3 +1,18 @@
+2017-05-22  Sam Weinig  <sam@webkit.org>
+
+        [WebIDL] Support callbacks with arbitrary return types
+        https://bugs.webkit.org/show_bug.cgi?id=172407
+
+        Reviewed by Chris Dumez.
+
+        * WebProcess/InjectedBundle/API/gtk/DOM/GObjectNodeFilterCondition.cpp:
+        * WebProcess/InjectedBundle/API/gtk/DOM/GObjectNodeFilterCondition.h:
+        Update to match new interface of NodeFilterCondition.
+
+        * WebProcess/InjectedBundle/API/gtk/DOM/WebKitDOMNodeIterator.cpp:
+        * WebProcess/InjectedBundle/API/gtk/DOM/WebKitDOMTreeWalker.cpp:
+        Update to account for new WebCore implementation return types.
+
 2017-05-22  Michael Catanzaro  <mcatanzaro@igalia.com>
 
         -Wreturn-type warning triggered by WKPage.cpp:2277
index 43ea1af..a0665b5 100644 (file)
@@ -31,11 +31,9 @@ GObjectNodeFilterCondition::~GObjectNodeFilterCondition()
     g_object_set_data(G_OBJECT(m_filter.get()), "webkit-core-node-filter", nullptr);
 }
 
-short GObjectNodeFilterCondition::acceptNode(Node* node) const
+unsigned short GObjectNodeFilterCondition::acceptNode(Node& node) const
 {
-    if (!node)
-        return NodeFilter::FILTER_REJECT;
-    return webkit_dom_node_filter_accept_node(m_filter.get(), WebKit::kit(node));
+    return webkit_dom_node_filter_accept_node(m_filter.get(), WebKit::kit(&node));
 }
 
 } // namespace WebKit
index 1ed1c7c..3bfce0f 100644 (file)
@@ -28,15 +28,14 @@ class Node;
 
 namespace WebKit {
 
-class GObjectNodeFilterCondition : public WebCore::NodeFilterCondition {
+class GObjectNodeFilterCondition final : public WebCore::NodeFilterCondition {
 public:
-
     static Ref<GObjectNodeFilterCondition> create(WebKitDOMNodeFilter* filter)
     {
         return adoptRef(*new GObjectNodeFilterCondition(filter));
     }
 
-    short acceptNode(WebCore::Node*) const override;
+    unsigned short acceptNode(WebCore::Node&) const override;
 
 private:
     GObjectNodeFilterCondition(WebKitDOMNodeFilter* filter)
index ea74a0a..20a9055 100644 (file)
@@ -196,7 +196,12 @@ WebKitDOMNode* webkit_dom_node_iterator_next_node(WebKitDOMNodeIterator* self, G
     g_return_val_if_fail(WEBKIT_DOM_IS_NODE_ITERATOR(self), 0);
     UNUSED_PARAM(error);
     WebCore::NodeIterator* item = WebKit::core(self);
-    RefPtr<WebCore::Node> gobjectResult = WTF::getPtr(item->nextNode());
+
+    auto result = item->nextNode();
+    if (result.hasException())
+        return nullptr;
+
+    RefPtr<WebCore::Node> gobjectResult = WTF::getPtr(result.releaseReturnValue());
     return WebKit::kit(gobjectResult.get());
 }
 
@@ -206,7 +211,12 @@ WebKitDOMNode* webkit_dom_node_iterator_previous_node(WebKitDOMNodeIterator* sel
     g_return_val_if_fail(WEBKIT_DOM_IS_NODE_ITERATOR(self), 0);
     UNUSED_PARAM(error);
     WebCore::NodeIterator* item = WebKit::core(self);
-    RefPtr<WebCore::Node> gobjectResult = WTF::getPtr(item->previousNode());
+
+    auto result = item->previousNode();
+    if (result.hasException())
+        return nullptr;
+
+    RefPtr<WebCore::Node> gobjectResult = WTF::getPtr(result.releaseReturnValue());
     return WebKit::kit(gobjectResult.get());
 }
 
index 8df3088..a24a530 100644 (file)
@@ -181,7 +181,12 @@ WebKitDOMNode* webkit_dom_tree_walker_parent_node(WebKitDOMTreeWalker* self)
     WebCore::JSMainThreadNullState state;
     g_return_val_if_fail(WEBKIT_DOM_IS_TREE_WALKER(self), 0);
     WebCore::TreeWalker* item = WebKit::core(self);
-    RefPtr<WebCore::Node> gobjectResult = WTF::getPtr(item->parentNode());
+
+    auto result = item->parentNode();
+    if (result.hasException())
+        return nullptr;
+
+    RefPtr<WebCore::Node> gobjectResult = WTF::getPtr(result.releaseReturnValue());
     return WebKit::kit(gobjectResult.get());
 }
 
@@ -190,7 +195,12 @@ WebKitDOMNode* webkit_dom_tree_walker_first_child(WebKitDOMTreeWalker* self)
     WebCore::JSMainThreadNullState state;
     g_return_val_if_fail(WEBKIT_DOM_IS_TREE_WALKER(self), 0);
     WebCore::TreeWalker* item = WebKit::core(self);
-    RefPtr<WebCore::Node> gobjectResult = WTF::getPtr(item->firstChild());
+
+    auto result = item->firstChild();
+    if (result.hasException())
+        return nullptr;
+
+    RefPtr<WebCore::Node> gobjectResult = WTF::getPtr(result.releaseReturnValue());
     return WebKit::kit(gobjectResult.get());
 }
 
@@ -199,7 +209,12 @@ WebKitDOMNode* webkit_dom_tree_walker_last_child(WebKitDOMTreeWalker* self)
     WebCore::JSMainThreadNullState state;
     g_return_val_if_fail(WEBKIT_DOM_IS_TREE_WALKER(self), 0);
     WebCore::TreeWalker* item = WebKit::core(self);
-    RefPtr<WebCore::Node> gobjectResult = WTF::getPtr(item->lastChild());
+
+    auto result = item->lastChild();
+    if (result.hasException())
+        return nullptr;
+
+    RefPtr<WebCore::Node> gobjectResult = WTF::getPtr(result.releaseReturnValue());
     return WebKit::kit(gobjectResult.get());
 }
 
@@ -208,7 +223,12 @@ WebKitDOMNode* webkit_dom_tree_walker_previous_sibling(WebKitDOMTreeWalker* self
     WebCore::JSMainThreadNullState state;
     g_return_val_if_fail(WEBKIT_DOM_IS_TREE_WALKER(self), 0);
     WebCore::TreeWalker* item = WebKit::core(self);
-    RefPtr<WebCore::Node> gobjectResult = WTF::getPtr(item->previousSibling());
+
+    auto result = item->previousSibling();
+    if (result.hasException())
+        return nullptr;
+
+    RefPtr<WebCore::Node> gobjectResult = WTF::getPtr(result.releaseReturnValue());
     return WebKit::kit(gobjectResult.get());
 }
 
@@ -217,7 +237,12 @@ WebKitDOMNode* webkit_dom_tree_walker_next_sibling(WebKitDOMTreeWalker* self)
     WebCore::JSMainThreadNullState state;
     g_return_val_if_fail(WEBKIT_DOM_IS_TREE_WALKER(self), 0);
     WebCore::TreeWalker* item = WebKit::core(self);
-    RefPtr<WebCore::Node> gobjectResult = WTF::getPtr(item->nextSibling());
+
+    auto result = item->nextSibling();
+    if (result.hasException())
+        return nullptr;
+
+    RefPtr<WebCore::Node> gobjectResult = WTF::getPtr(result.releaseReturnValue());
     return WebKit::kit(gobjectResult.get());
 }
 
@@ -226,7 +251,12 @@ WebKitDOMNode* webkit_dom_tree_walker_previous_node(WebKitDOMTreeWalker* self)
     WebCore::JSMainThreadNullState state;
     g_return_val_if_fail(WEBKIT_DOM_IS_TREE_WALKER(self), 0);
     WebCore::TreeWalker* item = WebKit::core(self);
-    RefPtr<WebCore::Node> gobjectResult = WTF::getPtr(item->previousNode());
+
+    auto result = item->previousNode();
+    if (result.hasException())
+        return nullptr;
+
+    RefPtr<WebCore::Node> gobjectResult = WTF::getPtr(result.releaseReturnValue());
     return WebKit::kit(gobjectResult.get());
 }
 
@@ -235,7 +265,12 @@ WebKitDOMNode* webkit_dom_tree_walker_next_node(WebKitDOMTreeWalker* self)
     WebCore::JSMainThreadNullState state;
     g_return_val_if_fail(WEBKIT_DOM_IS_TREE_WALKER(self), 0);
     WebCore::TreeWalker* item = WebKit::core(self);
-    RefPtr<WebCore::Node> gobjectResult = WTF::getPtr(item->nextNode());
+
+    auto result = item->nextNode();
+    if (result.hasException())
+        return nullptr;
+
+    RefPtr<WebCore::Node> gobjectResult = WTF::getPtr(result.releaseReturnValue());
     return WebKit::kit(gobjectResult.get());
 }