зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1142828 - Refactor to avoid having [[Set]]-specific weird cases in the [[DefineOwnProperty]] code. r=Waldo.
NativeSetExistingDataProperty is only moved in this changeset; its body is not modified. --HG-- extra : rebase_source : 413ad14802b8deb6bffef81897cd61ee004d35e2
This commit is contained in:
Родитель
5bb0f20d04
Коммит
39dccf0118
|
@ -1102,14 +1102,10 @@ UpdateShapeTypeAndValue(ExclusiveContext* cx, NativeObject* obj, Shape* shape, c
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
NativeSetExistingDataProperty(JSContext* cx, HandleNativeObject obj, HandleShape shape,
|
||||
HandleValue v, HandleValue receiver, ObjectOpResult& result);
|
||||
|
||||
static inline bool
|
||||
DefinePropertyOrElement(ExclusiveContext* cx, HandleNativeObject obj, HandleId id,
|
||||
GetterOp getter, SetterOp setter, unsigned attrs, HandleValue value,
|
||||
bool callSetterAfterwards, ObjectOpResult& result)
|
||||
ObjectOpResult& result)
|
||||
{
|
||||
MOZ_ASSERT(getter != JS_PropertyStub);
|
||||
MOZ_ASSERT(setter != JS_StrictPropertyStub);
|
||||
|
@ -1192,16 +1188,6 @@ DefinePropertyOrElement(ExclusiveContext* cx, HandleNativeObject obj, HandleId i
|
|||
if (!CallAddPropertyHook(cx, obj, shape, value))
|
||||
return false;
|
||||
|
||||
if (callSetterAfterwards && setter) {
|
||||
MOZ_ASSERT(!(attrs & JSPROP_GETTER));
|
||||
MOZ_ASSERT(!(attrs & JSPROP_SETTER));
|
||||
if (!cx->shouldBeJSContext())
|
||||
return false;
|
||||
RootedValue receiver(cx, ObjectValue(*obj));
|
||||
return NativeSetExistingDataProperty(cx->asJSContext(), obj, shape, value, receiver,
|
||||
result);
|
||||
}
|
||||
|
||||
return result.succeed();
|
||||
}
|
||||
|
||||
|
@ -1467,8 +1453,7 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
|
|||
// cleared the IGNORE flags by now. Since we can never get here with JSPROP_IGNORE_VALUE
|
||||
// relevant, just clear it.
|
||||
attrs = ApplyOrDefaultAttributes(attrs) & ~JSPROP_IGNORE_VALUE;
|
||||
return DefinePropertyOrElement(cx, obj, id, getter, setter,
|
||||
attrs, updateValue, false, result);
|
||||
return DefinePropertyOrElement(cx, obj, id, getter, setter, attrs, updateValue, result);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(shape);
|
||||
|
@ -1953,6 +1938,55 @@ MaybeReportUndeclaredVarAssignment(JSContext* cx, JSString* propname)
|
|||
JSMSG_UNDECLARED_VAR, bytes.ptr());
|
||||
}
|
||||
|
||||
/*
|
||||
* Finish assignment to a shapeful data property of a native object obj. This
|
||||
* conforms to no standard and there is a lot of legacy baggage here.
|
||||
*/
|
||||
static bool
|
||||
NativeSetExistingDataProperty(JSContext* cx, HandleNativeObject obj, HandleShape shape,
|
||||
HandleValue v, HandleValue receiver, ObjectOpResult& result)
|
||||
{
|
||||
MOZ_ASSERT(obj->isNative());
|
||||
MOZ_ASSERT(shape->isDataDescriptor());
|
||||
|
||||
if (shape->hasDefaultSetter()) {
|
||||
if (shape->hasSlot()) {
|
||||
// The common path. Standard data property.
|
||||
|
||||
// Global properties declared with 'var' will be initially
|
||||
// defined with an undefined value, so don't treat the initial
|
||||
// assignments to such properties as overwrites.
|
||||
bool overwriting = !obj->is<GlobalObject>() || !obj->getSlot(shape->slot()).isUndefined();
|
||||
obj->setSlotWithType(cx, shape, v, overwriting);
|
||||
return result.succeed();
|
||||
}
|
||||
|
||||
// Bizarre: shared (slotless) property that's writable but has no
|
||||
// JSSetterOp. JS code can't define such a property, but it can be done
|
||||
// through the JSAPI. Treat it as non-writable.
|
||||
return result.fail(JSMSG_GETTER_ONLY);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!obj->is<DynamicWithObject>()); // See bug 1128681.
|
||||
|
||||
uint32_t sample = cx->runtime()->propertyRemovals;
|
||||
RootedId id(cx, shape->propid());
|
||||
RootedValue value(cx, v);
|
||||
if (!CallJSSetterOp(cx, shape->setterOp(), obj, id, &value, result))
|
||||
return false;
|
||||
|
||||
// Update any slot for the shape with the value produced by the setter,
|
||||
// unless the setter deleted the shape.
|
||||
if (shape->hasSlot() &&
|
||||
(MOZ_LIKELY(cx->runtime()->propertyRemovals == sample) ||
|
||||
obj->contains(cx, shape)))
|
||||
{
|
||||
obj->setSlot(shape->slot(), value);
|
||||
}
|
||||
|
||||
return true; // result is populated by CallJSSetterOp above.
|
||||
}
|
||||
|
||||
/*
|
||||
* When a [[Set]] operation finds no existing property with the given id
|
||||
* or finds a writable data property on the prototype chain, we end up here.
|
||||
|
@ -2019,13 +2053,32 @@ js::SetPropertyByDefining(JSContext* cx, HandleObject obj, HandleId id, HandleVa
|
|||
JSSetterOp setter = clasp->setProperty;
|
||||
MOZ_ASSERT(getter != JS_PropertyStub);
|
||||
MOZ_ASSERT(setter != JS_StrictPropertyStub);
|
||||
if (!receiver->is<NativeObject>())
|
||||
return DefineProperty(cx, receiver, id, v, getter, setter, attrs, result);
|
||||
if (!DefineProperty(cx, receiver, id, v, getter, setter, attrs, result))
|
||||
return false;
|
||||
|
||||
// If the receiver is native, there is one more legacy wrinkle: the class
|
||||
// JSSetterOp is called after defining the new property.
|
||||
Rooted<NativeObject*> nativeReceiver(cx, &receiver->as<NativeObject>());
|
||||
return DefinePropertyOrElement(cx, nativeReceiver, id, getter, setter, attrs, v, true, result);
|
||||
if (setter && receiver->is<NativeObject>()) {
|
||||
if (!result)
|
||||
return true;
|
||||
|
||||
Rooted<NativeObject*> nativeReceiver(cx, &receiver->as<NativeObject>());
|
||||
if (!cx->shouldBeJSContext())
|
||||
return false;
|
||||
RootedValue receiverValue(cx, ObjectValue(*receiver));
|
||||
|
||||
// This lookup is a bit unfortunate, but not nearly the most
|
||||
// unfortunate thing about Class getters and setters. Since the above
|
||||
// DefineProperty call succeeded, receiver is native, and the property
|
||||
// has a setter (and thus can't be a dense element), this lookup is
|
||||
// guaranteed to succeed.
|
||||
RootedShape shape(cx, nativeReceiver->lookup(cx, id));
|
||||
MOZ_ASSERT(shape);
|
||||
return NativeSetExistingDataProperty(cx->asJSContext(), nativeReceiver, shape, v,
|
||||
receiverValue, result);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// When setting |id| for |receiver| and |obj| has no property for id, continue
|
||||
|
@ -2100,55 +2153,6 @@ SetDenseOrTypedArrayElement(JSContext* cx, HandleNativeObject obj, uint32_t inde
|
|||
return result.succeed();
|
||||
}
|
||||
|
||||
/*
|
||||
* Finish assignment to a shapeful data property of a native object obj. This
|
||||
* conforms to no standard and there is a lot of legacy baggage here.
|
||||
*/
|
||||
static bool
|
||||
NativeSetExistingDataProperty(JSContext* cx, HandleNativeObject obj, HandleShape shape,
|
||||
HandleValue v, HandleValue receiver, ObjectOpResult& result)
|
||||
{
|
||||
MOZ_ASSERT(obj->isNative());
|
||||
MOZ_ASSERT(shape->isDataDescriptor());
|
||||
|
||||
if (shape->hasDefaultSetter()) {
|
||||
if (shape->hasSlot()) {
|
||||
// The common path. Standard data property.
|
||||
|
||||
// Global properties declared with 'var' will be initially
|
||||
// defined with an undefined value, so don't treat the initial
|
||||
// assignments to such properties as overwrites.
|
||||
bool overwriting = !obj->is<GlobalObject>() || !obj->getSlot(shape->slot()).isUndefined();
|
||||
obj->setSlotWithType(cx, shape, v, overwriting);
|
||||
return result.succeed();
|
||||
}
|
||||
|
||||
// Bizarre: shared (slotless) property that's writable but has no
|
||||
// JSSetterOp. JS code can't define such a property, but it can be done
|
||||
// through the JSAPI. Treat it as non-writable.
|
||||
return result.fail(JSMSG_GETTER_ONLY);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!obj->is<DynamicWithObject>()); // See bug 1128681.
|
||||
|
||||
uint32_t sample = cx->runtime()->propertyRemovals;
|
||||
RootedId id(cx, shape->propid());
|
||||
RootedValue value(cx, v);
|
||||
if (!CallJSSetterOp(cx, shape->setterOp(), obj, id, &value, result))
|
||||
return false;
|
||||
|
||||
// Update any slot for the shape with the value produced by the setter,
|
||||
// unless the setter deleted the shape.
|
||||
if (shape->hasSlot() &&
|
||||
(MOZ_LIKELY(cx->runtime()->propertyRemovals == sample) ||
|
||||
obj->contains(cx, shape)))
|
||||
{
|
||||
obj->setSlot(shape->slot(), value);
|
||||
}
|
||||
|
||||
return true; // result is populated by CallJSSetterOp above.
|
||||
}
|
||||
|
||||
/*
|
||||
* Finish the assignment `receiver[id] = v` when an existing property (shape)
|
||||
* has been found on a native object (pobj). This implements ES6 draft rev 32
|
||||
|
|
Загрузка…
Ссылка в новой задаче