Adds the ability to evaluate expressions in the local scope
authortimothy@apple.com <timothy@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 16 May 2008 20:47:22 +0000 (20:47 +0000)
committertimothy@apple.com <timothy@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 16 May 2008 20:47:22 +0000 (20:47 +0000)
of the selected call frame.

https://bugs.webkit.org/show_bug.cgi?id=19052

Reviewed by Geoff Garen.

* bindings/js/JSJavaScriptCallFrameCustom.cpp:
(WebCore::JSJavaScriptCallFrame::evaluate): Pass the exception
from evaluate to the calling ExecState.
* page/JavaScriptCallFrame.cpp:
(WebCore::JavaScriptCallFrame::evaluate): Added an exception out
argument. Simplified the code by calling KJS:eval directly.
* page/JavaScriptCallFrame.h: Change evalutate to take an exception
out argument.
* page/inspector/Console.js: Check if the debugger is paused and
call evaluateInSelectedCallFrame on the Scripts panel.
* page/inspector/ScriptsPanel.js: Added a paused getter and
evaluateInSelectedCallFrame which does the evaluation and updates
the scope variables pane afterwards.

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

JavaScriptCore/JavaScriptCore.exp
WebCore/ChangeLog
WebCore/bindings/js/JSJavaScriptCallFrameCustom.cpp
WebCore/page/JavaScriptCallFrame.cpp
WebCore/page/JavaScriptCallFrame.h
WebCore/page/inspector/Console.js
WebCore/page/inspector/ScriptsPanel.js

index 93ac359..da0b287 100644 (file)
@@ -133,6 +133,7 @@ __ZN3KJS19InternalFunctionImp4infoE
 __ZN3KJS19InternalFunctionImpC2EPNS_17FunctionPrototypeERKNS_10IdentifierE
 __ZN3KJS19initializeThreadingEv
 __ZN3KJS23objectProtoFuncToStringEPNS_9ExecStateEPNS_8JSObjectERKNS_4ListE
+__ZN3KJS4evalEPNS_9ExecStateERKNS_10ScopeChainEPNS_16JSVariableObjectEPNS_14JSGlobalObjectEPNS_8JSObjectERKNS_4ListE
 __ZN3KJS4List15expandAndAppendEPNS_7JSValueE
 __ZN3KJS4List7markSetEv
 __ZN3KJS6JSCell9getObjectEv
index a5834c1..c84f057 100644 (file)
@@ -1,5 +1,28 @@
 2008-05-16  Timothy Hatcher  <timothy@apple.com>
 
+        Adds the ability to evaluate expressions in the local scope
+        of the selected call frame.
+
+        https://bugs.webkit.org/show_bug.cgi?id=19052
+
+        Reviewed by Geoff Garen.
+
+        * bindings/js/JSJavaScriptCallFrameCustom.cpp:
+        (WebCore::JSJavaScriptCallFrame::evaluate): Pass the exception
+        from evaluate to the calling ExecState.
+        * page/JavaScriptCallFrame.cpp:
+        (WebCore::JavaScriptCallFrame::evaluate): Added an exception out
+        argument. Simplified the code by calling KJS:eval directly.
+        * page/JavaScriptCallFrame.h: Change evalutate to take an exception
+        out argument.
+        * page/inspector/Console.js: Check if the debugger is paused and
+        call evaluateInSelectedCallFrame on the Scripts panel.
+        * page/inspector/ScriptsPanel.js: Added a paused getter and
+        evaluateInSelectedCallFrame which does the evaluation and updates
+        the scope variables pane afterwards.
+
+2008-05-16  Timothy Hatcher  <timothy@apple.com>
+
         Fixed the bug where the Inspector node highlight would not show
         in the correct place for nodes in frames.
 
index 0eff55d..beff3fb 100644 (file)
@@ -36,8 +36,15 @@ namespace WebCore {
 JSValue* JSJavaScriptCallFrame::evaluate(ExecState* exec, const List& args)
 {
     if (!impl()->isValid())
-        return jsNull();
-    return impl()->evaluate(args[0]->toString(exec));
+        return jsUndefined();
+
+    JSValue* exception = 0;
+    JSValue* result = impl()->evaluate(args[0]->toString(exec), exception);
+
+    if (exception)
+        exec->setException(exception);
+
+    return result;
 }
 
 JSValue* JSJavaScriptCallFrame::scopeChain(ExecState* exec) const
index 2491c24..210378b 100644 (file)
@@ -61,15 +61,8 @@ String JavaScriptCallFrame::functionName() const
     return String(function->functionName());
 }
 
