Bug 837060: Make Debugger.Object.prototype.evalInGlobal{,withBindings} outerize the global before using it as 'this'. r=jorendorff
authorJim Blandy <jimb@mozilla.com>
Tue, 01 Oct 2013 14:07:19 -0700
changeset 149555 66e0cac2533d7347248e8b17c5e353e6b88bd12a
parent 149554 8c590f0469cb0488bfa4901ba9d64aa04743282c
child 149556 3bbcea535e8f19854ca892037eb46b112e77b9e4
push id25394
push userkwierso@gmail.com
push dateWed, 02 Oct 2013 01:41:38 +0000
treeherdermozilla-central@e3c84e9f2490 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs837060
milestone27.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 837060: Make Debugger.Object.prototype.evalInGlobal{,withBindings} outerize the global before using it as 'this'. r=jorendorff
js/src/vm/Debugger.cpp
js/src/vm/Interpreter.cpp
--- a/js/src/vm/Debugger.cpp
+++ b/js/src/vm/Debugger.cpp
@@ -4324,17 +4324,25 @@ DebuggerGenericEval(JSContext *cx, const
         /* ExecuteInEnv requires 'fp' to have a computed 'this" value. */
         if (!iter->computeThis(cx))
             return false;
         thisv = iter->thisv();
         env = GetDebugScopeForFrame(cx, iter->abstractFramePtr());
         if (!env)
             return false;
     } else {
-        thisv = ObjectValue(*scope);
+        /*
+         * Use the global as 'this'. If the global is an inner object, it
+         * should have a thisObject hook that returns the appropriate outer
+         * object.
+         */
+        JSObject *thisObj = JSObject::thisObject(cx, scope);
+        if (!thisObj)
+            return false;
+        thisv = ObjectValue(*thisObj);
         env = scope;
     }
 
     /* If evalWithBindings, create the inner environment. */
     if (evalWithBindings) {
         /* TODO - This should probably be a Call object, like ES5 strict eval. */
         env = NewObjectWithGivenProto(cx, &JSObject::class_, nullptr, env);
         if (!env)
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -582,16 +582,22 @@ js::InvokeGetterOrSetter(JSContext *cx, 
 }
 
 bool
 js::ExecuteKernel(JSContext *cx, HandleScript script, JSObject &scopeChainArg, const Value &thisv,
                   ExecuteType type, AbstractFramePtr evalInFrame, Value *result)
 {
     JS_ASSERT_IF(evalInFrame, type == EXECUTE_DEBUG);
     JS_ASSERT_IF(type == EXECUTE_GLOBAL, !scopeChainArg.is<ScopeObject>());
+#ifdef DEBUG
+    if (thisv.isObject()) {
+        RootedObject thisObj(cx, &thisv.toObject());
+        JS_ASSERT(GetOuterObject(cx, thisObj) == thisObj);
+    }
+#endif
 
     if (script->isEmpty()) {
         if (result)
             result->setUndefined();
         return true;
     }
 
     TypeScript::SetThis(cx, script, thisv);