Commit bc1a3820 authored by henrique.ferreiro's avatar henrique.ferreiro Committed by Commit bot

Implement DefineOwnProperty for TypedArrays

TypedArrays need specific checks before calling OrdinaryDefineOwnProperty.

BUG=v8:5328

Review-Url: https://codereview.chromium.org/2431223005
Cr-Commit-Position: refs/heads/master@{#41333}
parent a39522f4
......@@ -503,8 +503,8 @@ class ErrorUtils : public AllStatic {
T(InvalidStringLength, "Invalid string length") \
T(InvalidTimeValue, "Invalid time value") \
T(InvalidTypedArrayAlignment, "% of % should be a multiple of %") \
T(InvalidTypedArrayIndex, "Invalid typed array index") \
T(InvalidTypedArrayLength, "Invalid typed array length") \
T(InvalidTypedArrayOffset, "Start offset is too large:") \
T(InvalidSimdIndex, "Index out of bounds for SIMD operation") \
T(InvalidSimdLaneValue, "Lane value out of bounds for SIMD operation") \
T(LetInLexicalBinding, "let is disallowed as a lexically bound name") \
......
......@@ -6604,12 +6604,15 @@ Maybe<bool> JSReceiver::DefineOwnProperty(Isolate* isolate,
return JSProxy::DefineOwnProperty(isolate, Handle<JSProxy>::cast(object),
key, desc, should_throw);
}
if (object->IsJSTypedArray()) {
return JSTypedArray::DefineOwnProperty(
isolate, Handle<JSTypedArray>::cast(object), key, desc, should_throw);
}
// TODO(neis): Special case for JSModuleNamespace?
// OrdinaryDefineOwnProperty, by virtue of calling
// DefineOwnPropertyIgnoreAttributes, can handle arguments (ES6 9.4.4.2)
// and IntegerIndexedExotics (ES6 9.4.5.3), with one exception:
// TODO(jkummerow): Setting an indexed accessor on a typed array should throw.
// DefineOwnPropertyIgnoreAttributes, can handle arguments
// (ES#sec-arguments-exotic-objects-defineownproperty-p-desc).
return OrdinaryDefineOwnProperty(isolate, Handle<JSObject>::cast(object), key,
desc, should_throw);
}
......@@ -17557,6 +17560,98 @@ Handle<Object> JSObject::PrepareElementsForSort(Handle<JSObject> object,
return isolate->factory()->NewNumberFromUint(result);
}
namespace {
bool CanonicalNumericIndexString(Isolate* isolate, Handle<Object> s,
Handle<Object>* index) {
DCHECK(s->IsString() || s->IsSmi());
Handle<Object> result;
if (s->IsSmi()) {
result = s;
} else {
result = String::ToNumber(Handle<String>::cast(s));
if (!result->IsMinusZero()) {
Handle<String> str = Object::ToString(isolate, result).ToHandleChecked();
// Avoid treating strings like "2E1" and "20" as the same key.
if (!str->SameValue(*s)) return false;
}
}
*index = result;
return true;
}
} // anonymous namespace
// ES#sec-integer-indexed-exotic-objects-defineownproperty-p-desc
// static
Maybe<bool> JSTypedArray::DefineOwnProperty(Isolate* isolate,
Handle<JSTypedArray> o,
Handle<Object> key,
PropertyDescriptor* desc,
ShouldThrow should_throw) {
// 1. Assert: IsPropertyKey(P) is true.
DCHECK(key->IsName() || key->IsNumber());
// 2. Assert: O is an Object that has a [[ViewedArrayBuffer]] internal slot.
// 3. If Type(P) is String, then
if (key->IsString() || key->IsSmi()) {
// 3a. Let numericIndex be ! CanonicalNumericIndexString(P)
// 3b. If numericIndex is not undefined, then
Handle<Object> numeric_index;
if (CanonicalNumericIndexString(isolate, key, &numeric_index)) {
// 3b i. If IsInteger(numericIndex) is false, return false.
// 3b ii. If numericIndex = -0, return false.
// 3b iii. If numericIndex < 0, return false.
// FIXME: the standard allows up to 2^53 elements.
uint32_t index;
if (numeric_index->IsMinusZero() || !numeric_index->ToUint32(&index)) {
RETURN_FAILURE(isolate, should_throw,
NewTypeError(MessageTemplate::kInvalidTypedArrayIndex));
}
// 3b iv. Let length be O.[[ArrayLength]].
uint32_t length = o->length()->Number();
// 3b v. If numericIndex ≥ length, return false.
if (index >= length) {
RETURN_FAILURE(isolate, should_throw,
NewTypeError(MessageTemplate::kInvalidTypedArrayIndex));
}
// 3b vi. If IsAccessorDescriptor(Desc) is true, return false.
if (PropertyDescriptor::IsAccessorDescriptor(desc)) {
RETURN_FAILURE(isolate, should_throw,
NewTypeError(MessageTemplate::kRedefineDisallowed, key));
}
// 3b vii. If Desc has a [[Configurable]] field and if
// Desc.[[Configurable]] is true, return false.
// 3b viii. If Desc has an [[Enumerable]] field and if Desc.[[Enumerable]]
// is false, return false.
// 3b ix. If Desc has a [[Writable]] field and if Desc.[[Writable]] is
// false, return false.
if ((desc->has_configurable() && desc->configurable()) ||
(desc->has_enumerable() && !desc->enumerable()) ||
(desc->has_writable() && !desc->writable())) {
RETURN_FAILURE(isolate, should_throw,
NewTypeError(MessageTemplate::kRedefineDisallowed, key));
}
// 3b x. If Desc has a [[Value]] field, then
// 3b x 1. Let value be Desc.[[Value]].
// 3b x 2. Return ? IntegerIndexedElementSet(O, numericIndex, value).
if (desc->has_value()) {
if (!desc->has_configurable()) desc->set_configurable(false);
if (!desc->has_enumerable()) desc->set_enumerable(true);
if (!desc->has_writable()) desc->set_writable(true);
Handle<Object> value = desc->value();
RETURN_ON_EXCEPTION_VALUE(isolate,
SetOwnElementIgnoreAttributes(
o, index, value, desc->ToAttributes()),
Nothing<bool>());
}
// 3b xi. Return true.
return Just(true);
}
}
// 4. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
return OrdinaryDefineOwnProperty(isolate, o, key, desc, should_throw);
}
ExternalArrayType JSTypedArray::type() {
switch (elements()->map()->instance_type()) {
......
......@@ -11165,6 +11165,11 @@ class JSTypedArray: public JSArrayBufferView {
DECL_ACCESSORS(length, Object)
inline uint32_t length_value() const;
// ES6 9.4.5.3
MUST_USE_RESULT static Maybe<bool> DefineOwnProperty(
Isolate* isolate, Handle<JSTypedArray> o, Handle<Object> key,
PropertyDescriptor* desc, ShouldThrow should_throw);
DECLARE_CAST(JSTypedArray)
ExternalArrayType type();
......
......@@ -29,9 +29,15 @@
})();
(function () {
var o = new Int32Array();
Object.defineProperty(o, "0", {get: function(){}});
assertEquals(undefined, Object.getOwnPropertyDescriptor(o, "0"));
var o = new Int32Array(1);
assertThrows(
() => Object.defineProperty(o, '0', {get: function() {}}), TypeError);
assertEquals({
value: 0,
writable: true,
enumerable: true,
configurable: false
}, Object.getOwnPropertyDescriptor(o, "0"));
})();
(function() {
......
......@@ -418,13 +418,6 @@
'built-ins/TypedArrays/internals/Set/key-is-out-of-bounds': [FAIL],
'built-ins/TypedArrays/internals/Set/tonumber-value-throws': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=5328
'built-ins/TypedArrays/internals/DefineOwnProperty/key-is-numericindex-desc-not-writable': [FAIL],
'built-ins/TypedArrays/internals/DefineOwnProperty/key-is-not-integer': [FAIL],
'built-ins/TypedArrays/internals/DefineOwnProperty/key-is-minus-zero': [FAIL],
'built-ins/TypedArrays/internals/DefineOwnProperty/key-is-lower-than-zero': [FAIL],
'built-ins/TypedArrays/internals/DefineOwnProperty/key-is-greater-than-last-index': [FAIL],
# https://bugs.chromium.org/p/v8/issues/detail?id=5329
'built-ins/RegExp/prototype/source/value-line-terminator': [FAIL],
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment