зеркало из https://github.com/mozilla/gecko-dev.git
Back out a8574322a3ba from a CLOSED TREE, for its predecessor is orangetastic on one platform.
This commit is contained in:
Родитель
4acdd015ce
Коммит
097210b32e
|
@ -3,10 +3,5 @@ var sb = evalcx('');
|
|||
sb.name = "inner";
|
||||
sb.parent = this;
|
||||
function f() { return this.name; }
|
||||
assertEq(evalcx('this.f = parent.f;\n' +
|
||||
'var s = "";\n' +
|
||||
'for (i = 0; i < 10; ++i)\n' +
|
||||
' s += f();\n' +
|
||||
's',
|
||||
sb),
|
||||
assertEq(evalcx('this.f = parent.f; var s = ""; for (i = 0; i < 10; ++i) s += f(); s', sb),
|
||||
"innerinnerinnerinnerinnerinnerinnerinnerinnerinner");
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
this.name = "outer";
|
||||
var sb = evalcx('');
|
||||
sb.name = "inner";
|
||||
sb.parent = this;
|
||||
function f() { return this.name; }
|
||||
f.notMuchTodo = '42';
|
||||
assertEq(evalcx('{\n' +
|
||||
' let f = parent.f;\n' +
|
||||
' let name = "block";\n' +
|
||||
' (function () {\n' +
|
||||
' eval(f.notMuchTodo);\n' + // reify Block
|
||||
' var s = "";\n' +
|
||||
' for (i = 0; i < 10; ++i)\n' +
|
||||
' s += f();\n' +
|
||||
' return s;\n' +
|
||||
' })();\n' +
|
||||
'}',
|
||||
sb),
|
||||
"outerouterouterouterouterouterouterouterouterouter");
|
|
@ -1,20 +0,0 @@
|
|||
this.name = "outer";
|
||||
var sb = evalcx('');
|
||||
sb.name = "inner";
|
||||
sb.parent = this;
|
||||
function f() { return this.name; }
|
||||
f.notMuchTodo = '42';
|
||||
assertEq(evalcx('(function () {\n' +
|
||||
' arguments = null;\n' + // force heavyweight
|
||||
' var f = parent.f;\n' +
|
||||
' var name = "call";\n' +
|
||||
' return (function () {\n' +
|
||||
' eval(f.notMuchTodo);\n' + // reify Call, make f() compile to JSOP_CALLNAME
|
||||
' var s = "";\n' +
|
||||
' for (i = 0; i < 10; ++i)\n' +
|
||||
' s += f();\n' +
|
||||
' return s;\n' +
|
||||
' })();\n' +
|
||||
'})()',
|
||||
sb),
|
||||
"outerouterouterouterouterouterouterouterouterouter");
|
|
@ -1,15 +0,0 @@
|
|||
this.name = "outer";
|
||||
var sb = evalcx('');
|
||||
sb.name = "inner";
|
||||
sb.parent = this;
|
||||
this.f = function name(outer) {
|
||||
if (outer) return name(false);
|
||||
return this.name;
|
||||
}
|
||||
assertEq(evalcx('this.f = parent.f;\n' +
|
||||
'var s = "";\n' +
|
||||
'for (i = 0; i < 10; ++i)\n' +
|
||||
' s += f(true);\n' +
|
||||
's',
|
||||
sb),
|
||||
"outerouterouterouterouterouterouterouterouterouter");
|
|
@ -55,16 +55,11 @@ static inline bool
|
|||
IsSafeForLazyThisCoercion(JSContext *cx, JSObject *callee)
|
||||
{
|
||||
/*
|
||||
* Look past any function wrappers. If the callee is a wrapped strict-mode
|
||||
* function, lazy 'this' coercion is vacuously safe because strict-mode
|
||||
* functions don't coerce 'this' at all. Otherwise, the callee is safe to
|
||||
* transform into the lazy 'this' cookie (the undefined value) only if it
|
||||
* is in the current scope.
|
||||
*
|
||||
* Without this restriction, lazy 'this' coercion would pick up the "wrong"
|
||||
* global at the end of the callee function object's scope, rather than the
|
||||
* "right" (backward compatible since 1995) global that was the "Reference
|
||||
* base object" in the callee expression.
|
||||
* Look past any wrappers. If the callee is a strict function it is always
|
||||
* safe because we won't do 'this' coercion in strict mode. Otherwise the
|
||||
* callee is only safe to transform into the lazy 'this' token (undefined)
|
||||
* if it is in the current scope. Without this restriction, lazy 'this'
|
||||
* coercion would pick up the wrong global in the other scope.
|
||||
*/
|
||||
if (callee->isProxy()) {
|
||||
callee = callee->unwrap();
|
||||
|
|
|
@ -2179,12 +2179,11 @@ ScriptPrologue(JSContext *cx, JSStackFrame *fp)
|
|||
}
|
||||
|
||||
static inline bool
|
||||
ComputeThis(JSContext *cx, JSObject *obj, const Value &funval, Value *vp)
|
||||
SlowThis(JSContext *cx, JSObject *obj, const Value &funval, Value *vp)
|
||||
{
|
||||
if (!funval.isObject() ||
|
||||
(obj->isGlobal()
|
||||
? IsSafeForLazyThisCoercion(cx, &funval.toObject())
|
||||
: IsCacheableNonGlobalScope(obj))) {
|
||||
((obj->isGlobal() || IsCacheableNonGlobalScope(obj)) &&
|
||||
IsSafeForLazyThisCoercion(cx, &funval.toObject()))) {
|
||||
/*
|
||||
* We can avoid computing 'this' eagerly and push the implicit 'this'
|
||||
* value (undefined), as long the scope is cachable and we are not
|
||||
|
@ -4817,10 +4816,10 @@ BEGIN_CASE(JSOP_SETCALL)
|
|||
}
|
||||
END_CASE(JSOP_SETCALL)
|
||||
|
||||
#define PUSH_THISV(cx, obj, funval) \
|
||||
#define SLOW_PUSH_THISV(cx, obj, funval) \
|
||||
JS_BEGIN_MACRO \
|
||||
Value v; \
|
||||
if (!ComputeThis(cx, obj, funval, &v)) \
|
||||
if (!SlowThis(cx, obj, funval, &v)) \
|
||||
goto error; \
|
||||
PUSH_COPY(v); \
|
||||
JS_END_MACRO \
|
||||
|
@ -4854,8 +4853,16 @@ BEGIN_CASE(JSOP_CALLNAME)
|
|||
}
|
||||
|
||||
JS_ASSERT(obj->isGlobal() || IsCacheableNonGlobalScope(obj));
|
||||
if (op == JSOP_CALLNAME || op == JSOP_CALLGNAME)
|
||||
PUSH_THISV(cx, obj, regs.sp[-1]);
|
||||
if (op == JSOP_CALLNAME || op == JSOP_CALLGNAME) {
|
||||
if (regs.sp[-1].isObject() &&
|
||||
!IsSafeForLazyThisCoercion(cx, ®s.sp[-1].toObject())) {
|
||||
if (!(obj = obj->thisObject(cx)))
|
||||
return false;
|
||||
PUSH_OBJECT(*obj);
|
||||
} else {
|
||||
PUSH_UNDEFINED();
|
||||
}
|
||||
}
|
||||
len = JSOP_NAME_LENGTH;
|
||||
DO_NEXT_OP(len);
|
||||
}
|
||||
|
@ -4893,7 +4900,7 @@ BEGIN_CASE(JSOP_CALLNAME)
|
|||
|
||||
/* obj must be on the scope chain, thus not a function. */
|
||||
if (op == JSOP_CALLNAME || op == JSOP_CALLGNAME)
|
||||
PUSH_THISV(cx, obj, rval);
|
||||
SLOW_PUSH_THISV(cx, obj, rval);
|
||||
}
|
||||
END_CASE(JSOP_NAME)
|
||||
|
||||
|
@ -6396,7 +6403,7 @@ BEGIN_CASE(JSOP_XMLNAME)
|
|||
goto error;
|
||||
regs.sp[-1] = rval;
|
||||
if (op == JSOP_CALLXMLNAME)
|
||||
PUSH_THISV(cx, obj, rval);
|
||||
SLOW_PUSH_THISV(cx, obj, rval);
|
||||
}
|
||||
END_CASE(JSOP_XMLNAME)
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче