summaryrefslogtreecommitdiff
path: root/js/src/vm/NativeObject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/vm/NativeObject.cpp')
-rw-r--r--js/src/vm/NativeObject.cpp142
1 files changed, 74 insertions, 68 deletions
diff --git a/js/src/vm/NativeObject.cpp b/js/src/vm/NativeObject.cpp
index 3625d86f5..53f7c0bfa 100644
--- a/js/src/vm/NativeObject.cpp
+++ b/js/src/vm/NativeObject.cpp
@@ -1044,7 +1044,7 @@ bool
js::NativeLookupOwnProperty(ExclusiveContext* cx,
typename MaybeRooted<NativeObject*, allowGC>::HandleType obj,
typename MaybeRooted<jsid, allowGC>::HandleType id,
- typename MaybeRooted<Shape*, allowGC>::MutableHandleType propp)
+ typename MaybeRooted<PropertyResult, allowGC>::MutableHandleType propp)
{
bool done;
return LookupOwnPropertyInline<allowGC>(cx, obj, id, propp, &done);
@@ -1052,11 +1052,11 @@ js::NativeLookupOwnProperty(ExclusiveContext* cx,
template bool
js::NativeLookupOwnProperty<CanGC>(ExclusiveContext* cx, HandleNativeObject obj, HandleId id,
- MutableHandleShape propp);
+ MutableHandle<PropertyResult> propp);
template bool
js::NativeLookupOwnProperty<NoGC>(ExclusiveContext* cx, NativeObject* const& obj, const jsid& id,
- FakeMutableHandle<Shape*> propp);
+ FakeMutableHandle<PropertyResult> propp);
/*** [[DefineOwnProperty]] ***********************************************************************/
@@ -1279,19 +1279,20 @@ GetExistingProperty(JSContext* cx,
static bool
GetExistingPropertyValue(ExclusiveContext* cx, HandleNativeObject obj, HandleId id,
- HandleShape shape, MutableHandleValue vp)
+ Handle<PropertyResult> prop, MutableHandleValue vp)
{
- if (IsImplicitDenseOrTypedArrayElement(shape)) {
+ if (prop.isDenseOrTypedArrayElement()) {
vp.set(obj->getDenseOrTypedArrayElement(JSID_TO_INT(id)));
return true;
}
if (!cx->shouldBeJSContext())
return false;
- MOZ_ASSERT(shape->propid() == id);
- MOZ_ASSERT(obj->contains(cx, shape));
+ MOZ_ASSERT(prop.shape()->propid() == id);
+ MOZ_ASSERT(obj->contains(cx, prop.shape()));
RootedValue receiver(cx, ObjectValue(*obj));
+ RootedShape shape(cx, prop.shape());
return GetExistingProperty<CanGC>(cx->asJSContext(), receiver, obj, shape, vp);
}
@@ -1302,7 +1303,7 @@ GetExistingPropertyValue(ExclusiveContext* cx, HandleNativeObject obj, HandleId
*/
static bool
DefinePropertyIsRedundant(ExclusiveContext* cx, HandleNativeObject obj, HandleId id,
- HandleShape shape, unsigned shapeAttrs,
+ Handle<PropertyResult> prop, unsigned shapeAttrs,
Handle<PropertyDescriptor> desc, bool *redundant)
{
*redundant = false;
@@ -1319,16 +1320,16 @@ DefinePropertyIsRedundant(ExclusiveContext* cx, HandleNativeObject obj, HandleId
if (desc.hasValue()) {
// Get the current value of the existing property.
RootedValue currentValue(cx);
- if (!IsImplicitDenseOrTypedArrayElement(shape) &&
- shape->hasSlot() &&
- shape->hasDefaultGetter())
+ if (!prop.isDenseOrTypedArrayElement() &&
+ prop.shape()->hasSlot() &&
+ prop.shape()->hasDefaultGetter())
{
// Inline GetExistingPropertyValue in order to omit a type
// correctness assertion that's too strict for this particular
// call site. For details, see bug 1125624 comments 13-16.
- currentValue.set(obj->getSlot(shape->slot()));
+ currentValue.set(obj->getSlot(prop.shape()->slot()));
} else {
- if (!GetExistingPropertyValue(cx, obj, id, shape, &currentValue))
+ if (!GetExistingPropertyValue(cx, obj, id, prop, &currentValue))
return false;
}
@@ -1339,22 +1340,24 @@ DefinePropertyIsRedundant(ExclusiveContext* cx, HandleNativeObject obj, HandleId
}
GetterOp existingGetterOp =
- IsImplicitDenseOrTypedArrayElement(shape) ? nullptr : shape->getter();
+ prop.isDenseOrTypedArrayElement() ? nullptr : prop.shape()->getter();
if (desc.getter() != existingGetterOp)
return true;
SetterOp existingSetterOp =
- IsImplicitDenseOrTypedArrayElement(shape) ? nullptr : shape->setter();
+ prop.isDenseOrTypedArrayElement() ? nullptr : prop.shape()->setter();
if (desc.setter() != existingSetterOp)
return true;
} else {
- if (desc.hasGetterObject()) {
- if (!(shapeAttrs & JSPROP_GETTER) || desc.getterObject() != shape->getterObject())
- return true;
+ if (desc.hasGetterObject() &&
+ (!(shapeAttrs & JSPROP_GETTER) || desc.getterObject() != prop.shape()->getterObject()))
+ {
+ return true;
}
- if (desc.hasSetterObject()) {
- if (!(shapeAttrs & JSPROP_SETTER) || desc.setterObject() != shape->setterObject())
- return true;
+ if (desc.hasSetterObject() &&
+ (!(shapeAttrs & JSPROP_SETTER) || desc.setterObject() != prop.shape()->setterObject()))
+ {
+ return true;
}
}
@@ -1421,14 +1424,14 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
}
// 9.1.6.1 OrdinaryDefineOwnProperty steps 1-2.
- RootedShape shape(cx);
+ Rooted<PropertyResult> prop(cx);
if (desc_.attributes() & JSPROP_RESOLVING) {
// We are being called from a resolve or enumerate hook to reify a
// lazily-resolved property. To avoid reentering the resolve hook and
// recursing forever, skip the resolve hook when doing this lookup.
- NativeLookupOwnPropertyNoResolve(cx, obj, id, &shape);
+ NativeLookupOwnPropertyNoResolve(cx, obj, id, &prop);
} else {
- if (!NativeLookupOwnProperty<CanGC>(cx, obj, id, &shape))
+ if (!NativeLookupOwnProperty<CanGC>(cx, obj, id, &prop))
return false;
}
@@ -1443,7 +1446,7 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
Rooted<PropertyDescriptor> desc(cx, desc_);
// Step 2.
- if (!shape) {
+ if (!prop) {
if (!obj->nonProxyIsExtensible())
return result.fail(JSMSG_CANT_DEFINE_PROP_OBJECT_NOT_EXTENSIBLE);
@@ -1455,21 +1458,20 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
return result.succeed();
}
- MOZ_ASSERT(shape);
-
// Steps 3-4. (Step 3 is a special case of step 4.) We use shapeAttrs as a
// stand-in for shape in many places below, since shape might not be a
// pointer to a real Shape (see IsImplicitDenseOrTypedArrayElement).
- unsigned shapeAttrs = GetShapeAttributes(obj, shape);
+ unsigned shapeAttrs = GetPropertyAttributes(obj, prop);
bool redundant;
- if (!DefinePropertyIsRedundant(cx, obj, id, shape, shapeAttrs, desc, &redundant))
+ if (!DefinePropertyIsRedundant(cx, obj, id, prop, shapeAttrs, desc, &redundant))
return false;
if (redundant) {
// In cases involving JSOP_NEWOBJECT and JSOP_INITPROP, obj can have a
// type for this property that doesn't match the value in the slot.
// Update the type here, even though this DefineProperty call is
// otherwise a no-op. (See bug 1125624 comment 13.)
- if (!IsImplicitDenseOrTypedArrayElement(shape) && desc.hasValue()) {
+ if (!prop.isDenseOrTypedArrayElement() && desc.hasValue()) {
+ RootedShape shape(cx, prop.shape());
if (!UpdateShapeTypeAndValue(cx, obj, shape, desc.value()))
return false;
}
@@ -1512,24 +1514,24 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
MOZ_ASSERT(!desc.hasSetterObject());
if (IsDataDescriptor(shapeAttrs)) {
RootedValue currentValue(cx);
- if (!GetExistingPropertyValue(cx, obj, id, shape, &currentValue))
+ if (!GetExistingPropertyValue(cx, obj, id, prop, &currentValue))
return false;
desc.setValue(currentValue);
desc.setWritable(IsWritable(shapeAttrs));
} else {
- desc.setGetterObject(shape->getterObject());
- desc.setSetterObject(shape->setterObject());
+ desc.setGetterObject(prop.shape()->getterObject());
+ desc.setSetterObject(prop.shape()->setterObject());
}
} else if (desc.isDataDescriptor() != IsDataDescriptor(shapeAttrs)) {
// Step 7.
if (!IsConfigurable(shapeAttrs) && !skipRedefineChecks)
return result.fail(JSMSG_CANT_REDEFINE_PROP);
- if (IsImplicitDenseOrTypedArrayElement(shape)) {
+ if (prop.isDenseOrTypedArrayElement()) {
MOZ_ASSERT(!obj->is<TypedArrayObject>());
if (!NativeObject::sparsifyDenseElement(cx, obj, JSID_TO_INT(id)))
return false;
- shape = obj->lookup(cx, id);
+ prop.setNativeProperty(obj->lookup(cx, id));
}
// Fill in desc fields with default values (steps 7.b.i and 7.c.i).
@@ -1541,15 +1543,15 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
return result.fail(JSMSG_CANT_REDEFINE_PROP);
if (frozen || !desc.hasValue()) {
- if (IsImplicitDenseOrTypedArrayElement(shape)) {
+ if (prop.isDenseOrTypedArrayElement()) {
MOZ_ASSERT(!obj->is<TypedArrayObject>());
if (!NativeObject::sparsifyDenseElement(cx, obj, JSID_TO_INT(id)))
return false;
- shape = obj->lookup(cx, id);
+ prop.setNativeProperty(obj->lookup(cx, id));
}
RootedValue currentValue(cx);
- if (!GetExistingPropertyValue(cx, obj, id, shape, &currentValue))
+ if (!GetExistingPropertyValue(cx, obj, id, prop, &currentValue))
return false;
if (!desc.hasValue()) {
@@ -1571,32 +1573,32 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
desc.setWritable(IsWritable(shapeAttrs));
} else {
// Step 9.
- MOZ_ASSERT(shape->isAccessorDescriptor());
+ MOZ_ASSERT(prop.shape()->isAccessorDescriptor());
MOZ_ASSERT(desc.isAccessorDescriptor());
// The spec says to use SameValue, but since the values in
// question are objects, we can just compare pointers.
if (desc.hasSetterObject()) {
if (!IsConfigurable(shapeAttrs) &&
- desc.setterObject() != shape->setterObject() &&
+ desc.setterObject() != prop.shape()->setterObject() &&
!skipRedefineChecks)
{
return result.fail(JSMSG_CANT_REDEFINE_PROP);
}
} else {
// Fill in desc.[[Set]] from shape.
- desc.setSetterObject(shape->setterObject());
+ desc.setSetterObject(prop.shape()->setterObject());
}
if (desc.hasGetterObject()) {
if (!IsConfigurable(shapeAttrs) &&
- desc.getterObject() != shape->getterObject() &&
+ desc.getterObject() != prop.shape()->getterObject() &&
!skipRedefineChecks)
{
return result.fail(JSMSG_CANT_REDEFINE_PROP);
}
} else {
// Fill in desc.[[Get]] from shape.
- desc.setGetterObject(shape->getterObject());
+ desc.setGetterObject(prop.shape()->getterObject());
}
}
@@ -1681,18 +1683,18 @@ bool
js::NativeHasProperty(JSContext* cx, HandleNativeObject obj, HandleId id, bool* foundp)
{
RootedNativeObject pobj(cx, obj);
- RootedShape shape(cx);
+ Rooted<PropertyResult> prop(cx);
// This loop isn't explicit in the spec algorithm. See the comment on step
// 7.a. below.
for (;;) {
// Steps 2-3. ('done' is a SpiderMonkey-specific thing, used below.)
bool done;
- if (!LookupOwnPropertyInline<CanGC>(cx, pobj, id, &shape, &done))
+ if (!LookupOwnPropertyInline<CanGC>(cx, pobj, id, &prop, &done))
return false;
// Step 4.
- if (shape) {
+ if (prop) {
*foundp = true;
return true;
}
@@ -1733,15 +1735,15 @@ bool
js::NativeGetOwnPropertyDescriptor(JSContext* cx, HandleNativeObject obj, HandleId id,
MutableHandle<PropertyDescriptor> desc)
{
- RootedShape shape(cx);
- if (!NativeLookupOwnProperty<CanGC>(cx, obj, id, &shape))
+ Rooted<PropertyResult> prop(cx);
+ if (!NativeLookupOwnProperty<CanGC>(cx, obj, id, &prop))
return false;
- if (!shape) {
+ if (!prop) {
desc.object().set(nullptr);
return true;
}
- desc.setAttributes(GetShapeAttributes(obj, shape));
+ desc.setAttributes(GetPropertyAttributes(obj, prop));
if (desc.isAccessorDescriptor()) {
MOZ_ASSERT(desc.isShared());
@@ -1754,13 +1756,13 @@ js::NativeGetOwnPropertyDescriptor(JSContext* cx, HandleNativeObject obj, Handle
// than return true with desc incomplete, we fill out the missing
// getter or setter with a null, following CompletePropertyDescriptor.
if (desc.hasGetterObject()) {
- desc.setGetterObject(shape->getterObject());
+ desc.setGetterObject(prop.shape()->getterObject());
} else {
desc.setGetterObject(nullptr);
desc.attributesRef() |= JSPROP_GETTER;
}
if (desc.hasSetterObject()) {
- desc.setSetterObject(shape->setterObject());
+ desc.setSetterObject(prop.shape()->setterObject());
} else {
desc.setSetterObject(nullptr);
desc.attributesRef() |= JSPROP_SETTER;
@@ -1776,9 +1778,10 @@ js::NativeGetOwnPropertyDescriptor(JSContext* cx, HandleNativeObject obj, Handle
desc.setSetter(nullptr);
desc.attributesRef() &= ~JSPROP_SHARED;
- if (IsImplicitDenseOrTypedArrayElement(shape)) {
+ if (prop.isDenseOrTypedArrayElement()) {
desc.value().set(obj->getDenseOrTypedArrayElement(JSID_TO_INT(id)));
} else {
+ RootedShape shape(cx, prop.shape());
if (!NativeGetExistingProperty(cx, obj, obj, shape, desc.value()))
return false;
}
@@ -2058,23 +2061,25 @@ NativeGetPropertyInline(JSContext* cx,
typename MaybeRooted<Value, allowGC>::MutableHandleType vp)
{
typename MaybeRooted<NativeObject*, allowGC>::RootType pobj(cx, obj);
- typename MaybeRooted<Shape*, allowGC>::RootType shape(cx);
+ typename MaybeRooted<PropertyResult, allowGC>::RootType prop(cx);
// This loop isn't explicit in the spec algorithm. See the comment on step
// 4.d below.
for (;;) {
// Steps 2-3. ('done' is a SpiderMonkey-specific thing, used below.)
bool done;
- if (!LookupOwnPropertyInline<allowGC>(cx, pobj, id, &shape, &done))
+ if (!LookupOwnPropertyInline<allowGC>(cx, pobj, id, &prop, &done))
return false;
- if (shape) {
+ if (prop) {
// Steps 5-8. Special case for dense elements because
// GetExistingProperty doesn't support those.
- if (IsImplicitDenseOrTypedArrayElement(shape)) {
+ if (prop.isDenseOrTypedArrayElement()) {
vp.set(pobj->getDenseOrTypedArrayElement(JSID_TO_INT(id)));
return true;
}
+
+ typename MaybeRooted<Shape*, allowGC>::RootType shape(cx, prop.shape());
return GetExistingProperty<allowGC>(cx, receiver, pobj, shape, vp);
}
@@ -2366,11 +2371,11 @@ SetDenseOrTypedArrayElement(JSContext* cx, HandleNativeObject obj, uint32_t inde
*/
static bool
SetExistingProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleValue v,
- HandleValue receiver, HandleNativeObject pobj, HandleShape shape,
+ HandleValue receiver, HandleNativeObject pobj, Handle<PropertyResult> prop,
ObjectOpResult& result)
{
// Step 5 for dense elements.
- if (IsImplicitDenseOrTypedArrayElement(shape)) {
+ if (prop.isDenseOrTypedArrayElement()) {
// Step 5.a.
if (pobj->getElementsHeader()->isFrozen())
return result.fail(JSMSG_READ_ONLY);
@@ -2384,6 +2389,7 @@ SetExistingProperty(JSContext* cx, HandleNativeObject obj, HandleId id, HandleVa
}
// Step 5 for all other properties.
+ RootedShape shape(cx, prop.shape());
if (shape->isDataDescriptor()) {
// Step 5.a.
if (!shape->writable())
@@ -2441,7 +2447,7 @@ js::NativeSetProperty(JSContext* cx, HandleNativeObject obj, HandleId id, Handle
// Step numbers below reference ES6 rev 27 9.1.9, the [[Set]] internal
// method for ordinary objects. We substitute our own names for these names
// used in the spec: O -> pobj, P -> id, ownDesc -> shape.
- RootedShape shape(cx);
+ Rooted<PropertyResult> prop(cx);
RootedNativeObject pobj(cx, obj);
// This loop isn't explicit in the spec algorithm. See the comment on step
@@ -2450,12 +2456,12 @@ js::NativeSetProperty(JSContext* cx, HandleNativeObject obj, HandleId id, Handle
for (;;) {
// Steps 2-3. ('done' is a SpiderMonkey-specific thing, used below.)
bool done;
- if (!LookupOwnPropertyInline<CanGC>(cx, pobj, id, &shape, &done))
+ if (!LookupOwnPropertyInline<CanGC>(cx, pobj, id, &prop, &done))
return false;
- if (shape) {
+ if (prop) {
// Steps 5-6.
- return SetExistingProperty(cx, obj, id, v, receiver, pobj, shape, result);
+ return SetExistingProperty(cx, obj, id, v, receiver, pobj, prop, result);
}
// Steps 4.a-b. The check for 'done' on this next line is tricky.
@@ -2513,12 +2519,12 @@ js::NativeDeleteProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
ObjectOpResult& result)
{
// Steps 2-3.
- RootedShape shape(cx);
- if (!NativeLookupOwnProperty<CanGC>(cx, obj, id, &shape))
+ Rooted<PropertyResult> prop(cx);
+ if (!NativeLookupOwnProperty<CanGC>(cx, obj, id, &prop))
return false;
// Step 4.
- if (!shape) {
+ if (!prop) {
// If no property call the class's delProperty hook, passing succeeded
// as the result parameter. This always succeeds when there is no hook.
return CallJSDeletePropertyOp(cx, obj->getClass()->getDelProperty(), obj, id, result);
@@ -2527,7 +2533,7 @@ js::NativeDeleteProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
cx->runtime()->gc.poke();
// Step 6. Non-configurable property.
- if (GetShapeAttributes(obj, shape) & JSPROP_PERMANENT)
+ if (GetPropertyAttributes(obj, prop) & JSPROP_PERMANENT)
return result.failCantDelete();
if (!CallJSDeletePropertyOp(cx, obj->getClass()->getDelProperty(), obj, id, result))
@@ -2536,7 +2542,7 @@ js::NativeDeleteProperty(JSContext* cx, HandleNativeObject obj, HandleId id,
return true;
// Step 5.
- if (IsImplicitDenseOrTypedArrayElement(shape)) {
+ if (prop.isDenseOrTypedArrayElement()) {
// Typed array elements are non-configurable.
MOZ_ASSERT(!obj->is<TypedArrayObject>());