Bug 1123011 - Box 'this' values when eval'ing strict scripts from a non-strict Ion script, r=jandem.
authorBrian Hackett <bhackett1024@gmail.com>
Fri, 23 Jan 2015 12:29:05 -0700
changeset 225430 4d669523c7ddd3c5148121c2a7f1e0e394c0651f
parent 225429 8031688ff76dbae5ede00f9a7678868b640932aa
child 225431 d04e39f96610152acee32647dab08847502c856e
push id54556
push userbhackett@mozilla.com
push dateFri, 23 Jan 2015 19:29:26 +0000
treeherdermozilla-inbound@4d669523c7dd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjandem
bugs1123011
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 1123011 - Box 'this' values when eval'ing strict scripts from a non-strict Ion script, r=jandem.
js/src/builtin/Eval.cpp
js/src/jit-test/tests/ion/bug1123011.js
js/src/jit/IonBuilder.cpp
--- a/js/src/builtin/Eval.cpp
+++ b/js/src/builtin/Eval.cpp
@@ -423,17 +423,29 @@ js::DirectEvalStringFromIon(JSContext *c
 
         esg.setNewScript(compiled);
     }
 
     // Primitive 'this' values should have been filtered out by Ion. If boxed,
     // the calling frame cannot be updated to store the new object.
     MOZ_ASSERT(thisValue.isObject() || thisValue.isUndefined() || thisValue.isNull());
 
-    return ExecuteKernel(cx, esg.script(), *scopeobj, thisValue, ExecuteType(DIRECT_EVAL),
+    // When eval'ing strict code in a non-strict context, compute the 'this'
+    // value to use from what the caller passed in. This isn't necessary if
+    // the callee is not strict, as it will compute the non-strict 'this'
+    // value as necessary while it executes.
+    RootedValue nthisValue(cx, thisValue);
+    if (!callerScript->strict() && esg.script()->strict() && !thisValue.isObject()) {
+        JSObject *obj = BoxNonStrictThis(cx, thisValue);
+        if (!obj)
+            return false;
+        nthisValue = ObjectValue(*obj);
+    }
+
+    return ExecuteKernel(cx, esg.script(), *scopeobj, nthisValue, ExecuteType(DIRECT_EVAL),
                          NullFramePtr() /* evalInFrame */, vp.address());
 }
 
 bool
 js::DirectEvalValueFromIon(JSContext *cx,
                            HandleObject scopeobj, HandleScript callerScript,
                            HandleValue thisValue, HandleValue evalArg,
                            jsbytecode *pc, MutableHandleValue vp)
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/ion/bug1123011.js
@@ -0,0 +1,8 @@
+
+var global = this;
+function f() {
+    return eval("'use strict'; this;");
+}
+for (var j = 0; j < 5; ++j) {
+    assertEq(f(), global);
+}
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -5938,16 +5938,19 @@ IonBuilder::jsop_eval(uint32_t argc)
 
     if (script()->global().valueIsEval(ObjectValue(*singleton))) {
         if (argc != 1)
             return abort("Direct eval with more than one argument");
 
         if (!info().funMaybeLazy())
             return abort("Direct eval in global code");
 
+        if (info().funMaybeLazy()->isArrow())
+            return abort("Direct eval from arrow function");
+
         // The 'this' value for the outer and eval scripts must be the
         // same. This is not guaranteed if a primitive string/number/etc.
         // is passed through to the eval invoke as the primitive may be
         // boxed into different objects if accessed via 'this'.
         MIRType type = thisTypes ? thisTypes->getKnownMIRType() : MIRType_Value;
         if (type != MIRType_Object && type != MIRType_Null && type != MIRType_Undefined)
             return abort("Direct eval from script with maybe-primitive 'this'");