Bug 915805 - Don't treat unbound names in Function() code as globals when the Function() code contains a direct eval or similarly-extensible scope. r=jorendorff
authord630ad6c <d630ad6c@seznam.cz>
Thu, 18 Jun 2015 08:35:24 -0700
changeset 281976 f08884c972231f6a0bf38dbd3758bbb86966b2b6
parent 281975 fe9781e4953b7b48d2f2f7e1a951dc236786525e
child 281977 ede9f497a5cc70239a2b7aa9e9f071b46f1089eb
push id897
push userjlund@mozilla.com
push dateMon, 14 Sep 2015 18:56:12 +0000
treeherdermozilla-release@9411e2d2b214 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs915805
milestone41.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 915805 - Don't treat unbound names in Function() code as globals when the Function() code contains a direct eval or similarly-extensible scope. r=jorendorff
js/src/frontend/Parser.cpp
js/src/tests/ecma_5/Function/Function-with-eval.js
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -823,24 +823,40 @@ Parser<FullParseHandler>::standaloneFunc
         report(ParseError, false, null(), JSMSG_GARBAGE_AFTER_INPUT,
                "function body", TokenKindToDesc(tt));
         return null();
     }
 
     if (!FoldConstants(context, &pn, this))
         return null();
 
+    fn->pn_pos.end = pos().end;
+
+    MOZ_ASSERT(fn->pn_body->isKind(PNK_ARGSBODY));
+    fn->pn_body->append(pn);
+
+    /*
+     * Make sure to deoptimize lexical dependencies that are polluted
+     * by eval and function statements (which both flag the function as
+     * having an extensible scope).
+     */
+    if (funbox->hasExtensibleScope() && pc->lexdeps->count()) {
+        for (AtomDefnRange r = pc->lexdeps->all(); !r.empty(); r.popFront()) {
+            Definition* dn = r.front().value().get<FullParseHandler>();
+            MOZ_ASSERT(dn->isPlaceholder());
+
+            handler.deoptimizeUsesWithin(dn, fn->pn_pos);
+        }
+    }
+
     InternalHandle<Bindings*> funboxBindings =
         InternalHandle<Bindings*>::fromMarkedLocation(&funbox->bindings);
     if (!funpc.generateFunctionBindings(context, tokenStream, alloc, funboxBindings))
         return null();
 
-    MOZ_ASSERT(fn->pn_body->isKind(PNK_ARGSBODY));
-    fn->pn_body->append(pn);
-    fn->pn_body->pn_pos = pn->pn_pos;
     return fn;
 }
 
 template <>
 bool
 Parser<FullParseHandler>::checkFunctionArguments()
 {
     /*
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_5/Function/Function-with-eval.js
@@ -0,0 +1,25 @@
+/*
+ * Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/licenses/publicdomain/
+ */
+
+assertEq(new Function(
+            "eval('var foo = 915805');" +
+            "return foo;"
+         )(),
+         915805);
+
+assertEq(new Function(
+            "eval('function foo() {" +
+                      "return 915805;" +
+                  "}');" +
+            "return foo;"
+         )()(),
+         915805);
+
+/******************************************************************************/
+
+if (typeof reportCompare === "function")
+    reportCompare(true, true);
+
+print("Tests complete");