Bug 1090636, part 4 - Update SetPropertyByDefining to implement ES6 draft rev 28 section 9.1.9 steps 5.c-f. r=efaust.

--HG--
extra : rebase_source : 558852c474d603299c47b630bd73b1ae951c6928
This commit is contained in:
Jason Orendorff 2014-10-29 17:16:45 -05:00
parent d6aa3d9c3f
commit b773e07dfe
2 changed files with 48 additions and 25 deletions

View File

@ -5,9 +5,7 @@ var t = {x: 1};
var p = new Proxy(t, {
defineProperty(t, id, desc) {
hits++;
assertEq(desc.enumerable, true);
assertEq(desc.configurable, true);
assertEq(desc.writable, true);
assertEq(Object.getOwnPropertyNames(desc).join(","), "value");
assertEq(desc.value, 42);
}
});

View File

@ -1979,17 +1979,37 @@ MaybeReportUndeclaredVarAssignment(JSContext *cx, JSString *propname)
* or finds a writable data property on the prototype chain, we end up here.
* Finish the [[Set]] by defining a new property on receiver.
*
* This should follow ES6 draft rev 28, 9.1.9 [[Set]] steps 5.c-f, but it
* is really old code and we're not there yet.
* This implements ES6 draft rev 28, 9.1.9 [[Set]] steps 5.c-f, but it
* is really old code and there are a few barnacles.
*/
template <ExecutionMode mode>
static bool
SetPropertyByDefining(typename ExecutionModeTraits<mode>::ContextType cxArg,
HandleObject receiver, HandleId id, HandleValue v, bool strict)
{
// If receiver is inextensible, stop. (According to the specification, this
// is supposed to be enforced by [[DefineOwnProperty]], but we haven't
// implemented that yet.)
// Step 5.c-d: Test whether receiver has an existing own property
// receiver[id]. The spec calls [[GetOwnProperty]]; js::HasOwnProperty is
// the same thing except faster in the non-proxy case. (Once
// SetPropertyHelper is better-behaved, we will be able to optimize away
// even the HasOwnProperty call.)
bool existing;
if (mode == ParallelExecution) {
// Not the fastest possible implementation, but the fastest possible
// without refactoring LookupPropertyPure or duplicating code.
NativeObject *npobj;
Shape *shape;
if (!LookupPropertyPure(cxArg, receiver, id, &npobj, &shape))
return false;
existing = (npobj == receiver);
} else {
if (!HasOwnProperty(cxArg->asJSContext(), receiver, id, &existing))
return false;
}
// If the property doesn't already exist, check for an inextensible
// receiver. (According to the specification, this is supposed to be
// enforced by [[DefineOwnProperty]], but we haven't implemented that yet.)
if (!existing) {
bool extensible;
if (mode == ParallelExecution) {
if (receiver->is<ProxyObject>())
@ -2011,6 +2031,7 @@ SetPropertyByDefining(typename ExecutionModeTraits<mode>::ContextType cxArg,
}
return true;
}
}
// Invalidate SpiderMonkey-specific caches or bail.
const Class *clasp = receiver->getClass();
@ -2026,7 +2047,11 @@ SetPropertyByDefining(typename ExecutionModeTraits<mode>::ContextType cxArg,
return false;
}
// Define the new data property.
// Step 5.e-f. Define the new data property.
unsigned attrs =
existing
? JSPROP_IGNORE_ENUMERATE | JSPROP_IGNORE_READONLY | JSPROP_IGNORE_PERMANENT
: JSPROP_ENUMERATE;
JSPropertyOp getter = clasp->getProperty;
JSStrictPropertyOp setter = clasp->setProperty;
MOZ_ASSERT(getter != JS_PropertyStub);
@ -2035,11 +2060,11 @@ SetPropertyByDefining(typename ExecutionModeTraits<mode>::ContextType cxArg,
if (mode == ParallelExecution)
return false;
return JSObject::defineGeneric(cxArg->asJSContext(), receiver, id, v, getter, setter,
JSPROP_ENUMERATE);
attrs);
}
Rooted<NativeObject*> nativeReceiver(cxArg, &receiver->as<NativeObject>());
return DefinePropertyOrElement<mode>(cxArg, nativeReceiver, id, getter, setter,
JSPROP_ENUMERATE, v, true, strict);
attrs, v, true, strict);
}
/*