Web Inspector: typing an expression in an iframe leads to multiple "Unsafe JavaScript...
authoryurys@chromium.org <yurys@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 1 Aug 2011 11:42:43 +0000 (11:42 +0000)
committeryurys@chromium.org <yurys@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 1 Aug 2011 11:42:43 +0000 (11:42 +0000)
https://bugs.webkit.org/show_bug.cgi?id=65457

Source/WebCore:

Console completions are now done using evaluation which returns a JSON object with all property names rather than a remote
object. Also Runtime.evaluate and Runtime.callFunctionOn commands were extended with an optional parameter that allows to
get result as JSON value.

Reviewed by Pavel Feldman.

Test: http/tests/inspector/console-cd-completions.html

* inspector/InjectedScript.cpp:
(WebCore::InjectedScript::evaluate):
(WebCore::InjectedScript::callFunctionOn):
* inspector/InjectedScript.h:
* inspector/InjectedScriptSource.js:
(.):
():
* inspector/Inspector.json:
* inspector/InspectorRuntimeAgent.cpp:
(WebCore::asBool):
(WebCore::InspectorRuntimeAgent::evaluate):
(WebCore::InspectorRuntimeAgent::callFunctionOn):
* inspector/InspectorRuntimeAgent.h:
* inspector/front-end/ConsoleView.js:
(WebInspector.ConsoleView.prototype._completions.evaluated.getCompletions):
(WebInspector.ConsoleView.prototype._completions.evaluated):
(WebInspector.ConsoleView.prototype._completions.receivedPropertySet):
(WebInspector.ConsoleView.prototype._completions):
(WebInspector.ConsoleView.prototype.evalInInspectedWindow):
* inspector/front-end/RemoteObject.js:
(WebInspector.RemoteObject):
(WebInspector.RemoteObject.prototype.callFunction):
(WebInspector.RemoteObject.prototype.callFunctionJSON):
* inspector/front-end/WatchExpressionsSidebarPane.js:
(WebInspector.WatchExpressionsSection.prototype.update):

LayoutTests:

Reviewed by Pavel Feldman.

* http/tests/inspector/console-cd-completions-expected.txt: Added.
* http/tests/inspector/console-cd-completions.html: Added.
* http/tests/inspector/resources/console-cd-completions-iframe.html: Added.

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

14 files changed:
LayoutTests/ChangeLog
LayoutTests/http/tests/inspector/console-cd-completions-expected.txt [new file with mode: 0644]
LayoutTests/http/tests/inspector/console-cd-completions.html [new file with mode: 0644]
LayoutTests/http/tests/inspector/resources/console-cd-completions-iframe.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/inspector/InjectedScript.cpp
Source/WebCore/inspector/InjectedScript.h
Source/WebCore/inspector/InjectedScriptSource.js
Source/WebCore/inspector/Inspector.json
Source/WebCore/inspector/InspectorRuntimeAgent.cpp
Source/WebCore/inspector/InspectorRuntimeAgent.h
Source/WebCore/inspector/front-end/ConsoleView.js
Source/WebCore/inspector/front-end/RemoteObject.js
Source/WebCore/inspector/front-end/WatchExpressionsSidebarPane.js

index 90062fb..28413e2 100644 (file)
@@ -1,3 +1,14 @@
+2011-08-01  Yury Semikhatsky  <yurys@chromium.org>
+
+        Web Inspector: typing an expression in an iframe leads to multiple "Unsafe JavaScript attempt to access frame..." errors
+        https://bugs.webkit.org/show_bug.cgi?id=65457
+
+        Reviewed by Pavel Feldman.
+
+        * http/tests/inspector/console-cd-completions-expected.txt: Added.
+        * http/tests/inspector/console-cd-completions.html: Added.
+        * http/tests/inspector/resources/console-cd-completions-iframe.html: Added.
+
 2011-08-01  Tony Gentilcore  <tonyg@chromium.org>
 
         [chromium] http/tests/inspector/resource-tree/resource-tree-document-url.html occasionally times out
