Bug 1101905 - Part 7: Use CompileOptions to pass strictness in eval, rather than the invoking script. (r=Waldo)
authorEric Faust <efaustbmo@gmail.com>
Wed, 26 Nov 2014 14:42:53 -0800
changeset 242114 9d174d48ff39933020b81512fb82cd7bf8f93f90
parent 242113 5b7b730484e49f890b15236dec156c8bc9c67ffd
child 242115 e39cad980949bbdfbdaacdb6252de18df20033a7
push id4311
push userraliiev@mozilla.com
push dateMon, 12 Jan 2015 19:37:41 +0000
treeherdermozilla-beta@150c9fed433b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersWaldo
bugs1101905
milestone36.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 1101905 - Part 7: Use CompileOptions to pass strictness in eval, rather than the invoking script. (r=Waldo)
js/src/builtin/Eval.cpp
js/src/frontend/BytecodeCompiler.cpp
js/src/jsapi.h
js/src/vm/Debugger.cpp
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -315,17 +315,18 @@ EvalKernel(JSContext *cx, const CallArgs
             introducerFilename = maybeScript->scriptSource()->introducerFilename();
 
         CompileOptions options(cx);
         options.setFileAndLine(filename, 1)
                .setCompileAndGo(true)
                .setForEval(true)
                .setNoScriptRval(false)
                .setMutedErrors(mutedErrors)
-               .setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset);
+               .setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset)
+               .maybeMakeStrictMode(evalType == DIRECT_EVAL && callerScript && callerScript->strict());
 
         AutoStableStringChars flatChars(cx);
         if (!flatChars.initTwoByte(cx, flatStr))
             return false;
 
         const char16_t *chars = flatChars.twoByteRange().start().get();
         SourceBufferHolder::Ownership ownership = flatChars.maybeGiveOwnershipToCaller()
                                                   ? SourceBufferHolder::GiveOwnership
@@ -388,17 +389,18 @@ js::DirectEvalStringFromIon(JSContext *c
             introducerFilename = maybeScript->scriptSource()->introducerFilename();
 
         CompileOptions options(cx);
         options.setFileAndLine(filename, 1)
                .setCompileAndGo(true)
                .setForEval(true)
                .setNoScriptRval(false)
                .setMutedErrors(mutedErrors)
-               .setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset);
+               .setIntroductionInfo(introducerFilename, "eval", lineno, maybeScript, pcOffset)
+               .maybeMakeStrictMode(callerScript->strict());
 
         AutoStableStringChars flatChars(cx);
         if (!flatChars.initTwoByte(cx, flatStr))
             return false;
 
         const char16_t *chars = flatChars.twoByteRange().start().get();
         SourceBufferHolder::Ownership ownership = flatChars.maybeGiveOwnershipToCaller()
                                                   ? SourceBufferHolder::GiveOwnership
--- a/js/src/frontend/BytecodeCompiler.cpp
+++ b/js/src/frontend/BytecodeCompiler.cpp
@@ -230,16 +230,17 @@ frontend::CompileScript(ExclusiveContext
     js::AutoTraceLog typeLogger(logger, TraceLogger::ParserCompileScript);
 
     /*
      * The scripted callerFrame can only be given for compile-and-go scripts
      * and non-zero static level requires callerFrame.
      */
     MOZ_ASSERT_IF(evalCaller, options.compileAndGo);
     MOZ_ASSERT_IF(evalCaller, options.forEval);
+    MOZ_ASSERT_IF(evalCaller && evalCaller->strict(), options.strictOption);
     MOZ_ASSERT_IF(staticLevel != 0, evalCaller);
 
     if (!CheckLength(cx, srcBuf))
         return nullptr;
     MOZ_ASSERT_IF(staticLevel != 0, !options.sourceIsLazy);
 
     RootedScriptSource sourceObject(cx, CreateScriptSourceObject(cx, options));
     if (!sourceObject)
@@ -309,28 +310,25 @@ frontend::CompileScript(ExclusiveContext
     Maybe<ParseContext<FullParseHandler> > pc;
 
     pc.emplace(&parser, (GenericParseContext *) nullptr, (ParseNode *) nullptr, &globalsc,
                (Directives *) nullptr, staticLevel, /* bodyid = */ 0,
                /* blockScopeDepth = */ 0);
     if (!pc->init(parser.tokenStream))
         return nullptr;
 
-    /* If this is a direct call to eval, inherit the caller's strictness.  */
-    if (evalCaller && evalCaller->strict())
-        globalsc.strict = true;
-
     if (savedCallerFun) {
         /*
          * An eval script in a caller frame needs to have its enclosing
          * function captured in case it refers to an upvar, and someone
          * wishes to decompile it while it's running.
          */
         JSFunction *fun = evalCaller->functionOrCallerFunction();
-        Directives directives(/* strict = */ fun->strict());
+        MOZ_ASSERT_IF(fun->strict(), options.strictOption);
+        Directives directives(/* strict = */ options.strictOption);
         ObjectBox *funbox = parser.newFunctionBox(/* fn = */ nullptr, fun, pc.ptr(),
                                                   directives, fun->generatorKind());
         if (!funbox)
             return nullptr;
         bce.objectList.add(funbox);
     }
 
     bool canHaveDirectives = true;
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -3897,16 +3897,20 @@ class MOZ_STACK_CLASS JS_FRIEND_API(Comp
         introducerFilename_ = introducerFn;
         introductionType = intro;
         introductionLineno = line;
         introductionScriptRoot = script;
         introductionOffset = offset;
         hasIntroductionInfo = true;
         return *this;
     }
+    CompileOptions &maybeMakeStrictMode(bool strict) {
+        strictOption = strictOption || strict;
+        return *this;
+    }
 
   private:
     void operator=(const CompileOptions &rhs) MOZ_DELETE;
 };
 
 /*
  * |script| will always be set. On failure, it will be set to nullptr.
  */
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -5624,17 +5624,18 @@ js::EvaluateInEnv(JSContext *cx, Handle<
      * static level will suffice.
      */
     CompileOptions options(cx);
     options.setCompileAndGo(true)
            .setForEval(true)
            .setNoScriptRval(false)
            .setFileAndLine(filename, lineno)
            .setCanLazilyParse(false)
-           .setIntroductionType("debugger eval");
+           .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,
                                                     options, srcBuf,
                                                     /* source = */ nullptr,
                                                     /* staticLevel = */ frame ? 1 : 0));
     if (!script)
         return false;