Bug 1303118 - Fix 'this' computation for Debugger.Frame.evalWithBindings. (r=efaust)
authorShu-yu Guo <shu@rfrn.org>
Thu, 22 Sep 2016 12:42:37 -0700
changeset 314938 1a89a84c1b7df7bedb6ae6540f1eaa3fed8f87e2
parent 314937 aca64a177c446e4cf4b080115a6569dc347e0df9
child 314939 28e850e728ae4a03f41c738820e9952334314cc3
push id82022
push usershu@rfrn.org
push dateThu, 22 Sep 2016 19:32:32 +0000
treeherdermozilla-inbound@1a89a84c1b7d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersefaust
bugs1303118
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1303118 - Fix 'this' computation for Debugger.Frame.evalWithBindings. (r=efaust)
js/src/frontend/Parser.cpp
js/src/jit-test/tests/debug/Frame-evalWithBindings-15.js
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -282,23 +282,29 @@ EvalSharedContext::EvalSharedContext(Exc
     computeThisBinding(enclosingScope);
 
     // Like all things Debugger, Debugger.Frame.eval needs special
     // handling. Since the environment chain of such evals are non-syntactic
     // (DebuggerEnvironmentProxy is not an EnvironmentObject), computing the
     // this binding with respect to enclosingScope is incorrect if the
     // Debugger.Frame is a function frame. Recompute the this binding if we
     // are such an eval.
-    if (enclosingEnv && enclosingEnv->is<DebugEnvironmentProxy>()) {
-        JSObject* env = &enclosingEnv->as<DebugEnvironmentProxy>().environment();
+    if (enclosingEnv && enclosingScope->hasOnChain(ScopeKind::NonSyntactic)) {
+        // For Debugger.Frame.eval with bindings, the environment chain may
+        // have more than the DebugEnvironmentProxy.
+        JSObject* env = enclosingEnv;
         while (env) {
+            if (env->is<DebugEnvironmentProxy>())
+                env = &env->as<DebugEnvironmentProxy>().environment();
+
             if (env->is<CallObject>()) {
                 computeThisBinding(env->as<CallObject>().callee().nonLazyScript()->bodyScope());
                 break;
             }
+
             env = env->enclosingEnvironment();
         }
     }
 }
 
 bool
 ParseContext::init()
 {
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Frame-evalWithBindings-15.js
@@ -0,0 +1,15 @@
+var g = newGlobal();
+var dbg = new Debugger(g);
+
+dbg.onDebuggerStatement = function (frame) {
+  // The bindings object is unused but adds another environment on the
+  // environment chain. Make sure 'this' computes the right value in light of
+  // this.
+  assertEq(frame.evalWithBindings(`this === foo;`, { bar: 42 }).return, true);
+  assertEq(frame.evalWithBindings(`eval('this') === foo;`, { bar: 42 }).return, true);
+};
+
+g.eval(`
+var foo = { bar: function() { debugger; } };
+foo.bar();
+`);