Bug 514570 - 2 - Push |undefined| rather than |null| when calling functions without a specified |this| value, per ES5. r=jorendorff

This commit is contained in:
Jeff Walden 2010-10-12 11:50:03 -07:00
Родитель 8a276492f8
Коммит 545f7104c0
14 изменённых файлов: 134 добавлений и 93 удалений

Просмотреть файл

@ -2816,12 +2816,17 @@ array_extra(JSContext *cx, ArrayExtraMode mode, uintN argc, Value *vp)
Value thisv;
if (argc > 1 && !REDUCE_MODE(mode)) {
JSObject *thisp;
if (!js_ValueToObjectOrNull(cx, argv[1], &thisp))
return JS_FALSE;
thisv.setObjectOrNull(thisp);
if (argv[1].isNullOrUndefined()) {
thisv.setUndefined();
} else {
JSObject *thisObj;
if (!js_ValueToObjectOrNull(cx, argv[1], &thisObj))
return JS_FALSE;
JS_ASSERT(thisObj);
thisv.setObject(*thisObj);
}
} else {
thisv.setNull();
thisv.setUndefined();
}
/*

Просмотреть файл

@ -6525,12 +6525,10 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
* interpose the lambda-initialized method read barrier -- see the code
* in jsinterp.cpp for JSOP_LAMBDA followed by JSOP_{SET,INIT}PROP.
*
* Then (or in a call case that has no explicit reference-base object)
* we emit JSOP_NULL as a placeholder local GC root to hold the |this|
* parameter: in the operator new case, the newborn instance; in the
* base-less call case, a cookie meaning "use the global object as the
* |this| value" (or in ES5 strict mode, "use undefined", so we should
* use JSOP_PUSH instead of JSOP_NULL -- see bug 514570).
* Then (or in a call case that has no explicit reference-base
* object) we emit JSOP_PUSH to produce the |this| slot required
* for calls (which non-strict mode functions will box into the
* global object).
*/
pn2 = pn->pn_head;
switch (pn2->pn_type) {
@ -6552,22 +6550,18 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn)
if (pn2->pn_op == JSOP_XMLNAME) {
if (!EmitXMLName(cx, pn2, JSOP_CALLXMLNAME, cg))
return JS_FALSE;
callop = true; /* suppress JSOP_NULL after */
callop = true; /* suppress JSOP_PUSH after */
break;
}
#endif
/* FALL THROUGH */
default:
/*
* Push null as a placeholder for the global object, per ECMA-262
* 11.2.3 step 6.
*/
if (!js_EmitTree(cx, cg, pn2))
return JS_FALSE;
callop = false; /* trigger JSOP_NULL after */
callop = false; /* trigger JSOP_PUSH after */
break;
}
if (!callop && js_Emit1(cx, cg, JSOP_NULL) < 0)
if (!callop && js_Emit1(cx, cg, JSOP_PUSH) < 0)
return JS_FALSE;
/* Remember start of callable-object bytecode for decompilation hint. */

Просмотреть файл

