Changeset 148495 in webkit


Ignore:
Timestamp:
Apr 15, 2013 11:12:22 PM (11 years ago)
Author:
timothy@apple.com
Message:

Web Inspector: Make var and function declarations work again in the Console.

https://webkit.org/b/114534
rdar://problem/13614477

Reviewed by Oliver Hunt.

Source/WebCore:

  • inspector/InjectedScriptSource.js:

(InjectedScript.prototype._evaluateOn): Use 'with' when not evaluating
on a call frame.

LayoutTests:

  • inspector/console/command-line-api-expected.txt:
  • inspector/console/console-eval-syntax-error-expected.txt:
  • inspector/extensions/extensions-eval-expected.txt:
  • platform/mac/http/tests/inspector/console-resource-errors-expected.txt:

Updated test results.

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r148484 r148495  
     12013-04-15  Timothy Hatcher  <timothy@apple.com>
     2
     3        Web Inspector: Make var and function declarations work again in the Console.
     4
     5        https://webkit.org/b/114534
     6        rdar://problem/13614477
     7
     8        Reviewed by Oliver Hunt.
     9
     10        * inspector/console/command-line-api-expected.txt:
     11        * inspector/console/console-eval-syntax-error-expected.txt:
     12        * inspector/extensions/extensions-eval-expected.txt:
     13        * platform/mac/http/tests/inspector/console-resource-errors-expected.txt:
     14        Updated test results.
     15
    1162013-04-15  James Craig  <james@cookiecrook.com>
    217
  • trunk/LayoutTests/inspector/console/command-line-api-expected.txt

    r147861 r148495  
    1 CONSOLE MESSAGE: line 1200: The console function $() has changed from $=getElementById(id) to $=querySelector(selector). You might try $("#%s")
     1CONSOLE MESSAGE: line 1223: 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/console/console-eval-syntax-error-expected.txt

    r147083 r148495  
    22
    33foo().
    4 SyntaxError: Unexpected EOF
     4SyntaxError: Expected an identifier but found '}' instead
    55
  • trunk/LayoutTests/inspector/extensions/extensions-eval-expected.txt

    r147083 r148495  
    66Evaluate: "function" (exception: undefined)
    77RUNNING TEST: extension_testEvalDefinesGlobalSymbols
    8 Evaluate: {"func":"undefined","variable":42} (exception: undefined)
     8Evaluate: {"func":"function","variable":42} (exception: undefined)
    99RUNNING TEST: extension_testEvalOk
    1010Evaluate: {"str":"foo","num":42} (exception: undefined)
  • trunk/LayoutTests/platform/mac/http/tests/inspector/console-resource-errors-expected.txt

    r147356 r148495  
    55GET http://127.0.0.1:8000/inspector/non-existent-iframe.html 404 (Not Found) non-existent-iframe.html:1 console-message console-error-level
    66GET http://127.0.0.1:8000/inspector/non-existent-script.js 404 (Not Found) console-resource-errors-iframe.html:4 console-message console-error-level
    7 GET http://127.0.0.1:8000/inspector/non-existent-xhr 404 (Not Found) [native code]:1send [native code]:1loadXHR console-resource-errors.html:18performActions console-resource-errors.html:10eval codeeval [native code]:1(anonymous function)(anonymous function)_evaluateOn_evaluateAndWrapevaluate console-message console-error-level
     7GET http://127.0.0.1:8000/inspector/non-existent-xhr 404 (Not Found) [native code]:1send [native code]:1loadXHR console-resource-errors.html:18performActions console-resource-errors.html:10eval codeeval [native code]:1_evaluateOn_evaluateAndWrapevaluate console-message console-error-level
    88
  • trunk/Source/WebCore/ChangeLog

    r148494 r148495  
     12013-04-15  Timothy Hatcher  <timothy@apple.com>
     2
     3        Web Inspector: Make var and function declarations work again in the Console.
     4
     5        https://webkit.org/b/114534
     6        rdar://problem/13614477
     7
     8        Reviewed by Oliver Hunt.
     9
     10        * inspector/InjectedScriptSource.js:
     11        (InjectedScript.prototype._evaluateOn): Use 'with' when not evaluating
     12        on a call frame.
     13
    1142013-04-15  Seokju Kwon  <seokju.kwon@gmail.com>
    215
  • trunk/Source/WebCore/inspector/InjectedScriptSource.js

    r147861 r148495  
    551551    _evaluateOn: function(evalFunction, object, objectGroup, expression, isEvalOnCallFrame, injectCommandLineAPI)
    552552    {
    553         // We can only use this approach if the evaluate function is the true 'eval'. That allows us to use it with
    554         // the 'eval' identifier when calling it. Using 'eval' grants access to the local scope of the closure we
    555         // create that provides the command line APIs.
    556 
    557         var parameters = [InjectedScriptHost.evaluate, expression];
    558         var expressionFunctionBody = "var __originalEval = window.eval; window.eval = __eval; try { return eval(__currentExpression); } finally { window.eval = __originalEval; }";
    559 
    560         if (injectCommandLineAPI) {
    561             // To avoid using a 'with' statement (which fails in strict mode and requires injecting the API object)
    562             // we instead create a closure where we evaluate the expression. The command line APIs are passed as
    563             // parameters to the closure so they are in scope but not injected. This allows the code evaluated in
    564             // the console to stay in strict mode (if is was already set), or to get strict mode by prefixing
    565             // expressions with 'use strict';.
    566 
    567             var commandLineAPI = new CommandLineAPI(this._commandLineAPIImpl, isEvalOnCallFrame ? object : null);
    568             var parameterNames = Object.getOwnPropertyNames(commandLineAPI);
    569             for (var i = 0; i < parameterNames.length; ++i)
    570                 parameters.push(commandLineAPI[parameterNames[i]]);
    571 
    572             var expressionFunctionString = "(function(__eval, __currentExpression, " + parameterNames.join(", ") + ") { " + expressionFunctionBody + " })";
    573         } else {
    574             // Use a closure in this case too to keep the same behavior of 'var' being captured by the closure instead
    575             // of leaking out into the calling scope.
    576             var expressionFunctionString = "(function(__eval, __currentExpression) { " + expressionFunctionBody + " })";
    577         }
    578 
    579         // Bind 'this' to the function expression using another closure instead of Function.prototype.bind. This ensures things will work if the page replaces bind.
    580         var boundExpressionFunctionString = "(function(__function, __thisObject) { return function() { return __function.apply(__thisObject, arguments) }; })(" + expressionFunctionString + ", this)";
    581         var expressionFunction = evalFunction.call(object, boundExpressionFunctionString);
    582         var result = expressionFunction.apply(null, parameters);
    583 
    584         if (objectGroup === "console")
    585             this._lastResult = result;
    586 
    587         return result;
     553        var commandLineAPI = injectCommandLineAPI ? new CommandLineAPI(this._commandLineAPIImpl, isEvalOnCallFrame ? object : null) : null;
     554
     555        if (isEvalOnCallFrame) {
     556            // We can only use this approach if the evaluate function is the true 'eval'. That allows us to use it with
     557            // the 'eval' identifier when calling it. Using 'eval' grants access to the local scope of the closure we
     558            // create that provides the command line APIs.
     559
     560            var parameters = [InjectedScriptHost.evaluate, expression];
     561            var expressionFunctionBody = "var __originalEval = window.eval; window.eval = __eval; try { return eval(__currentExpression); } finally { window.eval = __originalEval; }";
     562
     563            if (commandLineAPI) {
     564                // To avoid using a 'with' statement (which fails in strict mode and requires injecting the API object)
     565                // we instead create a closure where we evaluate the expression. The command line APIs are passed as
     566                // parameters to the closure so they are in scope but not injected. This allows the code evaluated in
     567                // the console to stay in strict mode (if is was already set), or to get strict mode by prefixing
     568                // expressions with 'use strict';.
     569
     570                var parameterNames = Object.getOwnPropertyNames(commandLineAPI);
     571                for (var i = 0; i < parameterNames.length; ++i)
     572                    parameters.push(commandLineAPI[parameterNames[i]]);
     573
     574                var expressionFunctionString = "(function(__eval, __currentExpression, " + parameterNames.join(", ") + ") { " + expressionFunctionBody + " })";
     575            } else {
     576                // Use a closure in this case too to keep the same behavior of 'var' being captured by the closure instead
     577                // of leaking out into the calling scope.
     578                var expressionFunctionString = "(function(__eval, __currentExpression) { " + expressionFunctionBody + " })";
     579            }
     580
     581            // Bind 'this' to the function expression using another closure instead of Function.prototype.bind. This ensures things will work if the page replaces bind.
     582            var boundExpressionFunctionString = "(function(__function, __thisObject) { return function() { return __function.apply(__thisObject, arguments) }; })(" + expressionFunctionString + ", this)";
     583            var expressionFunction = evalFunction.call(object, boundExpressionFunctionString);
     584            var result = expressionFunction.apply(null, parameters);
     585
     586            if (objectGroup === "console")
     587                this._lastResult = result;
     588
     589            return result;
     590        }
     591
     592        // When not evaluating on a call frame we use a 'with' statement to allow var and function statements to leak
     593        // into the global scope. This allow them to stick around between evaluations.
     594
     595        try {
     596            if (commandLineAPI && inspectedWindow.console) {
     597                inspectedWindow.console.__commandLineAPI = commandLineAPI;
     598                expression = "with ((window && window.console && window.console.__commandLineAPI) || {}) { " + expression + " }";
     599            }
     600
     601            var result = evalFunction.call(object, expression);
     602
     603            if (objectGroup === "console")
     604                this._lastResult = result;
     605
     606            return result;
     607        } finally {
     608            if (commandLineAPI && inspectedWindow.console)
     609                delete inspectedWindow.console.__commandLineAPI;
     610        }
    588611    },
    589612
Note: See TracChangeset for help on using the changeset viewer.