Changeset 248287 in webkit


Ignore:
Timestamp:
Aug 5, 2019 8:37:44 PM (5 years ago)
Author:
Devin Rousso
Message:

Can't use $0, $1 etc when inspecting Google Docs pages because the content uses these for function names
https://bugs.webkit.org/show_bug.cgi?id=195834

Reviewed by Joseph Pecoraro.

Allow the user to alias saved results by providing a different prefix (e.g. "$") from within
Web Inspector. When changing the alias, all existing saved results will update to be
reference-able from the new alias.

Source/JavaScriptCore:

  • inspector/protocol/Runtime.json:

Add setSavedResultAlias command.

  • inspector/agents/InspectorRuntimeAgent.h:
  • inspector/agents/InspectorRuntimeAgent.cpp:

(Inspector::InspectorRuntimeAgent::setSavedResultAlias): Added.

  • inspector/InjectedScriptHost.h:

(Inspector::InjectedScriptHost::setSavedResultAlias): Added.
(Inspector::InjectedScriptHost::savedResultAlias const): Added.

  • inspector/JSInjectedScriptHost.h:
  • inspector/JSInjectedScriptHost.cpp:

(Inspector::JSInjectedScriptHost::savedResultAlias const): Added.

  • inspector/JSInjectedScriptHostPrototype.cpp:

(Inspector::JSInjectedScriptHostPrototype::finishCreation):
(Inspector::jsInjectedScriptHostPrototypeAttributeSavedResultAlias): Added.
Store the saved result alias on the InjectedScriptHost since it is a shared object among
all InjectedScript.

  • inspector/InjectedScriptSource.js:

(BasicCommandLineAPI):

Source/WebCore:

Test: inspector/runtime/setSavedResultAlias.html

  • inspector/CommandLineAPIModuleSource.js:

(CommandLineAPI):

Source/WebInspectorUI:

  • UserInterface/Controllers/RuntimeManager.js:

(WI.RuntimeManager):
(WI.RuntimeManager.preferredSavedResultPrefix): Added.
(WI.RuntimeManager.prototype.initializeTarget):

  • UserInterface/Controllers/JavaScriptRuntimeCompletionProvider.js:

(WI.JavaScriptRuntimeCompletionProvider.completionControllerCompletionsNeeded.receivedPropertyNames):

  • UserInterface/Base/Setting.js:
  • UserInterface/Base/Main.js:

(WI.contentLoaded):
(WI.contentLoaded.updateConsoleSavedResultPrefixCSSVariable): Added.

  • UserInterface/Views/ConsoleMessageView.js:

(WI.ConsoleMessageView.prototype.toClipboardString):
(WI.ConsoleMessageView.prototype.removeEventListeners): Added.
(WI.ConsoleMessageView.prototype._appendSavedResultIndex):
(WI.ConsoleMessageView.prototype._appendSavedResultIndex.updateSavedVariableText): Added.
(WI.ConsoleMessageView.prototype._rootPropertyPathForObject):
(WI.ConsoleMessageView.prototype._rootPropertyPathForObject.prefixSavedResultIndex): Added.

  • UserInterface/Views/LogContentView.js:

(WI.LogContentView.prototype._sessionStarted):
(WI.LogContentView.prototype._logCleared):

  • UserInterface/Views/DOMTreeOutline.css:

(.tree-outline.dom.show-last-selected li.last-selected > span::after):

  • UserInterface/Views/QuickConsole.js:

(WI.QuickConsole):
(WI.QuickConsole.prototype.closed):
(WI.QuickConsole.prototype._updateAutomaticExecutionContextPathComponentTooltip): Added.
Listen for changes to the setting that holds the current saved result alias and update any
related UI accordingly.

  • UserInterface/Views/SettingsTabContentView.js:

(WI.SettingsTabContentView.prototype._createConsoleSettingsView):

  • UserInterface/Views/SettingsTabContentView.css:

(.content-view.settings > .settings-view > .container > .editor-group > .editor input[type="text"]): Added.

  • UserInterface/Views/SettingsGroup.js:

(WI.SettingsGroup.prototype.addCustomEditor): Added.
Add an input to the Settings tab that controls the saved result prefix alias. Only allow
[a-zA-Z0-9_$] as values (but [0-9] cannot be used as the start).

  • UserInterface/Models/PropertyPath.js:

(WI.PropertyPath.prototype.set pathComponent): Added.
Miscellaneous getters/setters.

  • Localizations/en.lproj/localizedStrings.js:
  • UserInterface/Test/TestHarness.js:

(TestHarness.prototype.newline): Added.
Convenience function for adding newlines to test results.

LayoutTests:

  • inspector/runtime/setSavedResultAlias.html: Added.
  • inspector/runtime/setSavedResultAlias-expected.txt: Added.
  • http/tests/inspector/dom/cross-domain-inspected-node-access-expected.txt:
  • inspector/console/command-line-api-expected.txt:
  • inspector/console/command-line-api-exception.html:
  • inspector/console/command-line-api-exception-expected.txt:
  • inspector/console/command-line-api-exception-nested-catch.html:
  • inspector/console/command-line-api-exception-nested-catch-expected.txt:
Location:
trunk
Files:
2 added
34 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r248286 r248287  
     12019-08-05  Devin Rousso  <drousso@apple.com>
     2
     3        Can't use $0, $1 etc when inspecting Google Docs pages because the content uses these for function names
     4        https://bugs.webkit.org/show_bug.cgi?id=195834
     5
     6        Reviewed by Joseph Pecoraro.
     7
     8        Allow the user to alias saved results by providing a different prefix (e.g. "$") from within
     9        Web Inspector. When changing the alias, all existing saved results will update to be
     10        reference-able from the new alias.
     11
     12        * inspector/runtime/setSavedResultAlias.html: Added.
     13        * inspector/runtime/setSavedResultAlias-expected.txt: Added.
     14        * http/tests/inspector/dom/cross-domain-inspected-node-access-expected.txt:
     15        * inspector/console/command-line-api-expected.txt:
     16        * inspector/console/command-line-api-exception.html:
     17        * inspector/console/command-line-api-exception-expected.txt:
     18        * inspector/console/command-line-api-exception-nested-catch.html:
     19        * inspector/console/command-line-api-exception-nested-catch-expected.txt:
     20
    1212019-08-05  Devin Rousso  <drousso@apple.com>
    222
  • trunk/LayoutTests/http/tests/inspector/dom/cross-domain-inspected-node-access-expected.txt

    r242992 r248287  
    1 CONSOLE MESSAGE: line 44: 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.
    2 CONSOLE MESSAGE: line 44: 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.
     1CONSOLE MESSAGE: line 49: 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.
     2CONSOLE MESSAGE: line 49: 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.
    33Test that code evaluated in the main frame cannot access $0 that resolves to a node in a frame from a different domain. Bug 105423.
    44
  • trunk/LayoutTests/inspector/console/command-line-api-expected.txt

    r243953 r248287  
    1 CONSOLE MESSAGE: line 12: The console function $() has changed from $=getElementById(id) to $=querySelector(selector). You might try $("#%s")
     1CONSOLE MESSAGE: line 17: The console function $() has changed from $=getElementById(id) to $=querySelector(selector). You might try $("#%s")
    22Tests that command line api works.
    33
  • trunk/LayoutTests/inspector/debugger/command-line-api-exception-expected.txt

    r219766 r248287  
    1616== Running test suite: CommandLineAPI.$exception
    1717-- Running test case: BeforeExceptions
    18 PASS: $exception should be undefined if there is no exception.
     18PASS: $exception should throw an error if there is no exception.
     19ReferenceError: Can't find variable: $exception
    1920
    2021-- Running test case: UncaughtTypeException
     
    7071
    7172-- Running test case: AfterExceptions
    72 PASS: $exception should be undefined if there is no exception.
     73PASS: $exception should throw an error if there is no exception.
     74ReferenceError: Can't find variable: $exception
    7375
  • trunk/LayoutTests/inspector/debugger/command-line-api-exception-nested-catch-expected.txt

    r202784 r248287  
    66== Running test suite: CommandLineAPI.$exception
    77-- Running test case: EmptyBefore
    8 PASS: $exception should be undefined if there is no exception.
     8PASS: $exception should throw an error if there is no exception.
     9ReferenceError: Can't find variable: $exception
    910
    1011-- Running test case: CheckExceptionInsideNestedCatchBlocks
     
    1718
    1819-- Running test case: EmptyAfter
    19 PASS: $exception should be undefined if there is no exception.
     20PASS: $exception should throw an error if there is no exception.
     21ReferenceError: Can't find variable: $exception
    2022
  • trunk/LayoutTests/inspector/debugger/command-line-api-exception-nested-catch.html

    r220119 r248287  
    2828    suite.addTestCase({
    2929        name: "EmptyBefore",
    30         description: "Without exceptions, $exception should be undefined",
     30        description: "Without exceptions, $exception should not be defined",
    3131        test(resolve, reject) {
    3232            WI.runtimeManager.evaluateInInspectedWindow("$exception", {objectGroup: "test", includeCommandLineAPI: true, doNotPauseOnExceptionsAndMuteConsole: true}, (result, wasThrown) => {
    33                 InspectorTest.expectThat(result.description === "undefined", "$exception should be undefined if there is no exception.");
     33                InspectorTest.expectThat(wasThrown, "$exception should throw an error if there is no exception.");
     34                InspectorTest.log(result.description);
    3435                resolve();
    3536            });
     
    8889    suite.addTestCase({
    8990        name: "EmptyAfter",
    90         description: "Without exceptions, $exception should be undefined",
     91        description: "Without exceptions, $exception should not be defined",
    9192        test(resolve, reject) {
    9293            WI.runtimeManager.evaluateInInspectedWindow("$exception", {objectGroup: "test", includeCommandLineAPI: true, doNotPauseOnExceptionsAndMuteConsole: true}, (result, wasThrown) => {
    93                 InspectorTest.expectThat(result.description === "undefined", "$exception should be undefined if there is no exception.");
     94                InspectorTest.expectThat(wasThrown, "$exception should throw an error if there is no exception.");
     95                InspectorTest.log(result.description);
    9496                resolve();
    9597            });
  • trunk/LayoutTests/inspector/debugger/command-line-api-exception.html

    r220119 r248287  
    1919            test(resolve, reject) {
    2020                WI.runtimeManager.evaluateInInspectedWindow("$exception", {objectGroup: "test", includeCommandLineAPI: true, doNotPauseOnExceptionsAndMuteConsole: true}, (result, wasThrown) => {
    21                     InspectorTest.expectThat(result.description === "undefined", "$exception should be undefined if there is no exception.");
     21                    InspectorTest.expectThat(wasThrown, "$exception should throw an error if there is no exception.");
     22                    InspectorTest.log(result.description);
    2223                    resolve();
    2324                });
  • trunk/Source/JavaScriptCore/ChangeLog

    r248286 r248287  
     12019-08-05  Devin Rousso  <drousso@apple.com>
     2
     3        Can't use $0, $1 etc when inspecting Google Docs pages because the content uses these for function names
     4        https://bugs.webkit.org/show_bug.cgi?id=195834
     5
     6        Reviewed by Joseph Pecoraro.
     7
     8        Allow the user to alias saved results by providing a different prefix (e.g. "$") from within
     9        Web Inspector. When changing the alias, all existing saved results will update to be
     10        reference-able from the new alias.
     11
     12        * inspector/protocol/Runtime.json:
     13        Add `setSavedResultAlias` command.
     14
     15        * inspector/agents/InspectorRuntimeAgent.h:
     16        * inspector/agents/InspectorRuntimeAgent.cpp:
     17        (Inspector::InspectorRuntimeAgent::setSavedResultAlias): Added.
     18
     19        * inspector/InjectedScriptHost.h:
     20        (Inspector::InjectedScriptHost::setSavedResultAlias): Added.
     21        (Inspector::InjectedScriptHost::savedResultAlias const): Added.
     22        * inspector/JSInjectedScriptHost.h:
     23        * inspector/JSInjectedScriptHost.cpp:
     24        (Inspector::JSInjectedScriptHost::savedResultAlias const): Added.
     25        * inspector/JSInjectedScriptHostPrototype.cpp:
     26        (Inspector::JSInjectedScriptHostPrototype::finishCreation):
     27        (Inspector::jsInjectedScriptHostPrototypeAttributeSavedResultAlias): Added.
     28        Store the saved result alias on the `InjectedScriptHost` since it is a shared object among
     29        all `InjectedScript`.
     30
     31        * inspector/InjectedScriptSource.js:
     32        (BasicCommandLineAPI):
     33
    1342019-08-05  Devin Rousso  <drousso@apple.com>
    235
  • trunk/Source/JavaScriptCore/inspector/InjectedScriptHost.h

    r228105 r248287  
    2828#include "JSCJSValueInlines.h"
    2929#include "PerGlobalObjectWrapperWorld.h"
     30#include <wtf/Optional.h>
    3031#include <wtf/RefCounted.h>
    3132
     
    4445    void clearAllWrappers();
    4546
     47    void setSavedResultAlias(const Optional<String>& alias) { m_savedResultAlias = alias; }
     48    const Optional<String>& savedResultAlias() const { return m_savedResultAlias; }
     49
    4650private:
    4751    PerGlobalObjectWrapperWorld m_wrappers;
     52    Optional<String> m_savedResultAlias;
    4853};
    4954
  • trunk/Source/JavaScriptCore/inspector/InjectedScriptSource.js

    r244312 r248287  
    14541454function BasicCommandLineAPI(callFrame)
    14551455{
    1456     this.$_ = injectedScript._lastResult;
    1457     this.$exception = injectedScript._exceptionValue;
     1456    let savedResultAlias = InjectedScriptHost.savedResultAlias;
     1457
     1458    let defineGetter = (key, value) => {
     1459        if (typeof value !== "function") {
     1460            let originalValue = value;
     1461            value = function() { return originalValue; };
     1462        }
     1463
     1464        this.__defineGetter__("$" + key, value);
     1465        if (savedResultAlias)
     1466            this.__defineGetter__(savedResultAlias + key, value);
     1467    };
     1468
     1469    if ("_lastResult" in injectedScript)
     1470        defineGetter("_", injectedScript._lastResult);
     1471
     1472    if ("_exceptionValue" in injectedScript)
     1473        defineGetter("exception", injectedScript._exceptionValue);
    14581474
    14591475    if ("_eventValue" in injectedScript)
    1460         this.$event = injectedScript._eventValue;
    1461     else if ("$event" in this)
    1462         delete this.$event;
     1476        defineGetter("event", injectedScript._eventValue);
    14631477
    14641478    // $1-$99
    14651479    for (let i = 1; i <= injectedScript._savedResults.length; ++i)
    1466         this.__defineGetter__("$" + i, bind(injectedScript._savedResult, injectedScript, i));
     1480        defineGetter(i, bind(injectedScript._savedResult, injectedScript, i));
    14671481
    14681482    // Command Line API methods.
    14691483    for (let i = 0; i < BasicCommandLineAPI.methods.length; ++i) {
    14701484        let method = BasicCommandLineAPI.methods[i];
    1471         this[method.name] = method;
     1485        this[method] = bind(commandLineAPIImpl[method], commandLineAPIImpl);
     1486        this[method].toString = function() { return "function " + method + "() { [Command Line API] }" };
    14721487    }
    14731488}
  • trunk/Source/JavaScriptCore/inspector/JSInjectedScriptHost.cpp

    r244312 r248287  
    103103}
    104104
     105JSValue JSInjectedScriptHost::savedResultAlias(ExecState* exec) const
     106{
     107    auto savedResultAlias = impl().savedResultAlias();
     108    if (!savedResultAlias)
     109        return jsUndefined();
     110    return jsString(exec, savedResultAlias.value());
     111}
     112
    105113JSValue JSInjectedScriptHost::evaluateWithScopeExtension(ExecState* exec)
    106114{
  • trunk/Source/JavaScriptCore/inspector/JSInjectedScriptHost.h

    r244312 r248287  
    5858    // Attributes.
    5959    JSC::JSValue evaluate(JSC::ExecState*) const;
     60    JSC::JSValue savedResultAlias(JSC::ExecState*) const;
    6061
    6162    // Functions.
  • trunk/Source/JavaScriptCore/inspector/JSInjectedScriptHostPrototype.cpp

    r246837 r248287  
    5555
    5656static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeAttributeEvaluate(ExecState*);
     57static EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeAttributeSavedResultAlias(ExecState*);
    5758
    5859const ClassInfo JSInjectedScriptHostPrototype::s_info = { "InjectedScriptHost", &Base::s_info, nullptr, nullptr, CREATE_METHOD_TABLE(JSInjectedScriptHostPrototype) };
     
    7980
    8081    JSC_NATIVE_GETTER_WITHOUT_TRANSITION("evaluate", jsInjectedScriptHostPrototypeAttributeEvaluate, PropertyAttribute::DontEnum | PropertyAttribute::Accessor);
     82    JSC_NATIVE_GETTER_WITHOUT_TRANSITION("savedResultAlias", jsInjectedScriptHostPrototypeAttributeSavedResultAlias, PropertyAttribute::DontEnum | PropertyAttribute::Accessor);
    8183}
    8284
     
    9496}
    9597
     98EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeAttributeSavedResultAlias(ExecState* exec)
     99{
     100    VM& vm = exec->vm();
     101    auto scope = DECLARE_THROW_SCOPE(vm);
     102
     103    JSValue thisValue = exec->thisValue();
     104    JSInjectedScriptHost* castedThis = jsDynamicCast<JSInjectedScriptHost*>(vm, thisValue);
     105    if (!castedThis)
     106        return throwVMTypeError(exec, scope);
     107
     108    return JSValue::encode(castedThis->savedResultAlias(exec));
     109}
     110
    96111EncodedJSValue JSC_HOST_CALL jsInjectedScriptHostPrototypeFunctionInternalConstructorName(ExecState* exec)
    97112{
  • trunk/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.cpp

    r243243 r248287  
    261261}
    262262
     263void InspectorRuntimeAgent::setSavedResultAlias(ErrorString&, const String* alias)
     264{
     265    Optional<String> savedResultAlias;
     266    if (alias && !alias->isEmpty())
     267        savedResultAlias = *alias;
     268    m_injectedScriptManager.injectedScriptHost().setSavedResultAlias(savedResultAlias);
     269}
     270
    263271void InspectorRuntimeAgent::releaseObject(ErrorString&, const String& objectId)
    264272{
  • trunk/Source/JavaScriptCore/inspector/agents/InspectorRuntimeAgent.h

    r243243 r248287  
    6969    void getCollectionEntries(ErrorString&, const String& objectId, const String* objectGroup, const int* startIndex, const int* numberToFetch, RefPtr<JSON::ArrayOf<Protocol::Runtime::CollectionEntry>>& entries) final;
    7070    void saveResult(ErrorString&, const JSON::Object& callArgument, const int* executionContextId, Optional<int>& savedResultIndex) final;
     71    void setSavedResultAlias(ErrorString&, const String* alias) final;
    7172    void releaseObjectGroup(ErrorString&, const String& objectGroup) final;
    7273    void getRuntimeTypesForVariablesAtOffsets(ErrorString&, const JSON::Array& locations, RefPtr<JSON::ArrayOf<Protocol::Runtime::TypeDescription>>&) override;
  • trunk/Source/JavaScriptCore/inspector/protocol/Runtime.json

    r241633 r248287  
    319319        },
    320320        {
     321            "name": "setSavedResultAlias",
     322            "description": "Creates an additional reference to all saved values in the Console using the the given string as a prefix instead of $.",
     323            "parameters": [
     324                { "name": "alias", "type": "string", "optional": true, "description": "Passing an empty/null string will clear the alias." }
     325            ]
     326        },
     327        {
    321328            "name": "releaseObject",
    322329            "description": "Releases remote object with given id.",
  • trunk/Source/WebCore/ChangeLog

    r248286 r248287  
     12019-08-05  Devin Rousso  <drousso@apple.com>
     2
     3        Can't use $0, $1 etc when inspecting Google Docs pages because the content uses these for function names
     4        https://bugs.webkit.org/show_bug.cgi?id=195834
     5
     6        Reviewed by Joseph Pecoraro.
     7
     8        Allow the user to alias saved results by providing a different prefix (e.g. "$") from within
     9        Web Inspector. When changing the alias, all existing saved results will update to be
     10        reference-able from the new alias.
     11
     12        Test: inspector/runtime/setSavedResultAlias.html
     13
     14        * inspector/CommandLineAPIModuleSource.js:
     15        (CommandLineAPI):
     16
    1172019-08-05  Devin Rousso  <drousso@apple.com>
    218
  • trunk/Source/WebCore/inspector/CommandLineAPIModuleSource.js

    r243161 r248287  
    4747function CommandLineAPI(commandLineAPIImpl, callFrame)
    4848{
    49     this.$_ = injectedScript._lastResult;
    50     this.$event = injectedScript._eventValue;
    51     this.$exception = injectedScript._exceptionValue;
     49    let savedResultAlias = InjectedScriptHost.savedResultAlias;
     50
     51    let defineGetter = (key, value) => {
     52        if (typeof value !== "function") {
     53            let originalValue = value;
     54            value = function() { return originalValue; };
     55        }
     56
     57        this.__defineGetter__("$" + key, value);
     58        if (savedResultAlias)
     59            this.__defineGetter__(savedResultAlias + key, value);
     60    };
     61
     62    if ("_lastResult" in injectedScript)
     63        defineGetter("_", injectedScript._lastResult);
     64
     65    if ("_exceptionValue" in injectedScript)
     66        defineGetter("exception", injectedScript._exceptionValue);
     67
     68    if ("_eventValue" in injectedScript)
     69        defineGetter("event", injectedScript._eventValue);
    5270
    5371    // $0
    54     this.__defineGetter__("$0", bind(commandLineAPIImpl._inspectedObject, commandLineAPIImpl));
     72    defineGetter("0", bind(commandLineAPIImpl._inspectedObject, commandLineAPIImpl));
    5573
    5674    // $1-$99
    5775    for (let i = 1; i <= injectedScript._savedResults.length; ++i)
    58         this.__defineGetter__("$" + i, bind(injectedScript._savedResult, injectedScript, i));
     76        defineGetter(i, bind(injectedScript._savedResult, injectedScript, i));
    5977
    6078    // Command Line API methods.
  • trunk/Source/WebInspectorUI/ChangeLog

    r248286 r248287  
     12019-08-05  Devin Rousso  <drousso@apple.com>
     2
     3        Can't use $0, $1 etc when inspecting Google Docs pages because the content uses these for function names
     4        https://bugs.webkit.org/show_bug.cgi?id=195834
     5
     6        Reviewed by Joseph Pecoraro.
     7
     8        Allow the user to alias saved results by providing a different prefix (e.g. "$") from within
     9        Web Inspector. When changing the alias, all existing saved results will update to be
     10        reference-able from the new alias.
     11
     12        * UserInterface/Controllers/RuntimeManager.js:
     13        (WI.RuntimeManager):
     14        (WI.RuntimeManager.preferredSavedResultPrefix): Added.
     15        (WI.RuntimeManager.prototype.initializeTarget):
     16        * UserInterface/Controllers/JavaScriptRuntimeCompletionProvider.js:
     17        (WI.JavaScriptRuntimeCompletionProvider.completionControllerCompletionsNeeded.receivedPropertyNames):
     18
     19        * UserInterface/Base/Setting.js:
     20        * UserInterface/Base/Main.js:
     21        (WI.contentLoaded):
     22        (WI.contentLoaded.updateConsoleSavedResultPrefixCSSVariable): Added.
     23        * UserInterface/Views/ConsoleMessageView.js:
     24        (WI.ConsoleMessageView.prototype.toClipboardString):
     25        (WI.ConsoleMessageView.prototype.removeEventListeners): Added.
     26        (WI.ConsoleMessageView.prototype._appendSavedResultIndex):
     27        (WI.ConsoleMessageView.prototype._appendSavedResultIndex.updateSavedVariableText): Added.
     28        (WI.ConsoleMessageView.prototype._rootPropertyPathForObject):
     29        (WI.ConsoleMessageView.prototype._rootPropertyPathForObject.prefixSavedResultIndex): Added.
     30        * UserInterface/Views/LogContentView.js:
     31        (WI.LogContentView.prototype._sessionStarted):
     32        (WI.LogContentView.prototype._logCleared):
     33        * UserInterface/Views/DOMTreeOutline.css:
     34        (.tree-outline.dom.show-last-selected li.last-selected > span::after):
     35        * UserInterface/Views/QuickConsole.js:
     36        (WI.QuickConsole):
     37        (WI.QuickConsole.prototype.closed):
     38        (WI.QuickConsole.prototype._updateAutomaticExecutionContextPathComponentTooltip): Added.
     39        Listen for changes to the setting that holds the current saved result alias and update any
     40        related UI accordingly.
     41
     42        * UserInterface/Views/SettingsTabContentView.js:
     43        (WI.SettingsTabContentView.prototype._createConsoleSettingsView):
     44        * UserInterface/Views/SettingsTabContentView.css:
     45        (.content-view.settings > .settings-view > .container > .editor-group > .editor input[type="text"]): Added.
     46        * UserInterface/Views/SettingsGroup.js:
     47        (WI.SettingsGroup.prototype.addCustomEditor): Added.
     48        Add an input to the Settings tab that controls the saved result prefix alias. Only allow
     49        [a-zA-Z0-9_$] as values (but [0-9] cannot be used as the start).
     50
     51        * UserInterface/Models/PropertyPath.js:
     52        (WI.PropertyPath.prototype.set pathComponent): Added.
     53        Miscellaneous getters/setters.
     54
     55        * Localizations/en.lproj/localizedStrings.js:
     56
     57        * UserInterface/Test/TestHarness.js:
     58        (TestHarness.prototype.newline): Added.
     59        Convenience function for adding newlines to test results.
     60
    1612019-08-05  Devin Rousso  <drousso@apple.com>
    262
  • trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js

    r248274 r248287  
    468468localizedStrings["Example: \u201C%s\u201D"] = "Example: \u201C%s\u201D";
    469469localizedStrings["Exception with thrown value: %s"] = "Exception with thrown value: %s";
    470 localizedStrings["Execution context for $0"] = "Execution context for $0";
     470localizedStrings["Execution context for %s"] = "Execution context for %s";
    471471localizedStrings["Exited Full-Screen Mode"] = "Exited Full-Screen Mode";
    472472localizedStrings["Expand All"] = "Expand All";
     
    925925localizedStrings["Save configuration"] = "Save configuration";
    926926localizedStrings["Saved Recordings"] = "Saved Recordings";
     927localizedStrings["Saved Result Alias:"] = "Saved Result Alias:";
    927928localizedStrings["Saved States"] = "Saved States";
    928929localizedStrings["Scheduling:"] = "Scheduling:";
  • trunk/Source/WebInspectorUI/UserInterface/Base/Main.js

    r248198 r248287  
    574574    WI.tabBar.addEventListener(WI.TabBar.Event.TabBarItemsReordered, WI._rememberOpenTabs);
    575575
     576    function updateConsoleSavedResultPrefixCSSVariable() {
     577        document.body.style.setProperty("--console-saved-result-prefix", "\"" + WI.RuntimeManager.preferredSavedResultPrefix() + "\"");
     578    }
     579    WI.settings.consoleSavedResultAlias.addEventListener(WI.Setting.Event.Changed, updateConsoleSavedResultPrefixCSSVariable);
     580    updateConsoleSavedResultPrefixCSSVariable();
     581
    576582    // Signal that the frontend is now ready to receive messages.
    577583    WI.whenTargetsAvailable().then(() => {
  • trunk/Source/WebInspectorUI/UserInterface/Base/Setting.js

    r248202 r248287  
    144144    canvasRecordingAutoCaptureFrameCount: new WI.Setting("canvas-recording-auto-capture-frame-count", 1),
    145145    consoleAutoExpandTrace: new WI.Setting("console-auto-expand-trace", true),
     146    consoleSavedResultAlias: new WI.Setting("console-saved-result-alias", ""),
    146147    cssChangesPerNode: new WI.Setting("css-changes-per-node", false),
    147148    clearLogOnNavigate: new WI.Setting("clear-log-on-navigate", true),
  • trunk/Source/WebInspectorUI/UserInterface/Controllers/JavaScriptRuntimeCompletionProvider.js

    r248201 r248287  
    230230                    propertyNames[name] = true;
    231231
     232                let savedResultAlias = WI.settings.consoleSavedResultAlias.value;
     233                if (savedResultAlias) {
     234                    propertyNames[savedResultAlias + "0"] = true;
     235                    propertyNames[savedResultAlias + "_"] = true;
     236                }
     237
    232238                // FIXME: Due to caching, sometimes old $n values show up as completion results even though they are not available. We should clear that proactively.
    233                 for (var i = 1; i <= WI.ConsoleCommandResultMessage.maximumSavedResultIndex; ++i)
     239                for (var i = 1; i <= WI.ConsoleCommandResultMessage.maximumSavedResultIndex; ++i) {
    234240                    propertyNames["$" + i] = true;
     241
     242                    if (savedResultAlias)
     243                        propertyNames[savedResultAlias + i] = true;
     244                }
    235245            }
    236246
  • trunk/Source/WebInspectorUI/UserInterface/Controllers/RuntimeManager.js

    r248097 r248287  
    3232        this._activeExecutionContext = null;
    3333
     34        WI.settings.consoleSavedResultAlias.addEventListener(WI.Setting.Event.Changed, (event) => {
     35            for (let target of WI.targets) {
     36                // COMPATIBILITY (iOS 12.2): Runtime.setSavedResultAlias did not exist.
     37                if (target.RuntimeAgent.setSavedResultAlias)
     38                    target.RuntimeAgent.setSavedResultAlias(WI.settings.consoleSavedResultAlias.value);
     39            }
     40        });
     41
    3442        WI.Frame.addEventListener(WI.Frame.Event.ExecutionContextsCleared, this._frameExecutionContextsCleared, this);
    3543    }
     
    4149        // COMPATIBILITY (iOS 12): Runtime.awaitPromise did not exist
    4250        return !!InspectorBackend.domains.Runtime.awaitPromise;
     51    }
     52
     53    static preferredSavedResultPrefix()
     54    {
     55        // COMPATIBILITY (iOS 12.2): Runtime.setSavedResultAlias did not exist.
     56        if (!InspectorBackend.domains.Runtime.setSavedResultAlias)
     57            return "$";
     58        return WI.settings.consoleSavedResultAlias.value || "$";
    4359    }
    4460
     
    5369            target.RuntimeAgent.enableTypeProfiler();
    5470
    55         // COMPATIBILITY (iOS 10): Runtime.enableControlFlowProfiler did not exist
     71        // COMPATIBILITY (iOS 10): Runtime.enableControlFlowProfiler did not exist.
    5672        if (target.RuntimeAgent.enableControlFlowProfiler && WI.settings.enableControlFlowProfiler.value)
    5773            target.RuntimeAgent.enableControlFlowProfiler();
     74
     75        // COMPATIBILITY (iOS 12.2): Runtime.setSavedResultAlias did not exist.
     76        if (target.RuntimeAgent.setSavedResultAlias && WI.settings.consoleSavedResultAlias.value)
     77            target.RuntimeAgent.setSavedResultAlias(WI.settings.consoleSavedResultAlias.value);
    5878    }
    5979
  • trunk/Source/WebInspectorUI/UserInterface/Models/PropertyPath.js

    r220119 r248287  
    5656    get parent() { return this._parent; }
    5757    get isPrototype() { return this._isPrototype; }
     58
    5859    get pathComponent() { return this._pathComponent; }
     60    set pathComponent(pathComponent) { this._pathComponent = pathComponent; }
    5961
    6062    get rootObject()
  • trunk/Source/WebInspectorUI/UserInterface/Test/TestHarness.js

    r239343 r248287  
    9696        else
    9797            this.addResult(message);
     98    }
     99
     100    newline()
     101    {
     102        this.log("");
    98103    }
    99104
  • trunk/Source/WebInspectorUI/UserInterface/Views/ConsoleMessageView.js

    r247790 r248287  
    204204        let clipboardString = this._messageBodyElement.innerText.removeWordBreakCharacters();
    205205        if (this._message.savedResultIndex)
    206             clipboardString = clipboardString.replace(/\s*=\s*(\$\d+)$/, "");
     206            clipboardString = clipboardString.replace(new RegExp(`\\s*=\\s*(${WI.RuntimeManager.preferredSavedResultPrefix()}\\d+)$`), "");
    207207
    208208        let hasStackTrace = this._shouldShowStackTrace();
     
    239239            return this._clipboardPrefixString() + clipboardString;
    240240        return clipboardString;
     241    }
     242
     243    removeEventListeners()
     244    {
     245        // FIXME: <https://webkit.org/b/196956> Web Inspector: use weak collections for holding event listeners
     246        WI.settings.consoleSavedResultAlias.removeEventListener(null, null, this);
    241247    }
    242248
     
    347353    _appendSavedResultIndex(element)
    348354    {
    349         if (!this._message.savedResultIndex)
     355        let savedResultIndex = this._message.savedResultIndex;
     356        if (!savedResultIndex)
    350357            return;
    351358
     
    355362        var savedVariableElement = document.createElement("span");
    356363        savedVariableElement.classList.add("console-saved-variable");
    357         savedVariableElement.textContent = " = $" + this._message.savedResultIndex;
     364
     365        // FIXME: <https://webkit.org/b/196956> Web Inspector: use weak collections for holding event listeners
     366        function updateSavedVariableText() {
     367            savedVariableElement.textContent = " = " + WI.RuntimeManager.preferredSavedResultPrefix() + savedResultIndex;
     368        }
     369        WI.settings.consoleSavedResultAlias.addEventListener(WI.Setting.Event.Changed, updateSavedVariableText, this);
     370        updateSavedVariableText();
    358371
    359372        if (this._objectTree)
     
    693706    _rootPropertyPathForObject(object)
    694707    {
    695         if (!this._message.savedResultIndex)
     708        let savedResultIndex = this._message.savedResultIndex;
     709        if (!savedResultIndex)
    696710            return null;
    697711
    698         return new WI.PropertyPath(object, "$" + this._message.savedResultIndex);
     712        function prefixSavedResultIndex() {
     713            return WI.RuntimeManager.preferredSavedResultPrefix() + savedResultIndex;
     714        }
     715
     716        let propertyPath = new WI.PropertyPath(object, prefixSavedResultIndex());
     717
     718        // FIXME: <https://webkit.org/b/196956> Web Inspector: use weak collections for holding event listeners
     719        WI.settings.consoleSavedResultAlias.addEventListener(WI.Setting.Event.Changed, (event) => {
     720            propertyPath.pathComponent = prefixSavedResultIndex();
     721        }, this);
     722
     723        return propertyPath;
    699724    }
    700725
  • trunk/Source/WebInspectorUI/UserInterface/Views/DOMTreeOutline.css

    r246855 r248287  
    7272
    7373.tree-outline.dom.show-last-selected li.last-selected > span::after {
    74     content: " = $0";
     74    content: " = " var(--console-saved-result-prefix) "0";
    7575    color: var(--console-secondary-text-color);
    7676    position: absolute;
  • trunk/Source/WebInspectorUI/UserInterface/Views/LogContentView.js

    r248180 r248287  
    395395        }
    396396
     397        for (let messageElement of this._allMessageElements()) {
     398            if (messageElement.__messageView)
     399                messageElement.__messageView.removeEventListeners();
     400        }
     401
    397402        const isFirstSession = false;
    398403        const newSessionReason = event.data.wasReloaded ? WI.ConsoleSession.NewSessionReason.PageReloaded : WI.ConsoleSession.NewSessionReason.PageNavigated;
     
    825830        for (let item of this._scopeBar.items)
    826831            item.element.classList.remove("unread");
     832
     833        for (let messageElement of this._allMessageElements()) {
     834            if (messageElement.__messageView)
     835                messageElement.__messageView.removeEventListeners();
     836        }
    827837
    828838        this._logViewController.clear();
  • trunk/Source/WebInspectorUI/UserInterface/Views/QuickConsole.js

    r248196 r248287  
    3434
    3535        this._automaticExecutionContextPathComponent = this._createExecutionContextPathComponent(null, WI.UIString("Auto"));
    36         this._automaticExecutionContextPathComponent.tooltip = WI.UIString("Execution context for $0");
     36        this._updateAutomaticExecutionContextPathComponentTooltip();
    3737
    3838        this._mainExecutionContextPathComponent = null;
     
    7272        this.initializeMainExecutionContextPathComponent();
    7373
     74        WI.settings.consoleSavedResultAlias.addEventListener(WI.Setting.Event.Changed, this._updateAutomaticExecutionContextPathComponentTooltip, this);
     75
    7476        WI.consoleDrawer.toggleButtonShortcutTooltip(this._toggleOrFocusKeyboardShortcut);
    7577        WI.consoleDrawer.addEventListener(WI.ConsoleDrawer.Event.CollapsedStateChanged, this._updateStyles, this);
     
    99101    closed()
    100102    {
     103        WI.settings.consoleSavedResultAlias.removeEventListener(null, null, this);
    101104        WI.Frame.removeEventListener(null, null, this);
    102105        WI.debuggerManager.removeEventListener(null, null, this);
     
    166169            WI.runtimeManager.activeExecutionContext = executionContext;
    167170        return changed;
     171    }
     172
     173    _updateAutomaticExecutionContextPathComponentTooltip()
     174    {
     175        this._automaticExecutionContextPathComponent.tooltip = WI.UIString("Execution context for %s").format(WI.RuntimeManager.preferredSavedResultPrefix() + "0");
    168176    }
    169177
  • trunk/Source/WebInspectorUI/UserInterface/Views/SettingsGroup.js

    r220119 r248287  
    6565        return editor;
    6666    }
     67
     68    addCustomEditor()
     69    {
     70        let element = this._editorGroupElement.appendChild(document.createElement("div"));
     71        element.classList.add("editor");
     72        return element;
     73    }
    6774};
  • trunk/Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.css

    r246410 r248287  
    129129}
    130130
     131.content-view.settings > .settings-view > .container > .editor-group > .editor input[type="text"] {
     132    padding-top: 0;
     133    padding-bottom: 0;
     134    vertical-align: 1px;
     135
     136    /* Vertically align <input> with the group title text. */
     137    --settings-editor-child-margin-top: -2px;
     138}
     139
    131140@media (prefers-color-scheme: dark) {
    132141    .content-view.settings .navigation-bar {
  • trunk/Source/WebInspectorUI/UserInterface/Views/SettingsTabContentView.js

    r248202 r248287  
    261261        let consoleSettingsView = new WI.SettingsView("console", WI.UIString("Console"));
    262262
     263        // COMPATIBILITY (iOS 12.2): Runtime.setSavedResultAlias did not exist.
     264        if (InspectorBackend.domains.Runtime.setSavedResultAlias) {
     265            let consoleSavedResultAliasEditor = consoleSettingsView.addGroupWithCustomEditor(WI.UIString("Saved Result Alias:"));
     266
     267            let consoleSavedResultAliasInput = consoleSavedResultAliasEditor.appendChild(document.createElement("input"));
     268            consoleSavedResultAliasInput.type = "text";
     269            consoleSavedResultAliasInput.value = WI.settings.consoleSavedResultAlias.value;
     270            consoleSavedResultAliasInput.placeholder = WI.unlocalizedString("$");
     271            consoleSavedResultAliasInput.addEventListener("keydown", (event) => {
     272                if (!/[a-zA-Z0-9_$]/.test(event.key) || (consoleSavedResultAliasInput.selectionStart === 0 && /[0-9]/.test(event.key))) {
     273                    event.preventDefault();
     274                    InspectorFrontendHost.beep();
     275                }
     276            });
     277            consoleSavedResultAliasInput.addEventListener("input", (event) => {
     278                let savedResultAlias = consoleSavedResultAliasInput.value;
     279                if (savedResultAlias === "$")
     280                    savedResultAlias = "";
     281                WI.settings.consoleSavedResultAlias.value = savedResultAlias;
     282            });
     283
     284            consoleSettingsView.addSeparator();
     285        }
     286
    263287        consoleSettingsView.addSetting(WI.UIString("Traces:"), WI.settings.consoleAutoExpandTrace, WI.UIString("Auto-expand"));
    264288
  • trunk/Source/WebInspectorUI/UserInterface/Views/SettingsView.js

    r220119 r248287  
    5353    }
    5454
     55    addGroupWithCustomEditor(title, element)
     56    {
     57        let settingsGroup = this.addGroup(title);
     58        return settingsGroup.addCustomEditor();
     59    }
     60
    5561    addGroup(title)
    5662    {
Note: See TracChangeset for help on using the changeset viewer.