@ -2258,15 +2258,20 @@ js_fun_call(JSContext *cx, uintN argc, Value *vp)
}
Value *argv = vp + 2;
Value thisv;
if (argc == 0) {
/* Call fun with its global object as the 'this' param if no args. */
obj = NULL;
thisv.setUndefined();
} else {
/* Otherwise convert the first arg to 'this' and skip over it. */
if (argv[0].isObject())
obj = &argv[0].toObject();
else if (!js_ValueToObjectOrNull(cx, argv[0], &obj))
return JS_FALSE;
if (argv[0].isNullOrUndefined()) {
thisv.setUndefined();
} else {
if (!js_ValueToObjectOrNull(cx, argv[0], &obj))
return JS_FALSE;
JS_ASSERT(obj);
thisv.setObject(*obj);
}
argc--;
argv++;
}
@ -2276,9 +2281,9 @@ js_fun_call(JSContext *cx, uintN argc, Value *vp)
if (!cx->stack().pushInvokeArgs(cx, argc, &args))
return JS_FALSE;
/* Push fval, obj, and the args. */
/* Push fval, thisv, and the args. */
args.callee() = fval;
args.thisv().setObjectOrNull(obj);
args.thisv() = thisv;
memcpy(args.argv(), argv, argc * sizeof *argv);
bool ok = Invoke(cx, args, 0);
@ -2360,11 +2365,17 @@ js_fun_apply(JSContext *cx, uintN argc, Value *vp)
}
}
/* Convert the first arg to 'this' and skip over it. */
if (vp[2].isObject())
obj = &vp[2].toObject();
else if (!js_ValueToObjectOrNull(cx, vp[2], &obj))
return JS_FALSE;
Value thisv;
if (vp[2].isNullOrUndefined()) {
thisv.setUndefined();
} else {
if (!js_ValueToObjectOrNull(cx, vp[2], &obj))
return JS_FALSE;
JS_ASSERT(obj);
thisv.setObject(*obj);
}
LeaveTrace(cx);
@ -2377,7 +2388,7 @@ js_fun_apply(JSContext *cx, uintN argc, Value *vp)
/* Push fval, obj, and aobj's elements as args. */
args.callee() = fval;
args.thisv().setObjectOrNull(obj);
args.thisv() = thisv;
/* Steps 7-8. */
if (aobj && aobj->isArguments() && !aobj->isArgsLengthOverridden()) {
@ -2525,15 +2536,15 @@ CallOrConstructBoundFunction(JSContext *cx, uintN argc, Value *vp)
* very shortly when this-boxing only occurs for non-strict
* functions, callee-side, in bug 514570.
*/
JSObject *boundThisObj;
if (boundThis.isObjectOrNull()) {
boundThisObj = boundThis.toObjectOrNull();
if (boundThis.isNullOrUndefined()) {
args.thisv().setUndefined();
} else {
JSObject *boundThisObj;
if (!js_ValueToObjectOrNull(cx, boundThis, &boundThisObj))
return false;
JS_ASSERT(boundThisObj);
args.thisv().setObject(*boundThisObj);
}
args.thisv() = ObjectOrNullValue(boundThisObj);
}
if (constructing ? !InvokeConstructor(cx, args) : !Invoke(cx, args, 0))

Просмотреть файл

@ -498,7 +498,7 @@ ComputeThisFromArgv(JSContext *cx, Value *argv)
*/
JS_ASSERT(!argv[-1].isMagic());
if (argv[-1].isNull())
if (argv[-1].isNullOrUndefined())
return ComputeGlobalThis(cx, argv);
if (!argv[-1].isObject())
@ -678,7 +678,7 @@ Invoke(JSContext *cx, const CallArgs &argsRef, uint32 flags)
JSFunction *fun = callee.getFunctionPrivate();
JS_ASSERT_IF(flags & JSINVOKE_CONSTRUCT, !fun->isConstructor());
if (fun->isNative()) {
JS_ASSERT(args.thisv().isObjectOrNull() || PrimitiveThisTest(fun, args.thisv()));
JS_ASSERT(args.thisv().isObject() || args.thisv().isUndefined() || PrimitiveThisTest(fun, args.thisv()));
return CallJSNative(cx, fun->u.n.native, args.argc(), args.base());
}
@ -4239,7 +4239,7 @@ BEGIN_CASE(JSOP_CALLPROP)
/* FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=412571 */
JSObject *funobj;
if (!IsFunctionObject(rval, &funobj) ||
!PrimitiveThisTest(GET_FUNCTION_PRIVATE(cx, funobj), lval)) {
!PrimitiveThisTest(funobj->getFunctionPrivate(), lval)) {
if (!js_PrimitiveToObject(cx, &regs.sp[-1]))
goto error;
}
@ -4721,7 +4721,7 @@ BEGIN_CASE(JSOP_APPLY)
DO_OP();
}
JS_ASSERT(vp[1].isObjectOrNull() || PrimitiveThisTest(newfun, vp[1]));
JS_ASSERT(vp[1].isObject() || vp[1].isUndefined() || PrimitiveThisTest(newfun, vp[1]));
Probes::enterJSFun(cx, newfun);
JSBool ok = CallJSNative(cx, newfun->u.n.native, argc, vp);
@ -4766,15 +4766,17 @@ END_CASE(JSOP_SETCALL)
(clasp = thisp->getClass()) == &js_CallClass || \
clasp == &js_BlockClass || \
clasp == &js_DeclEnvClass) { \
/* Normal case: thisp is global or an activation record. */ \
/* Callee determines |this|. */ \
thisp = NULL; \
/* Push the ImplicitThisValue for the Environment Record */ \
/* associated with obj. See ES5 sections 10.2.1.1.6 and */ \
/* 10.2.1.2.6 (ImplicitThisValue) and section 11.2.3 */ \
/* (Function Calls). */ \
PUSH_UNDEFINED(); \
} else { \
thisp = thisp->thisObject(cx); \
if (!thisp) \
goto error; \
PUSH_OBJECT(*thisp); \
} \
PUSH_OBJECT_OR_NULL(thisp); \
JS_END_MACRO
BEGIN_CASE(JSOP_GETGNAME)
@ -4819,7 +4821,7 @@ BEGIN_CASE(JSOP_CALLNAME)
clasp == &js_DeclEnvClass);
#endif
if (op == JSOP_CALLNAME || op == JSOP_CALLGNAME)
PUSH_NULL();
PUSH_UNDEFINED();
len = JSOP_NAME_LENGTH;
DO_NEXT_OP(len);
}
@ -5180,7 +5182,7 @@ BEGIN_CASE(JSOP_CALLARG)
METER_SLOT_OP(op, slot);
PUSH_COPY(argv[slot]);
if (op == JSOP_CALLARG)
PUSH_NULL();
PUSH_UNDEFINED();
}
END_CASE(JSOP_GETARG)
@ -5206,7 +5208,7 @@ BEGIN_CASE(JSOP_CALLLOCAL)
uint32 slot = GET_SLOTNO(regs.pc);
JS_ASSERT(slot < script->nslots);
PUSH_COPY(regs.fp->slots()[slot]);
PUSH_NULL();
PUSH_UNDEFINED();
}
END_CASE(JSOP_CALLLOCAL)
@ -5230,7 +5232,7 @@ BEGIN_CASE(JSOP_CALLUPVAR)
PUSH_COPY(rval);
if (op == JSOP_CALLUPVAR)
PUSH_NULL();
PUSH_UNDEFINED();
}
END_CASE(JSOP_GETUPVAR)
@ -5272,7 +5274,7 @@ BEGIN_CASE(JSOP_CALLUPVAR_DBG)
goto error;
if (op == JSOP_CALLUPVAR_DBG)
PUSH_NULL();
PUSH_UNDEFINED();
}
END_CASE(JSOP_GETUPVAR_DBG)
@ -5286,7 +5288,7 @@ BEGIN_CASE(JSOP_CALLFCSLOT)
JS_ASSERT(index < obj->getFunctionPrivate()->u.i.nupvars);
PUSH_COPY(obj->getFlatClosureUpvar(index));
if (op == JSOP_CALLFCSLOT)
PUSH_NULL();
PUSH_UNDEFINED();
}
END_CASE(JSOP_GETFCSLOT)
@ -5299,7 +5301,7 @@ BEGIN_CASE(JSOP_CALLGLOBAL)
JS_ASSERT(obj->containsSlot(slot));
PUSH_COPY(obj->getSlot(slot));
if (op == JSOP_CALLGLOBAL)
PUSH_NULL();
PUSH_UNDEFINED();
}
END_CASE(JSOP_GETGLOBAL)

