зеркало из https://github.com/mozilla/gecko-dev.git
[JAEGER] Bug 582411: Make JM throw an exception setting undefined global vars in strict mode, r=dvander
--HG-- extra : rebase_source : 6ee3399c7f4ffadab34765a4bf3c2ccaa4c8c1f2
This commit is contained in:
Родитель
86e20cfe21
Коммит
4290da179d
|
@ -2114,7 +2114,14 @@ BindNameToSlot(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
|
|||
return MakeUpvarForEval(pn, cg);
|
||||
}
|
||||
|
||||
if (cg->compileAndGo() && cg->compiler()->globalScope->globalObj) {
|
||||
/*
|
||||
* Optimize accesses to undeclared globals, but only if we are in
|
||||
* compile-and-go mode, the global is the same as the scope chain,
|
||||
* and we are not in strict mode.
|
||||
*/
|
||||
if (cg->compileAndGo() &&
|
||||
cg->compiler()->globalScope->globalObj &&
|
||||
!(cg->flags & TCF_STRICT_MODE_CODE)) {
|
||||
switch (op) {
|
||||
case JSOP_NAME: op = JSOP_GETGNAME; break;
|
||||
case JSOP_SETNAME: op = JSOP_SETGNAME; break;
|
||||
|
@ -2405,7 +2412,7 @@ JSCodeGenerator::addGlobalUse(JSAtom *atom, uint32 slot, UpvarCookie &cookie)
|
|||
{
|
||||
JSAtomListElement *ale = globalMap.lookup(atom);
|
||||
if (ale) {
|
||||
cookie.set(0, ALE_INDEX(ale));
|
||||
cookie.set(0, uint16(ALE_INDEX(ale)));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -1138,14 +1138,30 @@ mjit::Compiler::generateMethod()
|
|||
BEGIN_CASE(JSOP_LAMBDA)
|
||||
{
|
||||
JSFunction *fun = script->getFunction(fullAtomIndex(PC));
|
||||
prepareStubCall(Uses(0));
|
||||
masm.move(ImmPtr(fun), Registers::ArgReg1);
|
||||
|
||||
JSObjStubFun stub = stubs::Lambda;
|
||||
uint32 uses = 0;
|
||||
|
||||
JSOp next = JSOp(PC[JSOP_LAMBDA_LENGTH]);
|
||||
if (next == JSOP_INITMETHOD)
|
||||
stubCall(stubs::LambdaForInit);
|
||||
else
|
||||
stubCall(stubs::Lambda);
|
||||
if (next == JSOP_INITMETHOD) {
|
||||
stub = stubs::LambdaForInit;
|
||||
} else if (next == JSOP_SETMETHOD) {
|
||||
stub = stubs::LambdaForSet;
|
||||
uses = 1;
|
||||
} else if (fun->joinable()) {
|
||||
if (next == JSOP_CALL) {
|
||||
stub = stubs::LambdaJoinableForCall;
|
||||
uses = frame.frameDepth();
|
||||
} else if (next == JSOP_NULL) {
|
||||
stub = stubs::LambdaJoinableForNull;
|
||||
}
|
||||
}
|
||||
|
||||
prepareStubCall(Uses(uses));
|
||||
masm.move(ImmPtr(fun), Registers::ArgReg1);
|
||||
|
||||
stubCall(stub);
|
||||
|
||||
frame.takeReg(Registers::ReturnReg);
|
||||
frame.pushTypedPayload(JSVAL_TYPE_OBJECT, Registers::ReturnReg);
|
||||
}
|
||||
|
|
|
@ -1782,9 +1782,7 @@ ic::SetProp(VMFrame &f, uint32 index)
|
|||
}
|
||||
|
||||
Value rval = f.regs.sp[-1];
|
||||
if (!obj->setProperty(f.cx, ATOM_TO_JSID(atom), &f.regs.sp[-1]))
|
||||
THROW();
|
||||
f.regs.sp[-2] = rval;
|
||||
stub(f, index);
|
||||
}
|
||||
|
||||
static void JS_FASTCALL
|
||||
|
|
|
@ -1522,24 +1522,76 @@ JSObject * JS_FASTCALL
|
|||
stubs::LambdaForInit(VMFrame &f, JSFunction *fun)
|
||||
{
|
||||
JSObject *obj = FUN_OBJECT(fun);
|
||||
|
||||
JSObject *parent;
|
||||
if (FUN_NULL_CLOSURE(fun)) {
|
||||
parent = f.fp->scopeChain;
|
||||
|
||||
if (obj->getParent() == parent)
|
||||
return obj;
|
||||
} else {
|
||||
parent = js_GetScopeChain(f.cx, f.fp);
|
||||
if (!parent)
|
||||
THROWV(NULL);
|
||||
if (FUN_NULL_CLOSURE(fun) && obj->getParent() == f.fp->scopeChain) {
|
||||
fun->setMethodAtom(f.fp->script->getAtom(GET_SLOTNO(f.regs.pc + JSOP_LAMBDA_LENGTH)));
|
||||
return obj;
|
||||
}
|
||||
return Lambda(f, fun);
|
||||
}
|
||||
|
||||
obj = CloneFunctionObject(f.cx, fun, parent);
|
||||
if (!obj)
|
||||
THROWV(NULL);
|
||||
JSObject * JS_FASTCALL
|
||||
stubs::LambdaForSet(VMFrame &f, JSFunction *fun)
|
||||
{
|
||||
JSObject *obj = FUN_OBJECT(fun);
|
||||
if (FUN_NULL_CLOSURE(fun) && obj->getParent() == f.fp->scopeChain) {
|
||||
const Value &lref = f.regs.sp[-1];
|
||||
if (lref.isObject() && lref.toObject().canHaveMethodBarrier()) {
|
||||
fun->setMethodAtom(f.fp->script->getAtom(GET_SLOTNO(f.regs.pc + JSOP_LAMBDA_LENGTH)));
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
return Lambda(f, fun);
|
||||
}
|
||||
|
||||
return obj;
|
||||
JSObject * JS_FASTCALL
|
||||
stubs::LambdaJoinableForCall(VMFrame &f, JSFunction *fun)
|
||||
{
|
||||
JSObject *obj = FUN_OBJECT(fun);
|
||||
if (FUN_NULL_CLOSURE(fun) && obj->getParent() == f.fp->scopeChain) {
|
||||
/*
|
||||
* Array.prototype.sort and String.prototype.replace are
|
||||
* optimized as if they are special form. We know that they
|
||||
* won't leak the joined function object in obj, therefore
|
||||
* we don't need to clone that compiler- created function
|
||||
* object for identity/mutation reasons.
|
||||
*/
|
||||
int iargc = GET_ARGC(f.regs.pc + JSOP_LAMBDA_LENGTH);
|
||||
|
||||
/*
|
||||
* Note that we have not yet pushed obj as the final argument,
|
||||
* so regs.sp[1 - (iargc + 2)], and not regs.sp[-(iargc + 2)],
|
||||
* is the callee for this JSOP_CALL.
|
||||
*/
|
||||
const Value &cref = f.regs.sp[1 - (iargc + 2)];
|
||||
JSObject *callee;
|
||||
|
||||
if (IsFunctionObject(cref, &callee)) {
|
||||
JSFunction *calleeFun = GET_FUNCTION_PRIVATE(cx, callee);
|
||||
FastNative fastNative = FUN_FAST_NATIVE(calleeFun);
|
||||
|
||||
if (fastNative) {
|
||||
if (iargc == 1 && fastNative == array_sort)
|
||||
return obj;
|
||||
if (iargc == 2 && fastNative == str_replace)
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
return Lambda(f, fun);
|
||||
}
|
||||
|
||||
JSObject * JS_FASTCALL
|
||||
stubs::LambdaJoinableForNull(VMFrame &f, JSFunction *fun)
|
||||
{
|
||||
JSObject *obj = FUN_OBJECT(fun);
|
||||
if (FUN_NULL_CLOSURE(fun) && obj->getParent() == f.fp->scopeChain) {
|
||||
jsbytecode *pc2 = f.regs.pc + JSOP_LAMBDA_LENGTH + JSOP_NULL_LENGTH;
|
||||
JSOp op2 = JSOp(*pc2);
|
||||
|
||||
if (op2 == JSOP_CALL && GET_ARGC(pc2) == 0)
|
||||
return obj;
|
||||
}
|
||||
return Lambda(f, fun);
|
||||
}
|
||||
|
||||
JSObject * JS_FASTCALL
|
||||
|
|
|
@ -116,6 +116,9 @@ JSObject * JS_FASTCALL DefLocalFun_FC(VMFrame &f, JSFunction *fun);
|
|||
JSObject * JS_FASTCALL RegExp(VMFrame &f, JSObject *regex);
|
||||
JSObject * JS_FASTCALL Lambda(VMFrame &f, JSFunction *fun);
|
||||
JSObject * JS_FASTCALL LambdaForInit(VMFrame &f, JSFunction *fun);
|
||||
JSObject * JS_FASTCALL LambdaForSet(VMFrame &f, JSFunction *fun);
|
||||
JSObject * JS_FASTCALL LambdaJoinableForCall(VMFrame &f, JSFunction *fun);
|
||||
JSObject * JS_FASTCALL LambdaJoinableForNull(VMFrame &f, JSFunction *fun);
|
||||
JSObject * JS_FASTCALL FlatLambda(VMFrame &f, JSFunction *fun);
|
||||
void JS_FASTCALL Arguments(VMFrame &f);
|
||||
void JS_FASTCALL ArgSub(VMFrame &f, uint32 n);
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// |trace-test| error: ReferenceError;
|
||||
|
||||
function f() {
|
||||
"use strict";
|
||||
foo = 1;
|
||||
}
|
||||
|
||||
f();
|
Загрузка…
Ссылка в новой задаче