Web Inspector: do not use window's eval in InjectedScript
authorpfeldman@chromium.org <pfeldman@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 21 Aug 2012 17:03:12 +0000 (17:03 +0000)
committerpfeldman@chromium.org <pfeldman@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 21 Aug 2012 17:03:12 +0000 (17:03 +0000)
https://bugs.webkit.org/show_bug.cgi?id=94610

Reviewed by Yury Semikhatsky.

Source/WebCore:

Otherwise, inspector does not work when eval is overriden.

Test: inspector/console/console-eval-fake.html

* bindings/js/JSInjectedScriptHostCustom.cpp:
(WebCore::JSInjectedScriptHost::evaluate):
(WebCore):
* bindings/v8/custom/V8InjectedScriptHostCustom.cpp:
(WebCore::V8InjectedScriptHost::evaluateCallback):
(WebCore):
* inspector/InjectedScriptHost.idl:
* inspector/InjectedScriptSource.js:
(.):

LayoutTests:

* inspector/console/console-eval-fake-expected.txt: Added.
* inspector/console/console-eval-fake.html: Added.

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

LayoutTests/ChangeLog
LayoutTests/inspector/console/console-eval-fake-expected.txt [new file with mode: 0644]
LayoutTests/inspector/console/console-eval-fake.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/bindings/js/JSInjectedScriptHostCustom.cpp
Source/WebCore/bindings/v8/custom/V8InjectedScriptHostCustom.cpp
Source/WebCore/inspector/InjectedScriptHost.idl
Source/WebCore/inspector/InjectedScriptSource.js

index 149889f..a66a93e 100644 (file)
@@ -1,3 +1,13 @@
+2012-08-21  Pavel Feldman  <pfeldman@chromium.org>
+
+        Web Inspector: do not use window's eval in InjectedScript
+        https://bugs.webkit.org/show_bug.cgi?id=94610
+
+        Reviewed by Yury Semikhatsky.
+
+        * inspector/console/console-eval-fake-expected.txt: Added.
+        * inspector/console/console-eval-fake.html: Added.
+
 2012-08-21  Adam Barth  <abarth@webkit.org>
 
         Implement JSDOMWindow*::allowsAccessFrom* in terms of BindingSecurity
diff --git a/LayoutTests/inspector/console/console-eval-fake-expected.txt b/LayoutTests/inspector/console/console-eval-fake-expected.txt
new file mode 100644 (file)
index 0000000..80737d1
--- /dev/null
@@ -0,0 +1,5 @@
+Tests that overriding window.eval does not break inspector.
+
+foo
+"fooValue"
+
diff --git a/LayoutTests/inspector/console/console-eval-fake.html b/LayoutTests/inspector/console/console-eval-fake.html
new file mode 100644 (file)
index 0000000..e838a93
--- /dev/null
@@ -0,0 +1,29 @@
+<html>
+<head>
+<script src="../../http/tests/inspector/inspector-test.js"></script>
+<script src="../../http/tests/inspector/console-test.js"></script>
+<script>
+var foo = 'fooValue';
+
+window.eval = "Non-function";
+
+function test()
+{
+    InspectorTest.evaluateInConsole("foo", step1);
+
+    function step1()
+    {
+        InspectorTest.dumpConsoleMessages();
+        InspectorTest.completeTest();
+    }
+}
+</script>
+</head>
+
+<body onload="runTest()">
+<p>
+Tests that overriding window.eval does not break inspector.
+</p>
+
+</body>
+</html>
index 991ff50..ad3fd73 100644 (file)
@@ -1,3 +1,24 @@
+2012-08-21  Pavel Feldman  <pfeldman@chromium.org>
+
+        Web Inspector: do not use window's eval in InjectedScript
+        https://bugs.webkit.org/show_bug.cgi?id=94610
+
+        Reviewed by Yury Semikhatsky.
+
+        Otherwise, inspector does not work when eval is overriden.
+
+        Test: inspector/console/console-eval-fake.html
+
+        * bindings/js/JSInjectedScriptHostCustom.cpp:
+        (WebCore::JSInjectedScriptHost::evaluate):
+        (WebCore):
+        * bindings/v8/custom/V8InjectedScriptHostCustom.cpp:
+        (WebCore::V8InjectedScriptHost::evaluateCallback):
+        (WebCore):
+        * inspector/InjectedScriptHost.idl:
+        * inspector/InjectedScriptSource.js:
+        (.):
+
 2012-08-21  Adam Barth  <abarth@webkit.org>
 
         Implement JSDOMWindow*::allowsAccessFrom* in terms of BindingSecurity
index f0d93ab..1413750 100644 (file)
@@ -275,6 +275,28 @@ JSValue JSInjectedScriptHost::storageId(ExecState* exec)
     return jsUndefined();
 }
 
+JSValue JSInjectedScriptHost::evaluate(ExecState* exec)
+{
+    JSValue expression = exec->argument(0);
+    if (!expression.isString())
+        return throwError(exec, createError(exec, "String argument expected."));
+    JSGlobalObject* globalObject = exec->lexicalGlobalObject();
+    JSFunction* evalFunction = globalObject->evalFunction();
+    CallData callData;
+    CallType callType = evalFunction->methodTable()->getCallData(evalFunction, callData);
+    if (callType == CallTypeNone)
+        return jsUndefined();
+    MarkedArgumentBuffer args;
+    args.append(expression);
+
+    bool wasEvalEnabled = globalObject->evalEnabled();
+    globalObject->setEvalEnabled(true);
+    JSValue result = JSC::call(exec, evalFunction, callType, callData, exec->globalThisValue(), args);
+    globalObject->setEvalEnabled(wasEvalEnabled);
+
+    return result;
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(INSPECTOR)
index 4dd181b..baacee0 100644 (file)
@@ -299,6 +299,22 @@ v8::Handle<v8::Value> V8InjectedScriptHost::storageIdCallback(const v8::Argument
     return v8::Undefined();
 }
 
+v8::Handle<v8::Value> V8InjectedScriptHost::evaluateCallback(const v8::Arguments& args)
+{
+    INC_STATS("InjectedScriptHost.evaluate()");
+    if (args.Length() < 1)
+        return v8::ThrowException(v8::Exception::Error(v8::String::New("One argument expected.")));
+
+    v8::Handle<v8::String> expression = args[0]->ToString();
+    if (expression.IsEmpty())
+        return v8::ThrowException(v8::Exception::Error(v8::String::New("The argument must be a string.")));
+
+    v8::Handle<v8::Script> script = v8::Script::Compile(expression);
+    if (script.IsEmpty()) // Return immediately in case of exception to let the caller handle it.
+        return v8::Handle<v8::Value>();
+    return script->Run();
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(INSPECTOR)
index 71b88b1..d144dd0 100644 (file)
@@ -47,6 +47,7 @@ module core {
 
         [Custom] DOMString databaseId(in DOMObject database);
         [Custom] DOMString storageId(in DOMObject storage);
+        [Custom] DOMObject evaluate(in DOMString text);
     };
 }
 
index 069b7c0..e11e25a 100644 (file)
@@ -174,7 +174,7 @@ InjectedScript.prototype = {
      */
     _parseObjectId: function(objectId)
     {
-        return eval("(" + objectId + ")");
+        return InjectedScriptHost.evaluate("(" + objectId + ")");
     },
 
     /**
@@ -197,7 +197,7 @@ InjectedScript.prototype = {
      */
     dispatch: function(methodName, args)
     {
-        var argsArray = eval("(" + args + ")");
+        var argsArray = InjectedScriptHost.evaluate("(" + args + ")");
         var result = this[methodName].apply(this, argsArray);
         if (typeof result === "undefined") {
             inspectedWindow.console.error("Web Inspector error: InjectedScript.%s returns undefined", methodName);
@@ -342,7 +342,7 @@ InjectedScript.prototype = {
      */
     evaluate: function(expression, objectGroup, injectCommandLineAPI, returnByValue)
     {
-        return this._evaluateAndWrap(inspectedWindow.eval, inspectedWindow, expression, objectGroup, false, injectCommandLineAPI, returnByValue);
+        return this._evaluateAndWrap(InjectedScriptHost.evaluate, InjectedScriptHost, expression, objectGroup, false, injectCommandLineAPI, returnByValue);
     },
 
     /**
@@ -360,7 +360,7 @@ InjectedScript.prototype = {
 
         if (args) {
             var resolvedArgs = [];
-            args = eval(args);
+            args = InjectedScriptHost.evaluate(args);
             for (var i = 0; i < args.length; ++i) {
                 objectId = args[i].objectId;
                 if (objectId) {
@@ -382,7 +382,7 @@ InjectedScript.prototype = {
 
         try {
             var objectGroup = this._idToObjectGroupName[parsedObjectId.id];
-            var func = eval("(" + expression + ")");
+            var func = InjectedScriptHost.evaluate("(" + expression + ")");
             if (typeof func !== "function")
                 return "Given expression does not evaluate to a function";
 
@@ -515,7 +515,7 @@ InjectedScript.prototype = {
      */
     _callFrameForId: function(topCallFrame, callFrameId)
     {
-        var parsedCallFrameId = eval("(" + callFrameId + ")");
+        var parsedCallFrameId = InjectedScriptHost.evaluate("(" + callFrameId + ")");
         var ordinal = parsedCallFrameId["ordinal"];
         var callFrame = topCallFrame;
         while (--ordinal >= 0 && callFrame)
@@ -562,7 +562,7 @@ InjectedScript.prototype = {
     injectModule: function(name, source)
     {
         delete this._modules[name];
-        var module = eval("(" + source + ")");
+        var module = InjectedScriptHost.evaluate("(" + source + ")");
         this._modules[name] = module;
         return module;
     },