--- a/js/src/vm/NativeObject.cpp
+++ b/js/src/vm/NativeObject.cpp
@@ -1424,42 +1424,49 @@ js::NativeDefineProperty(ExclusiveContex
if (shape->isAccessorDescriptor() &&
!CheckAccessorRedefinition(cx, obj, shape, getter, setter, id, attrs))
{
return false;
}
attrs = ApplyOrDefaultAttributes(attrs, shape);
- /* Keep everything from the shape that isn't the things we're changing */
- unsigned attrMask = ~(JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT);
- shape = NativeObject::changeProperty(cx, obj, shape, attrs, attrMask,
- shape->getter(), shape->setter());
- if (!shape)
- return false;
- if (shape->hasSlot())
- updateValue = obj->getSlot(shape->slot());
- shouldDefine = false;
+ if (shape->isAccessorDescriptor() && !(attrs & JSPROP_IGNORE_READONLY)) {
+ // ES6 draft 2014-10-14 9.1.6.3 step 7.c: Since [[Writable]]
+ // is present, change the existing accessor property to a data
+ // property.
+ updateValue = UndefinedValue();
+ } else {
+ // We are at most changing some attributes, and cannot convert
+ // from data descriptor to accessor, or vice versa. Take
+ // everything from the shape that we aren't changing.
+ uint32_t propMask = JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT;
+ attrs = (shape->attributes() & ~propMask) | (attrs & propMask);
+ getter = shape->getter();
+ setter = shape->setter();
+ if (shape->hasSlot())
+ updateValue = obj->getSlot(shape->slot());
+ }
}
}
/*
* Purge the property cache of any properties named by id that are about
* to be shadowed in obj's scope chain.
*/
if (!PurgeScopeChain(cx, obj, id))
return false;
if (shouldDefine) {
// Handle the default cases here. Anyone that wanted to set non-default attributes has
// 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, value, false, false);
+ attrs, updateValue, false, false);
}
MOZ_ASSERT(shape);
JS_ALWAYS_TRUE(UpdateShapeTypeAndValue(cx, obj, shape, updateValue));
return CallAddPropertyHook(cx, obj, shape, updateValue);
}