Web Inspector: create additional command line api functions for other console methods
authordrousso@apple.com <drousso@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 24 Aug 2019 00:46:56 +0000 (00:46 +0000)
committerdrousso@apple.com <drousso@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 24 Aug 2019 00:46:56 +0000 (00:46 +0000)
https://bugs.webkit.org/show_bug.cgi?id=200971

Reviewed by Joseph Pecoraro.

Source/JavaScriptCore:

Expose all `console.*` functions in the command line API, since they're all already able to
be referenced via the `console` object.

Provide a simpler interface for other injected scripts to modify the command line API.

* inspector/InjectedScriptModule.cpp:
(Inspector::InjectedScriptModule::ensureInjected):

* inspector/InjectedScriptSource.js:
(InjectedScript.prototype.inspectObject):
(InjectedScript.prototype.addCommandLineAPIGetter): Added.
(InjectedScript.prototype.addCommandLineAPIMethod): Added.
(InjectedScript.prototype.hasInjectedModule): Added.
(InjectedScript.prototype.injectModule):
(InjectedScript.prototype._evaluateOn):
(InjectedScript.CommandLineAPI): Added.
(InjectedScript.prototype.module): Deleted.
(InjectedScript.prototype._savedResult): Deleted.
(bind): Deleted.
(BasicCommandLineAPI): Deleted.
(clear): Deleted.
(table): Deleted.
(profile): Deleted.
(profileEnd): Deleted.
(keys): Deleted.
(values): Deleted.
(queryInstances): Deleted.
(queryObjects): Deleted.
(queryHolders): Deleted.

Source/WebCore:

Expose all `console.*` functions in the command line API, since they're all already able to
be referenced via the `console` object.

Provide a simpler interface for other injected scripts to modify the command line API.

* inspector/CommandLineAPIModuleSource.js:
(injectedScript._inspectObject): Added.
(normalizeEventTypes): Added.
(logEvent): Added.
(canQuerySelectorOnNode): Added.
(bind): Deleted.
(value): Deleted.
(this.method.toString): Deleted.
(CommandLineAPI): Deleted.
(CommandLineAPIImpl): Deleted.
(CommandLineAPIImpl.prototype): Deleted.
(CommandLineAPIImpl.prototype._canQuerySelectorOnNode): Deleted.
(CommandLineAPIImpl.prototype.x): Deleted.
(CommandLineAPIImpl.prototype.dir): Deleted.
(CommandLineAPIImpl.prototype.dirxml): Deleted.
(CommandLineAPIImpl.prototype.keys): Deleted.
(CommandLineAPIImpl.prototype.values): Deleted.
(CommandLineAPIImpl.prototype.profile): Deleted.
(CommandLineAPIImpl.prototype.profileEnd): Deleted.
(CommandLineAPIImpl.prototype.table): Deleted.
(CommandLineAPIImpl.prototype.screenshot): Deleted.
(CommandLineAPIImpl.prototype.monitorEvents): Deleted.
(CommandLineAPIImpl.prototype.unmonitorEvents): Deleted.
(CommandLineAPIImpl.prototype.inspect): Deleted.
(CommandLineAPIImpl.prototype.queryInstances): Deleted.
(CommandLineAPIImpl.prototype.queryObjects): Deleted.
(CommandLineAPIImpl.prototype.queryHolders): Deleted.
(CommandLineAPIImpl.prototype.copy): Deleted.
(CommandLineAPIImpl.prototype.clear): Deleted.
(CommandLineAPIImpl.prototype.getEventListeners): Deleted.
(CommandLineAPIImpl.prototype._inspectedObject): Deleted.
(CommandLineAPIImpl.prototype._normalizeEventTypes): Deleted.
(CommandLineAPIImpl.prototype._logEvent): Deleted.
(CommandLineAPIImpl.prototype._inspect): Deleted.

Source/WebInspectorUI:

Expose all `console.*` functions in the command line API, since they're all already able to
be referenced via the `console` object.

Provide a simpler interface for other injected scripts to modify the command line API.

* UserInterface/Controllers/JavaScriptRuntimeCompletionProvider.js:
(WI.JavaScriptRuntimeCompletionProvider.prototype.get _commandLineAPIKeys): Added.
(WI.JavaScriptRuntimeCompletionProvider.prototype.completionControllerCompletionsNeeded.updateLastPropertyNames):
(WI.JavaScriptRuntimeCompletionProvider.prototype.completionControllerCompletionsNeeded.receivedPropertyNames):

LayoutTests:

* http/tests/inspector/dom/cross-domain-inspected-node-access-expected.txt:
* inspector/console/command-line-api-expected.txt:

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

LayoutTests/ChangeLog
LayoutTests/http/tests/inspector/dom/cross-domain-inspected-node-access-expected.txt
LayoutTests/inspector/console/command-line-api-expected.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/inspector/InjectedScriptModule.cpp
Source/JavaScriptCore/inspector/InjectedScriptSource.js
Source/WebCore/ChangeLog
Source/WebCore/inspector/CommandLineAPIModuleSource.js
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/UserInterface/Controllers/JavaScriptRuntimeCompletionProvider.js

index 3a2626f..05646b9 100644 (file)
@@ -1,3 +1,13 @@
+2019-08-23  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: create additional command line api functions for other console methods
+        https://bugs.webkit.org/show_bug.cgi?id=200971
+
+        Reviewed by Joseph Pecoraro.
+
+        * http/tests/inspector/dom/cross-domain-inspected-node-access-expected.txt:
+        * inspector/console/command-line-api-expected.txt:
+
 2019-08-23  Wenson Hsieh  <wenson_hsieh@apple.com>
 
         [iOS] [WebKit2] Tapping on the “I’m” text suggestion after typing “i’” does nothing
index 2bd86b0..5b08b41 100644 (file)
@@ -1,5 +1,5 @@
-CONSOLE MESSAGE: line 51: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
-CONSOLE MESSAGE: line 51: Blocked a frame with origin "http://localhost:8000" from accessing a frame with origin "http://127.0.0.1:8000". Protocols, domains, and ports must match.
+CONSOLE MESSAGE: line 8: Blocked a frame with origin "http://127.0.0.1:8000" from accessing a frame with origin "http://localhost:8000". Protocols, domains, and ports must match.
+CONSOLE MESSAGE: line 8: Blocked a frame with origin "http://localhost:8000" from accessing a frame with origin "http://127.0.0.1:8000". Protocols, domains, and ports must match.
 Test that code evaluated in the main frame cannot access $0 that resolves to a node in a frame from a different domain. Bug 105423.
 
 
index 43e0dea..6cf68b8 100644 (file)
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 17: The console function $() has changed from $=getElementById(id) to $=querySelector(selector). You might try $("#%s")
+CONSOLE MESSAGE: line 31: The console function $() has changed from $=getElementById(id) to $=querySelector(selector). You might try $("#%s")
 Tests that command line api works.
 
 
index 1542547..f1ae0f7 100644 (file)
@@ -1,3 +1,40 @@
+2019-08-23  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: create additional command line api functions for other console methods
+        https://bugs.webkit.org/show_bug.cgi?id=200971
+
+        Reviewed by Joseph Pecoraro.
+
+        Expose all `console.*` functions in the command line API, since they're all already able to
+        be referenced via the `console` object.
+
+        Provide a simpler interface for other injected scripts to modify the command line API.
+
+        * inspector/InjectedScriptModule.cpp:
+        (Inspector::InjectedScriptModule::ensureInjected):
+
+        * inspector/InjectedScriptSource.js:
+        (InjectedScript.prototype.inspectObject):
+        (InjectedScript.prototype.addCommandLineAPIGetter): Added.
+        (InjectedScript.prototype.addCommandLineAPIMethod): Added.
+        (InjectedScript.prototype.hasInjectedModule): Added.
+        (InjectedScript.prototype.injectModule):
+        (InjectedScript.prototype._evaluateOn):
+        (InjectedScript.CommandLineAPI): Added.
+        (InjectedScript.prototype.module): Deleted.
+        (InjectedScript.prototype._savedResult): Deleted.
+        (bind): Deleted.
+        (BasicCommandLineAPI): Deleted.
+        (clear): Deleted.
+        (table): Deleted.
+        (profile): Deleted.
+        (profileEnd): Deleted.
+        (keys): Deleted.
+        (values): Deleted.
+        (queryInstances): Deleted.
+        (queryObjects): Deleted.
+        (queryHolders): Deleted.
+
 2019-08-23  Tadeu Zagallo  <tzagallo@apple.com>
 
         Remove MaximalFlushInsertionPhase
index 403f671..fd0206e 100644 (file)
@@ -62,20 +62,21 @@ void InjectedScriptModule::ensureInjected(InjectedScriptManager* injectedScriptM
 
     // FIXME: Make the InjectedScript a module itself.
     JSC::JSLockHolder locker(injectedScript.scriptState());
-    Deprecated::ScriptFunctionCall function(injectedScript.injectedScriptObject(), "module"_s, injectedScriptManager->inspectorEnvironment().functionCallHandler());
+    Deprecated::ScriptFunctionCall function(injectedScript.injectedScriptObject(), "hasInjectedModule"_s, injectedScriptManager->inspectorEnvironment().functionCallHandler());
     function.appendArgument(name());
     bool hadException = false;
     auto resultValue = injectedScript.callFunctionWithEvalEnabled(function, hadException);
     ASSERT(!hadException);
-    if (hadException || !resultValue || !resultValue.isObject()) {
+    if (hadException || !resultValue || !resultValue.isBoolean() || !resultValue.asBoolean()) {
         Deprecated::ScriptFunctionCall function(injectedScript.injectedScriptObject(), "injectModule"_s, injectedScriptManager->inspectorEnvironment().functionCallHandler());
         function.appendArgument(name());
         function.appendArgument(source());
         function.appendArgument(host(injectedScriptManager, injectedScript.scriptState()));
         resultValue = injectedScript.callFunctionWithEvalEnabled(function, hadException);
         if (hadException) {
-            ASSERT_NOT_REACHED();
-            return;
+            WTFLogAlways("Failed to parse/execute %s!", name().ascii().data());
+            WTFLogAlways("%s\n", source().ascii().data());
+            RELEASE_ASSERT_NOT_REACHED();
         }
     }
 }
index 363ab6a..7b38c98 100644 (file)
@@ -389,8 +389,8 @@ let InjectedScript = class InjectedScript
 
     inspectObject(object)
     {
-        if (this._commandLineAPIImpl)
-            this._commandLineAPIImpl.inspect(object);
+        if (this._inspectObject)
+            this._inspectObject(object);
     }
 
     releaseObject(objectId)
@@ -417,27 +417,36 @@ let InjectedScript = class InjectedScript
         delete this._objectGroups[objectGroupName];
     }
 
+    // CommandLineAPI
+
+    addCommandLineAPIGetter(name, func)
+    {
+        InjectedScript.CommandLineAPI._getters.push({name, func});
+    }
+
+    addCommandLineAPIMethod(name, func)
+    {
+        func.toString = function() { return "function " + name + "() { [Command Line API] }" };
+        InjectedScript.CommandLineAPI._methods.push({name, func});
+    }
+
     // InjectedScriptModule C++ API
 
-    module(name)
+    hasInjectedModule(name)
     {
         return this._modules[name];
     }
 
     injectModule(name, source, host)
     {
-        delete this._modules[name];
+        this._modules[name] = false;
 
         let moduleFunction = InjectedScriptHost.evaluate("(" + source + ")");
-        if (typeof moduleFunction !== "function") {
-            if (inspectedGlobalObject.console)
-                inspectedGlobalObject.console.error("Web Inspector error: A function was expected for module %s evaluation", name);
-            return null;
-        }
+        if (typeof moduleFunction !== "function")
+            throw "Error: Web Inspector: a function was expected for injectModule";
+        moduleFunction.call(inspectedGlobalObject, InjectedScriptHost, inspectedGlobalObject, injectedScriptId, this, RemoteObject, host);
 
-        let module = moduleFunction.call(inspectedGlobalObject, InjectedScriptHost, inspectedGlobalObject, injectedScriptId, this, RemoteObject, host);
-        this._modules[name] = module;
-        return module;
+        this._modules[name] = true;
     }
 
     // InjectedScriptModule JavaScript API
@@ -568,13 +577,8 @@ let InjectedScript = class InjectedScript
     _evaluateOn(evalFunction, object, expression, isEvalOnCallFrame, includeCommandLineAPI)
     {
         let commandLineAPI = null;
-        if (includeCommandLineAPI) {
-            if (this.CommandLineAPI)
-                commandLineAPI = new this.CommandLineAPI(this._commandLineAPIImpl, isEvalOnCallFrame ? object : null);
-            else
-                commandLineAPI = new BasicCommandLineAPI(isEvalOnCallFrame ? object : null);
-        }
-
+        if (includeCommandLineAPI)
+            commandLineAPI = new InjectedScript.CommandLineAPI(isEvalOnCallFrame ? object : null)
         return evalFunction.call(object, expression, commandLineAPI);
     }
 
@@ -869,11 +873,6 @@ let InjectedScript = class InjectedScript
         if (this._nextSavedResultIndex >= 100)
             this._nextSavedResultIndex = 1;
     }
-
-    _savedResult(index)
-    {
-        return this._savedResults[index];
-    }
 };
 
 InjectedScript.CollectionMode = {
@@ -1457,80 +1456,89 @@ InjectedScript.CallFrameProxy._createScopeJson = function(object, {name, type, l
 
 // -------
 
-function bind(func, thisObject, ...outerArgs)
+InjectedScript.CommandLineAPI = class CommandLineAPI
 {
-    return function(...innerArgs) {
-        return func.apply(thisObject, outerArgs.concat(innerArgs));
-    };
-}
+    constructor(callFrame)
+    {
+        let savedResultAlias = InjectedScriptHost.savedResultAlias;
 
-function BasicCommandLineAPI(callFrame)
-{
-    let savedResultAlias = InjectedScriptHost.savedResultAlias;
+        let defineGetter = (key, value) => {
+            if (typeof value !== "function") {
+                let originalValue = value;
+                value = function() { return originalValue; };
+            }
 
-    let defineGetter = (key, value) => {
-        if (typeof value !== "function") {
-            let originalValue = value;
-            value = function() { return originalValue; };
-        }
+            this.__defineGetter__("$" + key, value);
+            if (savedResultAlias)
+                this.__defineGetter__(savedResultAlias + key, value);
+        };
 
-        this.__defineGetter__("$" + key, value);
-        if (savedResultAlias)
-            this.__defineGetter__(savedResultAlias + key, value);
-    };
+        if ("_lastResult" in injectedScript)
+            defineGetter("_", injectedScript._lastResult);
 
-    if ("_lastResult" in injectedScript)
-        defineGetter("_", injectedScript._lastResult);
+        if ("_exceptionValue" in injectedScript)
+            defineGetter("exception", injectedScript._exceptionValue);
 
-    if ("_exceptionValue" in injectedScript)
-        defineGetter("exception", injectedScript._exceptionValue);
+        if ("_eventValue" in injectedScript)
+            defineGetter("event", injectedScript._eventValue);
 
-    if ("_eventValue" in injectedScript)
-        defineGetter("event", injectedScript._eventValue);
+        // $1-$99
+        for (let i = 1; i <= injectedScript._savedResults.length; ++i) {
+            defineGetter(i, function() {
+                return injectedScript._savedResults[i];
+            });
+        }
 
-    // $1-$99
-    for (let i = 1; i <= injectedScript._savedResults.length; ++i)
-        defineGetter(i, bind(injectedScript._savedResult, injectedScript, i));
+        for (let i = 0; i < InjectedScript.CommandLineAPI._getters.length; ++i) {
+            let {name, func} = InjectedScript.CommandLineAPI._getters[i];
+            defineGetter(name, func);
+        }
 
-    // Command Line API methods.
-    for (let i = 0; i < BasicCommandLineAPI.methods.length; ++i) {
-        let method = BasicCommandLineAPI.methods[i];
-        this[method.name] = method;
+        for (let i = 0; i < InjectedScript.CommandLineAPI._methods.length; ++i) {
+            let {name, func} = InjectedScript.CommandLineAPI._methods[i];
+            this[name] = func;
+        }
     }
-}
-
-BasicCommandLineAPI.methods = [
-    function dir() { return inspectedGlobalObject.console.dir(...arguments); },
-    function clear() { return inspectedGlobalObject.console.clear(...arguments); },
-    function table() { return inspectedGlobalObject.console.table(...arguments); },
-    function profile() { return inspectedGlobalObject.console.profile(...arguments); },
-    function profileEnd() { return inspectedGlobalObject.console.profileEnd(...arguments); },
-
-    function keys(object) { return Object.keys(object); },
-    function values(object) {
-        let result = [];
-        for (let key in object)
-            result.push(object[key]);
-        return result;
-    },
-
-    function queryInstances() {
-        return InjectedScriptHost.queryInstances(...arguments);
-    },
-
-    function queryObjects() {
-        return InjectedScriptHost.queryInstances(...arguments);
-    },
-
-    function queryHolders() {
-        return InjectedScriptHost.queryHolders(...arguments);
-    },
-];
+};
 
-for (let i = 0; i < BasicCommandLineAPI.methods.length; ++i) {
-    let method = BasicCommandLineAPI.methods[i];
-    method.toString = function() { return "function " + method.name + "() { [Command Line API] }"; };
-}
+InjectedScript.CommandLineAPI._getters = [];
+InjectedScript.CommandLineAPI._methods = [];
+
+injectedScript.addCommandLineAPIMethod("keys", function(object) { return Object.keys(object); });
+injectedScript.addCommandLineAPIMethod("values", function(object) { return Object.values(object); });
+
+injectedScript.addCommandLineAPIMethod("queryInstances", function() { return InjectedScriptHost.queryInstances(...arguments); });
+injectedScript.addCommandLineAPIMethod("queryObjects", function() { return InjectedScriptHost.queryInstances(...arguments); });
+injectedScript.addCommandLineAPIMethod("queryHolders", function() { return InjectedScriptHost.queryHolders(...arguments); });
+
+injectedScript.addCommandLineAPIMethod("inspect", function(object) { return injectedScript.inspectObject(object); });
+
+injectedScript.addCommandLineAPIMethod("assert", function() { return inspectedGlobalObject.console.assert(...arguments); });
+injectedScript.addCommandLineAPIMethod("clear", function() { return inspectedGlobalObject.console.clear(...arguments); });
+injectedScript.addCommandLineAPIMethod("count", function() { return inspectedGlobalObject.console.count(...arguments); });
+injectedScript.addCommandLineAPIMethod("countReset", function() { return inspectedGlobalObject.console.countReset(...arguments); });
+injectedScript.addCommandLineAPIMethod("debug", function() { return inspectedGlobalObject.console.debug(...arguments); });
+injectedScript.addCommandLineAPIMethod("dir", function() { return inspectedGlobalObject.console.dir(...arguments); });
+injectedScript.addCommandLineAPIMethod("dirxml", function() { return inspectedGlobalObject.console.dirxml(...arguments); });
+injectedScript.addCommandLineAPIMethod("error", function() { return inspectedGlobalObject.console.error(...arguments); });
+injectedScript.addCommandLineAPIMethod("group", function() { return inspectedGlobalObject.console.group(...arguments); });
+injectedScript.addCommandLineAPIMethod("groupCollapsed", function() { return inspectedGlobalObject.console.groupCollapsed(...arguments); });
+injectedScript.addCommandLineAPIMethod("groupEnd", function() { return inspectedGlobalObject.console.groupEnd(...arguments); });
+injectedScript.addCommandLineAPIMethod("info", function() { return inspectedGlobalObject.console.info(...arguments); });
+injectedScript.addCommandLineAPIMethod("log", function() { return inspectedGlobalObject.console.log(...arguments); });
+injectedScript.addCommandLineAPIMethod("profile", function() { return inspectedGlobalObject.console.profile(...arguments); });
+injectedScript.addCommandLineAPIMethod("profileEnd", function() { return inspectedGlobalObject.console.profileEnd(...arguments); });
+injectedScript.addCommandLineAPIMethod("record", function() { return inspectedGlobalObject.console.record(...arguments); });
+injectedScript.addCommandLineAPIMethod("recordEnd", function() { return inspectedGlobalObject.console.recordEnd(...arguments); });
+injectedScript.addCommandLineAPIMethod("screenshot", function() { return inspectedGlobalObject.console.screenshot(...arguments); });
+injectedScript.addCommandLineAPIMethod("table", function() { return inspectedGlobalObject.console.table(...arguments); });
+injectedScript.addCommandLineAPIMethod("takeHeapSnapshot", function() { return inspectedGlobalObject.console.takeHeapSnapshot(...arguments); });
+injectedScript.addCommandLineAPIMethod("time", function() { return inspectedGlobalObject.console.time(...arguments); });
+injectedScript.addCommandLineAPIMethod("timeEnd", function() { return inspectedGlobalObject.console.timeEnd(...arguments); });
+injectedScript.addCommandLineAPIMethod("timeLog", function() { return inspectedGlobalObject.console.timeLog(...arguments); });
+injectedScript.addCommandLineAPIMethod("timeStamp", function() { return inspectedGlobalObject.console.timeStamp(...arguments); });
+injectedScript.addCommandLineAPIMethod("trace", function() { return inspectedGlobalObject.console.trace(...arguments); });
+injectedScript.addCommandLineAPIMethod("warn", function() { return inspectedGlobalObject.console.warn(...arguments); });
 
 return injectedScript;
 })
index ddd4674..426f9c7 100644 (file)
@@ -1,3 +1,50 @@
+2019-08-23  Devin Rousso  <drousso@apple.com>
+
+        Web Inspector: create additional command line api functions for other console methods
+        https://bugs.webkit.org/show_bug.cgi?id=200971
+
+        Reviewed by Joseph Pecoraro.
+
+        Expose all `console.*` functions in the command line API, since they're all already able to
+        be referenced via the `console` object.
+
+        Provide a simpler interface for other injected scripts to modify the command line API.
+
+        * inspector/CommandLineAPIModuleSource.js:
+        (injectedScript._inspectObject): Added.
+        (normalizeEventTypes): Added.
+        (logEvent): Added.
+        (canQuerySelectorOnNode): Added.
+        (bind): Deleted.
+        (value): Deleted.
+        (this.method.toString): Deleted.
+        (CommandLineAPI): Deleted.
+        (CommandLineAPIImpl): Deleted.
+        (CommandLineAPIImpl.prototype): Deleted.
+        (CommandLineAPIImpl.prototype._canQuerySelectorOnNode): Deleted.
+        (CommandLineAPIImpl.prototype.x): Deleted.
+        (CommandLineAPIImpl.prototype.dir): Deleted.
+        (CommandLineAPIImpl.prototype.dirxml): Deleted.
+        (CommandLineAPIImpl.prototype.keys): Deleted.
+        (CommandLineAPIImpl.prototype.values): Deleted.
+        (CommandLineAPIImpl.prototype.profile): Deleted.
+        (CommandLineAPIImpl.prototype.profileEnd): Deleted.
+        (CommandLineAPIImpl.prototype.table): Deleted.
+        (CommandLineAPIImpl.prototype.screenshot): Deleted.
+        (CommandLineAPIImpl.prototype.monitorEvents): Deleted.
+        (CommandLineAPIImpl.prototype.unmonitorEvents): Deleted.
+        (CommandLineAPIImpl.prototype.inspect): Deleted.
+        (CommandLineAPIImpl.prototype.queryInstances): Deleted.
+        (CommandLineAPIImpl.prototype.queryObjects): Deleted.
+        (CommandLineAPIImpl.prototype.queryHolders): Deleted.
+        (CommandLineAPIImpl.prototype.copy): Deleted.
+        (CommandLineAPIImpl.prototype.clear): Deleted.
+        (CommandLineAPIImpl.prototype.getEventListeners): Deleted.
+        (CommandLineAPIImpl.prototype._inspectedObject): Deleted.
+        (CommandLineAPIImpl.prototype._normalizeEventTypes): Deleted.
+        (CommandLineAPIImpl.prototype._logEvent): Deleted.
+        (CommandLineAPIImpl.prototype._inspect): Deleted.
+
 2019-08-23  Chris Dumez  <cdumez@apple.com>
 
         Crash under TimerBase::setNextFireTime() in the NetworkProcess
index d5f84ed..8e55c6f 100644 (file)
 
 //# sourceURL=__InjectedScript_CommandLineAPIModuleSource.js
 
-(function (InjectedScriptHost, inspectedWindow, injectedScriptId, injectedScript, RemoteObject, CommandLineAPIHost) {
+(function (InjectedScriptHost, inspectedGlobalObject, injectedScriptId, injectedScript, RemoteObject, CommandLineAPIHost) {
 
 // FIXME: <https://webkit.org/b/152294> Web Inspector: Parse InjectedScriptSource as a built-in to get guaranteed non-user-overridden built-ins
 
-function bind(func, thisObject, ...outerArgs)
-{
-    return function(...innerArgs) {
-        return func.apply(thisObject, outerArgs.concat(innerArgs));
-    };
-}
-
-/**
- * @constructor
- * @param {CommandLineAPIImpl} commandLineAPIImpl
- * @param {Object} callFrame
- */
-function CommandLineAPI(commandLineAPIImpl, callFrame)
-{
-    let savedResultAlias = InjectedScriptHost.savedResultAlias;
+injectedScript._inspectObject = function(object) {
+    if (arguments.length === 0)
+        return;
+
+    let objectId = RemoteObject.create(object, "");
+    let hints = {};
+
+    switch (RemoteObject.describe(object)) {
+    case "Database":
+        let databaseId = CommandLineAPIHost.databaseId(object)
+        if (databaseId)
+            hints.databaseId = databaseId;
+        break;
+    case "Storage":
+        let storageId = CommandLineAPIHost.storageId(object)
+        if (storageId)
+            hints.domStorageId = InjectedScriptHost.evaluate("(" + storageId + ")");
+        break;
+    }
 
-    let defineGetter = (key, value) => {
-        if (typeof value !== "function") {
-            let originalValue = value;
-            value = function() { return originalValue; };
+    CommandLineAPIHost.inspect(objectId, hints);
+    return object;
+};
+
+injectedScript.addCommandLineAPIGetter("0", function() {
+    return CommandLineAPIHost.inspectedObject();
+});
+
+injectedScript.addCommandLineAPIMethod("copy", function(object) {
+    let string = null;
+
+    let subtype = RemoteObject.subtype(object);
+    if (subtype === "node")
+        string = object.outerHTML;
+    else if (subtype === "regexp")
+        string = "" + object;
+    else if (injectedScript.isPrimitiveValue(object))
+        string = "" + object;
+    else if (typeof object === "symbol")
+        string = String(object);
+    else if (typeof object === "function")
+        string = "" + object;
+    else {
+        try {
+            string = JSON.stringify(object, null, "  ");
+        } catch {
+            string = "" + object;
         }
+    }
 
-        this.__defineGetter__("$" + key, value);
-        if (savedResultAlias)
-            this.__defineGetter__(savedResultAlias + key, value);
-    };
-
-    if ("_lastResult" in injectedScript)
-        defineGetter("_", injectedScript._lastResult);
-
-    if ("_exceptionValue" in injectedScript)
-        defineGetter("exception", injectedScript._exceptionValue);
-
-    if ("_eventValue" in injectedScript)
-        defineGetter("event", injectedScript._eventValue);
-
-    // $0
-    defineGetter("0", bind(commandLineAPIImpl._inspectedObject, commandLineAPIImpl));
-
-    // $1-$99
-    for (let i = 1; i <= injectedScript._savedResults.length; ++i)
-        defineGetter(i, bind(injectedScript._savedResult, injectedScript, i));
-
-    // Command Line API methods.
-    for (let i = 0; i < CommandLineAPI.methods.length; ++i) {
-        let method = CommandLineAPI.methods[i];
-        this[method] = bind(commandLineAPIImpl[method], commandLineAPIImpl);
-        this[method].toString = function() { return "function " + method + "() { [Command Line API] }" };
+    CommandLineAPIHost.copyText(string);
+});
+
+injectedScript.addCommandLineAPIMethod("getEventListeners", function(target) {
+    return CommandLineAPIHost.getEventListeners(target);
+});
+
+function normalizeEventTypes(types) {
+    if (types === undefined)
+        types = ["mouse", "key", "touch", "control", "abort", "blur", "change", "devicemotion", "deviceorientation", "error", "focus", "load", "reset", "resize", "scroll", "search", "select", "submit", "unload"];
+    else if (typeof types === "string")
+        types = [types];
+
+    let result = [];
+    for (let i = 0; i < types.length; i++) {
+        if (types[i] === "mouse")
+            result.push("click", "dblclick", "mousedown", "mousemove", "mouseout", "mouseover", "mouseup", "mousewheel");
+        else if (types[i] === "key")
+            result.push("keydown", "keypress", "keyup", "textInput");
+        else if (types[i] === "touch")
+            result.push("touchcancel", "touchend", "touchmove", "touchstart");
+        else if (types[i] === "control")
+            result.push("blur", "change", "focus", "reset", "resize", "scroll", "select", "submit", "zoom");
+        else
+            result.push(types[i]);
     }
+    return result;
 }
 
-/**
- * @type {Array.<string>}
- * @const
- */
-CommandLineAPI.methods = [
-    "$",
-    "$$",
-    "$x",
-    "clear",
-    "copy",
-    "dir",
-    "dirxml",
-    "getEventListeners",
-    "inspect",
-    "keys",
-    "monitorEvents",
-    "profile",
-    "profileEnd",
-    "queryInstances",
-    "queryObjects",
-    "queryHolders",
-    "screenshot",
-    "table",
-    "unmonitorEvents",
-    "values",
-];
-
-/**
- * @constructor
- */
-function CommandLineAPIImpl()
+function logEvent(event)
 {
+    inspectedGlobalObject.console.log(event.type, event);
 }
 
-CommandLineAPIImpl.prototype = {
-    /**
-     * @param {string} selector
-     * @param {Node=} start
-     */
-    $: function (selector, start)
-    {
-        if (this._canQuerySelectorOnNode(start))
+injectedScript.addCommandLineAPIMethod("monitorEvents", function(object, types) {
+    if (!object || !object.addEventListener || !object.removeEventListener)
+        return;
+    types = normalizeEventTypes(types);
+    for (let i = 0; i < types.length; ++i) {
+        object.removeEventListener(types[i], logEvent, false);
+        object.addEventListener(types[i], logEvent, false);
+    }
+});
+
+injectedScript.addCommandLineAPIMethod("unmonitorEvents", function(object, types) {
+    if (!object || !object.addEventListener || !object.removeEventListener)
+        return;
+    types = normalizeEventTypes(types);
+    for (let i = 0; i < types.length; ++i)
+        object.removeEventListener(types[i], logEvent, false);
+});
+
+if (inspectedGlobalObject.document && inspectedGlobalObject.Node) {
+    function canQuerySelectorOnNode(node) {
+        return node && InjectedScriptHost.subtype(node) === "node" && (node.nodeType === inspectedGlobalObject.Node.ELEMENT_NODE || node.nodeType === inspectedGlobalObject.Node.DOCUMENT_NODE || node.nodeType === inspectedGlobalObject.Node.DOCUMENT_FRAGMENT_NODE);
+    }
+
+    injectedScript.addCommandLineAPIMethod("$", function(selector, start) {
+        if (canQuerySelectorOnNode(start))
             return start.querySelector(selector);
 
-        var result = inspectedWindow.document.querySelector(selector);
+        let result = inspectedGlobalObject.document.querySelector(selector);
         if (result)
             return result;
+
         if (selector && selector[0] !== "#") {
-            result = inspectedWindow.document.getElementById(selector);
+            result = inspectedGlobalObject.document.getElementById(selector);
             if (result) {
-                inspectedWindow.console.warn("The console function $() has changed from $=getElementById(id) to $=querySelector(selector). You might try $(\"#%s\")", selector);
+                inspectedGlobalObject.console.warn("The console function $() has changed from $=getElementById(id) to $=querySelector(selector). You might try $(\"#%s\")", selector);
                 return null;
             }
         }
+
         return result;
-    },
+    });
 
-    /**
-     * @param {string} selector
-     * @param {Node=} start
-     */
-    $$: function (selector, start)
-    {
-        if (this._canQuerySelectorOnNode(start))
+    injectedScript.addCommandLineAPIMethod("$$", function(selector, start) {
+        if (canQuerySelectorOnNode(start))
             return Array.from(start.querySelectorAll(selector));
-        return Array.from(inspectedWindow.document.querySelectorAll(selector));
-    },
+        return Array.from(inspectedGlobalObject.document.querySelectorAll(selector));
+    });
 
-    /**
-     * @param {Node=} node
-     * @return {boolean}
-     */
-    _canQuerySelectorOnNode: function(node)
-    {
-        return !!node && InjectedScriptHost.subtype(node) === "node" && (node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.DOCUMENT_NODE || node.nodeType === Node.DOCUMENT_FRAGMENT_NODE);
-    },
-
-    /**
-     * @param {string} xpath
-     * @param {Node=} context
-     */
-    $x: function(xpath, context)
-    {
-        var doc = (context && context.ownerDocument) || inspectedWindow.document;
+    injectedScript.addCommandLineAPIMethod("$x", function(xpath, context) {
+        let doc = (context && context.ownerDocument) || inspectedGlobalObject.document;
         var result = doc.evaluate(xpath, context || doc, null, XPathResult.ANY_TYPE, null);
         switch (result.resultType) {
         case XPathResult.NUMBER_TYPE:
@@ -182,213 +181,7 @@ CommandLineAPIImpl.prototype = {
                 nodes.push(node);
             return nodes;
         }
-    },
-
-    dir: function()
-    {
-        return inspectedWindow.console.dir.apply(inspectedWindow.console, arguments)
-    },
-
-    dirxml: function()
-    {
-        return inspectedWindow.console.dirxml.apply(inspectedWindow.console, arguments)
-    },
-
-    keys: function(object)
-    {
-        return Object.keys(object);
-    },
-
-    values: function(object)
-    {
-        var result = [];
-        for (var key in object)
-            result.push(object[key]);
-        return result;
-    },
-
-    profile: function()
-    {
-        return inspectedWindow.console.profile.apply(inspectedWindow.console, arguments)
-    },
-
-    profileEnd: function()
-    {
-        return inspectedWindow.console.profileEnd.apply(inspectedWindow.console, arguments)
-    },
-
-    table: function()
-    {
-        return inspectedWindow.console.table.apply(inspectedWindow.console, arguments)
-    },
-
-    screenshot: function()
-    {
-        return inspectedWindow.console.screenshot.apply(inspectedWindow.console, arguments)
-    },
-
-    /**
-     * @param {Object} object
-     * @param {Array.<string>|string=} types
-     */
-    monitorEvents: function(object, types)
-    {
-        if (!object || !object.addEventListener || !object.removeEventListener)
-            return;
-        types = this._normalizeEventTypes(types);
-        for (var i = 0; i < types.length; ++i) {
-            object.removeEventListener(types[i], this._logEvent, false);
-            object.addEventListener(types[i], this._logEvent, false);
-        }
-    },
-
-    /**
-     * @param {Object} object
-     * @param {Array.<string>|string=} types
-     */
-    unmonitorEvents: function(object, types)
-    {
-        if (!object || !object.addEventListener || !object.removeEventListener)
-            return;
-        types = this._normalizeEventTypes(types);
-        for (var i = 0; i < types.length; ++i)
-            object.removeEventListener(types[i], this._logEvent, false);
-    },
-
-    /**
-     * @param {*} object
-     * @return {*}
-     */
-    inspect: function(object)
-    {
-        return this._inspect(object);
-    },
-
-    queryInstances()
-    {
-        return InjectedScriptHost.queryInstances(...arguments);
-    },
-
-    queryObjects()
-    {
-        return InjectedScriptHost.queryInstances(...arguments);
-    },
-
-    queryHolders()
-    {
-        return InjectedScriptHost.queryHolders(...arguments);
-    },
-
-    copy: function(object)
-    {
-        var string;
-        var subtype = RemoteObject.subtype(object);
-        if (subtype === "node")
-            string = object.outerHTML;
-        else if (subtype === "regexp")
-            string = "" + object;
-        else if (injectedScript.isPrimitiveValue(object))
-            string = "" + object;
-        else if (typeof object === "symbol")
-            string = String(object);
-        else if (typeof object === "function")
-            string = "" + object;
-        else {
-            try {
-                string = JSON.stringify(object, null, "  ");
-            } catch (e) {
-                string = "" + object;
-            }
-        }
-
-        CommandLineAPIHost.copyText(string);
-    },
-
-    clear: function()
-    {
-        CommandLineAPIHost.clearConsoleMessages();
-    },
-
-    getEventListeners: function(target)
-    {
-        return CommandLineAPIHost.getEventListeners(target);
-    },
-
-    _inspectedObject: function()
-    {
-        return CommandLineAPIHost.inspectedObject();
-    },
-
-    /**
-     * @param {Array.<string>|string=} types
-     * @return {Array.<string>}
-     */
-    _normalizeEventTypes: function(types)
-    {
-        if (typeof types === "undefined")
-            types = [ "mouse", "key", "touch", "control", "load", "unload", "abort", "error", "select", "change", "submit", "reset", "focus", "blur", "resize", "scroll", "search", "devicemotion", "deviceorientation" ];
-        else if (typeof types === "string")
-            types = [ types ];
-
-        var result = [];
-        for (var i = 0; i < types.length; i++) {
-            if (types[i] === "mouse")
-                result.splice(0, 0, "mousedown", "mouseup", "click", "dblclick", "mousemove", "mouseover", "mouseout", "mousewheel");
-            else if (types[i] === "key")
-                result.splice(0, 0, "keydown", "keyup", "keypress", "textInput");
-            else if (types[i] === "touch")
-                result.splice(0, 0, "touchstart", "touchmove", "touchend", "touchcancel");
-            else if (types[i] === "control")
-                result.splice(0, 0, "resize", "scroll", "zoom", "focus", "blur", "select", "change", "submit", "reset");
-            else
-                result.push(types[i]);
-        }
-        return result;
-    },
-
-    /**
-     * @param {Event} event
-     */
-    _logEvent: function(event)
-    {
-        inspectedWindow.console.log(event.type, event);
-    },
-
-    /**
-     * @param {*} object
-     * @return {*}
-     */
-    _inspect: function(object)
-    {
-        if (arguments.length === 0)
-            return;
-
-        var objectId = RemoteObject.create(object, "");
-        var hints = {};
-
-        switch (RemoteObject.describe(object)) {
-        case "Database":
-            var databaseId = CommandLineAPIHost.databaseId(object)
-            if (databaseId)
-                hints.databaseId = databaseId;
-            break;
-        case "Storage":
-            var storageId = CommandLineAPIHost.storageId(object)
-            if (storageId)
-                hints.domStorageId = InjectedScriptHost.evaluate("(" + storageId + ")");
-            break;
-        }
-
-        CommandLineAPIHost.inspect(objectId, hints);
-        return object;
-    }
+    });
 }
 
-injectedScript.CommandLineAPI = CommandLineAPI;
-injectedScript._commandLineAPIImpl = new CommandLineAPIImpl();
-
-// This Module doesn't expose an object, it just adds an extension that InjectedScript uses.
-// However, we return an empty object, so that InjectedScript knows this module has been loaded.
-return {};
-
 })
index 8565260..d04a694 100644 (file)
@@ -1,5 +1,22 @@
 2019-08-23  Devin Rousso  <drousso@apple.com>
 
+        Web Inspector: create additional command line api functions for other console methods
+        https://bugs.webkit.org/show_bug.cgi?id=200971
+
+        Reviewed by Joseph Pecoraro.
+
+        Expose all `console.*` functions in the command line API, since they're all already able to
+        be referenced via the `console` object.
+
+        Provide a simpler interface for other injected scripts to modify the command line API.
+
+        * UserInterface/Controllers/JavaScriptRuntimeCompletionProvider.js:
+        (WI.JavaScriptRuntimeCompletionProvider.prototype.get _commandLineAPIKeys): Added.
+        (WI.JavaScriptRuntimeCompletionProvider.prototype.completionControllerCompletionsNeeded.updateLastPropertyNames):
+        (WI.JavaScriptRuntimeCompletionProvider.prototype.completionControllerCompletionsNeeded.receivedPropertyNames):
+
+2019-08-23  Devin Rousso  <drousso@apple.com>
+
         Web Inspector: transparency checkerboard is too bright in dark mode
         https://bugs.webkit.org/show_bug.cgi?id=201067
 
index a47e7da..d12d42b 100644 (file)
@@ -44,6 +44,50 @@ WI.JavaScriptRuntimeCompletionProvider = class JavaScriptRuntimeCompletionProvid
         WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.ActiveCallFrameDidChange, this._clearLastProperties, this);
     }
 
+    // Static
+
+    static get _commandLineAPIKeys()
+    {
+        if (!JavaScriptRuntimeCompletionProvider.__cachedCommandLineAPIKeys) {
+            JavaScriptRuntimeCompletionProvider.__cachedCommandLineAPIKeys = [
+                "$_",
+                "assert",
+                "clear",
+                "count",
+                "countReset",
+                "debug",
+                "dir",
+                "dirxml",
+                "error",
+                "group",
+                "groupCollapsed",
+                "groupEnd",
+                "info",
+                "inspect",
+                "keys",
+                "log",
+                "profile",
+                "profileEnd",
+                "queryHolders",
+                "queryInstances",
+                "queryObjects",
+                "record",
+                "recordEnd",
+                "screenshot",
+                "table",
+                "takeHeapSnapshot",
+                "time",
+                "timeEnd",
+                "timeLog",
+                "timeStamp",
+                "trace",
+                "values",
+                "warn",
+            ];
+        }
+        return JavaScriptRuntimeCompletionProvider.__cachedCommandLineAPIKeys;
+    }
+
     // Protected
 
     completionControllerCompletionsNeeded(completionController, defaultCompletions, base, prefix, suffix, forced)
@@ -113,7 +157,7 @@ WI.JavaScriptRuntimeCompletionProvider = class JavaScriptRuntimeCompletionProvid
                 clearTimeout(this._clearLastPropertiesTimeout);
             this._clearLastPropertiesTimeout = setTimeout(this._clearLastProperties.bind(this), WI.JavaScriptLogViewController.CachedPropertiesDuration);
 
-            this._lastPropertyNames = propertyNames || {};
+            this._lastPropertyNames = propertyNames || [];
         }
 
         function evaluated(result, wasThrown)
@@ -211,41 +255,60 @@ WI.JavaScriptRuntimeCompletionProvider = class JavaScriptRuntimeCompletionProvid
 
         function receivedPropertyNames(propertyNames)
         {
-            propertyNames = propertyNames || {};
+            propertyNames = propertyNames ? Object.keys(propertyNames) : [];
 
             updateLastPropertyNames.call(this, propertyNames);
 
             WI.runtimeManager.activeExecutionContext.target.RuntimeAgent.releaseObjectGroup("completion");
 
             if (!base) {
-                let commandLineAPI = WI.JavaScriptRuntimeCompletionProvider._commandLineAPI.slice(0);
+                propertyNames.push(...JavaScriptRuntimeCompletionProvider._commandLineAPIKeys);
+
+                let savedResultAlias = WI.settings.consoleSavedResultAlias.value;
+                if (savedResultAlias)
+                    propertyNames.push(savedResultAlias + "_");
+
+                let target = WI.runtimeManager.activeExecutionContext.target;
+
                 if (WI.debuggerManager.paused) {
-                    let targetData = WI.debuggerManager.dataForTarget(WI.runtimeManager.activeExecutionContext.target);
-                    if (targetData.pauseReason === WI.DebuggerManager.PauseReason.Listener || targetData.pauseReason === WI.DebuggerManager.PauseReason.EventListener)
-                        commandLineAPI.push("$event");
-                    else if (targetData.pauseReason === WI.DebuggerManager.PauseReason.Exception)
-                        commandLineAPI.push("$exception");
+                    let targetData = WI.debuggerManager.dataForTarget(target);
+                    if (targetData.pauseReason === WI.DebuggerManager.PauseReason.Listener || targetData.pauseReason === WI.DebuggerManager.PauseReason.EventListener) {
+                        propertyNames.push("$event");
+                        if (savedResultAlias)
+                            propertyNames.push(savedResultAlias + "event");
+                    } else if (targetData.pauseReason === WI.DebuggerManager.PauseReason.Exception) {
+                        propertyNames.push("$exception");
+                        if (savedResultAlias)
+                            propertyNames.push(savedResultAlias + "exception");
+                    }
                 }
-                for (let name of commandLineAPI)
-                    propertyNames[name] = true;
 
-                let savedResultAlias = WI.settings.consoleSavedResultAlias.value;
-                if (savedResultAlias) {
-                    propertyNames[savedResultAlias + "0"] = true;
-                    propertyNames[savedResultAlias + "_"] = true;
+                switch (target.type) {
+                case WI.Target.Type.Page:
+                    propertyNames.push("$");
+                    propertyNames.push("$$");
+                    propertyNames.push("$0");
+                    if (savedResultAlias)
+                        propertyNames.push(savedResultAlias + "0");
+                    propertyNames.push("$x");
+                    // fallthrough
+                case WI.Target.Type.ServiceWorker:
+                case WI.Target.Type.Worker:
+                    propertyNames.push("copy");
+                    propertyNames.push("getEventListeners");
+                    propertyNames.push("monitorEvents");
+                    propertyNames.push("unmonitorEvents");
+                    break;
                 }
 
                 // FIXME: Due to caching, sometimes old $n values show up as completion results even though they are not available. We should clear that proactively.
                 for (var i = 1; i <= WI.ConsoleCommandResultMessage.maximumSavedResultIndex; ++i) {
-                    propertyNames["$" + i] = true;
-
+                    propertyNames.push("$" + i);
                     if (savedResultAlias)
-                        propertyNames[savedResultAlias + i] = true;
+                        propertyNames.push(savedResultAlias + i);
                 }
             }
 
-            propertyNames = Object.keys(propertyNames);
-
             var implicitSuffix = "";
             if (bracketNotation) {
                 var quoteUsed = prefix[0] === "'" ? "'" : "\"";
@@ -313,28 +376,3 @@ WI.JavaScriptRuntimeCompletionProvider = class JavaScriptRuntimeCompletionProvid
         this._lastPropertyNames = null;
     }
 };
-
-WI.JavaScriptRuntimeCompletionProvider._commandLineAPI = [
-    "$",
-    "$$",
-    "$0",
-    "$_",
-    "$x",
-    "clear",
-    "copy",
-    "dir",
-    "dirxml",
-    "getEventListeners",
-    "inspect",
-    "keys",
-    "monitorEvents",
-    "profile",
-    "profileEnd",
-    "queryHolders",
-    "queryInstances",
-    "queryObjects",
-    "screenshot",
-    "table",
-    "unmonitorEvents",
-    "values",
-];