Bug 1145491 part 6. Fix script cloning to propagate the polluted-global-scope state to the lambda templates in the script. r=luke
authorBoris Zbarsky <bzbarsky@mit.edu>
Fri, 20 Mar 2015 21:34:18 -0400
changeset 265387 72accc37764a13c01209db6f1d963c428ea2bf6d
parent 265386 d9a838776f94969f9235e8c1b372fb79aa62a5c1
child 265388 55f700adddec0f3daf8eacacf5a5c2d9eb86c3b9
push id830
push userraliiev@mozilla.com
push dateFri, 19 Jun 2015 19:24:37 +0000
treeherdermozilla-release@932614382a68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersluke
bugs1145491
milestone39.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 1145491 part 6. Fix script cloning to propagate the polluted-global-scope state to the lambda templates in the script. r=luke
js/src/jit-test/tests/basic/weird-scopechains.js
js/src/jsfun.cpp
js/src/jsfun.h
js/src/jsscript.cpp
--- a/js/src/jit-test/tests/basic/weird-scopechains.js
+++ b/js/src/jit-test/tests/basic/weird-scopechains.js
@@ -6,16 +6,25 @@ function assertWithMessage(got, expected
     assertEq(message + ": " + got, message + ": " + expected);
 }
 
 // Create our test func via "evaluate" so it won't be compileAndGo and
 // we can clone it.
 evaluate(`function testFunc() {
     assertWithMessage(checkNameLookup(), "local", "nameLookup");
     assertWithMessage(checkThisBinding(), "local", "thisBinding");
+
+    // Important: lambda needs to close over "reason", so it won't just get the
+    // scope of testFunc as its scope.  Instead it'll get the Call object
+    // "reason" lives in.
+    var reason = " in lambda in Call";
+    (function() {
+	assertWithMessage(checkNameLookup(), "local", "nameLookup" + reason);
+	assertWithMessage(checkThisBinding(), "local", "thisBinding" + reason);
+    })();
 }`, { compileAndGo: false });
 
 var obj = {
     checkNameLookup: function() {
 	return "local";
     },
 
     checkThisBinding: function() {
--- a/js/src/jsfun.cpp
+++ b/js/src/jsfun.cpp
@@ -638,17 +638,18 @@ js::XDRInterpretedFunction(XDRState<mode
 
 template bool
 js::XDRInterpretedFunction(XDRState<XDR_ENCODE> *, HandleObject, HandleScript, MutableHandleFunction);
 
 template bool
 js::XDRInterpretedFunction(XDRState<XDR_DECODE> *, HandleObject, HandleScript, MutableHandleFunction);
 
 JSObject *
-js::CloneFunctionAndScript(JSContext *cx, HandleObject enclosingScope, HandleFunction srcFun)
+js::CloneFunctionAndScript(JSContext *cx, HandleObject enclosingScope, HandleFunction srcFun,
+                           PollutedGlobalScopeOption polluted)
 {
     /* NB: Keep this in sync with XDRInterpretedFunction. */
     RootedObject cloneProto(cx);
     if (srcFun->isStarGenerator()) {
         cloneProto = GlobalObject::getOrCreateStarGeneratorFunctionPrototype(cx, cx->global());
         if (!cloneProto)
             return nullptr;
     }
@@ -660,17 +661,17 @@ js::CloneFunctionAndScript(JSContext *cx
                                                   JSFunction::INTERPRETED, NullPtr(), NullPtr(),
                                                   cloneProto, allocKind, TenuredObject));
     if (!clone)
         return nullptr;
 
     RootedScript srcScript(cx, srcFun->getOrCreateScript(cx));
     if (!srcScript)
         return nullptr;
-    RootedScript clonedScript(cx, CloneScript(cx, enclosingScope, clone, srcScript));
+    RootedScript clonedScript(cx, CloneScript(cx, enclosingScope, clone, srcScript, polluted));
     if (!clonedScript)
         return nullptr;
 
     clone->setArgCount(srcFun->nargs());
     clone->setFlags(srcFun->flags());
     clone->initAtom(srcFun->displayAtom());
     clone->initScript(clonedScript);
     clonedScript->setFunction(clone);
--- a/js/src/jsfun.h
+++ b/js/src/jsfun.h
@@ -649,17 +649,18 @@ namespace js {
 JSString *FunctionToString(JSContext *cx, HandleFunction fun, bool bodyOnly, bool lambdaParen);
 
 template<XDRMode mode>
 bool
 XDRInterpretedFunction(XDRState<mode> *xdr, HandleObject enclosingScope,
                        HandleScript enclosingScript, MutableHandleFunction objp);
 
 extern JSObject *
-CloneFunctionAndScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun);
+CloneFunctionAndScript(JSContext *cx, HandleObject enclosingScope, HandleFunction fun,
+                       PollutedGlobalScopeOption polluted);
 
 /*
  * Report an error that call.thisv is not compatible with the specified class,
  * assuming that the method (clasp->name).prototype.<name of callee function>
  * is what was called.
  */
 extern void
 ReportIncompatibleMethod(JSContext *cx, CallReceiver call, const Class *clasp);
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -3026,17 +3026,17 @@ js::CloneScript(JSContext *cx, HandleObj
                     RootedObject enclosingScope(cx);
                     if (ssi.done() || ssi.type() == StaticScopeIter<CanGC>::Function)
                         enclosingScope = fun;
                     else if (ssi.type() == StaticScopeIter<CanGC>::Block)
                         enclosingScope = objects[FindScopeObjectIndex(src, ssi.block())];
                     else
                         enclosingScope = objects[FindScopeObjectIndex(src, ssi.staticWith())];
 
-                    clone = CloneFunctionAndScript(cx, enclosingScope, innerFun);
+                    clone = CloneFunctionAndScript(cx, enclosingScope, innerFun, polluted);
                 }
             } else {
                 /*
                  * Clone object literals emitted for the JSOP_NEWOBJECT opcode. We only emit that
                  * instead of the less-optimized JSOP_NEWINIT for self-hosted code or code compiled
                  * with JSOPTION_COMPILE_N_GO set. As we don't clone the latter type of code, this
                  * case should only ever be hit when cloning objects from self-hosted code.
                  */