Web Inspector: Include ConsoleAgent in Workers - real console.log support
authorjoepeck@webkit.org <joepeck@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 27 Oct 2016 22:19:33 +0000 (22:19 +0000)
committerjoepeck@webkit.org <joepeck@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 27 Oct 2016 22:19:33 +0000 (22:19 +0000)
https://bugs.webkit.org/show_bug.cgi?id=163844
<rdar://problem/28903328>

Reviewed by Brian Burg.

LayoutTests/imported/w3c:

* web-platform-tests/fetch/api/policies/csp-blocked-worker-expected.txt:
* web-platform-tests/streams/readable-streams/garbage-collection.https-expected.txt:

Source/JavaScriptCore:

* inspector/protocol/Worker.json:

Source/WebCore:

Test: inspector/worker/console-basic.html

This introduces a real ConsoleAgent in the Worker InspectorController.
We no longer need to pass partial ConsoleMessage objects to be logged
through the Page, we can just send the full ConsoleMessages to a
frontend once it connects to the Worker.

In order to guarantee that the Worker InspectorController is properly
all Workers will start paused if there is an Inspector attached to
the Page. The frontend _must_ call the new Worker.initialized method
after sending its setup commands to the Worker. This ensures we get
handle all initialization commands (like Agent.enable(), and
setting state like breakpoints) before any script executes in the
Worker. This mirrors the Inspector.initialized method that does the
same thing for JSContext auto-attach of the Main target.

In the backend, the wait until initialized state is just running
the WorkerThread's RunLoop in a special debugger mode to only process
debugger commands until we are ready. This will effectively be
the same as pausing so it is generalized into WorkerThread.

* CMakeLists.txt:
* WebCore.xcodeproj/project.pbxproj:
* inspector/InspectorAllInOne.cpp:
New files.

* inspector/InspectorWorkerAgent.cpp:
(WebCore::InspectorWorkerAgent::initialized):
(WebCore::InspectorWorkerAgent::shouldWaitForDebuggerOnStart):
* inspector/InspectorWorkerAgent.h:
Add the new initialized method. This just uses the proxy to send
a message to be handled on the Worker Thread and unpause.

* inspector/WorkerConsoleAgent.cpp:
(WebCore::WorkerConsoleAgent::WorkerConsoleAgent):
(WebCore::WorkerConsoleAgent::addInspectedNode):
* inspector/WorkerConsoleAgent.h:
* inspector/WorkerInspectorController.cpp:
(WebCore::WorkerInspectorController::WorkerInspectorController):
Add a ConsoleAgent to WorkerInspectorController.

* workers/WorkerInspectorProxy.h:
* workers/WorkerInspectorProxy.cpp:
(WebCore::WorkerInspectorProxy::workerStartMode):
(WebCore::WorkerInspectorProxy::resumeWorkerIfPaused):
(WebCore::WorkerInspectorProxy::connectToWorkerInspector):
(WebCore::WorkerInspectorProxy::disconnectFromWorkerInspector):
(WebCore::WorkerInspectorProxy::sendMessageToWorkerInspector):
Use the debugger mode when sending messages to the WorkerThread.

* workers/Worker.cpp:
(WebCore::Worker::notifyFinished):
* workers/WorkerMessagingProxy.cpp:
(WebCore::WorkerMessagingProxy::startWorkerGlobalScope):
(WebCore::WorkerMessagingProxy::postConsoleMessageToWorkerObject): Deleted.
* workers/WorkerMessagingProxy.h:
* workers/WorkerReportingProxy.h:
* workers/WorkerGlobalScope.cpp:
(WebCore::WorkerGlobalScope::addConsoleMessage):
(WebCore::WorkerGlobalScope::addMessage):
* workers/WorkerGlobalScope.h:
* workers/WorkerGlobalScopeProxy.h:
Remove legacy partial console support.

* workers/WorkerRunLoop.h:
* workers/WorkerRunLoop.cpp:
(WebCore::WorkerRunLoop::debuggerMode):
* workers/WorkerThread.h:
* workers/WorkerThread.cpp:
(WebCore::WorkerThread::workerThread):
(WebCore::WorkerThread::startRunningDebuggerTasks):
(WebCore::WorkerThread::stopRunningDebuggerTasks):
General code for spinning the WorkerThread and only processing debugger
(Inspector) commands. Use this when starting the thread to ensure the
frontend initializes the Worker's Agents before any JavaScript executes.

* page/PageConsoleClient.cpp:
* workers/WorkerConsoleClient.cpp:
(WebCore::WorkerConsoleClient::count):
(WebCore::WorkerConsoleClient::time):
(WebCore::WorkerConsoleClient::timeEnd):
* inspector/InspectorConsoleInstrumentation.h: Removed.
* inspector/InspectorInstrumentation.cpp:
(WebCore::InspectorInstrumentation::startConsoleTimingImpl):
(WebCore::InspectorInstrumentation::stopConsoleTimingImpl):
(WebCore::InspectorInstrumentation::shouldWaitForDebuggerOnStartImpl):
* inspector/InspectorInstrumentation.h:
(WebCore::InspectorInstrumentation::shouldWaitForDebuggerOnStart):
(WebCore::InspectorInstrumentation::addMessageToConsole):
(WebCore::InspectorInstrumentation::consoleCount):
(WebCore::InspectorInstrumentation::takeHeapSnapshot):
(WebCore::InspectorInstrumentation::startConsoleTiming):
(WebCore::InspectorInstrumentation::stopConsoleTiming):
(WebCore::InspectorInstrumentation::consoleTimeStamp):
(WebCore::InspectorInstrumentation::startProfiling):
(WebCore::InspectorInstrumentation::stopProfiling):
Implement a few more basic console APIs that required ConsoleAgent.

Source/WebInspectorUI:

* UserInterface/Protocol/Target.js:
(WebInspector.Target.prototype.get ConsoleAgent):
(WebInspector.Target.prototype._initializeNonMainTarget):
* UserInterface/Protocol/Connection.js:
(InspectorBackend.WorkerConnection):
Add ConsoleAgent.

* UserInterface/Controllers/LogManager.js:
(WebInspector.LogManager.prototype.messageWasAdded):
(WebInspector.LogManager.prototype.requestClearMessages):
Handle ConsoleAgent calls with multiple targets.

* UserInterface/Protocol/ConsoleObserver.js:
(WebInspector.ConsoleObserver.prototype.messageAdded):
Dispatch with the target in case we create Model objects.

* UserInterface/Controllers/WorkerManager.js:
(WebInspector.WorkerManager.prototype.workerCreated):
The frontend must now call "initialized" on Workers after
sending our setup messages (enable, set breakpoints, etc).

* UserInterface/Protocol/RemoteObject.js:
(WebInspector.RemoteObject.prototype.get target):
Expose an accessor for tests.

* UserInterface/Protocol/LoggingProtocolTracer.js:
(WebInspector.LoggingProtocolTracer.prototype._processEntry):
Actually output the Exception, useful when debugging failures in tests.

LayoutTests:

* inspector/console/messageAdded-from-worker-expected.txt: Removed.
* inspector/console/messageAdded-from-worker.html: Removed.
* inspector/console/resources/worker-console-log.js: Removed.
Remove the old partial console in Worker test.

* inspector/worker/console-basic-expected.txt: Added.
* inspector/worker/console-basic.html: Added.
* inspector/worker/resources/worker-console.js: Added.
New console in Worker test.

* inspector/worker/worker-create-and-terminate.html:
The frontend must call initialize on Workers, otherwise they
are paused forever.

* http/tests/security/contentSecurityPolicy/worker-blob-inherits-csp-expected.txt:
* http/tests/security/contentSecurityPolicy/worker-blob-inherits-csp-importScripts-block-aborts-all-subsequent-imports-expected.txt:
* http/tests/security/contentSecurityPolicy/worker-connect-src-blocked-expected.txt:
* http/tests/security/contentSecurityPolicy/worker-csp-blocks-xhr-redirect-cross-origin-expected.txt:
* http/tests/security/contentSecurityPolicy/worker-importscripts-blocked-expected.txt:
* http/tests/security/contentSecurityPolicy/worker-multiple-csp-headers-expected.txt:
* http/tests/security/contentSecurityPolicy/worker-set-timeout-blocked-expected.txt:
* http/tests/websocket/tests/hybi/workers/close-expected.txt:
* http/tests/xmlhttprequest/workers/access-control-basic-get-fail-non-simple-expected.txt:
* security/contentSecurityPolicy/worker-inherits-blocks-xhr-expected.txt:
Rebaseline. We no longer send Worker console messages through the Page, and likewise
we don't send them to the WebKit client, so they will no longer appear in test output.

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

62 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/security/contentSecurityPolicy/worker-blob-inherits-csp-expected.txt
LayoutTests/http/tests/security/contentSecurityPolicy/worker-blob-inherits-csp-importScripts-block-aborts-all-subsequent-imports-expected.txt
LayoutTests/http/tests/security/contentSecurityPolicy/worker-connect-src-blocked-expected.txt
LayoutTests/http/tests/security/contentSecurityPolicy/worker-csp-blocks-xhr-redirect-cross-origin-expected.txt
LayoutTests/http/tests/security/contentSecurityPolicy/worker-importscripts-blocked-expected.txt
LayoutTests/http/tests/security/contentSecurityPolicy/worker-multiple-csp-headers-expected.txt
LayoutTests/http/tests/security/contentSecurityPolicy/worker-set-timeout-blocked-expected.txt
LayoutTests/http/tests/websocket/tests/hybi/workers/close-expected.txt
LayoutTests/http/tests/xmlhttprequest/workers/access-control-basic-get-fail-non-simple-expected.txt
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/fetch/api/policies/csp-blocked-worker-expected.txt
LayoutTests/imported/w3c/web-platform-tests/streams/readable-streams/garbage-collection.https-expected.txt
LayoutTests/inspector/console/messageAdded-from-worker-expected.txt [deleted file]
LayoutTests/inspector/console/messageAdded-from-worker.html [deleted file]
LayoutTests/inspector/console/resources/worker-console-log.js [deleted file]
LayoutTests/inspector/worker/console-basic-expected.txt [new file with mode: 0644]
LayoutTests/inspector/worker/console-basic.html [new file with mode: 0644]
LayoutTests/inspector/worker/resources/worker-console.js [new file with mode: 0644]
LayoutTests/inspector/worker/worker-create-and-terminate.html
LayoutTests/security/contentSecurityPolicy/worker-inherits-blocks-xhr-expected.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/inspector/protocol/Worker.json
Source/WebCore/CMakeLists.txt
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/inspector/InspectorAllInOne.cpp
Source/WebCore/inspector/InspectorConsoleInstrumentation.h [deleted file]
Source/WebCore/inspector/InspectorInstrumentation.cpp
Source/WebCore/inspector/InspectorInstrumentation.h
Source/WebCore/inspector/InspectorWorkerAgent.cpp
Source/WebCore/inspector/InspectorWorkerAgent.h
Source/WebCore/inspector/WorkerConsoleAgent.cpp [new file with mode: 0644]
Source/WebCore/inspector/WorkerConsoleAgent.h [new file with mode: 0644]
Source/WebCore/inspector/WorkerInspectorController.cpp
Source/WebCore/page/PageConsoleClient.cpp
Source/WebCore/workers/Worker.cpp
Source/WebCore/workers/WorkerConsoleClient.cpp
Source/WebCore/workers/WorkerGlobalScope.cpp
Source/WebCore/workers/WorkerGlobalScope.h
Source/WebCore/workers/WorkerGlobalScopeProxy.h
Source/WebCore/workers/WorkerInspectorProxy.cpp
Source/WebCore/workers/WorkerInspectorProxy.h
Source/WebCore/workers/WorkerMessagingProxy.cpp
Source/WebCore/workers/WorkerMessagingProxy.h
Source/WebCore/workers/WorkerReportingProxy.h
Source/WebCore/workers/WorkerRunLoop.cpp
Source/WebCore/workers/WorkerRunLoop.h
Source/WebCore/workers/WorkerThread.cpp
Source/WebCore/workers/WorkerThread.h
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/UserInterface/Controllers/JavaScriptLogViewController.js
Source/WebInspectorUI/UserInterface/Controllers/LogManager.js
Source/WebInspectorUI/UserInterface/Controllers/WorkerManager.js
Source/WebInspectorUI/UserInterface/Models/ConsoleCommandResultMessage.js
Source/WebInspectorUI/UserInterface/Models/ConsoleMessage.js
Source/WebInspectorUI/UserInterface/Protocol/Connection.js
Source/WebInspectorUI/UserInterface/Protocol/ConsoleObserver.js
Source/WebInspectorUI/UserInterface/Protocol/LoggingProtocolTracer.js
Source/WebInspectorUI/UserInterface/Protocol/RemoteObject.js
Source/WebInspectorUI/UserInterface/Protocol/Target.js
Source/WebInspectorUI/UserInterface/Views/ConsoleMessageView.js