Просмотреть файл

@ -5926,12 +5926,14 @@ js_PrimitiveToObject(JSContext *cx, Value *vp)
JS_ASSERT(v.isPrimitive());
Class *clasp;
if (v.isNumber())
if (v.isNumber()) {
clasp = &js_NumberClass;
else if (v.isString())
} else if (v.isString()) {
clasp = &js_StringClass;
else
} else {
JS_ASSERT(v.isBoolean());
clasp = &js_BooleanClass;
}
JSObject *obj = NewBuiltinClassInstance(cx, clasp);
if (!obj)

Просмотреть файл

@ -4117,8 +4117,8 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
} else {
JS_NOT_REACHED("should see block chain operation");
}
LOCAL_ASSERT(*pc == JSOP_NULL);
pc += JSOP_NULL_LENGTH;
LOCAL_ASSERT(*pc == JSOP_PUSH);
pc += JSOP_PUSH_LENGTH;
LOCAL_ASSERT(*pc == JSOP_CALL);
LOCAL_ASSERT(GET_ARGC(pc) == 0);
len = JSOP_CALL_LENGTH;

Просмотреть файл

@ -856,7 +856,7 @@ Class js_StringClass = {
static JSString *
NormalizeThis(JSContext *cx, Value *vp)
{
if (vp[1].isNull() && (!ComputeThisFromVp(cx, vp) || vp[1].isNull()))
if (vp[1].isNullOrUndefined() && !ComputeThisFromVp(cx, vp))
return NULL;
/*
@ -2100,7 +2100,7 @@ FindReplaceLength(JSContext *cx, RegExpStatics *res, ReplaceData &rdata, size_t
InvokeSessionGuard &session = rdata.session;
if (!session.started()) {
Value lambdav = ObjectValue(*lambda);
if (!rdata.session.start(cx, lambdav, NullValue(), argc))
if (!session.start(cx, lambdav, UndefinedValue(), argc))
return false;
}
@ -2409,7 +2409,7 @@ str_replace_flat_lambda(JSContext *cx, uintN argc, Value *vp, ReplaceData &rdata
CallArgs &args = rdata.singleShot;
args.callee().setObject(*rdata.lambda);
args.thisv().setNull();
args.thisv().setUndefined();
Value *sp = args.argv();
sp[0].setString(matchStr);

Просмотреть файл

@ -7063,12 +7063,6 @@ LeaveTree(TraceMonitor *tm, TracerState& state, VMSideExit* lr)
JS_ASSERT(state.eos == state.stackBase + MAX_NATIVE_STACK_SLOTS);
JSObject* globalObj = outermostTree->globalObj;
FlushNativeGlobalFrame(cx, globalObj, state.eos, ngslots, gslots, globalTypeMap);
#ifdef DEBUG
/* Verify that our state restoration worked. */
for (JSStackFrame* fp = cx->fp(); fp; fp = fp->prev()) {
JS_ASSERT_IF(fp->isFunctionFrame(), fp->thisValue().isObjectOrNull());
}
#endif
#ifdef JS_JIT_SPEW
if (innermost->exitType != TIMEOUT_EXIT)
@ -10063,10 +10057,10 @@ TraceRecorder::getThis(LIns*& this_ins)
JS_ASSERT(fp->callee().getGlobal() == globalObj);
const Value& thisv = fp->thisValue();
if (!thisv.isNull()) {
if (!thisv.isUndefined()) {
/*
* fp->argv[-1] has already been computed. Since the type-specialization
* of traces distinguishes between null and objects, the same will be
* of traces distinguishes between |undefined| and objects, the same will be
* true at run time (or we won't get this far).
*/
this_ins = get(&fp->thisValue());
@ -13139,7 +13133,7 @@ TraceRecorder::record_JSOP_CALLNAME()
NameResult nr;
CHECK_STATUS_A(scopeChainProp(obj, vp, ins, nr));
stack(0, ins);
stack(1, INS_NULL());
stack(1, INS_UNDEFINED());
return ARECORD_CONTINUE;
}
@ -13153,7 +13147,7 @@ TraceRecorder::record_JSOP_CALLNAME()
RETURN_STOP_A("callee is not an object");
stack(0, INS_CONSTOBJ(&pcval.toFunObj()));
stack(1, INS_NULL());
stack(1, INS_UNDEFINED());
return ARECORD_CONTINUE;
}
@ -13282,7 +13276,7 @@ JS_REQUIRES_STACK AbortableRecordingStatus
TraceRecorder::record_JSOP_CALLUPVAR()
{
CHECK_STATUS_A(record_JSOP_GETUPVAR());
stack(1, INS_NULL());
stack(1, INS_UNDEFINED());
return ARECORD_CONTINUE;
}
@ -13306,7 +13300,7 @@ JS_REQUIRES_STACK AbortableRecordingStatus
TraceRecorder::record_JSOP_CALLFCSLOT()
{
CHECK_STATUS_A(record_JSOP_GETFCSLOT());
stack(1, INS_NULL());
stack(1, INS_UNDEFINED());
return ARECORD_CONTINUE;
}
@ -15954,7 +15948,7 @@ TraceRecorder::record_JSOP_CALLLOCAL()
{
uintN slot = GET_SLOTNO(cx->regs->pc);
stack(0, var(slot));
stack(1, INS_NULL());
stack(1, INS_UNDEFINED());
return ARECORD_CONTINUE;
}
@ -15963,7 +15957,7 @@ TraceRecorder::record_JSOP_CALLARG()
{
uintN slot = GET_ARGNO(cx->regs->pc);
stack(0, arg(slot));
stack(1, INS_NULL());
stack(1, INS_UNDEFINED());
return ARECORD_CONTINUE;
}
@ -16167,7 +16161,7 @@ TraceRecorder::record_JSOP_CALLGLOBAL()
Value &v = globalObj->getSlotRef(slot);
stack(0, get(&v));
stack(1, INS_NULL());
stack(1, INS_UNDEFINED());
return ARECORD_CONTINUE;
}

Просмотреть файл

@ -1208,7 +1208,7 @@ mjit::Compiler::generateMethod()
{
jsop_getarg(GET_SLOTNO(PC));
if (op == JSOP_CALLARG)
frame.push(NullValue());
frame.push(UndefinedValue());
}
END_CASE(JSOP_GETARG)
@ -1497,7 +1497,7 @@ mjit::Compiler::generateMethod()
frame.freeReg(reg);
frame.push(Address(reg, index * sizeof(Value)));
if (op == JSOP_CALLFCSLOT)
frame.push(NullValue());
frame.push(UndefinedValue());
}
END_CASE(JSOP_CALLFCSLOT)
@ -1536,7 +1536,7 @@ mjit::Compiler::generateMethod()
BEGIN_CASE(JSOP_CALLGNAME)
jsop_getgname(fullAtomIndex(PC));
if (op == JSOP_CALLGNAME)
frame.push(NullValue());
frame.push(UndefinedValue());
END_CASE(JSOP_GETGNAME)
BEGIN_CASE(JSOP_SETGNAME)
@ -1571,7 +1571,7 @@ mjit::Compiler::generateMethod()
stubCall(stubs::GetUpvar);
frame.pushSynced();
if (op == JSOP_CALLUPVAR)
frame.push(NullValue());
frame.push(UndefinedValue());
}
END_CASE(JSOP_CALLUPVAR)
@ -1607,7 +1607,7 @@ mjit::Compiler::generateMethod()
BEGIN_CASE(JSOP_CALLLOCAL)
frame.pushLocal(GET_SLOTNO(PC));
frame.push(NullValue());
frame.push(UndefinedValue());
END_CASE(JSOP_CALLLOCAL)
BEGIN_CASE(JSOP_INT8)
@ -1682,7 +1682,7 @@ mjit::Compiler::generateMethod()
BEGIN_CASE(JSOP_CALLGLOBAL)
jsop_getglobal(GET_SLOTNO(PC));
if (op == JSOP_CALLGLOBAL)
frame.push(NullValue());
frame.push(UndefinedValue());
END_CASE(JSOP_GETGLOBAL)
BEGIN_CASE(JSOP_SETGLOBAL)
@ -3314,7 +3314,7 @@ mjit::Compiler::jsop_this()
{
Address thisvAddr(JSFrameReg, JSStackFrame::offsetOfThis(fun));
if (0 && !script->strictModeCode) {
Jump null = masm.testNull(Assembler::Equal, thisvAddr);
Jump null = masm.testUndefined(Assembler::Equal, thisvAddr);
stubcc.linkExit(null, Uses(1));
stubcc.leave();
stubcc.call(stubs::ComputeThis);
@ -3325,7 +3325,7 @@ mjit::Compiler::jsop_this()
frame.pushTypedPayload(JSVAL_TYPE_OBJECT, reg);
} else {
frame.push(thisvAddr);
Jump null = frame.testNull(Assembler::Equal, frame.peek(-1));
Jump null = frame.testUndefined(Assembler::Equal, frame.peek(-1));
stubcc.linkExit(null, Uses(1));
stubcc.leave();
stubcc.call(stubs::This);

Просмотреть файл

@ -567,6 +567,15 @@ FrameState::testNull(Assembler::Condition cond, FrameEntry *fe)
return masm.testNull(cond, tempRegForType(fe));
}
inline JSC::MacroAssembler::Jump
FrameState::testUndefined(Assembler::Condition cond, FrameEntry *fe)
{
JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
if (shouldAvoidTypeRemat(fe))
return masm.testUndefined(cond, addressOf(fe));
return masm.testUndefined(cond, tempRegForType(fe));
}
inline JSC::MacroAssembler::Jump
FrameState::testInt32(Assembler::Condition cond, FrameEntry *fe)
{

Просмотреть файл

@ -660,43 +660,49 @@ class FrameState
void discardFe(FrameEntry *fe);
/*
* Helper function. Tests if a slot's type is null. Condition should
* Helper function. Tests if a slot's type is null. Condition must
* be Equal or NotEqual.
*/
inline Jump testNull(Assembler::Condition cond, FrameEntry *fe);
/*
* Helper function. Tests if a slot's type is an integer. Condition should
* Helper function. Tests if a slot's type is undefined. Condition must
* be Equal or NotEqual.
*/
inline Jump testUndefined(Assembler::Condition cond, FrameEntry *fe);
/*
* Helper function. Tests if a slot's type is an integer. Condition must
* be Equal or NotEqual.
*/
inline Jump testInt32(Assembler::Condition cond, FrameEntry *fe);
/*
* Helper function. Tests if a slot's type is a double. Condition should
* Helper function. Tests if a slot's type is a double. Condition must
* be Equal or Not Equal.
*/
inline Jump testDouble(Assembler::Condition cond, FrameEntry *fe);
/*
* Helper function. Tests if a slot's type is a boolean. Condition should
* Helper function. Tests if a slot's type is a boolean. Condition must
* be Equal or NotEqual.
*/
inline Jump testBoolean(Assembler::Condition cond, FrameEntry *fe);
/*
* Helper function. Tests if a slot's type is a string. Condition should
* Helper function. Tests if a slot's type is a string. Condition must
* be Equal or NotEqual.
*/
inline Jump testString(Assembler::Condition cond, FrameEntry *fe);
/*
* Helper function. Tests if a slot's type is a non-funobj. Condition should
* Helper function. Tests if a slot's type is a non-funobj. Condition must
* be Equal or NotEqual.
*/
inline Jump testObject(Assembler::Condition cond, FrameEntry *fe);
/*
* Helper function. Tests if a slot's type is primitve. Condition should
* Helper function. Tests if a slot's type is primitive. Condition must
* be Equal or NotEqual.
*/
inline Jump testPrimitive(Assembler::Condition cond, FrameEntry *fe);

Просмотреть файл

@ -215,6 +215,14 @@ class Assembler : public BaseAssembler
return branch32(cond, tagOf(address), ImmTag(JSVAL_TAG_NULL));
}
Jump testUndefined(Assembler::Condition cond, RegisterID reg) {
return branch32(cond, reg, ImmTag(JSVAL_TAG_UNDEFINED));
}
Jump testUndefined(Assembler::Condition cond, Address address) {
return branch32(cond, tagOf(address), ImmTag(JSVAL_TAG_UNDEFINED));
}
Jump testInt32(Assembler::Condition cond, RegisterID reg) {
return branch32(cond, reg, ImmTag(JSVAL_TAG_INT32));
}

Просмотреть файл

@ -236,6 +236,15 @@ class Assembler : public BaseAssembler
return branchPtr(cond, Registers::ValueReg, Imm64(JSVAL_BITS(JSVAL_NULL)));
}
Jump testUndefined(Assembler::Condition cond, RegisterID reg) {
return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_UNDEFINED));
}
Jump testUndefined(Assembler::Condition cond, Address address) {
loadValue(address, Registers::ValueReg);
return branchPtr(cond, Registers::ValueReg, Imm64(JSVAL_BITS(JSVAL_VOID)));
}
Jump testInt32(Assembler::Condition cond, RegisterID reg) {
return branchPtr(cond, reg, ImmTag(JSVAL_SHIFTED_TAG_INT32));
}

