UIScriptController: script with no async tasks fails if an earlier script registered...
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 16 Nov 2016 00:23:39 +0000 (00:23 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 16 Nov 2016 00:23:39 +0000 (00:23 +0000)
https://bugs.webkit.org/show_bug.cgi?id=164762

Reviewed by Wenson Hsieh.
Tools:

UIScriptContext::runUIScript() considers a script to be "immediate" if that script doesn't
queue any async tasks. However, if an earlier UI script registered a callback, UIScriptContext::runUIScript()
would consider that an outstanding task.

Fix by unregistering any callbacks associated with the current UI script when uiScriptComplete() is called.

* TestRunnerShared/UIScriptContext/UIScriptContext.cpp:
(UIScriptContext::tryToCompleteUIScriptForCurrentParentCallback):

LayoutTests:

* fast/harness/ui-side-script-with-callback-expected.txt: Added.
* fast/harness/ui-side-script-with-callback.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/fast/harness/ui-side-script-with-callback-expected.txt [new file with mode: 0644]
LayoutTests/fast/harness/ui-side-script-with-callback.html [new file with mode: 0644]
Tools/ChangeLog
Tools/TestRunnerShared/UIScriptContext/UIScriptContext.cpp

index 1fdc6a8..a34a4d4 100644 (file)
@@ -1,5 +1,15 @@
 2016-11-15  Simon Fraser  <simon.fraser@apple.com>
 
+        UIScriptController: script with no async tasks fails if an earlier script registered a callback
+        https://bugs.webkit.org/show_bug.cgi?id=164762
+
+        Reviewed by Wenson Hsieh.
+
+        * fast/harness/ui-side-script-with-callback-expected.txt: Added.
+        * fast/harness/ui-side-script-with-callback.html: Added.
+
+2016-11-15  Simon Fraser  <simon.fraser@apple.com>
+
         UIScriptController: setting a callback to undefined should unregister it
         https://bugs.webkit.org/show_bug.cgi?id=164796
 
diff --git a/LayoutTests/fast/harness/ui-side-script-with-callback-expected.txt b/LayoutTests/fast/harness/ui-side-script-with-callback-expected.txt
new file mode 100644 (file)
index 0000000..ac1b014
--- /dev/null
@@ -0,0 +1,11 @@
+Test that a second immediate UI script returns if an earlier script registered a callback
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+PASS scriptResult is "async task complete"
+PASS scriptResult is "immediate script complete"
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/harness/ui-side-script-with-callback.html b/LayoutTests/fast/harness/ui-side-script-with-callback.html
new file mode 100644 (file)
index 0000000..ea3e48b
--- /dev/null
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+
+<html>
+<head>
+    <script src="../../resources/js-test-pre.js"></script>
+    <script>
+        
+        var jsTestIsAsync = true;
+        
+        function getAsyncTaskScript()
+        {
+            return `(function() {
+                uiController.willBeginZoomingCallback = function() {};
+
+                uiController.doAsyncTask(function() {
+                    uiController.uiScriptComplete('async task complete');
+                });
+            })();`;
+        }
+
+        function getImmediateScript()
+        {
+            return `(function() {
+                return 'immediate script complete';
+            })();`;
+        }
+    
+        var scriptResult;
+        function runTest()
+        {
+            description('Test that a second immediate UI script returns if an earlier script registered a callback');
+
+            if (!window.testRunner) {
+                debug('This test requires testRunner');
+                return;
+            }
+
+            if (!testRunner.runUIScript) {
+                debug('This test requires runUIScript');
+                return;
+            }
+
+            testRunner.runUIScript(getAsyncTaskScript(), function(result) {
+                scriptResult = result;
+                shouldBeEqualToString('scriptResult', 'async task complete');
+
+                testRunner.runUIScript(getImmediateScript(), function(result) {
+                    scriptResult = result;
+                    shouldBeEqualToString('scriptResult', 'immediate script complete');
+                    finishJSTest();
+                });
+            });
+        }
+        window.addEventListener('load', runTest, false);
+    </script>
+</head>
+<body>
+
+<pre id="results"></pre>
+<script src="../../resources/js-test-post.js"></script>
+</body>
+</html>
index 1e3dfe5..5cbf954 100644 (file)
@@ -1,5 +1,21 @@
 2016-11-15  Simon Fraser  <simon.fraser@apple.com>
 
+        UIScriptController: script with no async tasks fails if an earlier script registered a callback
+        https://bugs.webkit.org/show_bug.cgi?id=164762
+
+        Reviewed by Wenson Hsieh.
+        
+        UIScriptContext::runUIScript() considers a script to be "immediate" if that script doesn't
+        queue any async tasks. However, if an earlier UI script registered a callback, UIScriptContext::runUIScript()
+        would consider that an outstanding task.
+        
+        Fix by unregistering any callbacks associated with the current UI script when uiScriptComplete() is called.
+
+        * TestRunnerShared/UIScriptContext/UIScriptContext.cpp:
+        (UIScriptContext::tryToCompleteUIScriptForCurrentParentCallback):
+
+2016-11-15  Simon Fraser  <simon.fraser@apple.com>
+
         UIScriptController: setting a callback to undefined should unregister it
         https://bugs.webkit.org/show_bug.cgi?id=164796
 
index bb5c9e8..62d4f30 100644 (file)
@@ -172,6 +172,12 @@ void UIScriptContext::tryToCompleteUIScriptForCurrentParentCallback()
     String scriptResult(JSStringGetCharactersPtr(result), JSStringGetLength(result));
 
     m_delegate.uiScriptDidComplete(scriptResult, m_currentScriptCallbackID);
+    
+    // Unregister tasks associated with this callback
+    m_callbacks.removeIf([&](auto& keyAndValue) {
+        return keyAndValue.value.parentScriptCallbackID == m_currentScriptCallbackID;
+    });
+    
     m_currentScriptCallbackID = 0;
     if (result)
         JSStringRelease(result);