index 164abbe..e7d4b63 100644 (file)
@@ -1,5 +1,40 @@
 2016-10-27  Joseph Pecoraro  <pecoraro@apple.com>
 
+        Web Inspector: Include ConsoleAgent in Workers - real console.log support
+        https://bugs.webkit.org/show_bug.cgi?id=163844
+        <rdar://problem/28903328>
+
+        Reviewed by Brian Burg.
+
+        * inspector/console/messageAdded-from-worker-expected.txt: Removed.
+        * inspector/console/messageAdded-from-worker.html: Removed.
+        * inspector/console/resources/worker-console-log.js: Removed.
+        Remove the old partial console in Worker test.
+
+        * inspector/worker/console-basic-expected.txt: Added.
+        * inspector/worker/console-basic.html: Added.
+        * inspector/worker/resources/worker-console.js: Added.
+        New console in Worker test.
+
+        * inspector/worker/worker-create-and-terminate.html:
+        The frontend must call initialize on Workers, otherwise they
+        are paused forever.
+
+        * http/tests/security/contentSecurityPolicy/worker-blob-inherits-csp-expected.txt:
+        * http/tests/security/contentSecurityPolicy/worker-blob-inherits-csp-importScripts-block-aborts-all-subsequent-imports-expected.txt:
+        * http/tests/security/contentSecurityPolicy/worker-connect-src-blocked-expected.txt:
+        * http/tests/security/contentSecurityPolicy/worker-csp-blocks-xhr-redirect-cross-origin-expected.txt:
+        * http/tests/security/contentSecurityPolicy/worker-importscripts-blocked-expected.txt:
+        * http/tests/security/contentSecurityPolicy/worker-multiple-csp-headers-expected.txt:
+        * http/tests/security/contentSecurityPolicy/worker-set-timeout-blocked-expected.txt:
+        * http/tests/websocket/tests/hybi/workers/close-expected.txt:
+        * http/tests/xmlhttprequest/workers/access-control-basic-get-fail-non-simple-expected.txt:
+        * security/contentSecurityPolicy/worker-inherits-blocks-xhr-expected.txt:
+        Rebaseline. We no longer send Worker console messages through the Page, and likewise
+        we don't send them to the WebKit client, so they will no longer appear in test output.
+
+2016-10-27  Joseph Pecoraro  <pecoraro@apple.com>
+
         Web Inspector: Include RuntimeAgent in Workers - evaluate in Worker context
         https://bugs.webkit.org/show_bug.cgi?id=163835
         <rdar://problem/28901465>
index 89c7007..0aad67e 100644 (file)
@@ -1,4 +1,3 @@
-CONSOLE MESSAGE: Refused to load http://localhost:8000/security/contentSecurityPolicy/resources/post-message.js because it does not appear in the script-src directive of the Content Security Policy.
 
 PASS Blob worker inherits CSP 
 
index 263de57..152e679 100644 (file)
@@ -1,4 +1,3 @@
-CONSOLE MESSAGE: Refused to load http://localhost:8000/workers/resources/worker-importScripts-source1.js because it does not appear in the script-src directive of the Content Security Policy.
 This tests that when calling WorkerGlobalScope.importScripts() will two script URLs that the second script is not loaded if the first script URL was blocked by the Content Security Policy of the worker (inherited from this page).
 
 PASS threw exception NetworkError (DOM Exception 19):  A network error occurred..
index 4432c7b..978ee85 100644 (file)
@@ -1,3 +1,2 @@
-CONSOLE MESSAGE: Refused to connect to http://127.0.0.1:8000/xmlhttprequest/resources/get.txt because it does not appear in the connect-src directive of the Content Security Policy.
 ALERT: xhr blocked
 
index 54e3172..c2510ab 100644 (file)
@@ -1,4 +1,3 @@
-CONSOLE MESSAGE: XMLHttpRequest cannot load http://127.0.0.1:8000/security/contentSecurityPolicy/resources/redir.php?url=http://localhost:8000/xmlhttprequest/resources/access-control-basic-allow.cgi. Cross-origin redirection denied by Content Security Policy.
 This tests an XHR request made from a worker is blocked if it redirects to a cross-origin resource that is not listed as a connect-src in the CSP of the worker.
 
 PASS threw exception NetworkError (DOM Exception 19):  A network error occurred..
index 83e1d0c..6f51f98 100644 (file)
@@ -1,4 +1,3 @@
-CONSOLE MESSAGE: Refused to load http://localhost:8000/security/contentSecurityPolicy/resources/post-message.js because it does not appear in the script-src directive of the Content Security Policy.
 PASS result is "importScripts blocked: NetworkError (DOM Exception 19):  A network error occurred."
 PASS successfullyParsed is true
 
index a472dd6..20b538b 100644 (file)
@@ -1,4 +1,3 @@
-CONSOLE MESSAGE: Refused to connect to http://127.0.0.1:8000/xmlhttprequest/resources/get.txt because it does not appear in the connect-src directive of the Content Security Policy.
 
 PASS Worker can have multiple CSP headers 
 
index 470e76c..e8e80d4 100644 (file)
@@ -1,6 +1,4 @@
 CONSOLE MESSAGE: WebSocket connection to 'ws://127.0.0.1:8880/websocket/tests/hybi/close' failed: WebSocket is closed before the connection is established.
-CONSOLE MESSAGE: WebSocket close message is too long.
-CONSOLE MESSAGE: WebSocket close message is too long.
 CONSOLE MESSAGE: WebSocket connection to 'ws://127.0.0.1:8880/websocket/tests/hybi/close' failed: WebSocket is closed before the connection is established.
 Verify WebSocket::close behaviors in Worker.
 
index 233f46b..11ec36a 100644 (file)
@@ -1,4 +1,3 @@
-CONSOLE MESSAGE: XMLHttpRequest cannot load http://localhost:8000/xmlhttprequest/resources/access-control-basic-get-fail-non-simple.cgi. Preflight response is not successful
 GET should not trigger a preflight request from a worker unless it has non-simple headers.
 
 PASS: Cross-domain access allowed for simple get.
index f2a77fe..f47c7b7 100644 (file)
@@ -1,3 +1,14 @@
+2016-10-27  Joseph Pecoraro  <pecoraro@apple.com>
+
+        Web Inspector: Include ConsoleAgent in Workers - real console.log support
+        https://bugs.webkit.org/show_bug.cgi?id=163844
+        <rdar://problem/28903328>
+
+        Reviewed by Brian Burg.
+
+        * web-platform-tests/fetch/api/policies/csp-blocked-worker-expected.txt:
+        * web-platform-tests/streams/readable-streams/garbage-collection.https-expected.txt:
+
 2016-10-27  Chris Dumez  <cdumez@apple.com>
 
         testharnessreport.js should sanitize the results before printing them
index cfb4dbb..5598102 100644 (file)
@@ -1,4 +1,3 @@
-CONSOLE MESSAGE: Refused to connect to http://localhost:8800/fetch/api/resources/top.txt because it does not appear in the connect-src directive of the Content Security Policy.
 
 PASS Fetch is blocked by CSP, got a TypeError 
 
index 6e1c330..f2fa53d 100644 (file)
@@ -1,7 +1,3 @@
-CONSOLE MESSAGE: line 37: Tests are running without the ability to do manual garbage collection. They will still work, but coverage will be suboptimal.
-CONSOLE MESSAGE: line 37: Tests are running without the ability to do manual garbage collection. They will still work, but coverage will be suboptimal.
-CONSOLE MESSAGE: line 37: Tests are running without the ability to do manual garbage collection. They will still work, but coverage will be suboptimal.
-CONSOLE MESSAGE: line 37: Tests are running without the ability to do manual garbage collection. They will still work, but coverage will be suboptimal.
 
 PASS ReadableStreamController methods should continue working properly when scripts lose their reference to the readable stream 
 PASS ReadableStream closed promise should fulfill even if the stream and reader JS references are lost 
