mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-24 13:21:05 +00:00
Bug 603201 - Enable primitive receivers in [[Set]]. r=jorendorff
This commit is contained in:
parent
a8dd690edf
commit
f81ea0f69a
@ -1059,7 +1059,8 @@ function traverse (node, cb) {
|
||||
cb(node);
|
||||
keys(node).map(key => {
|
||||
if (key === 'parent' || !node[key]) return;
|
||||
node[key].parent = node;
|
||||
if (typeof node[key] === "object")
|
||||
node[key].parent = node;
|
||||
traverse(node[key], cb);
|
||||
});
|
||||
}
|
||||
|
@ -2766,7 +2766,7 @@ DoSetElemFallback(JSContext* cx, BaselineFrame* frame, ICSetElem_Fallback* stub_
|
||||
if (!InitArrayElemOperation(cx, pc, obj, index.toInt32(), rhs))
|
||||
return false;
|
||||
} else {
|
||||
if (!SetObjectElement(cx, obj, index, rhs, JSOp(*pc) == JSOP_STRICTSETELEM, script, pc))
|
||||
if (!SetObjectElement(cx, obj, index, rhs, objv, JSOp(*pc) == JSOP_STRICTSETELEM, script, pc))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -4777,9 +4777,12 @@ DoSetPropFallback(JSContext* cx, BaselineFrame* frame, ICSetProp_Fallback* stub_
|
||||
} else {
|
||||
MOZ_ASSERT(op == JSOP_SETPROP || op == JSOP_STRICTSETPROP);
|
||||
|
||||
RootedValue v(cx, rhs);
|
||||
if (!PutProperty(cx, obj, id, v, op == JSOP_STRICTSETPROP))
|
||||
ObjectOpResult result;
|
||||
if (!SetProperty(cx, obj, id, rhs, lhs, result) ||
|
||||
!result.checkStrictErrorOrWarning(cx, obj, id, op == JSOP_STRICTSETPROP))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Leave the RHS on the stack.
|
||||
|
@ -7,34 +7,36 @@
|
||||
|
||||
#include "jsapi-tests/tests.h"
|
||||
|
||||
using namespace JS;
|
||||
|
||||
BEGIN_TEST(testForwardSetProperty)
|
||||
{
|
||||
JS::RootedValue v1(cx);
|
||||
RootedValue v1(cx);
|
||||
EVAL("var foundValue; \n"
|
||||
"var obj1 = { set prop(val) { foundValue = this; } }; \n"
|
||||
"obj1;",
|
||||
&v1);
|
||||
|
||||
JS::RootedValue v2(cx);
|
||||
RootedValue v2(cx);
|
||||
EVAL("var obj2 = Object.create(obj1); \n"
|
||||
"obj2;",
|
||||
&v2);
|
||||
|
||||
JS::RootedValue v3(cx);
|
||||
RootedValue v3(cx);
|
||||
EVAL("var obj3 = {}; \n"
|
||||
"obj3;",
|
||||
&v3);
|
||||
|
||||
JS::RootedObject obj1(cx, &v1.toObject());
|
||||
JS::RootedObject obj2(cx, &v2.toObject());
|
||||
JS::RootedObject obj3(cx, &v3.toObject());
|
||||
RootedObject obj1(cx, &v1.toObject());
|
||||
RootedObject obj2(cx, &v2.toObject());
|
||||
RootedObject obj3(cx, &v3.toObject());
|
||||
|
||||
JS::RootedValue setval(cx, JS::Int32Value(42));
|
||||
RootedValue setval(cx, Int32Value(42));
|
||||
|
||||
JS::RootedValue propkey(cx);
|
||||
RootedValue propkey(cx);
|
||||
EVAL("'prop';", &propkey);
|
||||
|
||||
JS::RootedId prop(cx);
|
||||
RootedId prop(cx);
|
||||
CHECK(JS_ValueToId(cx, propkey, &prop));
|
||||
|
||||
EXEC("function assertEq(a, b, msg) \n"
|
||||
@ -68,42 +70,20 @@ BEGIN_TEST(testForwardSetProperty)
|
||||
|
||||
// Strict setter
|
||||
|
||||
EVAL("obj1 = { set prop(val) { 'use strict'; foundValue = this; } }; \n"
|
||||
"obj1;",
|
||||
&v1);
|
||||
RootedValue v4(cx);
|
||||
EVAL("({ set prop(val) { 'use strict'; foundValue = this; } })", &v4);
|
||||
RootedObject obj4(cx, &v4.toObject());
|
||||
|
||||
CHECK(JS_ForwardSetPropertyTo(cx, obj2, prop, setval, v3, result));
|
||||
CHECK(JS_ForwardSetPropertyTo(cx, obj4, prop, setval, v3, result));
|
||||
CHECK(result);
|
||||
|
||||
EXEC("assertEq(foundValue, obj3, 'wrong receiver passed to strict setter');");
|
||||
|
||||
CHECK(JS_ForwardSetPropertyTo(cx, obj2, prop, setval, setval, result));
|
||||
CHECK(JS_ForwardSetPropertyTo(cx, obj4, prop, setval, setval, result));
|
||||
CHECK(result);
|
||||
|
||||
JS::RootedValue strictSetSupported(cx);
|
||||
EVAL("var strictSetSupported = false; \n"
|
||||
"Object.defineProperty(Object.prototype, \n"
|
||||
" 'strictSetter', \n"
|
||||
" { \n"
|
||||
" set(v) { \n"
|
||||
" 'use strict'; \n"
|
||||
" strictSetSupported = \n"
|
||||
" typeof this === 'number'; \n"
|
||||
" } \n"
|
||||
" }); \n"
|
||||
"17..strictSetter = 42; \n"
|
||||
"strictSetSupported;",
|
||||
&strictSetSupported);
|
||||
CHECK(strictSetSupported.isBoolean());
|
||||
|
||||
if (strictSetSupported.toBoolean()) {
|
||||
// XXX Bug 603201 will fix this.
|
||||
MOZ_ASSERT(false,
|
||||
"remove the support-testing check when bug 603201 is fixt");
|
||||
EXEC("assertEq(foundValue, 42, \n"
|
||||
" '42 passed as receiver to strict setter ' + \n"
|
||||
" 'was mangled');");
|
||||
}
|
||||
EXEC("assertEq(foundValue, 42, \n"
|
||||
" '42 passed as receiver to strict setter was mangled');");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -27,9 +27,8 @@ Object.defineProperty(Symbol.prototype, "prop", {
|
||||
set: function (v) {
|
||||
"use strict";
|
||||
sets++;
|
||||
assertEq(typeof this, "object");
|
||||
assertEq(this instanceof Symbol, true);
|
||||
assertEq(this.valueOf(), sym);
|
||||
assertEq(typeof this, "symbol");
|
||||
assertEq(this, sym);
|
||||
assertEq(v, "newvalue");
|
||||
}
|
||||
});
|
||||
|
@ -282,11 +282,8 @@ SetPropertyOperation(JSContext* cx, JSOp op, HandleValue lval, HandleId id, Hand
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
// Note: ES6 specifies that the value lval, not obj, is passed as receiver
|
||||
// to obj's [[Set]] internal method. See bug 603201.
|
||||
RootedValue receiver(cx, ObjectValue(*obj));
|
||||
ObjectOpResult result;
|
||||
return SetProperty(cx, obj, id, rval, receiver, result) &&
|
||||
return SetProperty(cx, obj, id, rval, lval, result) &&
|
||||
result.checkStrictErrorOrWarning(cx, obj, id, op == JSOP_STRICTSETPROP);
|
||||
}
|
||||
|
||||
@ -1409,9 +1406,9 @@ ModOperation(JSContext* cx, HandleValue lhs, HandleValue rhs, MutableHandleValue
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
SetObjectElementOperation(JSContext* cx, HandleObject obj, HandleValue receiver, HandleId id,
|
||||
const Value& value, bool strict, JSScript* script = nullptr,
|
||||
jsbytecode* pc = nullptr)
|
||||
SetObjectElementOperation(JSContext* cx, HandleObject obj, HandleId id, HandleValue value,
|
||||
HandleValue receiver, bool strict,
|
||||
JSScript* script = nullptr, jsbytecode* pc = nullptr)
|
||||
{
|
||||
// receiver != obj happens only at super[expr], where we expect to find the property
|
||||
// People probably aren't building hashtables with |super| anyway.
|
||||
@ -1430,9 +1427,8 @@ SetObjectElementOperation(JSContext* cx, HandleObject obj, HandleValue receiver,
|
||||
if (obj->isNative() && !JSID_IS_INT(id) && !obj->setHadElementsAccess(cx))
|
||||
return false;
|
||||
|
||||
RootedValue tmp(cx, value);
|
||||
ObjectOpResult result;
|
||||
return SetProperty(cx, obj, id, tmp, receiver, result) &&
|
||||
return SetProperty(cx, obj, id, value, receiver, result) &&
|
||||
result.checkStrictErrorOrWarning(cx, obj, id, strict);
|
||||
}
|
||||
|
||||
@ -2677,13 +2673,15 @@ CASE(JSOP_STRICTSETELEM)
|
||||
{
|
||||
static_assert(JSOP_SETELEM_LENGTH == JSOP_STRICTSETELEM_LENGTH,
|
||||
"setelem and strictsetelem must be the same size");
|
||||
HandleValue receiver = REGS.stackHandleAt(-3);
|
||||
ReservedRooted<JSObject*> obj(&rootObject0);
|
||||
FETCH_OBJECT(cx, -3, obj);
|
||||
obj = ToObjectFromStack(cx, receiver);
|
||||
if (!obj)
|
||||
goto error;
|
||||
ReservedRooted<jsid> id(&rootId0);
|
||||
FETCH_ELEMENT_ID(-2, id);
|
||||
Value& value = REGS.sp[-1];
|
||||
ReservedRooted<Value> receiver(&rootValue0, ObjectValue(*obj));
|
||||
if (!SetObjectElementOperation(cx, obj, receiver, id, value, *REGS.pc == JSOP_STRICTSETELEM))
|
||||
HandleValue value = REGS.stackHandleAt(-1);
|
||||
if (!SetObjectElementOperation(cx, obj, id, value, receiver, *REGS.pc == JSOP_STRICTSETELEM))
|
||||
goto error;
|
||||
REGS.sp[-3] = value;
|
||||
REGS.sp -= 2;
|
||||
@ -2700,10 +2698,10 @@ CASE(JSOP_STRICTSETELEM_SUPER)
|
||||
FETCH_ELEMENT_ID(-4, id);
|
||||
ReservedRooted<Value> receiver(&rootValue0, REGS.sp[-3]);
|
||||
ReservedRooted<JSObject*> obj(&rootObject1, ®S.sp[-2].toObject());
|
||||
Value& value = REGS.sp[-1];
|
||||
HandleValue value = REGS.stackHandleAt(-1);
|
||||
|
||||
bool strict = JSOp(*REGS.pc) == JSOP_STRICTSETELEM_SUPER;
|
||||
if (!SetObjectElementOperation(cx, obj, receiver, id, value, strict))
|
||||
if (!SetObjectElementOperation(cx, obj, id, value, receiver, strict))
|
||||
goto error;
|
||||
REGS.sp[-4] = value;
|
||||
REGS.sp -= 3;
|
||||
@ -4333,7 +4331,7 @@ js::SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index, HandleV
|
||||
if (!ToPropertyKey(cx, index, &id))
|
||||
return false;
|
||||
RootedValue receiver(cx, ObjectValue(*obj));
|
||||
return SetObjectElementOperation(cx, obj, receiver, id, value, strict);
|
||||
return SetObjectElementOperation(cx, obj, id, value, receiver, strict);
|
||||
}
|
||||
|
||||
bool
|
||||
@ -4345,7 +4343,18 @@ js::SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index, HandleV
|
||||
if (!ToPropertyKey(cx, index, &id))
|
||||
return false;
|
||||
RootedValue receiver(cx, ObjectValue(*obj));
|
||||
return SetObjectElementOperation(cx, obj, receiver, id, value, strict, script, pc);
|
||||
return SetObjectElementOperation(cx, obj, id, value, receiver, strict, script, pc);
|
||||
}
|
||||
|
||||
bool
|
||||
js::SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index, HandleValue value,
|
||||
HandleValue receiver, bool strict, HandleScript script, jsbytecode* pc)
|
||||
{
|
||||
MOZ_ASSERT(pc);
|
||||
RootedId id(cx);
|
||||
if (!ToPropertyKey(cx, index, &id))
|
||||
return false;
|
||||
return SetObjectElementOperation(cx, obj, id, value, receiver, strict, script, pc);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -369,6 +369,10 @@ bool
|
||||
SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index, HandleValue value,
|
||||
bool strict, HandleScript script, jsbytecode* pc);
|
||||
|
||||
bool
|
||||
SetObjectElement(JSContext* cx, HandleObject obj, HandleValue index, HandleValue value,
|
||||
HandleValue receiver, bool strict, HandleScript script, jsbytecode* pc);
|
||||
|
||||
bool
|
||||
InitElementArray(JSContext* cx, jsbytecode* pc,
|
||||
HandleObject obj, uint32_t index, HandleValue value);
|
||||
|
Loading…
Reference in New Issue
Block a user