-// Evaluate some JavaScript code in the context of this frame.
-// The code is evaluated as if by "eval", and the result is returned.
-// If there is an (uncaught) exception, it is returned as though _it_ were the result.
-
-// FIXME: If "script" contains var declarations, the machinery to handle local variables
-// efficiently in JavaScriptCore will not work properly. This could lead to crashes or
-// incorrect variable values. So this is not appropriate for evaluating arbitrary scripts.
-
-JSValue* JavaScriptCallFrame::evaluate(const UString& script) const
+// Evaluate some JavaScript code in the scope of this frame.
+JSValue* JavaScriptCallFrame::evaluate(const UString& script, JSValue*& exception) const
 {
     if (!m_exec)
         return jsNull();
@@ -79,32 +72,15 @@ JSValue* JavaScriptCallFrame::evaluate(const UString& script) const
     ExecState* exec = m_exec;
     JSGlobalObject* globalObject = exec->dynamicGlobalObject();
 
-    // find "eval"
-    JSObject* eval = 0;
-    if (exec->scopeNode()) {  // "eval" won't work without context (i.e. at global scope)
-        JSValue* v = globalObject->get(exec, "eval");
-        if (v->isObject() && static_cast<JSObject*>(v)->implementsCall())
-            eval = static_cast<JSObject*>(v);
-        else
-            // no "eval" - fallback operates on global exec state
-            exec = globalObject->globalExec();
-    }
-
     JSValue* savedException = exec->exception();
     exec->clearException();
 
-    // evaluate
-    JSValue* result = 0;
-    if (eval) {
-        List args;
-        args.append(jsString(script));
-        result = eval->call(exec, 0, args);
-    } else
-        // no "eval", or no context (i.e. global scope) - use global fallback
-        result = Interpreter::evaluate(exec, UString(), 0, script.data(), script.size(), globalObject).value();
+    List args;
+    args.append(jsString(script));
+    JSValue* result = eval(exec, exec->scopeChain(), globalObject, globalObject, exec->thisValue(), args);
 
     if (exec->hadException())
-        result = exec->exception();    // (may be redundant depending on which eval path was used)
+        exception = exec->takeException();
     exec->setException(savedException);
 
     return result;
index b172af0..635002b 100644 (file)
@@ -53,7 +53,7 @@ namespace WebCore {
 
         String functionName() const;
         const KJS::ScopeChain& scopeChain() const { return m_exec->scopeChain(); }
-        KJS::JSValue* evaluate(const KJS::UString& script) const;
+        KJS::JSValue* evaluate(const KJS::UString& script, KJS::JSValue*& exception) const;
 
     private:
         JavaScriptCallFrame(KJS::ExecState*, PassRefPtr<JavaScriptCallFrame> caller, int sourceID, int line);
index aac624c..97b6c7c 100644 (file)
@@ -308,6 +308,8 @@ WebInspector.Console.prototype = {
 
     _evalInInspectedWindow: function(expression)
     {
+        if (WebInspector.panels.scripts.paused)
+            return WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression);
         return InspectorController.inspectedWindow().eval(expression);
     },
 
index 56d1c85..b7bd0ef 100644 (file)
@@ -185,6 +185,11 @@ WebInspector.ScriptsPanel.prototype = {
         return [this.debuggingButton, this.pauseOnExceptionButtons];
     },
 
+    get paused()
+    {
+        return this._paused;
+    },
+
     show: function()
     {
         WebInspector.Panel.prototype.show.call(this);
@@ -275,6 +280,16 @@ WebInspector.ScriptsPanel.prototype = {
             sourceFrame.removeBreakpoint(breakpoint);
     },
 
+    evaluateInSelectedCallFrame: function(code)
+    {
+        var selectedCallFrame = this.sidebarPanes.callstack.selectedCallFrame;
+        if (!this._paused || !selectedCallFrame)
+            return;
+        var result = selectedCallFrame.evaluate(code);
+        this.sidebarPanes.scopechain.update(selectedCallFrame);
+        return result;
+    },
+
     debuggerPaused: function()
     {
         this._paused = true;