diff --git a/LayoutTests/inspector/console/messageAdded-from-worker-expected.txt b/LayoutTests/inspector/console/messageAdded-from-worker-expected.txt
deleted file mode 100644 (file)
index 752bdcb..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-CONSOLE MESSAGE: line 1: WORKER STARTED
-CONSOLE MESSAGE: line 7: WORKER RECEIVED MESSAGE
-Console messages should be received from console logs in a Worker.
-
-
-== Running test suite: Console.messageAdded.worker
--- Running test case: TriggerConsoleMessagesInWorker
-PASS: MessageAdded event should fire for started log.
-PASS: MessageAdded event should fire for received message log.
-
diff --git a/LayoutTests/inspector/console/messageAdded-from-worker.html b/LayoutTests/inspector/console/messageAdded-from-worker.html
deleted file mode 100644 (file)
index 5a29d59..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-<!DOCTYPE html>
-<html>
-<head>
-<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
-<script>
-function triggerWorkerConsoleLog() {
-    let worker = new Worker("resources/worker-console-log.js");
-    worker.postMessage("log");
-}
-
-function test()
-{
-    let suite = InspectorTest.createAsyncSuite("Console.messageAdded.worker");
-
-    suite.addTestCase({
-        name: "TriggerConsoleMessagesInWorker",
-        description: "Triggered console messages in a Worker should be received.",
-        test(resolve, reject) {
-            let eventCount = 0;
-            WebInspector.logManager.addEventListener(WebInspector.LogManager.Event.MessageAdded, (event) => {
-                ++eventCount;
-
-                if (eventCount === 1)
-                    InspectorTest.expectThat(event.data.message.messageText === "WORKER STARTED", "MessageAdded event should fire for started log.");
-                else if (eventCount === 2) {
-                    InspectorTest.expectThat(event.data.message.messageText === "WORKER RECEIVED MESSAGE", "MessageAdded event should fire for received message log.");
-                    resolve();
-                } else
-                    reject();
-            });
-
-            InspectorTest.evaluateInPage("triggerWorkerConsoleLog()");
-        }
-    });
-
-    suite.runTestCasesAndFinish();
-}
-</script>
-</head>
-<body onload="runTest()">
-<p>Console messages should be received from console logs in a Worker.</p>
-</body>
-</html>
diff --git a/LayoutTests/inspector/console/resources/worker-console-log.js b/LayoutTests/inspector/console/resources/worker-console-log.js
deleted file mode 100644 (file)
index 94255f8..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-console.log("WORKER STARTED");
-
-self.addEventListener("message", (event) => {
-    // FIXME: <https://webkit.org/b/154213> Web Inspector: Improve support for console logging within workers
-    // Currently the arguments to the console.log are lost when crossing thread boundaries. This should be
-    // addressed when adding better worker debugging in general.
-    console.log("WORKER RECEIVED MESSAGE", "argument");
-});
-
diff --git a/LayoutTests/inspector/worker/console-basic-expected.txt b/LayoutTests/inspector/worker/console-basic-expected.txt
new file mode 100644 (file)
index 0000000..792d429
--- /dev/null
@@ -0,0 +1,158 @@
+Test for ConsoleAgent in a Worker.
+
+
+== Running test suite: Worker.Console.basic
+-- Running test case: Worker.Console.log
+PASS: ConsoleMessage parameter RemoteObjects should be from the Worker target.
+{
+  "_source": "console-api",
+  "_level": "log",
+  "_messageText": "log!",
+  "_type": "log",
+  "_url": "inspector/worker/resources/worker-console.js",
+  "_line": 4,
+  "_column": 20,
+  "_repeatCount": 1,
+  "_parameters": [
+    {
+      "_type": "string",
+      "_description": "log!",
+      "_value": "log!"
+    },
+    {
+      "_type": "object",
+      "_subtype": "array",
+      "_objectId": "<filtered>",
+      "_description": "Array",
+      "_size": 4,
+      "_preview": {
+        "_type": "object",
+        "_subtype": "array",
+        "_description": "Array",
+        "_lossless": false,
+        "_overflow": false,
+        "_size": 4,
+        "_properties": [
+          {
+            "_name": "0",
+            "_type": "object",
+            "_value": "DedicatedWorkerGlobalScope"
+          },
+          {
+            "_name": "1",
+            "_type": "object",
+            "_value": "WorkerLocation"
+          },
+          {
+            "_name": "2",
+            "_type": "number",
+            "_value": "123"
+          },
+          {
+            "_name": "3",
+            "_type": "symbol",
+            "_value": "Symbol()"
+          }
+        ],
+        "_entries": null
+      }
+    }
+  ],
+  "_stackTrace": "<filtered>",
+  "_request": null
+}
+
+-- Running test case: Worker.Console.warn
+{
+  "_source": "console-api",
+  "_level": "warning",
+  "_messageText": "warning!",
+  "_type": "log",
+  "_url": "inspector/worker/resources/worker-console.js",
+  "_line": 7,
+  "_column": 21,
+  "_sourceCodeLocation": null,
+  "_repeatCount": 1,
+  "_parameters": [
+    {
+      "_type": "string",
+      "_description": "warning!",
+      "_value": "warning!"
+    }
+  ],
+  "_stackTrace": "<filtered>",
+  "_request": null
+}
+
+-- Running test case: Worker.Console.error
+{
+  "_source": "console-api",
+  "_level": "error",
+  "_messageText": "error!",
+  "_type": "log",
+  "_url": "inspector/worker/resources/worker-console.js",
+  "_line": 10,
+  "_column": 22,
+  "_sourceCodeLocation": null,
+  "_repeatCount": 1,
+  "_parameters": [
+    {
+      "_type": "string",
+      "_description": "error!",
+      "_value": "error!"
+    }
+  ],
+  "_stackTrace": "<filtered>",
+  "_request": null
+}
+
+-- Running test case: Worker.Console.assert
+{
+  "_source": "console-api",
+  "_level": "error",
+  "_messageText": "Assertion Failure",
+  "_type": "assert",
+  "_url": "inspector/worker/resources/worker-console.js",
+  "_line": 14,
+  "_column": 23,
+  "_sourceCodeLocation": null,
+  "_repeatCount": 1,
+  "_parameters": [
+    {
+      "_type": "string",
+      "_description": "Assertion Failure",
+      "_value": "Assertion Failure"
+    }
+  ],
+  "_stackTrace": "<filtered>",
+  "_request": null
+}
+
+-- Running test case: Worker.Console.time
+{
+  "_source": "console-api",
+  "_level": "debug",
+  "_messageText": "name: <filtered>ms",
+  "_type": "timing",
+  "_url": "inspector/worker/resources/worker-console.js",
+  "_line": 18,
+  "_column": 24,
+  "_repeatCount": 1,
+  "_stackTrace": "<filtered>",
+  "_request": null
+}
+
+-- Running test case: Worker.Console.count
+{
+  "_source": "console-api",
+  "_level": "debug",
+  "_messageText": "Global: 1",
+  "_type": "log",
+  "_url": "inspector/worker/resources/worker-console.js",
+  "_line": 21,
+  "_column": 22,
+  "_repeatCount": 1,
+  "_stackTrace": "<filtered>",
+  "_request": null
+}
+
diff --git a/LayoutTests/inspector/worker/console-basic.html b/LayoutTests/inspector/worker/console-basic.html
new file mode 100644 (file)
index 0000000..f185cdd
--- /dev/null
@@ -0,0 +1,121 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src="../../http/tests/inspector/resources/inspector-test.js"></script>
+<script>
+let worker = new Worker("resources/worker-console.js");
+
+function triggerConsoleMethodInWorker(msg) {
+    worker.postMessage(msg);
+}
+
+function test()
+{
+    function sanitizeURL(url) {
+        return url.replace(/^.*?LayoutTests\//, "");
+    }
+
+    function remoteObjectJSONFilter(key, value) {
+        if (key === "_target" || key === "_hasChildren" || key === "_listeners")
+            return undefined;
+        if (key === "_objectId" || key === "_stackTrace")
+            return "<filtered>";
+        if (key === "_url")
+            return sanitizeURL(value);
+        return value;
+    }
+
+    let triggerNextConsoleMessage;
+
+    function nextConsoleMessage() {
+        return new Promise((resolve, reject) => {
+            triggerNextConsoleMessage = resolve;
+        });
+    }
+
+    WebInspector.logManager.addEventListener(WebInspector.LogManager.Event.MessageAdded, function(event) {
+        let message = event.data.message;
+        InspectorTest.assert(message instanceof WebInspector.ConsoleMessage);
+        if (triggerNextConsoleMessage)
+            triggerNextConsoleMessage(message);
+    });
+
+    let mainTarget = WebInspector.mainTarget;
+    let workerTarget = Array.from(WebInspector.targets).find((target) => target.type === WebInspector.Target.Type.Worker);
+    if (!workerTarget) {
+        InspectorTest.fail("Missing Worker Target");
+        InspectorTest.completeTest();
+        return;
+    }
+
+
+    let suite = InspectorTest.createAsyncSuite("Worker.Console.basic");
+
+    function addConsoleTestCase({name, message, description, validate, preprocess}) {
+        suite.addTestCase({
+            name, description,
+            test(resolve, reject) {
+                InspectorTest.evaluateInPage(`triggerConsoleMethodInWorker("${message}")`);
+                nextConsoleMessage()
+                    .then((message) => {
+                        if (validate)
+                            validate(message);
+                        if (preprocess)
+                            preprocess(message);
+                        InspectorTest.log(JSON.stringify(message, remoteObjectJSONFilter, "  "));
+                        resolve();
+                    }).catch(reject);
+            }
+        })
+    }
+
+    addConsoleTestCase({
+        name: "Worker.Console.log",
+        description: "console.log with multiple values should work.",
+        message: "log",
+        validate(message) {
+            InspectorTest.expectEqual(message.parameters[1].target, workerTarget, "ConsoleMessage parameter RemoteObjects should be from the Worker target.");
+        }
+    });
+
+    addConsoleTestCase({
+        name: "Worker.Console.warn",
+        description: "console.warn should produce a warning message.",
+        message: "warn",
+    });
+
+    addConsoleTestCase({
+        name: "Worker.Console.error",
+        description: "console.error should produce an error message.",
+        message: "error",
+    });
+
+    addConsoleTestCase({
+        name: "Worker.Console.assert",
+        description: "console.assert should produce an assertion message.",
+        message: "assert",
+    });
+
+    addConsoleTestCase({
+        name: "Worker.Console.time",
+        description: "console.time/timeEnd should produce a timing message.",
+        message: "time",
+        preprocess(message) {
+            message._messageText = message._messageText.replace(/[0-9.]+/, "<filtered>");
+        }
+    });
+
+    addConsoleTestCase({
+        name: "Worker.Console.count",
+        description: "console.count should produce a count message.",
+        message: "count",
+    });
+
+    suite.runTestCasesAndFinish();
+}
+</script>
+</head>
+<body onload="runTest()">
+<p>Test for ConsoleAgent in a Worker.</p>
+</body>
+</html>
diff --git a/LayoutTests/inspector/worker/resources/worker-console.js b/LayoutTests/inspector/worker/resources/worker-console.js
new file mode 100644 (file)
index 0000000..e8b7475
--- /dev/null
@@ -0,0 +1,24 @@
+onmessage = function(event) {
+    switch (event.data) {
+    case "log":
+        console.log("log!", [self, self.location, 123, Symbol()]);
+        break;
+    case "warn":
+        console.warn("warning!");
+        break;
+    case "error":
+        console.error("error!");
+        break;
+    case "assert":
+        console.assert(true, "SHOULD NOT SEE THIS");
+        console.assert(false, "Assertion Failure");
+        break;
+    case "time":
+        console.time("name");
+        console.timeEnd("name");
+        break;
+    case "count":
+        console.count();
+        break;
+    }
+}
index 9c1b32b..a01fb2c 100644 (file)
@@ -65,6 +65,7 @@ function test()
 
     InspectorProtocol.eventHandler["Worker.workerCreated"] = (messageObject) => {
         addWorker(messageObject.params.workerId, messageObject.params.url);
+        InspectorProtocol.sendCommand("Worker.initialized", {workerId: messageObject.params.workerId});
         if (triggerNextCreate)
             triggerNextCreate();
     };
index 8eb1bef..af3dab6 100644 (file)
@@ -1,4 +1,3 @@
-CONSOLE MESSAGE: Refused to connect to non-existent-file because it does not appear in the connect-src directive of the Content Security Policy.
 This tests that the Content Security Policy (CSP) of the owner document (this page) blocks a file-URL Web Worker from making an XHR request because the parent's CSP contains "connect-src 'none'"
 
 PASS threw exception NetworkError (DOM Exception 19):  A network error occurred..
index 00606b9..7c14df7 100644 (file)
@@ -1,5 +1,15 @@
 2016-10-27  Joseph Pecoraro  <pecoraro@apple.com>
 
+        Web Inspector: Include ConsoleAgent in Workers - real console.log support
+        https://bugs.webkit.org/show_bug.cgi?id=163844
+        <rdar://problem/28903328>
+
+        Reviewed by Brian Burg.
+
+        * inspector/protocol/Worker.json:
+
+2016-10-27  Joseph Pecoraro  <pecoraro@apple.com>
+
         Web Inspector: Introduce Page WorkerAgent and Worker InspectorController
         https://bugs.webkit.org/show_bug.cgi?id=163817
         <rdar://problem/28899063>
index 9d48226..a57fac0 100644 (file)
             "description": "Disable Worker domain events."
         },
         {
+            "name": "initialized",
+            "description": "Sent after the frontend has sent all initialization messages and can resume this worker. This command is required to allow execution in the worker.",
+            "parameters": [
+                { "name": "workerId", "type": "string" }
+            ]            
+        },
+        {
             "name": "sendMessageToWorker",
             "description": "Send an Inspector Protocol message to be dispatched to a Worker's agents.",
             "parameters": [
index e07b476..613b63f 100644 (file)
@@ -1907,6 +1907,7 @@ set(WebCore_SOURCES
     inspector/WebDebuggerAgent.cpp
     inspector/WebInjectedScriptHost.cpp
     inspector/WebInjectedScriptManager.cpp
+    inspector/WorkerConsoleAgent.cpp
     inspector/WorkerInspectorController.cpp
     inspector/WorkerRuntimeAgent.cpp
     inspector/WorkerScriptDebugServer.cpp
index 7d6d112..4858515 100644 (file)
@@ -1,5 +1,111 @@
 2016-10-27  Joseph Pecoraro  <pecoraro@apple.com>
 
+        Web Inspector: Include ConsoleAgent in Workers - real console.log support
+        https://bugs.webkit.org/show_bug.cgi?id=163844
+        <rdar://problem/28903328>
+
+        Reviewed by Brian Burg.
+
+        Test: inspector/worker/console-basic.html
+
+        This introduces a real ConsoleAgent in the Worker InspectorController.
+        We no longer need to pass partial ConsoleMessage objects to be logged
+        through the Page, we can just send the full ConsoleMessages to a
+        frontend once it connects to the Worker.
+
+        In order to guarantee that the Worker InspectorController is properly
+        all Workers will start paused if there is an Inspector attached to
+        the Page. The frontend _must_ call the new Worker.initialized method
+        after sending its setup commands to the Worker. This ensures we get
+        handle all initialization commands (like Agent.enable(), and
+        setting state like breakpoints) before any script executes in the
+        Worker. This mirrors the Inspector.initialized method that does the
+        same thing for JSContext auto-attach of the Main target.
+
+        In the backend, the wait until initialized state is just running
+        the WorkerThread's RunLoop in a special debugger mode to only process
+        debugger commands until we are ready. This will effectively be
+        the same as pausing so it is generalized into WorkerThread.
+
+        * CMakeLists.txt:
+        * WebCore.xcodeproj/project.pbxproj:
+        * inspector/InspectorAllInOne.cpp:
+        New files.
+
+        * inspector/InspectorWorkerAgent.cpp:
+        (WebCore::InspectorWorkerAgent::initialized):
+        (WebCore::InspectorWorkerAgent::shouldWaitForDebuggerOnStart):
+        * inspector/InspectorWorkerAgent.h:
+        Add the new initialized method. This just uses the proxy to send
+        a message to be handled on the Worker Thread and unpause.
+
+        * inspector/WorkerConsoleAgent.cpp:
+        (WebCore::WorkerConsoleAgent::WorkerConsoleAgent):
+        (WebCore::WorkerConsoleAgent::addInspectedNode):
+        * inspector/WorkerConsoleAgent.h:
+        * inspector/WorkerInspectorController.cpp:
+        (WebCore::WorkerInspectorController::WorkerInspectorController):
+        Add a ConsoleAgent to WorkerInspectorController.
+
+        * workers/WorkerInspectorProxy.h:
+        * workers/WorkerInspectorProxy.cpp:
+        (WebCore::WorkerInspectorProxy::workerStartMode):
+        (WebCore::WorkerInspectorProxy::resumeWorkerIfPaused):
+        (WebCore::WorkerInspectorProxy::connectToWorkerInspector):
+        (WebCore::WorkerInspectorProxy::disconnectFromWorkerInspector):
+        (WebCore::WorkerInspectorProxy::sendMessageToWorkerInspector):
+        Use the debugger mode when sending messages to the WorkerThread.
+
+        * workers/Worker.cpp:
+        (WebCore::Worker::notifyFinished):
+        * workers/WorkerMessagingProxy.cpp:
+        (WebCore::WorkerMessagingProxy::startWorkerGlobalScope):
+        (WebCore::WorkerMessagingProxy::postConsoleMessageToWorkerObject): Deleted.
+        * workers/WorkerMessagingProxy.h:
+        * workers/WorkerReportingProxy.h:
+        * workers/WorkerGlobalScope.cpp:
+        (WebCore::WorkerGlobalScope::addConsoleMessage):
+        (WebCore::WorkerGlobalScope::addMessage):
+        * workers/WorkerGlobalScope.h:
+        * workers/WorkerGlobalScopeProxy.h:
+        Remove legacy partial console support.
+
+        * workers/WorkerRunLoop.h:
+        * workers/WorkerRunLoop.cpp:
+        (WebCore::WorkerRunLoop::debuggerMode):
+        * workers/WorkerThread.h:
+        * workers/WorkerThread.cpp:
+        (WebCore::WorkerThread::workerThread):
+        (WebCore::WorkerThread::startRunningDebuggerTasks):
+        (WebCore::WorkerThread::stopRunningDebuggerTasks):
+        General code for spinning the WorkerThread and only processing debugger
+        (Inspector) commands. Use this when starting the thread to ensure the
+        frontend initializes the Worker's Agents before any JavaScript executes.
+
+        * page/PageConsoleClient.cpp:
+        * workers/WorkerConsoleClient.cpp:
+        (WebCore::WorkerConsoleClient::count):
+        (WebCore::WorkerConsoleClient::time):
+        (WebCore::WorkerConsoleClient::timeEnd):
+        * inspector/InspectorConsoleInstrumentation.h: Removed.
+        * inspector/InspectorInstrumentation.cpp:
+        (WebCore::InspectorInstrumentation::startConsoleTimingImpl):
+        (WebCore::InspectorInstrumentation::stopConsoleTimingImpl):
+        (WebCore::InspectorInstrumentation::shouldWaitForDebuggerOnStartImpl):
+        * inspector/InspectorInstrumentation.h:
+        (WebCore::InspectorInstrumentation::shouldWaitForDebuggerOnStart):
+        (WebCore::InspectorInstrumentation::addMessageToConsole):
+        (WebCore::InspectorInstrumentation::consoleCount):
+        (WebCore::InspectorInstrumentation::takeHeapSnapshot):
+        (WebCore::InspectorInstrumentation::startConsoleTiming):
+        (WebCore::InspectorInstrumentation::stopConsoleTiming):
+        (WebCore::InspectorInstrumentation::consoleTimeStamp):
+        (WebCore::InspectorInstrumentation::startProfiling):
+        (WebCore::InspectorInstrumentation::stopProfiling):
+        Implement a few more basic console APIs that required ConsoleAgent.
+
+2016-10-27  Joseph Pecoraro  <pecoraro@apple.com>
+
         Web Inspector: Include RuntimeAgent in Workers - evaluate in Worker context
         https://bugs.webkit.org/show_bug.cgi?id=163835
         <rdar://problem/28901465>
index c5120f8..4138cdd 100644 (file)
                A513B3D8114B166A001C429B /* KeyEventCocoa.mm in Sources */ = {isa = PBXBuildFile; fileRef = A5C974D011485FF10066F2AB /* KeyEventCocoa.mm */; };
                A516E8B7136E04DB0076C3C0 /* LocalizedDateCache.h in Headers */ = {isa = PBXBuildFile; fileRef = A516E8B4136E04DB0076C3C0 /* LocalizedDateCache.h */; };
                A516E8B8136E04DB0076C3C0 /* LocalizedDateCache.mm in Sources */ = {isa = PBXBuildFile; fileRef = A516E8B5136E04DB0076C3C0 /* LocalizedDateCache.mm */; };
+               A52A68611DBB0F630083373F /* WorkerConsoleAgent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A52A685F1DBB0F5B0083373F /* WorkerConsoleAgent.cpp */; };
+               A52A68621DBB0F630083373F /* WorkerConsoleAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = A52A68601DBB0F5B0083373F /* WorkerConsoleAgent.h */; };
                A5416FE518810EF80009FC5F /* YouTubeEmbedShadowElement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A5416FE318810EF80009FC5F /* YouTubeEmbedShadowElement.cpp */; };
                A5416FE618810EF80009FC5F /* YouTubeEmbedShadowElement.h in Headers */ = {isa = PBXBuildFile; fileRef = A5416FE418810EF80009FC5F /* YouTubeEmbedShadowElement.h */; };
                A54A0C5D1DB6D9C00017A90B /* InspectorWorkerAgent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A54A0C5B1DB6D9B10017A90B /* InspectorWorkerAgent.cpp */; };
                F3D461491161D53200CA0D09 /* JSErrorHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = F3D461471161D53200CA0D09 /* JSErrorHandler.h */; };
                F3D4C47812E07663003DA150 /* InspectorDOMDebuggerAgent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F3D4C47612E07663003DA150 /* InspectorDOMDebuggerAgent.cpp */; };
                F3D4C47912E07663003DA150 /* InspectorDOMDebuggerAgent.h in Headers */ = {isa = PBXBuildFile; fileRef = F3D4C47712E07663003DA150 /* InspectorDOMDebuggerAgent.h */; };
