Bug 1148652, part 2 - Use mostly-compliant code for defining TypedArray elements, already used from StandardDefineProperty, in NativeDefineProperty as well. r=efaust.

This commit is contained in:
Jason Orendorff 2015-03-23 14:32:31 -05:00
parent 0859395dae
commit 04f1f59ecb
4 changed files with 61 additions and 41 deletions

View File

@ -627,44 +627,8 @@ DefinePropertyOnTypedArray(JSContext* cx, HandleObject obj, HandleId id,
MOZ_ASSERT(IsAnyTypedArray(obj));
// Steps 3.a-c.
uint64_t index;
if (IsTypedArrayIndex(id, &index)) {
// These are all substeps of 3.c.
// Steps i-vi.
// We (wrongly) ignore out of range defines with a value.
if (index >= AnyTypedArrayLength(obj))
return result.succeed();
// Step vii.
if (desc.isAccessorDescriptor())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
// Step viii.
if (desc.hasConfigurable() && desc.configurable())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
// Step ix.
if (desc.hasEnumerable() && !desc.enumerable())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
// Step x.
if (desc.hasWritable() && !desc.writable())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
// Step xi.
if (desc.hasValue()) {
double d;
if (!ToNumber(cx, desc.value(), &d))
return false;
if (obj->is<TypedArrayObject>())
TypedArrayObject::setElement(obj->as<TypedArrayObject>(), index, d);
else
SharedTypedArrayObject::setElement(obj->as<SharedTypedArrayObject>(), index, d);
}
// Step xii.
return result.succeed();
}
if (IsTypedArrayIndex(id, &index))
return DefineTypedArrayElement(cx, obj, index, desc, result);
// Step 4.
return DefinePropertyOnObject(cx, obj.as<NativeObject>(), id, desc, result);

View File

@ -1302,10 +1302,13 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
return result.fail(JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH);
}
} else if (IsAnyTypedArray(obj)) {
// Don't define new indexed properties on typed arrays.
// 9.4.5.3 step 3. Indexed properties of typed arrays are special.
uint64_t index;
if (IsTypedArrayIndex(id, &index))
return result.succeed();
if (IsTypedArrayIndex(id, &index)) {
if (!cx->shouldBeJSContext())
return false;
return DefineTypedArrayElement(cx->asJSContext(), obj, index, desc_, result);
}
}
Rooted<PropertyDescriptor> desc(cx, desc_);

View File

@ -2105,6 +2105,51 @@ js::StringIsTypedArrayIndex(const char16_t* s, size_t length, uint64_t* indexp);
template bool
js::StringIsTypedArrayIndex(const Latin1Char* s, size_t length, uint64_t* indexp);
/* ES6 draft rev 34 (2015 Feb 20) 9.4.5.3 [[DefineOwnProperty]] step 3.c. */
bool
js::DefineTypedArrayElement(JSContext *cx, HandleObject obj, uint64_t index,
Handle<PropertyDescriptor> desc, ObjectOpResult &result)
{
MOZ_ASSERT(IsAnyTypedArray(obj));
// These are all substeps of 3.c.
// Steps i-vi.
// We (wrongly) ignore out of range defines with a value.
if (index >= AnyTypedArrayLength(obj))
return result.succeed();
// Step vii.
if (desc.isAccessorDescriptor())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
// Step viii.
if (desc.hasConfigurable() && desc.configurable())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
// Step ix.
if (desc.hasEnumerable() && !desc.enumerable())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
// Step x.
if (desc.hasWritable() && !desc.writable())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
// Step xi.
if (desc.hasValue()) {
double d;
if (!ToNumber(cx, desc.value(), &d))
return false;
if (obj->is<TypedArrayObject>())
TypedArrayObject::setElement(obj->as<TypedArrayObject>(), index, d);
else
SharedTypedArrayObject::setElement(obj->as<SharedTypedArrayObject>(), index, d);
}
// Step xii.
return result.succeed();
}
/* JS Friend API */
JS_FRIEND_API(bool)

View File

@ -277,6 +277,14 @@ IsTypedArrayIndex(jsid id, uint64_t* indexp)
return StringIsTypedArrayIndex(s, length, indexp);
}
/*
* Implements [[DefineOwnProperty]] for TypedArrays and SharedTypedArrays
* when the property key is a TypedArray index.
*/
bool
DefineTypedArrayElement(JSContext *cx, HandleObject arr, uint64_t index,
Handle<PropertyDescriptor> desc, ObjectOpResult &result);
static inline unsigned
TypedArrayShift(Scalar::Type viewType)
{