diff --git a/LayoutTests/http/tests/inspector/console-cd-completions-expected.txt b/LayoutTests/http/tests/inspector/console-cd-completions-expected.txt
new file mode 100644 (file)
index 0000000..346f390
--- /dev/null
@@ -0,0 +1,6 @@
+Test that completions in the context of an iframe with a different origin will result in names of its global variables. Test passes if all global variables are found among completions AND there are NO console messages. Bug 65457.
+
+
+myGlobalVar
+myGlobalFunction
+
diff --git a/LayoutTests/http/tests/inspector/console-cd-completions.html b/LayoutTests/http/tests/inspector/console-cd-completions.html
new file mode 100644 (file)
index 0000000..472d6e0
--- /dev/null
@@ -0,0 +1,53 @@
+<html>
+<head>
+<script src="console-test.js"></script>
+<script src="inspector-test.js"></script>
+<script>
+
+function test()
+{
+    InspectorTest.showConsolePanel();
+    var selector = WebInspector.console._contextSelectElement;
+    var option = selector.firstChild;
+    while (option) {
+        if (option.textContent && option.textContent.indexOf("myIFrame") === 0)
+            break;
+        option = option.nextSibling;
+    }
+    if (!option) {
+        InspectorTest.addResult("FAILED: myIFrame not found in the context list");
+        InspectorTest.completeTest();
+        return;
+    }
+    option.selected = true;
+
+
+    WebInspector.console._completions("", "myGlob", false, checkCompletions.bind(this));
+    function checkCompletions(completions)
+    {
+        var expected = ["myGlobalVar", "myGlobalFunction"];
+        for (var i = 0; i < expected.length; ++i) {
+            if (completions.indexOf(expected[i]) !== -1)
+                InspectorTest.addResult(expected[i]);
+            else
+                InspectorTest.addResult("NOT FOUND: " + expected[i]);
+        }
+        InspectorTest.dumpConsoleMessages();
+        InspectorTest.completeTest();
+    }
+}
+
+</script>
+</head>
+
+<body>
+<p>
+Test that completions in the context of an iframe with a different origin will
+result in names of its global variables. Test passes if all global variables
+are found among completions AND there are NO console messages.
+<a href="https://bugs.webkit.org/show_bug.cgi?id=65457">Bug 65457.</a>
+</p>
+<iframe name="myIFrame" src="http://localhost:8000/inspector/resources/console-cd-completions-iframe.html" onload="runTest()"></iframe>
+
+</body>
+</html>
diff --git a/LayoutTests/http/tests/inspector/resources/console-cd-completions-iframe.html b/LayoutTests/http/tests/inspector/resources/console-cd-completions-iframe.html
new file mode 100644 (file)
index 0000000..e23f340
--- /dev/null
@@ -0,0 +1,4 @@
+<script>
+var myGlobalVar = 2011;
+function myGlobalFunction() { }
+</script>
index 6ab0c03..e3a5f95 100644 (file)
@@ -1,3 +1,42 @@
+2011-08-01  Yury Semikhatsky  <yurys@chromium.org>
+
+        Web Inspector: typing an expression in an iframe leads to multiple "Unsafe JavaScript attempt to access frame..." errors
+        https://bugs.webkit.org/show_bug.cgi?id=65457
+
+        Console completions are now done using evaluation which returns a JSON object with all property names rather than a remote
+        object. Also Runtime.evaluate and Runtime.callFunctionOn commands were extended with an optional parameter that allows to
+        get result as JSON value.
+
+        Reviewed by Pavel Feldman.
+
+        Test: http/tests/inspector/console-cd-completions.html
+
+        * inspector/InjectedScript.cpp:
+        (WebCore::InjectedScript::evaluate):
+        (WebCore::InjectedScript::callFunctionOn):
+        * inspector/InjectedScript.h:
+        * inspector/InjectedScriptSource.js:
+        (.):
+        ():
+        * inspector/Inspector.json:
+        * inspector/InspectorRuntimeAgent.cpp:
+        (WebCore::asBool):
+        (WebCore::InspectorRuntimeAgent::evaluate):
+        (WebCore::InspectorRuntimeAgent::callFunctionOn):
+        * inspector/InspectorRuntimeAgent.h:
+        * inspector/front-end/ConsoleView.js:
+        (WebInspector.ConsoleView.prototype._completions.evaluated.getCompletions):
+        (WebInspector.ConsoleView.prototype._completions.evaluated):
+        (WebInspector.ConsoleView.prototype._completions.receivedPropertySet):
+        (WebInspector.ConsoleView.prototype._completions):
+        (WebInspector.ConsoleView.prototype.evalInInspectedWindow):
+        * inspector/front-end/RemoteObject.js:
+        (WebInspector.RemoteObject):
+        (WebInspector.RemoteObject.prototype.callFunction):
+        (WebInspector.RemoteObject.prototype.callFunctionJSON):
+        * inspector/front-end/WatchExpressionsSidebarPane.js:
+        (WebInspector.WatchExpressionsSection.prototype.update):
+
 2011-08-01  Mihnea Ovidenie  <mihnea@adobe.com>
 
         BORDER attribute with the object tag, using percentage values not working.