-               F3F5CF1112ED81A80084C569 /* InspectorConsoleInstrumentation.h in Headers */ = {isa = PBXBuildFile; fileRef = F3F5CF1012ED81A80084C569 /* InspectorConsoleInstrumentation.h */; };
                F40EA8AB1B867E4400CE5581 /* NSScrollingInputFilterSPI.h in Headers */ = {isa = PBXBuildFile; fileRef = F40EA8AA1B867D6500CE5581 /* NSScrollingInputFilterSPI.h */; settings = {ATTRIBUTES = (Private, ); }; };
                F42FFB461984B71600F6837F /* LengthRepeat.h in Headers */ = {isa = PBXBuildFile; fileRef = F42FFB451984B71600F6837F /* LengthRepeat.h */; };
                F433E9031DBBDBA200EF0D14 /* StaticPasteboard.h in Headers */ = {isa = PBXBuildFile; fileRef = F433E9021DBBDBA200EF0D14 /* StaticPasteboard.h */; settings = {ATTRIBUTES = (Private, ); }; };
                A516E8B5136E04DB0076C3C0 /* LocalizedDateCache.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = LocalizedDateCache.mm; sourceTree = "<group>"; };
                A518225417E2A0D400A9BA1D /* InspectorOverlayPage.css */ = {isa = PBXFileReference; lastKnownFileType = text.css; path = InspectorOverlayPage.css; sourceTree = "<group>"; };
                A518225517E2A0D400A9BA1D /* InspectorOverlayPage.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = InspectorOverlayPage.js; sourceTree = "<group>"; };
+               A52A685F1DBB0F5B0083373F /* WorkerConsoleAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WorkerConsoleAgent.cpp; sourceTree = "<group>"; };
+               A52A68601DBB0F5B0083373F /* WorkerConsoleAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WorkerConsoleAgent.h; sourceTree = "<group>"; };
                A5416FE318810EF80009FC5F /* YouTubeEmbedShadowElement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = YouTubeEmbedShadowElement.cpp; sourceTree = "<group>"; };
                A5416FE418810EF80009FC5F /* YouTubeEmbedShadowElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = YouTubeEmbedShadowElement.h; sourceTree = "<group>"; };
                A54A0C5B1DB6D9B10017A90B /* InspectorWorkerAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorWorkerAgent.cpp; sourceTree = "<group>"; };
                F3D461471161D53200CA0D09 /* JSErrorHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSErrorHandler.h; sourceTree = "<group>"; };
                F3D4C47612E07663003DA150 /* InspectorDOMDebuggerAgent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorDOMDebuggerAgent.cpp; sourceTree = "<group>"; };
                F3D4C47712E07663003DA150 /* InspectorDOMDebuggerAgent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorDOMDebuggerAgent.h; sourceTree = "<group>"; };
-               F3F5CF1012ED81A80084C569 /* InspectorConsoleInstrumentation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorConsoleInstrumentation.h; sourceTree = "<group>"; };
                F40EA8AA1B867D6500CE5581 /* NSScrollingInputFilterSPI.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NSScrollingInputFilterSPI.h; sourceTree = "<group>"; };
                F42FFB451984B71600F6837F /* LengthRepeat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LengthRepeat.h; sourceTree = "<group>"; };
                F433E9021DBBDBA200EF0D14 /* StaticPasteboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StaticPasteboard.h; sourceTree = "<group>"; };
                                B885E8D311E06DD2009FFBF4 /* InspectorApplicationCacheAgent.h */,
                                7A1F2B51126C61B20006A7E6 /* InspectorClient.cpp */,
                                1C81B9580E97330800266E07 /* InspectorClient.h */,
-                               F3F5CF1012ED81A80084C569 /* InspectorConsoleInstrumentation.h */,
                                1C81B9570E97330800266E07 /* InspectorController.cpp */,
                                1C81B9560E97330800266E07 /* InspectorController.h */,
                                82AB1741124B99EC00C5069D /* InspectorCSSAgent.cpp */,
                                A5840E23187B8AC200843B10 /* WebInjectedScriptHost.h */,
                                A584FE2D1864CB8400843B10 /* WebInjectedScriptManager.cpp */,
                                A584FE2E1864CB8400843B10 /* WebInjectedScriptManager.h */,
+                               A52A685F1DBB0F5B0083373F /* WorkerConsoleAgent.cpp */,
+                               A52A68601DBB0F5B0083373F /* WorkerConsoleAgent.h */,
                                A54A0C5F1DB7F8B70017A90B /* WorkerInspectorController.cpp */,
                                A54A0C601DB7F8B70017A90B /* WorkerInspectorController.h */,
                                A57FD7191DB94236006AE24B /* WorkerRuntimeAgent.cpp */,
                                93309DF2099E64920056E581 /* InsertTextCommand.h in Headers */,
                                B885E8D511E06DD2009FFBF4 /* InspectorApplicationCacheAgent.h in Headers */,
                                1C81B95C0E97330800266E07 /* InspectorClient.h in Headers */,
-                               F3F5CF1112ED81A80084C569 /* InspectorConsoleInstrumentation.h in Headers */,
                                1C81B95A0E97330800266E07 /* InspectorController.h in Headers */,
                                82AB1744124B99EC00C5069D /* InspectorCSSAgent.h in Headers */,
                                4A9CC82116BF9BB400EC645A /* InspectorCSSOMWrappers.h in Headers */,
                                A14832C6187F668F00DA63A6 /* WKViewPrivate.h in Headers */,
                                379919971200DDF400EA041C /* WOFFFileFormat.h in Headers */,
                                2E4346460F546A8200B0F1BA /* Worker.h in Headers */,
+                               A52A68621DBB0F630083373F /* WorkerConsoleAgent.h in Headers */,
                                A55639D11C6F09E300806D8E /* WorkerConsoleClient.h in Headers */,
                                A3E2643114748991005A8588 /* WorkerEventQueue.h in Headers */,
                                2E4346490F546A8200B0F1BA /* WorkerGlobalScope.h in Headers */,
                                A14832C5187F668300DA63A6 /* WKView.mm in Sources */,
                                379919961200DDF400EA041C /* WOFFFileFormat.cpp in Sources */,
                                2E4346450F546A8200B0F1BA /* Worker.cpp in Sources */,
+                               A52A68611DBB0F630083373F /* WorkerConsoleAgent.cpp in Sources */,
                                A55639D21C6F09E700806D8E /* WorkerConsoleClient.cpp in Sources */,
                                A3E2643014748991005A8588 /* WorkerEventQueue.cpp in Sources */,
                                2E4346480F546A8200B0F1BA /* WorkerGlobalScope.cpp in Sources */,
index 8375c3b..6f28e6a 100644 (file)
@@ -63,6 +63,7 @@
 #include "WebDebuggerAgent.cpp"
 #include "WebInjectedScriptHost.cpp"
 #include "WebInjectedScriptManager.cpp"
+#include "WorkerConsoleAgent.cpp"
 #include "WorkerInspectorController.cpp"
 #include "WorkerRuntimeAgent.cpp"
 #include "WorkerScriptDebugServer.cpp"
diff --git a/Source/WebCore/inspector/InspectorConsoleInstrumentation.h b/Source/WebCore/inspector/InspectorConsoleInstrumentation.h
deleted file mode 100644 (file)
index 964c9af..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
-* Copyright (C) 2011 Google Inc. All rights reserved.
-* Copyright (C) 2015 Apple Inc. All rights reserved.
-*
-* Redistribution and use in source and binary forms, with or without
-* modification, are permitted provided that the following conditions are
-* met:
-*
-*     * Redistributions of source code must retain the above copyright
-* notice, this list of conditions and the following disclaimer.
-*     * Redistributions in binary form must reproduce the above
-* copyright notice, this list of conditions and the following disclaimer
-* in the documentation and/or other materials provided with the
-* distribution.
-*     * Neither the name of Google Inc. nor the names of its
-* contributors may be used to endorse or promote products derived from
-* this software without specific prior written permission.
-*
-* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#pragma once
-
-#include "InspectorInstrumentation.h"
-#include <inspector/ScriptArguments.h>
-#include <inspector/ScriptCallStack.h>
-
-namespace WebCore {
-
-inline void InspectorInstrumentation::addMessageToConsole(Page& page, std::unique_ptr<Inspector::ConsoleMessage> message)
-{
-    addMessageToConsoleImpl(instrumentingAgentsForPage(page), WTFMove(message));
-}
-
-inline void InspectorInstrumentation::addMessageToConsole(WorkerGlobalScope*, std::unique_ptr<Inspector::ConsoleMessage>)
-{
-    // FIXME: <https://webkit.org/b/127634> Web Inspector: support debugging web workers
-}
-
-inline void InspectorInstrumentation::consoleCount(Page& page, JSC::ExecState* state, RefPtr<Inspector::ScriptArguments>&& arguments)
-{
-    consoleCountImpl(instrumentingAgentsForPage(page), state, WTFMove(arguments));
-}
-
-inline void InspectorInstrumentation::takeHeapSnapshot(Frame& frame, const String& title)
-{
-    FAST_RETURN_IF_NO_FRONTENDS(void());
-    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
-        takeHeapSnapshotImpl(*instrumentingAgents, title);
-}
-
-inline void InspectorInstrumentation::startConsoleTiming(Frame& frame, const String& title)
-{
-    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
-        startConsoleTimingImpl(*instrumentingAgents, frame, title);
-}
-
-inline void InspectorInstrumentation::stopConsoleTiming(Frame& frame, const String& title, RefPtr<Inspector::ScriptCallStack>&& stack)
-{
-    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
-        stopConsoleTimingImpl(*instrumentingAgents, frame, title, WTFMove(stack));
-}
-
-inline void InspectorInstrumentation::consoleTimeStamp(Frame& frame, RefPtr<Inspector::ScriptArguments>&& arguments)
-{
-    FAST_RETURN_IF_NO_FRONTENDS(void());
-    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
-        consoleTimeStampImpl(*instrumentingAgents, frame, WTFMove(arguments));
-}
-
-inline void InspectorInstrumentation::startProfiling(Page& page, JSC::ExecState* exec, const String &title)
-{
-    startProfilingImpl(instrumentingAgentsForPage(page), exec, title);
-}
-
-inline void InspectorInstrumentation::stopProfiling(Page& page, JSC::ExecState* exec, const String &title)
-{
-    stopProfilingImpl(instrumentingAgentsForPage(page), exec, title);
-}
-
-} // namespace WebCore
-
index 026cdfb..d573b3d 100644 (file)
@@ -884,6 +884,12 @@ void InspectorInstrumentation::startConsoleTimingImpl(InstrumentingAgents& instr
         consoleAgent->startTiming(title);
 }
 
+void InspectorInstrumentation::startConsoleTimingImpl(InstrumentingAgents& instrumentingAgents, const String& title)
+{
+    if (WebConsoleAgent* consoleAgent = instrumentingAgents.webConsoleAgent())
+        consoleAgent->startTiming(title);
+}
+
 void InspectorInstrumentation::stopConsoleTimingImpl(InstrumentingAgents& instrumentingAgents, Frame& frame, const String& title, RefPtr<ScriptCallStack>&& stack)
 {
     if (WebConsoleAgent* consoleAgent = instrumentingAgents.webConsoleAgent())
@@ -892,6 +898,12 @@ void InspectorInstrumentation::stopConsoleTimingImpl(InstrumentingAgents& instru
         timelineAgent->timeEnd(frame, title);
 }
 
+void InspectorInstrumentation::stopConsoleTimingImpl(InstrumentingAgents& instrumentingAgents, const String& title, RefPtr<ScriptCallStack>&& stack)
+{
+    if (WebConsoleAgent* consoleAgent = instrumentingAgents.webConsoleAgent())
+        consoleAgent->stopTiming(title, stack);
+}
+
 void InspectorInstrumentation::consoleTimeStampImpl(InstrumentingAgents& instrumentingAgents, Frame& frame, RefPtr<ScriptArguments>&& arguments)
 {
     if (InspectorTimelineAgent* timelineAgent = instrumentingAgents.inspectorTimelineAgent()) {
@@ -927,6 +939,13 @@ void InspectorInstrumentation::didDispatchDOMStorageEventImpl(InstrumentingAgent
         domStorageAgent->didDispatchDOMStorageEvent(key, oldValue, newValue, storageType, securityOrigin, page);
 }
 
+bool InspectorInstrumentation::shouldWaitForDebuggerOnStartImpl(InstrumentingAgents& instrumentingAgents)
+{
+    if (InspectorWorkerAgent* workerAgent = instrumentingAgents.inspectorWorkerAgent())
+        return workerAgent->shouldWaitForDebuggerOnStart();
+    return false;
+}
+
 void InspectorInstrumentation::workerStartedImpl(InstrumentingAgents& instrumentingAgents, WorkerInspectorProxy* proxy, const URL& url)
 {
     if (InspectorWorkerAgent* workerAgent = instrumentingAgents.inspectorWorkerAgent())
index 074bba1..108b0ee 100644 (file)
@@ -199,28 +199,29 @@ public:
     static void willDestroyCachedResource(CachedResource&);
 
     static void addMessageToConsole(Page&, std::unique_ptr<Inspector::ConsoleMessage>);
-
-    // FIXME: Convert to ScriptArguments to match non-worker context.
     static void addMessageToConsole(WorkerGlobalScope*, std::unique_ptr<Inspector::ConsoleMessage>);
 
     static void consoleCount(Page&, JSC::ExecState*, RefPtr<Inspector::ScriptArguments>&&);
+    static void consoleCount(WorkerGlobalScope&, JSC::ExecState*, RefPtr<Inspector::ScriptArguments>&&);
     static void takeHeapSnapshot(Frame&, const String& title);
     static void startConsoleTiming(Frame&, const String& title);
+    static void startConsoleTiming(WorkerGlobalScope&, const String& title);
     static void stopConsoleTiming(Frame&, const String& title, RefPtr<Inspector::ScriptCallStack>&&);
+    static void stopConsoleTiming(WorkerGlobalScope&, const String& title, RefPtr<Inspector::ScriptCallStack>&&);
     static void consoleTimeStamp(Frame&, RefPtr<Inspector::ScriptArguments>&&);
+    static void startProfiling(Page&, JSC::ExecState*, const String& title);
+    static void stopProfiling(Page&, JSC::ExecState*, const String& title);
 
     static void didRequestAnimationFrame(Document*, int callbackId);
     static void didCancelAnimationFrame(Document*, int callbackId);
     static InspectorInstrumentationCookie willFireAnimationFrame(Document*, int callbackId);
     static void didFireAnimationFrame(const InspectorInstrumentationCookie&);
 
-    static void startProfiling(Page&, JSC::ExecState*, const String& title);
-    static void stopProfiling(Page&, JSC::ExecState*, const String& title);
-
     static void didOpenDatabase(ScriptExecutionContext*, RefPtr<Database>&&, const String& domain, const String& name, const String& version);
 
     static void didDispatchDOMStorageEvent(const String& key, const String& oldValue, const String& newValue, StorageType, SecurityOrigin*, Page*);
 
+    static bool shouldWaitForDebuggerOnStart(ScriptExecutionContext*);
     static void workerStarted(ScriptExecutionContext*, WorkerInspectorProxy*, const URL&);
     static void workerTerminated(ScriptExecutionContext*, WorkerInspectorProxy*);
 
@@ -378,7 +379,9 @@ private:
     static void consoleCountImpl(InstrumentingAgents&, JSC::ExecState*, RefPtr<Inspector::ScriptArguments>&&);
     static void takeHeapSnapshotImpl(InstrumentingAgents&, const String& title);
     static void startConsoleTimingImpl(InstrumentingAgents&, Frame&, const String& title);
+    static void startConsoleTimingImpl(InstrumentingAgents&, const String& title);
     static void stopConsoleTimingImpl(InstrumentingAgents&, Frame&, const String& title, RefPtr<Inspector::ScriptCallStack>&&);
+    static void stopConsoleTimingImpl(InstrumentingAgents&, const String& title, RefPtr<Inspector::ScriptCallStack>&&);
     static void consoleTimeStampImpl(InstrumentingAgents&, Frame&, RefPtr<Inspector::ScriptArguments>&&);
 
     static void didRequestAnimationFrameImpl(InstrumentingAgents&, int callbackId, Frame*);
@@ -393,6 +396,7 @@ private:
 
     static void didDispatchDOMStorageEventImpl(InstrumentingAgents&, const String& key, const String& oldValue, const String& newValue, StorageType, SecurityOrigin*, Page*);
 
+    static bool shouldWaitForDebuggerOnStartImpl(InstrumentingAgents&);
     static void workerStartedImpl(InstrumentingAgents&, WorkerInspectorProxy*, const URL&);
     static void workerTerminatedImpl(InstrumentingAgents&, WorkerInspectorProxy*);
 
@@ -1059,6 +1063,14 @@ inline void InspectorInstrumentation::didDispatchDOMStorageEvent(const String& k
         didDispatchDOMStorageEventImpl(*instrumentingAgents, key, oldValue, newValue, storageType, securityOrigin, page);
 }
 
+inline bool InspectorInstrumentation::shouldWaitForDebuggerOnStart(ScriptExecutionContext* context)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(false);
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForContext(context))
+        return shouldWaitForDebuggerOnStartImpl(*instrumentingAgents);
+    return false;
+}
+
 inline void InspectorInstrumentation::workerStarted(ScriptExecutionContext* context, WorkerInspectorProxy* proxy, const URL& url)
 {
     FAST_RETURN_IF_NO_FRONTENDS(void());
@@ -1227,6 +1239,76 @@ inline void InspectorInstrumentation::updateApplicationCacheStatus(Frame* frame)
         updateApplicationCacheStatusImpl(*instrumentingAgents, frame);
 }
 
+inline void InspectorInstrumentation::addMessageToConsole(Page& page, std::unique_ptr<Inspector::ConsoleMessage> message)
+{
+    addMessageToConsoleImpl(instrumentingAgentsForPage(page), WTFMove(message));
+}
+
+inline void InspectorInstrumentation::addMessageToConsole(WorkerGlobalScope* workerGlobalScope, std::unique_ptr<Inspector::ConsoleMessage> message)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForWorkerGlobalScope(workerGlobalScope))
+        addMessageToConsoleImpl(*instrumentingAgents, WTFMove(message));
+}
+
+inline void InspectorInstrumentation::consoleCount(Page& page, JSC::ExecState* state, RefPtr<Inspector::ScriptArguments>&& arguments)
+{
+    consoleCountImpl(instrumentingAgentsForPage(page), state, WTFMove(arguments));
+}
+
+inline void InspectorInstrumentation::consoleCount(WorkerGlobalScope& workerGlobalScope, JSC::ExecState* state, RefPtr<Inspector::ScriptArguments>&& arguments)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForWorkerGlobalScope(&workerGlobalScope))
+        consoleCountImpl(*instrumentingAgents, state, WTFMove(arguments));
+}
+
+inline void InspectorInstrumentation::takeHeapSnapshot(Frame& frame, const String& title)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        takeHeapSnapshotImpl(*instrumentingAgents, title);
+}
+
+inline void InspectorInstrumentation::startConsoleTiming(Frame& frame, const String& title)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        startConsoleTimingImpl(*instrumentingAgents, frame, title);
+}
+
+inline void InspectorInstrumentation::startConsoleTiming(WorkerGlobalScope& workerGlobalScope, const String& title)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForWorkerGlobalScope(&workerGlobalScope))
+        startConsoleTimingImpl(*instrumentingAgents, title);
+}
+
+inline void InspectorInstrumentation::stopConsoleTiming(Frame& frame, const String& title, RefPtr<Inspector::ScriptCallStack>&& stack)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        stopConsoleTimingImpl(*instrumentingAgents, frame, title, WTFMove(stack));
+}
+
+inline void InspectorInstrumentation::stopConsoleTiming(WorkerGlobalScope& workerGlobalScope, const String& title, RefPtr<Inspector::ScriptCallStack>&& stack)
+{
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForWorkerGlobalScope(&workerGlobalScope))
+        stopConsoleTimingImpl(*instrumentingAgents, title, WTFMove(stack));
+}
+
+inline void InspectorInstrumentation::consoleTimeStamp(Frame& frame, RefPtr<Inspector::ScriptArguments>&& arguments)
+{
+    FAST_RETURN_IF_NO_FRONTENDS(void());
+    if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForFrame(frame))
+        consoleTimeStampImpl(*instrumentingAgents, frame, WTFMove(arguments));
+}
+
+inline void InspectorInstrumentation::startProfiling(Page& page, JSC::ExecState* exec, const String &title)
+{
+    startProfilingImpl(instrumentingAgentsForPage(page), exec, title);
+}
+
+inline void InspectorInstrumentation::stopProfiling(Page& page, JSC::ExecState* exec, const String &title)
+{
+    stopProfilingImpl(instrumentingAgentsForPage(page), exec, title);
+}
+
 inline void InspectorInstrumentation::didRequestAnimationFrame(Document* document, int callbackId)
 {
     if (InstrumentingAgents* instrumentingAgents = instrumentingAgentsForDocument(document))
index 652d4fa..13222c7 100644 (file)
@@ -74,6 +74,17 @@ void InspectorWorkerAgent::disable(ErrorString&)
     disconnectFromAllWorkerInspectorProxies();
 }
 
+void InspectorWorkerAgent::initialized(ErrorString& errorString, const String& workerId)
+{
+    WorkerInspectorProxy* proxy = m_connectedProxies.get(workerId);
+    if (!proxy) {
+        errorString = ASCIILiteral("Worker not found.");
+        return;
+    }
+
+    proxy->resumeWorkerIfPaused();
+}
+
 void InspectorWorkerAgent::sendMessageToWorker(ErrorString& errorString, const String& workerId, const String& message)
 {
     if (!m_enabled) {
@@ -95,6 +106,11 @@ void InspectorWorkerAgent::sendMessageFromWorkerToFrontend(WorkerInspectorProxy*
     m_frontendDispatcher->dispatchMessageFromWorker(proxy->identifier(), message);
 }
 
+bool InspectorWorkerAgent::shouldWaitForDebuggerOnStart() const
+{
+    return m_enabled;
+}
+
 void InspectorWorkerAgent::workerStarted(WorkerInspectorProxy* proxy, const URL&)
 {
     if (!m_enabled)
index ab33d30..400bb59 100644 (file)
@@ -51,12 +51,14 @@ public:
     // WorkerBackendDispatcherHandler
     void enable(ErrorString&) override;
     void disable(ErrorString&) override;
+    void initialized(ErrorString&, const String& workerId) override;
     void sendMessageToWorker(ErrorString&, const String& workerId, const String& message) override;
 
     // PageChannel
     void sendMessageFromWorkerToFrontend(WorkerInspectorProxy*, const String& message) override;
 
     // InspectorInstrumentation
+    bool shouldWaitForDebuggerOnStart() const;
     void workerStarted(WorkerInspectorProxy*, const URL&);
     void workerTerminated(WorkerInspectorProxy*);
 
diff --git a/Source/WebCore/inspector/WorkerConsoleAgent.cpp b/Source/WebCore/inspector/WorkerConsoleAgent.cpp
new file mode 100644 (file)
index 0000000..af71429
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "WorkerConsoleAgent.h"
+
+using namespace Inspector;
+
+namespace WebCore {
+
+WorkerConsoleAgent::WorkerConsoleAgent(WorkerAgentContext& context, InspectorHeapAgent* heapAgent)
+    : WebConsoleAgent(context, heapAgent)
+{
+}
+
+void WorkerConsoleAgent::addInspectedNode(ErrorString& errorString, int)
+{
+    errorString = ASCIILiteral("Unsupported for Workers.");
+}
+
+} // namespace WebCore
diff --git a/Source/WebCore/inspector/WorkerConsoleAgent.h b/Source/WebCore/inspector/WorkerConsoleAgent.h
new file mode 100644 (file)
index 0000000..d2078b8
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include "InspectorWebAgentBase.h"
+#include "WebConsoleAgent.h"
+
+namespace WebCore {
+
+class WorkerConsoleAgent final : public WebConsoleAgent {
+    WTF_MAKE_NONCOPYABLE(WorkerConsoleAgent);
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    WorkerConsoleAgent(WorkerAgentContext&, Inspector::InspectorHeapAgent*);
+    ~WorkerConsoleAgent() { }
+
+private:
+    void addInspectedNode(ErrorString&, int nodeId) override;
+};
+
+} // namespace WebCore
index 5c48960..1c2ee72 100644 (file)
 #include "config.h"
 #include "WorkerInspectorController.h"
 
+#include "CommandLineAPIHost.h"
 #include "InstrumentingAgents.h"
 #include "JSMainThreadExecState.h"
 #include "WebInjectedScriptHost.h"
 #include "WebInjectedScriptManager.h"
+#include "WorkerConsoleAgent.h"
 #include "WorkerGlobalScope.h"
 #include "WorkerRuntimeAgent.h"
 #include "WorkerThread.h"
@@ -74,8 +76,22 @@ WorkerInspectorController::WorkerInspectorController(WorkerGlobalScope& workerGl
     auto runtimeAgent = std::make_unique<WorkerRuntimeAgent>(workerContext);
     m_agents.append(WTFMove(runtimeAgent));
 
-    // FIXME: ConsoleAgent
+    auto consoleAgent = std::make_unique<WorkerConsoleAgent>(workerContext, nullptr);
+    m_instrumentingAgents->setWebConsoleAgent(consoleAgent.get());
+    m_agents.append(WTFMove(consoleAgent));
+
     // FIXME: DebuggerAgent
+    // FIXME: HeapAgent
+
+    if (CommandLineAPIHost* commandLineAPIHost = m_injectedScriptManager->commandLineAPIHost()) {
+        commandLineAPIHost->init(
+              nullptr // InspectorAgent
+            , m_instrumentingAgents->webConsoleAgent()
+            , nullptr // InspectorDOMAgent
+            , nullptr // InspectorDOMStorageAgent
+            , nullptr // InspectorDatabaseAgent
+        );
+    }
 }
 
 WorkerInspectorController::~WorkerInspectorController()
index 9d0e0a4..260c29e 100644 (file)
@@ -33,8 +33,8 @@
 #include "ChromeClient.h"
 #include "Document.h"
 #include "Frame.h"
-#include "InspectorConsoleInstrumentation.h"
 #include "InspectorController.h"
+#include "InspectorInstrumentation.h"
 #include "JSMainThreadExecState.h"
 #include "MainFrame.h"
 #include "Page.h"
index 1adccda..19d93bd 100644 (file)
@@ -154,7 +154,7 @@ void Worker::notifyFinished()
         dispatchEvent(Event::create(eventNames().errorEvent, false, true));
     else {
         const ContentSecurityPolicyResponseHeaders& contentSecurityPolicyResponseHeaders = m_contentSecurityPolicyResponseHeaders ? m_contentSecurityPolicyResponseHeaders.value() : scriptExecutionContext()->contentSecurityPolicy()->responseHeaders();
-        m_contextProxy->startWorkerGlobalScope(m_scriptLoader->url(), scriptExecutionContext()->userAgent(m_scriptLoader->url()), m_scriptLoader->script(), contentSecurityPolicyResponseHeaders, m_shouldBypassMainWorldContentSecurityPolicy, DontPauseWorkerGlobalScopeOnStart);
+        m_contextProxy->startWorkerGlobalScope(m_scriptLoader->url(), scriptExecutionContext()->userAgent(m_scriptLoader->url()), m_scriptLoader->script(), contentSecurityPolicyResponseHeaders, m_shouldBypassMainWorldContentSecurityPolicy);
         InspectorInstrumentation::scriptImported(scriptExecutionContext(), m_scriptLoader->identifier(), m_scriptLoader->script());
     }
     m_scriptLoader = nullptr;
index b3edd41..6d824c2 100644 (file)
 #include "config.h"
 #include "WorkerConsoleClient.h"
 
+#include "InspectorInstrumentation.h"
 #include <inspector/ConsoleMessage.h>
 #include <inspector/ScriptArguments.h>
+#include <inspector/ScriptCallStack.h>
+#include <inspector/ScriptCallStackFactory.h>
 
 using namespace Inspector;
 
@@ -50,15 +53,28 @@ void WorkerConsoleClient::messageWithTypeAndLevel(MessageType type, MessageLevel
     m_workerGlobalScope.addConsoleMessage(WTFMove(message));
 }
 
+void WorkerConsoleClient::count(JSC::ExecState* exec, RefPtr<ScriptArguments>&& arguments)
+{
+    InspectorInstrumentation::consoleCount(m_workerGlobalScope, exec, WTFMove(arguments));
+}
+
+void WorkerConsoleClient::time(JSC::ExecState*, const String& title)
+{
+    InspectorInstrumentation::startConsoleTiming(m_workerGlobalScope, title);
+}
+
+void WorkerConsoleClient::timeEnd(JSC::ExecState* exec, const String& title)
+{
+    RefPtr<ScriptCallStack> callStack(createScriptCallStackForConsole(exec, 1));
+    InspectorInstrumentation::stopConsoleTiming(m_workerGlobalScope, title, WTFMove(callStack));
+}
+
 // FIXME: <https://webkit.org/b/153499> Web Inspector: console.profile should use the new Sampling Profiler
 void WorkerConsoleClient::profile(JSC::ExecState*, const String&) { }
 void WorkerConsoleClient::profileEnd(JSC::ExecState*, const String&) { }
 
 // FIXME: <https://webkit.org/b/127634> Web Inspector: support debugging web workers
-void WorkerConsoleClient::count(JSC::ExecState*, RefPtr<ScriptArguments>&&) { }
 void WorkerConsoleClient::takeHeapSnapshot(JSC::ExecState*, const String&) { }
-void WorkerConsoleClient::time(JSC::ExecState*, const String&) { }
-void WorkerConsoleClient::timeEnd(JSC::ExecState*, const String&) { }
 void WorkerConsoleClient::timeStamp(JSC::ExecState*, RefPtr<ScriptArguments>&&) { }
 
 } // namespace WebCore
index fa0a20f..48bb103 100644 (file)
@@ -32,7 +32,7 @@
 #include "Crypto.h"
 #include "ExceptionCode.h"
 #include "IDBConnectionProxy.h"
-#include "InspectorConsoleInstrumentation.h"
+#include "InspectorInstrumentation.h"
 #include "ScheduledAction.h"
 #include "ScriptSourceCode.h"
 #include "SecurityOrigin.h"
@@ -45,7 +45,8 @@
 #include "WorkerReportingProxy.h"
 #include "WorkerScriptLoader.h"
 #include "WorkerThread.h"
-#include <inspector/ConsoleMessage.h>
+#include <inspector/ScriptArguments.h>
+#include <inspector/ScriptCallStack.h>
 
 using namespace Inspector;
 
@@ -257,7 +258,6 @@ void WorkerGlobalScope::addConsoleMessage(std::unique_ptr<Inspector::ConsoleMess
         return;
     }
 
-    thread().workerReportingProxy().postConsoleMessageToWorkerObject(message->source(), message->level(), message->message(), message->line(), message->column(), message->url());
     InspectorInstrumentation::addMessageToConsole(this, WTFMove(message));
 }
 
@@ -273,8 +273,6 @@ void WorkerGlobalScope::addMessage(MessageSource source, MessageLevel level, con
         return;
     }
 
-    thread().workerReportingProxy().postConsoleMessageToWorkerObject(source, level, messageText, lineNumber, columnNumber, sourceURL);
-
     std::unique_ptr<Inspector::ConsoleMessage> message;
     if (callStack)
         message = std::make_unique<Inspector::ConsoleMessage>(source, MessageType::Log, level, messageText, WTFMove(callStack), requestIdentifier);
index 0f0b656..e92878d 100644 (file)
 #include "URL.h"
 #include "WorkerEventQueue.h"
 #include "WorkerScriptController.h"
+#include <inspector/ConsoleMessage.h>
 #include <memory>
 
-namespace Inspector {
-class ConsoleMessage;
-}
-
 namespace WebCore {
 
 class ContentSecurityPolicyResponseHeaders;
index 87b58c9..dd7d00f 100644 (file)
@@ -48,7 +48,7 @@ namespace WebCore {
 
         virtual ~WorkerGlobalScopeProxy() { }
 
-        virtual void startWorkerGlobalScope(const URL& scriptURL, const String& userAgent, const String& sourceCode, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy, WorkerThreadStartMode) = 0;
+        virtual void startWorkerGlobalScope(const URL& scriptURL, const String& userAgent, const String& sourceCode, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy) = 0;
 
         virtual void terminateWorkerGlobalScope() = 0;
 
index 1e49c8f..901c89d 100644 (file)
@@ -30,7 +30,7 @@
 #include "ScriptExecutionContext.h"
 #include "WorkerGlobalScope.h"
 #include "WorkerInspectorController.h"
-#include "WorkerThread.h"
+#include "WorkerRunLoop.h"
 #include <inspector/IdentifiersFactory.h>
 #include <inspector/InspectorAgentBase.h>
 #include <wtf/NeverDestroyed.h>
@@ -56,6 +56,12 @@ WorkerInspectorProxy::~WorkerInspectorProxy()
     ASSERT(!m_pageChannel);
 }
 
+WorkerThreadStartMode WorkerInspectorProxy::workerStartMode(ScriptExecutionContext* scriptExecutionContext)
+{
+    bool pauseOnStart = InspectorInstrumentation::shouldWaitForDebuggerOnStart(scriptExecutionContext);
+    return pauseOnStart ? WorkerThreadStartMode::WaitForInspector : WorkerThreadStartMode::Normal;
+}
+
 void WorkerInspectorProxy::workerStarted(ScriptExecutionContext* scriptExecutionContext, WorkerThread* thread, const URL& url)
 {
     ASSERT(!m_workerThread);
@@ -83,6 +89,13 @@ void WorkerInspectorProxy::workerTerminated()
     m_pageChannel = nullptr;
 }
 
+void WorkerInspectorProxy::resumeWorkerIfPaused()
+{
+    m_workerThread->runLoop().postTaskForMode([] (ScriptExecutionContext& context) {
+        downcast<WorkerGlobalScope>(context).thread().stopRunningDebuggerTasks();
+    }, WorkerRunLoop::debuggerMode());
+}
+
 void WorkerInspectorProxy::connectToWorkerInspectorController(PageChannel* channel)
 {
     ASSERT(m_workerThread);
@@ -91,9 +104,9 @@ void WorkerInspectorProxy::connectToWorkerInspectorController(PageChannel* chann
 
     m_pageChannel = channel;
 
-    m_workerThread->runLoop().postTask([] (ScriptExecutionContext& context) {
+    m_workerThread->runLoop().postTaskForMode([] (ScriptExecutionContext& context) {
         downcast<WorkerGlobalScope>(context).inspectorController().connectFrontend();
-    });
+    }, WorkerRunLoop::debuggerMode());
 }
 
 void WorkerInspectorProxy::disconnectFromWorkerInspectorController()
@@ -104,9 +117,9 @@ void WorkerInspectorProxy::disconnectFromWorkerInspectorController()
 
     m_pageChannel = nullptr;
 
-    m_workerThread->runLoop().postTask([] (ScriptExecutionContext& context) {
+    m_workerThread->runLoop().postTaskForMode([] (ScriptExecutionContext& context) {
         downcast<WorkerGlobalScope>(context).inspectorController().disconnectFrontend(DisconnectReason::InspectorDestroyed);
-    });
+    }, WorkerRunLoop::debuggerMode());
 }
 
 void WorkerInspectorProxy::sendMessageToWorkerInspectorController(const String& message)
@@ -115,9 +128,9 @@ void WorkerInspectorProxy::sendMessageToWorkerInspectorController(const String&
     if (!m_workerThread)
         return;
 
-    m_workerThread->runLoop().postTask([message = message.isolatedCopy()] (ScriptExecutionContext& context) {
+    m_workerThread->runLoop().postTaskForMode([message = message.isolatedCopy()] (ScriptExecutionContext& context) {
         downcast<WorkerGlobalScope>(context).inspectorController().dispatchMessageFromFrontend(message);
-    });
+    }, WorkerRunLoop::debuggerMode());
 }
 
 void WorkerInspectorProxy::sendMessageFromWorkerToFrontend(const String& message)
index d54c5ba..d95ba22 100644 (file)
@@ -26,6 +26,7 @@
 #pragma once
 
 #include "URL.h"
+#include "WorkerThread.h"
 #include <wtf/HashSet.h>
 #include <wtf/text/WTFString.h>
 
@@ -57,9 +58,11 @@ public:
     const String& identifier() const { return m_identifier; }
     ScriptExecutionContext* scriptExecutionContext() const { return m_scriptExecutionContext.get(); }
 
+    WorkerThreadStartMode workerStartMode(ScriptExecutionContext*);
     void workerStarted(ScriptExecutionContext*, WorkerThread*, const URL&);
     void workerTerminated();
 
+    void resumeWorkerIfPaused();
     void connectToWorkerInspectorController(PageChannel*);
     void disconnectFromWorkerInspectorController();
     void sendMessageToWorkerInspectorController(const String&);
index 2b534e3..aa14b7f 100644 (file)
@@ -74,11 +74,12 @@ WorkerMessagingProxy::~WorkerMessagingProxy()
         || (is<WorkerGlobalScope>(*m_scriptExecutionContext) && currentThread() == downcast<WorkerGlobalScope>(*m_scriptExecutionContext).thread().threadID()));
 }
 
-void WorkerMessagingProxy::startWorkerGlobalScope(const URL& scriptURL, const String& userAgent, const String& sourceCode, const ContentSecurityPolicyResponseHeaders& contentSecurityPolicyResponseHeaders, bool shouldBypassMainWorldContentSecurityPolicy, WorkerThreadStartMode startMode)
+void WorkerMessagingProxy::startWorkerGlobalScope(const URL& scriptURL, const String& userAgent, const String& sourceCode, const ContentSecurityPolicyResponseHeaders& contentSecurityPolicyResponseHeaders, bool shouldBypassMainWorldContentSecurityPolicy)
 {
     // FIXME: This need to be revisited when we support nested worker one day
     ASSERT(m_scriptExecutionContext);
     Document& document = downcast<Document>(*m_scriptExecutionContext);
+    WorkerThreadStartMode startMode = m_inspectorProxy->workerStartMode(m_scriptExecutionContext.get());
 
 #if ENABLE(INDEXED_DATABASE)
     IDBClient::IDBConnectionProxy* proxy = document.idbConnectionProxy();
@@ -165,15 +166,6 @@ void WorkerMessagingProxy::postExceptionToWorkerObject(const String& errorMessag
     });
 }
 
-void WorkerMessagingProxy::postConsoleMessageToWorkerObject(MessageSource source, MessageLevel level, const String& message, int lineNumber, int columnNumber, const String& sourceURL)
-{
-    m_scriptExecutionContext->postTask([this, source, level, message = message.isolatedCopy(), sourceURL = sourceURL.isolatedCopy(), lineNumber, columnNumber] (ScriptExecutionContext& context) {
-        if (askedToTerminate())
-            return;
-        context.addConsoleMessage(source, level, message, sourceURL, lineNumber, columnNumber);
-    });
-}
-
 void WorkerMessagingProxy::postMessageToPageInspector(const String& message)
 {
     m_scriptExecutionContext->postTask([this, message = message.isolatedCopy()] (ScriptExecutionContext&) {
index 768b2cb..b0d43cb 100644 (file)
@@ -50,7 +50,7 @@ namespace WebCore {
 
         // Implementations of WorkerGlobalScopeProxy.
         // (Only use these methods in the worker object thread.)
-        void startWorkerGlobalScope(const URL& scriptURL, const String& userAgent, const String& sourceCode, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy, WorkerThreadStartMode) override;
+        void startWorkerGlobalScope(const URL& scriptURL, const String& userAgent, const String& sourceCode, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy) override;
         void terminateWorkerGlobalScope() override;
         void postMessageToWorkerGlobalScope(RefPtr<SerializedScriptValue>&&, std::unique_ptr<MessagePortChannelArray>) override;
         bool hasPendingActivity() const override;
@@ -61,7 +61,6 @@ namespace WebCore {
         // (Only use these methods in the worker context thread.)
         void postMessageToWorkerObject(RefPtr<SerializedScriptValue>&&, std::unique_ptr<MessagePortChannelArray>) override;
         void postExceptionToWorkerObject(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL) override;
-        void postConsoleMessageToWorkerObject(MessageSource, MessageLevel, const String& message, int lineNumber, int columnNumber, const String& sourceURL) override;
         void postMessageToPageInspector(const String&) override;
         void confirmMessageFromWorkerObject(bool hasPendingActivity) override;
         void reportPendingActivity(bool hasPendingActivity) override;
index 9b851ba..68519cd 100644 (file)
@@ -41,7 +41,6 @@ namespace WebCore {
 
         virtual void postExceptionToWorkerObject(const String& errorMessage, int lineNumber, int columnNumber, const String& sourceURL) = 0;
 
-        virtual void postConsoleMessageToWorkerObject(MessageSource, MessageLevel, const String& message, int lineNumber, int columnNumber, const String& sourceURL) = 0;
         virtual void postMessageToPageInspector(const String&) = 0;
 
         // Invoked when close() is invoked on the worker context.
index 9d4210f..cc36119 100644 (file)
@@ -101,6 +101,11 @@ String WorkerRunLoop::defaultMode()
     return String();
 }
 
+String WorkerRunLoop::debuggerMode()
+{
+    return ASCIILiteral("debugger");
+}
+
 class RunLoopSetup {
     WTF_MAKE_NONCOPYABLE(RunLoopSetup);
 public:
index 3a2cffc..e53e599 100644 (file)
@@ -63,6 +63,7 @@ namespace WebCore {
         unsigned long createUniqueId() { return ++m_uniqueId; }
 
         static String defaultMode();
+        static String debuggerMode();
 
         class Task {
             WTF_MAKE_NONCOPYABLE(Task); WTF_MAKE_FAST_ALLOCATED;
index 81b5ea7..0fb4c87 100644 (file)
@@ -167,6 +167,14 @@ void WorkerThread::workerThread()
         }
     }
 
+    if (m_startupData->m_startMode == WorkerThreadStartMode::WaitForInspector) {
+        startRunningDebuggerTasks();
+
+        // If the worker was somehow terminated while processing debugger commands.
+        if (m_runLoop.terminated())
+            m_workerGlobalScope->script()->forbidExecution();
+    }
+
     WorkerScriptController* script = m_workerGlobalScope->script();
     script->evaluate(ScriptSourceCode(m_startupData->m_sourceCode, m_startupData->m_scriptURL));
     // Free the startup data to cause its member variable deref's happen on the worker's thread (since
@@ -195,6 +203,22 @@ void WorkerThread::workerThread()
     detachThread(threadID);
 }
 
+void WorkerThread::startRunningDebuggerTasks()
+{
+    ASSERT(!m_pausedForDebugger);
+    m_pausedForDebugger = true;
+
+    MessageQueueWaitResult result;
+    do {
+        result = m_runLoop.runInMode(m_workerGlobalScope.get(), WorkerRunLoop::debuggerMode());
+    } while (result != MessageQueueTerminated && m_pausedForDebugger);
+}
+
+void WorkerThread::stopRunningDebuggerTasks()
+{
+    m_pausedForDebugger = false;
+}
+
 void WorkerThread::runEventLoop()
 {
     // Does not return until terminated.
index c4c4725..c711afe 100644 (file)
@@ -42,7 +42,10 @@ class WorkerGlobalScope;
 class WorkerLoaderProxy;
 class WorkerReportingProxy;
 
-enum WorkerThreadStartMode { DontPauseWorkerGlobalScopeOnStart, PauseWorkerGlobalScopeOnStart };
+enum class WorkerThreadStartMode {
+    Normal,
+    WaitForInspector,
+};
 
 namespace IDBClient {
 class IDBConnectionProxy;
@@ -71,6 +74,9 @@ public:
     void setNotificationClient(NotificationClient* client) { m_notificationClient = client; }
 #endif
 
+    void startRunningDebuggerTasks();
+    void stopRunningDebuggerTasks();
+
 protected:
     WorkerThread(const URL&, const String& userAgent, const String& sourceCode, WorkerLoaderProxy&, WorkerReportingProxy&, WorkerThreadStartMode, const ContentSecurityPolicyResponseHeaders&, bool shouldBypassMainWorldContentSecurityPolicy, const SecurityOrigin* topOrigin, IDBClient::IDBConnectionProxy*, SocketProvider*);
 
@@ -94,6 +100,7 @@ private:
     WorkerRunLoop m_runLoop;
     WorkerLoaderProxy& m_workerLoaderProxy;
     WorkerReportingProxy& m_workerReportingProxy;
+    bool m_pausedForDebugger { false };
 
     RefPtr<WorkerGlobalScope> m_workerGlobalScope;
     Lock m_threadCreationMutex;
index ca2a58e..72a5802 100644 (file)
@@ -1,5 +1,42 @@
 2016-10-27  Joseph Pecoraro  <pecoraro@apple.com>
 
+        Web Inspector: Include ConsoleAgent in Workers - real console.log support
+        https://bugs.webkit.org/show_bug.cgi?id=163844
+        <rdar://problem/28903328>
+
+        Reviewed by Brian Burg.
+
+        * UserInterface/Protocol/Target.js:
+        (WebInspector.Target.prototype.get ConsoleAgent):
+        (WebInspector.Target.prototype._initializeNonMainTarget):
+        * UserInterface/Protocol/Connection.js:
+        (InspectorBackend.WorkerConnection):
+        Add ConsoleAgent.
+
+        * UserInterface/Controllers/LogManager.js:
+        (WebInspector.LogManager.prototype.messageWasAdded):
+        (WebInspector.LogManager.prototype.requestClearMessages):
+        Handle ConsoleAgent calls with multiple targets.
+
+        * UserInterface/Protocol/ConsoleObserver.js:
+        (WebInspector.ConsoleObserver.prototype.messageAdded):
+        Dispatch with the target in case we create Model objects.
+
+        * UserInterface/Controllers/WorkerManager.js:
+        (WebInspector.WorkerManager.prototype.workerCreated):
+        The frontend must now call "initialized" on Workers after
+        sending our setup messages (enable, set breakpoints, etc).
+
+        * UserInterface/Protocol/RemoteObject.js:
+        (WebInspector.RemoteObject.prototype.get target):
+        Expose an accessor for tests.
+
+        * UserInterface/Protocol/LoggingProtocolTracer.js:
+        (WebInspector.LoggingProtocolTracer.prototype._processEntry):
+        Actually output the Exception, useful when debugging failures in tests.
+
+2016-10-27  Joseph Pecoraro  <pecoraro@apple.com>
+
         Web Inspector: Include RuntimeAgent in Workers - evaluate in Worker context
         https://bugs.webkit.org/show_bug.cgi?id=163835
         <rdar://problem/28901465>
index 92d2304..c6e7c2d 100644 (file)
@@ -132,7 +132,7 @@ WebInspector.JavaScriptLogViewController = class JavaScriptLogViewController ext
 
         function saveResultCallback(savedResultIndex)
         {
-            let commandResultMessage = new WebInspector.ConsoleCommandResultMessage(result, false, savedResultIndex, shouldRevealConsole);
+            let commandResultMessage = new WebInspector.ConsoleCommandResultMessage(result.target, result, false, savedResultIndex, shouldRevealConsole);
             let commandResultMessageView = new WebInspector.ConsoleMessageView(commandResultMessage);
             this._appendConsoleMessageView(commandResultMessageView, true);
         }
@@ -231,7 +231,7 @@ WebInspector.JavaScriptLogViewController = class JavaScriptLogViewController ext
                 return;
 
             let shouldRevealConsole = true;
-            let commandResultMessage = new WebInspector.ConsoleCommandResultMessage(result, wasThrown, savedResultIndex, shouldRevealConsole);
+            let commandResultMessage = new WebInspector.ConsoleCommandResultMessage(result.target, result, wasThrown, savedResultIndex, shouldRevealConsole);
             let commandResultMessageView = new WebInspector.ConsoleMessageView(commandResultMessage);
             this._appendConsoleMessageView(commandResultMessageView, true);
         }
index 8377e52..dd89c82 100644 (file)
@@ -40,16 +40,16 @@ WebInspector.LogManager = class LogManager extends WebInspector.Object
 
     // Public
 
-    messageWasAdded(source, level, text, type, url, line, column, repeatCount, parameters, stackTrace, requestId)
+    messageWasAdded(target, source, level, text, type, url, line, column, repeatCount, parameters, stackTrace, requestId)
     {
         // Called from WebInspector.ConsoleObserver.
 
         // FIXME: Get a request from request ID.
 
         if (parameters)
-            parameters = parameters.map(WebInspector.RemoteObject.fromPayload);
+            parameters = parameters.map((x) => WebInspector.RemoteObject.fromPayload(x, target));
 
-        let message = new WebInspector.ConsoleMessage(source, level, text, type, url, line, column, repeatCount, parameters, stackTrace, null);
+        let message = new WebInspector.ConsoleMessage(target, source, level, text, type, url, line, column, repeatCount, parameters, stackTrace, null);
 
         this.dispatchEventToListeners(WebInspector.LogManager.Event.MessageAdded, {message});
 
@@ -100,7 +100,8 @@ WebInspector.LogManager = class LogManager extends WebInspector.Object
     {
         this._clearMessagesRequested = true;
 
-        ConsoleAgent.clearMessages();
+        for (let target of WebInspector.targets)
+            target.ConsoleAgent.clearMessages();
     }
 
     // Private
index 2e7465a..2ff0521 100644 (file)
@@ -44,6 +44,9 @@ WebInspector.WorkerManager = class WorkerManager extends WebInspector.Object
         WebInspector.targetManager.addTarget(workerTarget);
 
         this._connections.set(workerId, connection);
+
+        // Unpause the worker now that we have sent all initialization messages.
+        WorkerAgent.initialized(workerId);
     }
 
     workerTerminated(workerId)
index 20732da..f76c8a8 100644 (file)
 
 WebInspector.ConsoleCommandResultMessage = class ConsoleCommandResult extends WebInspector.ConsoleMessage
 {
-    constructor(result, wasThrown, savedResultIndex, shouldRevealConsole = true)
+    constructor(target, result, wasThrown, savedResultIndex, shouldRevealConsole = true)
     {
         let source = WebInspector.ConsoleMessage.MessageSource.JS;
         let level = wasThrown ? WebInspector.ConsoleMessage.MessageLevel.Error : WebInspector.ConsoleMessage.MessageLevel.Log;
         let type = WebInspector.ConsoleMessage.MessageType.Result;
 
-        super(source, level, "", type, undefined, undefined, undefined, 0, [result], undefined, undefined);
+        super(target, source, level, "", type, undefined, undefined, undefined, 0, [result], undefined, undefined);
 
         this._savedResultIndex = savedResultIndex;
         this._shouldRevealConsole = shouldRevealConsole;
index 7e1c4a6..9a8c736 100644 (file)
 
 WebInspector.ConsoleMessage = class ConsoleMessage extends WebInspector.Object
 {
-    constructor(source, level, message, type, url, line, column, repeatCount, parameters, stackTrace, request)
+    constructor(target, source, level, message, type, url, line, column, repeatCount, parameters, stackTrace, request)
     {
         super();
 
         console.assert(typeof source === "string");
         console.assert(typeof level === "string");
         console.assert(typeof message === "string");
+        console.assert(target instanceof WebInspector.Target);
         console.assert(!parameters || parameters.every((x) => x instanceof WebInspector.RemoteObject));
 
+        this._target = target;
         this._source = source;
         this._level = level;
         this._messageText = message;
@@ -54,6 +56,7 @@ WebInspector.ConsoleMessage = class ConsoleMessage extends WebInspector.Object
 
     // Public
 
+    get target() { return this._target; }
     get source() { return this._source; }
     get level() { return this._level; }
     get messageText() { return this._messageText; }
index 699df4b..3d2ba26 100644 (file)
@@ -296,7 +296,7 @@ InspectorBackend.WorkerConnection = class InspectorBackendWorkerConnection exten
         this._workerId = workerId;
 
         // FIXME: Get this list from generated InspectorBackendCommands / InspectorBackend.
-        const workerDomains = ["Runtime"];
+        const workerDomains = ["Runtime", "Console"];
 
         for (let domain of workerDomains) {
             let agent = InspectorBackend._agents[domain];
index 6ee4e69..1dff619 100644 (file)
@@ -35,7 +35,7 @@ WebInspector.ConsoleObserver = class ConsoleObserver
         if (message.type === "assert" && !message.text)
             message.text = WebInspector.UIString("Assertion");
 
-        WebInspector.logManager.messageWasAdded(message.source, message.level, message.text, message.type, message.url, message.line, message.column || 0, message.repeatCount, message.parameters, message.stackTrace, message.networkRequestId);
+        WebInspector.logManager.messageWasAdded(this.target, message.source, message.level, message.text, message.type, message.url, message.line, message.column || 0, message.repeatCount, message.parameters, message.stackTrace, message.networkRequestId);
     }
 
     messageRepeatCountUpdated(count)
index 2d13dcc..c2c0fa6 100644 (file)
@@ -108,7 +108,13 @@ WebInspector.LoggingProtocolTracer = class LoggingProtocolTracer extends WebInsp
                 this._logToConsole(`time-stats: Handling: ${entry.timings.dispatch || NaN}ms; RTT: ${entry.timings.rtt}ms`);
             else if (entry.timings.dispatch)
                 this._logToConsole(`time-stats: Handling: ${entry.timings.dispatch || NaN}ms`);
-        } else if (this._dumpMessagesToConsole && !entry.timings)
+        } else if (this._dumpMessagesToConsole && !entry.timings) {
             this._logToConsole(`${entry.type}: ${JSON.stringify(entry.message)}`);
+            if (entry.exception) {
+                this._logToConsole(entry.exception);
+                if (entry.exception.stack)
+                    this._logToConsole(entry.exception.stack);
+            }
+        }
     }
 };
index 1bfef2c..1986a38 100644 (file)
@@ -152,6 +152,11 @@ WebInspector.RemoteObject = class RemoteObject
 
     // Public
 
+    get target()
+    {
+        return this._target;
+    }
+
     get objectId()
     {
         return this._objectId;
index fc38a1b..4e4b8c2 100644 (file)
@@ -42,6 +42,7 @@ WebInspector.Target = class Target extends WebInspector.Object
     // Agents
 
     get RuntimeAgent() { return this._connection._agents.Runtime; }
+    get ConsoleAgent() { return this._connection._agents.Console; }
 
     // Public
 
@@ -98,5 +99,8 @@ WebInspector.WorkerTarget = class WorkerTarget extends WebInspector.Target
             this.RuntimeAgent.enable();
             this._executionContext = new WebInspector.ExecutionContext(this, WebInspector.RuntimeManager.TopLevelContextExecutionIdentifier, this.displayName, false, null);
         }
+
+        if (this.ConsoleAgent)
+            this.ConsoleAgent.enable();
     }
 }
index 65bf51c..3122aab 100644 (file)
@@ -416,7 +416,7 @@ WebInspector.ConsoleMessageView = class ConsoleMessageView extends WebInspector.
             return parameter;
 
         if (typeof parameter === "object")
-            return WebInspector.RemoteObject.fromPayload(parameter);
+            return WebInspector.RemoteObject.fromPayload(parameter, this._message.target);
 
         return WebInspector.RemoteObject.fromPrimitiveValue(parameter);
     }