Bug 1122335 - Fix static scope chain for Debugger.Frame.prototype.eval. (r=jimb)
authorShu-yu Guo <shu@rfrn.org>
Sat, 24 Jan 2015 12:30:56 -0800
changeset 225580 d082ba907669faf1f8e60aa8563b27605f4a88a7
parent 225579 fb315ec11af4f5d0d9b297a66bf0d88a205cbb1e
child 225581 2cca9e9d7ccf68261e262a04c41b469d56411c20
push id28167
push userryanvm@gmail.com
push dateSun, 25 Jan 2015 00:24:46 +0000
treeherdermozilla-central@c18776175a69 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimb
bugs1122335
milestone38.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 1122335 - Fix static scope chain for Debugger.Frame.prototype.eval. (r=jimb)
js/src/builtin/Eval.cpp
js/src/jit-test/tests/debug/Frame-eval-28.js
js/src/vm/Debugger.cpp
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -306,16 +306,18 @@ EvalKernel(JSContext *cx, const CallArgs
         const char *introducerFilename = filename;
         if (maybeScript && maybeScript->scriptSource()->introducerFilename())
             introducerFilename = maybeScript->scriptSource()->introducerFilename();
 
         RootedObject enclosing(cx);
         if (evalType == DIRECT_EVAL)
             enclosing = callerScript->innermostStaticScope(pc);
         Rooted<StaticEvalObject *> staticScope(cx, StaticEvalObject::create(cx, enclosing));
+        if (!staticScope)
+            return false;
 
         CompileOptions options(cx);
         options.setFileAndLine(filename, 1)
                .setCompileAndGo(true)
                .setForEval(true)
                .setNoScriptRval(false)
                .setMutedErrors(mutedErrors)
                .setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset)
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/debug/Frame-eval-28.js
@@ -0,0 +1,12 @@
+// Test that strict Debugger.Frame.eval has a correct static scope.
+options('strict_mode');
+var g = newGlobal();
+var dbg = new Debugger(g);
+var hits = 0;
+dbg.onEnterFrame = function(f) {
+  hits++;
+  if (hits > 2)
+    return;
+  f.eval("42");
+};
+g.eval("42");
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -5936,33 +5936,38 @@ EvaluateInEnv(JSContext *cx, Handle<Env*
 
     MOZ_ASSERT(!IsPoisonedPtr(chars.start().get()));
 
     /*
      * NB: This function breaks the assumption that the compiler can see all
      * calls and properly compute a static level. In practice, any non-zero
      * static level will suffice.
      *
-     * Pass in NullPtr for evalStaticScope, as ScopeIter should stop at any
-     * non-ScopeObject boundaries, and we are putting a DebugScopeProxy on the
-     * scope chain.
+     * Pass in a StaticEvalObject *not* linked to env for evalStaticScope, as
+     * ScopeIter should stop at any non-ScopeObject boundaries, and we are
+     * putting a DebugScopeProxy on the scope chain.
      */
+    Rooted<StaticEvalObject *> staticScope(cx, StaticEvalObject::create(cx, js::NullPtr()));
+    if (!staticScope)
+        return false;
+    if (frame && frame.script()->strict())
+        staticScope->setStrict();
     CompileOptions options(cx);
     options.setCompileAndGo(true)
            .setForEval(true)
            .setNoScriptRval(false)
            .setFileAndLine(filename, lineno)
            .setCanLazilyParse(false)
            .setIntroductionType("debugger eval")
            .maybeMakeStrictMode(frame ? frame.script()->strict() : false);
     RootedScript callerScript(cx, frame ? frame.script() : nullptr);
     SourceBufferHolder srcBuf(chars.start().get(), chars.length(), SourceBufferHolder::NoOwnership);
     RootedScript script(cx, frontend::CompileScript(cx, &cx->tempLifoAlloc(), env, callerScript,
-                                                    /* evalStaticScope = */ js::NullPtr(),
-                                                    options, srcBuf, /* source = */ nullptr,
+                                                    staticScope, options, srcBuf,
+                                                    /* source = */ nullptr,
                                                     /* staticLevel = */ frame ? 1 : 0));
     if (!script)
         return false;
 
     script->setActiveEval();
     ExecuteType type = !frame ? EXECUTE_DEBUG_GLOBAL : EXECUTE_DEBUG;
     return ExecuteKernel(cx, script, *env, thisv, type, frame, rval.address());
 }