index 52bfade..8c2bc7c 100644 (file)
@@ -54,21 +54,23 @@ InjectedScript::InjectedScript(ScriptObject injectedScriptObject, InspectedState
 {
 }
 
-void InjectedScript::evaluate(ErrorString* errorString, const String& expression, const String& objectGroup, bool includeCommandLineAPI, RefPtr<InspectorObject>* result, bool* wasThrown)
+void InjectedScript::evaluate(ErrorString* errorString, const String& expression, const String& objectGroup, bool includeCommandLineAPI, bool sendResultByValue, RefPtr<InspectorObject>* result, bool* wasThrown)
 {
     ScriptFunctionCall function(m_injectedScriptObject, "evaluate");
     function.appendArgument(expression);
     function.appendArgument(objectGroup);
     function.appendArgument(includeCommandLineAPI);
+    function.appendArgument(sendResultByValue);
     makeEvalCall(errorString, function, result, wasThrown);
 }
 
-void InjectedScript::callFunctionOn(ErrorString* errorString, const String& objectId, const String& expression, const String& arguments, RefPtr<InspectorObject>* result, bool* wasThrown)
+void InjectedScript::callFunctionOn(ErrorString* errorString, const String& objectId, const String& expression, const String& arguments, bool sendResultByValue, RefPtr<InspectorObject>* result, bool* wasThrown)
 {
     ScriptFunctionCall function(m_injectedScriptObject, "callFunctionOn");
     function.appendArgument(objectId);
     function.appendArgument(expression);
     function.appendArgument(arguments);
+    function.appendArgument(sendResultByValue);
     makeEvalCall(errorString, function, result, wasThrown);
 }
 
index 70b8c67..5e8ffc0 100644 (file)
@@ -55,8 +55,20 @@ public:
 
     bool hasNoValue() const { return m_injectedScriptObject.hasNoValue(); }
 
-    void evaluate(ErrorString*, const String& expression, const String& objectGroup, bool includeCommandLineAPI, RefPtr<InspectorObject>* result, bool* wasThrown);
-    void callFunctionOn(ErrorString*, const String& objectId, const String& expression, const String& arguments, RefPtr<InspectorObject>* result, bool* wasThrown);
+    void evaluate(ErrorString*,
+                  const String& expression,
+                  const String& objectGroup,
+                  bool includeCommandLineAPI,
+                  bool sendResultByValue,
+                  RefPtr<InspectorObject>* result,
+                  bool* wasThrown);
+    void callFunctionOn(ErrorString*,
+                        const String& objectId,
+                        const String& expression,
+                        const String& arguments,
+                        bool sendResultByValue,
+                        RefPtr<InspectorObject>* result,
+                        bool* wasThrown);
     void evaluateOnCallFrame(ErrorString*, const ScriptValue& callFrames, const String& callFrameId, const String& expression, const String& objectGroup, bool includeCommandLineAPI, RefPtr<InspectorObject>* result, bool* wasThrown);
     void getProperties(ErrorString*, const String& objectId, bool ignoreHasOwnProperty, RefPtr<InspectorArray>* result);
     Node* nodeForObjectId(const String& objectId);
index 67ba846..af7aff6 100644 (file)
@@ -108,10 +108,10 @@ InjectedScript.prototype = {
     },
 
     // This method cannot throw.
-    _wrapObject: function(object, objectGroupName)
+    _wrapObject: function(object, objectGroupName, forceValueType)
     {
         try {
-            return new InjectedScript.RemoteObject(object, objectGroupName);
+            return new InjectedScript.RemoteObject(object, objectGroupName, forceValueType);
         } catch (e) {
             try {
                 var description = injectedScript._describe(e);
@@ -183,8 +183,8 @@ InjectedScript.prototype = {
         for (var i = 0; i < propertyNames.length; ++i) {
             var propertyName = propertyNames[i];
 
-            var getter = object["__lookupGetter__"] && object.__lookupGetter__(propertyName);
-            var setter = object["__lookupSetter__"] && object.__lookupSetter__(propertyName);
+            var getter = (typeof object["__lookupGetter__"] === "function") && object.__lookupGetter__(propertyName);
+            var setter = (typeof object["__lookupSetter__"] === "function") && object.__lookupSetter__(propertyName);
             if (getter || setter) {
                 if (getter) {
                     var property = {};
@@ -246,12 +246,12 @@ InjectedScript.prototype = {
         return Object.keys(propertyNameSet);
     },
 
-    evaluate: function(expression, objectGroup, injectCommandLineAPI)
+    evaluate: function(expression, objectGroup, injectCommandLineAPI, sendResultByValue)
     {
-        return this._evaluateAndWrap(InjectedScriptHost.evaluate, InjectedScriptHost, expression, objectGroup, false, injectCommandLineAPI);
+        return this._evaluateAndWrap(InjectedScriptHost.evaluate, InjectedScriptHost, expression, objectGroup, false, injectCommandLineAPI, sendResultByValue);
     },
 
-    callFunctionOn: function(objectId, expression, args)
+    callFunctionOn: function(objectId, expression, args, sendResultByValue)
     {
         var parsedObjectId = this._parseObjectId(objectId);
         var object = this._objectForId(parsedObjectId);
@@ -287,18 +287,18 @@ InjectedScript.prototype = {
                 return "Given expression does not evaluate to a function";
 
             return { wasThrown: false,
-                     result: this._wrapObject(func.apply(object, resolvedArgs), objectGroup) };
+                     result: this._wrapObject(func.apply(object, resolvedArgs), objectGroup, sendResultByValue) };
         } catch (e) {
             return { wasThrown: true,
                      result: this._wrapObject(e, objectGroup) };
         }
     },
 
-    _evaluateAndWrap: function(evalFunction, object, expression, objectGroup, isEvalOnCallFrame, injectCommandLineAPI)
+    _evaluateAndWrap: function(evalFunction, object, expression, objectGroup, isEvalOnCallFrame, injectCommandLineAPI, sendResultByValue)
     {
         try {
             return { wasThrown: false,
-                     result: this._wrapObject(this._evaluateOn(evalFunction, object, expression, isEvalOnCallFrame, injectCommandLineAPI), objectGroup) };
+                     result: this._wrapObject(this._evaluateOn(evalFunction, object, expression, isEvalOnCallFrame, injectCommandLineAPI), objectGroup, sendResultByValue) };
         } catch (e) {
             return { wasThrown: true,
                      result: this._wrapObject(e, objectGroup) };
@@ -450,10 +450,10 @@ InjectedScript.prototype = {
 
 var injectedScript = new InjectedScript();
 
-InjectedScript.RemoteObject = function(object, objectGroupName)
+InjectedScript.RemoteObject = function(object, objectGroupName, forceValueType)
 {
     this.type = typeof object;
-    if (injectedScript.isPrimitiveValue(object) || object === null) {
+    if (injectedScript.isPrimitiveValue(object) || object === null || forceValueType) {
 
         // We don't send undefined values over JSON.
         if (typeof object !== "undefined")
index 2235e43..00cd154 100644 (file)
                     { "name": "type", "type": "string", "enum": ["object", "function", "undefined", "string", "number", "boolean"], "description": "Object type." },
                     { "name": "subtype", "type": "string", "optional": true, "enum": ["array", "null", "node", "regexp", "date"], "description": "Object subtype hint. Specified for <code>object</code> type values only." },
                     { "name": "className", "type": "string", "optional": true, "description": "Object class (constructor) name. Specified for <code>object</code> type values only." },
-                    { "name": "value", "type": "any", "optional": true, "description": "Remote object value (in case of primitive values)." },
+                    { "name": "value", "type": "any", "optional": true, "description": "Remote object value (in case of primitive values or JSON values if it was requested)." },
                     { "name": "description", "type": "string", "optional": true, "description": "String representation of the object." },
                     { "name": "objectId", "$ref": "RemoteObjectId", "optional": true, "description": "Unique object identifier (for non-primitive values)." }
                 ]
                     { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." },
                     { "name": "includeCommandLineAPI", "type": "boolean", "optional": true, "description": "Determines whether Command Line API should be available during the evaluation." },
                     { "name": "doNotPauseOnExceptions", "type": "boolean", "optional": true, "description": "Specifies whether evaluation should stop on exceptions. Overrides setPauseOnException state." },
-                    { "name": "frameId", "type": "string", "optional": true, "description": "Specifies in which frame to perform evaluation." }
+                    { "name": "frameId", "type": "string", "optional": true, "description": "Specifies in which frame to perform evaluation." },
+                    { "name": "sendResultByValue", "type": "boolean", "optional": true, "description": "Whether the result is expected to be a JSON object which should be sent by value." }
                 ],
                 "returns": [
                     { "name": "result", "$ref": "RemoteObject", "description": "Evaluation result." },
                 "parameters": [
                     { "name": "objectId", "$ref": "RemoteObjectId", "description": "Identifier of the object to call function on." },
                     { "name": "functionDeclaration", "type": "string", "description": "Declaration of the function to call." },
-                    { "name": "arguments", "type": "array", "items": { "$ref": "CallArgument", "description": "Call argument." }, "optional": true, "description": "Call arguments. All call arguments must belong to the same JavaScript world as the target object." }
+                    { "name": "arguments", "type": "array", "items": { "$ref": "CallArgument", "description": "Call argument." }, "optional": true, "description": "Call arguments. All call arguments must belong to the same JavaScript world as the target object." },
+                    { "name": "sendResultByValue", "type": "boolean", "optional": true, "description": "Whether the result is expected to be a JSON object which should be sent by value." }
                 ],
                 "returns": [
                     { "name": "result", "$ref": "RemoteObject", "description": "Call result." },
index e43ada8..6a24539 100644 (file)
 
 namespace WebCore {
 
+static bool asBool(const bool* const b)
+{
+    return b ? *b : false;
+}
+
 InspectorRuntimeAgent::InspectorRuntimeAgent(InjectedScriptManager* injectedScriptManager)
     : m_injectedScriptManager(injectedScriptManager)
 #if ENABLE(JAVASCRIPT_DEBUGGER)
@@ -57,7 +62,7 @@ InspectorRuntimeAgent::~InspectorRuntimeAgent()
 {
 }
 
-void InspectorRuntimeAgent::evaluate(ErrorString* errorString, const String& expression, const String* const objectGroup, const bool* const includeCommandLineAPI, const bool* const doNotPauseOnExceptions, const String* const frameId, RefPtr<InspectorObject>* result, bool* wasThrown)
+void InspectorRuntimeAgent::evaluate(ErrorString* errorString, const String& expression, const String* const objectGroup, const bool* const includeCommandLineAPI, const bool* const doNotPauseOnExceptions, const String* const frameId, const bool* const sendResultByValue, RefPtr<InspectorObject>* result, bool* wasThrown)
 {
     ScriptState* scriptState = 0;
     if (frameId) {
@@ -77,13 +82,13 @@ void InspectorRuntimeAgent::evaluate(ErrorString* errorString, const String& exp
     ASSERT(m_scriptDebugServer);
     bool pauseStateChanged = false;
     ScriptDebugServer::PauseOnExceptionsState presentState = m_scriptDebugServer->pauseOnExceptionsState();
-    if (doNotPauseOnExceptions && *doNotPauseOnExceptions && presentState != ScriptDebugServer::DontPauseOnExceptions) {
+    if (asBool(doNotPauseOnExceptions) && presentState != ScriptDebugServer::DontPauseOnExceptions) {
         m_scriptDebugServer->setPauseOnExceptionsState(ScriptDebugServer::DontPauseOnExceptions);
         pauseStateChanged = true;
     }
 #endif
 
-    injectedScript.evaluate(errorString, expression, objectGroup ? *objectGroup : "", includeCommandLineAPI ? *includeCommandLineAPI : false, result, wasThrown);
+    injectedScript.evaluate(errorString, expression, objectGroup ? *objectGroup : "", asBool(includeCommandLineAPI), asBool(sendResultByValue), result, wasThrown);
 
 #if ENABLE(JAVASCRIPT_DEBUGGER)
     if (pauseStateChanged)
@@ -91,7 +96,7 @@ void InspectorRuntimeAgent::evaluate(ErrorString* errorString, const String& exp
 #endif
 }
 
-void InspectorRuntimeAgent::callFunctionOn(ErrorString* errorString, const String& objectId, const String& expression, const RefPtr<InspectorArray>* const optionalArguments, RefPtr<InspectorObject>* result, bool* wasThrown)
+void InspectorRuntimeAgent::callFunctionOn(ErrorString* errorString, const String& objectId, const String& expression, const RefPtr<InspectorArray>* const optionalArguments, const bool* const sendResultByValue, RefPtr<InspectorObject>* result, bool* wasThrown)
 {
     InjectedScript injectedScript = m_injectedScriptManager->injectedScriptForObjectId(objectId);
     if (injectedScript.hasNoValue()) {
@@ -101,7 +106,7 @@ void InspectorRuntimeAgent::callFunctionOn(ErrorString* errorString, const Strin
     String arguments;
     if (optionalArguments)
         arguments = (*optionalArguments)->toJSONString();
-    injectedScript.callFunctionOn(errorString, objectId, expression, arguments, result, wasThrown);
+    injectedScript.callFunctionOn(errorString, objectId, expression, arguments, asBool(sendResultByValue), result, wasThrown);
 }
 
 void InspectorRuntimeAgent::getProperties(ErrorString* errorString, const String& objectId, bool ignoreHasOwnProperty, RefPtr<InspectorArray>* result)
index 3e1a3a2..646d455 100644 (file)
@@ -53,8 +53,22 @@ public:
     virtual ~InspectorRuntimeAgent();
 
     // Part of the protocol.
-    void evaluate(ErrorString*, const String& expression, const String* const objectGroup, const bool* const includeCommandLineAPI, const bool* const doNotPauseOnExceptions, const String* const frameId, RefPtr<InspectorObject>* result, bool* wasThrown);
-    void callFunctionOn(ErrorString*, const String& objectId, const String& expression, const RefPtr<InspectorArray>* const optionalArguments, RefPtr<InspectorObject>* result, bool* wasThrown);
+    void evaluate(ErrorString*,
+                  const String& expression,
+                  const String* const objectGroup,
+                  const bool* const includeCommandLineAPI,
+                  const bool* const doNotPauseOnExceptions,
+                  const String* const frameId,
+                  const bool* const sendResultByValue,
+                  RefPtr<InspectorObject>* result,
+                  bool* wasThrown);
+    void callFunctionOn(ErrorString*,
+                        const String& objectId,
+                        const String& expression,
+                        const RefPtr<InspectorArray>* const optionalArguments,
+                        const bool* const sendResultByValue,
+                        RefPtr<InspectorObject>* result,
+                        bool* wasThrown);
     void releaseObject(ErrorString*, const String& objectId);
     void getProperties(ErrorString*, const String& objectId, bool ignoreHasOwnProperty, RefPtr<InspectorArray>* result);
     void releaseObjectGroup(ErrorString*, const String& objectGroup);
index 6b0805f..b7525b8 100644 (file)
@@ -408,26 +408,33 @@ WebInspector.ConsoleView.prototype = {
         if (!expressionString && WebInspector.panels.scripts.paused)
             WebInspector.panels.scripts.getSelectedCallFrameVariables(reportCompletions.bind(this));
         else
-            this.evalInInspectedWindow(expressionString, "completion", true, true, evaluated.bind(this));
+            this.evalInInspectedWindow(expressionString, "completion", true, true, undefined, evaluated.bind(this));
 
         function evaluated(result, wasThrown)
         {
             if (wasThrown)
                 return;
-            result.getAllProperties(evaluatedProperties.bind(this));
+            var getCompletions = function()
+            {
+                var resultSet = {};
+                for (var o = this; o; o = o.__proto__) {
+                    try {
+                        var names = Object.getOwnPropertyNames(o);
+                        for (var i = 0; i < names.length; ++i)
+                            resultSet[names[i]] = true;
+                    } catch (e) {
+                    }
+                }
+                return resultSet;
+            }
+            result.callFunctionJSON(getCompletions, receivedPropertyNames.bind(this));
         }
 
-        function evaluatedProperties(properties)
+        function receivedPropertyNames(propertyNames)
         {
             RuntimeAgent.releaseObjectGroup("completion");
-            var propertyNames = {};
-            for (var i = 0; properties && i < properties.length; ++i)
-                propertyNames[properties[i].name] = true;
-            reportCompletions.call(this, propertyNames);
-        }
-
-        function reportCompletions(propertyNames)
-        {
+            if (!propertyNames)
+                return;
             var includeCommandLineAPI = (!dotNotation && !bracketNotation);
             if (includeCommandLineAPI) {
                 const commandLineAPI = ["dir", "dirxml", "keys", "values", "profile", "profileEnd", "monitorEvents", "unmonitorEvents", "inspect", "copy", "clear"];
@@ -595,7 +602,7 @@ WebInspector.ConsoleView.prototype = {
         }
     },
 
-    evalInInspectedWindow: function(expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptions, callback)
+    evalInInspectedWindow: function(expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptions, evalAsJSONValue, callback)
     {
         if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused) {
             WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, objectGroup, includeCommandLineAPI, callback);
@@ -612,7 +619,7 @@ WebInspector.ConsoleView.prototype = {
             if (!error)
                 callback(WebInspector.RemoteObject.fromPayload(result), wasThrown);
         }
-        RuntimeAgent.evaluate(expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptions, this._currentEvaluationContextId(), evalCallback);
+        RuntimeAgent.evaluate(expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptions, this._currentEvaluationContextId(), evalAsJSONValue, evalCallback);
     },
 
     _enterKeyPressed: function(event)
@@ -643,7 +650,7 @@ WebInspector.ConsoleView.prototype = {
 
             self.addMessage(new WebInspector.ConsoleCommandResult(result, wasThrown, commandMessage));
         }
-        this.evalInInspectedWindow(str, "console", true, undefined, printResult);
+        this.evalInInspectedWindow(str, "console", true, undefined, undefined, printResult);
 
         WebInspector.userMetrics.ConsoleEvaluated.record();
     },
index 34dd27a..a45d7c5 100644 (file)
@@ -194,7 +194,17 @@ WebInspector.RemoteObject.prototype = {
             callback((error || wasThrown) ? null : WebInspector.RemoteObject.fromPayload(result));
         }
 
-        RuntimeAgent.callFunctionOn(this._objectId, functionDeclaration.toString(), undefined, mycallback);
+        RuntimeAgent.callFunctionOn(this._objectId, functionDeclaration.toString(), undefined, undefined, mycallback);
+    },
+
+    callFunctionJSON: function(functionDeclaration, callback)
+    {
+        function mycallback(error, result, wasThrown)
+        {
+            callback((error || wasThrown) ? null : result.value);
+        }
+
+        RuntimeAgent.callFunctionOn(this._objectId, functionDeclaration.toString(), undefined, true, mycallback);
     },
 
     release: function()
index 2d7ba21..4bbad29 100644 (file)
@@ -159,7 +159,7 @@ WebInspector.WatchExpressionsSection.prototype = {
             if (!expression)
                 continue;
 
-            WebInspector.console.evalInInspectedWindow(expression, this._watchObjectGroupId, false, true, appendResult.bind(this, expression, i));
+            WebInspector.console.evalInInspectedWindow(expression, this._watchObjectGroupId, false, true, undefined, appendResult.bind(this, expression, i));
         }
 
         if (!propertyCount) {