Просмотреть файл

@ -371,7 +371,7 @@ NameOp(VMFrame &f, JSObject *obj, bool callname = false)
#endif
if (callname) {
f.regs.sp++;
f.regs.sp[-1].setNull();
f.regs.sp[-1].setUndefined();
}
return obj;
}
@ -416,14 +416,15 @@ NameOp(VMFrame &f, JSObject *obj, bool callname = false)
(clasp = thisp->getClass()) == &js_CallClass ||
clasp == &js_BlockClass ||
clasp == &js_DeclEnvClass) {
thisp = NULL;
f.regs.sp++;
f.regs.sp[-1].setUndefined();
} else {
thisp = thisp->thisObject(cx);
if (!thisp)
return NULL;
f.regs.sp++;
f.regs.sp[-1].setObject(*thisp);
}
f.regs.sp++;
f.regs.sp[-1].setObjectOrNull(thisp);
}
return obj;
}
@ -2161,7 +2162,7 @@ stubs::CallProp(VMFrame &f, JSAtom *origAtom)
/* FIXME: https://bugzilla.mozilla.org/show_bug.cgi?id=412571 */
JSObject *funobj;
if (!IsFunctionObject(rval, &funobj) ||
!PrimitiveThisTest(GET_FUNCTION_PRIVATE(cx, funobj), lval)) {
!PrimitiveThisTest(funobj->getFunctionPrivate(), lval)) {
if (!js_PrimitiveToObject(cx, &regs.sp[-1]))
THROW();
}