|
|
@ -1,3 +1,5 @@ |
|
|
|
|
|
|
|
use boa_macros::utf16; |
|
|
|
|
|
|
|
|
|
|
|
use crate::{ |
|
|
|
use crate::{ |
|
|
|
builtins::{array_buffer::SharedMemoryOrder, typed_array::integer_indexed_object::ContentType}, |
|
|
|
builtins::{array_buffer::SharedMemoryOrder, typed_array::integer_indexed_object::ContentType}, |
|
|
|
object::JsObject, |
|
|
|
object::JsObject, |
|
|
@ -39,7 +41,8 @@ pub(crate) fn integer_indexed_exotic_get_own_property( |
|
|
|
// 1. If Type(P) is String, then
|
|
|
|
// 1. If Type(P) is String, then
|
|
|
|
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
|
|
|
|
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
|
|
|
|
// b. If numericIndex is not undefined, then
|
|
|
|
// b. If numericIndex is not undefined, then
|
|
|
|
if let PropertyKey::Index(index) = key { |
|
|
|
match key { |
|
|
|
|
|
|
|
PropertyKey::Index(index) => { |
|
|
|
// i. Let value be ! IntegerIndexedElementGet(O, numericIndex).
|
|
|
|
// i. Let value be ! IntegerIndexedElementGet(O, numericIndex).
|
|
|
|
// ii. If value is undefined, return undefined.
|
|
|
|
// ii. If value is undefined, return undefined.
|
|
|
|
// iii. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }.
|
|
|
|
// iii. Return the PropertyDescriptor { [[Value]]: value, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }.
|
|
|
@ -53,11 +56,16 @@ pub(crate) fn integer_indexed_exotic_get_own_property( |
|
|
|
.build() |
|
|
|
.build() |
|
|
|
}), |
|
|
|
}), |
|
|
|
) |
|
|
|
) |
|
|
|
} else { |
|
|
|
} |
|
|
|
|
|
|
|
// The following step is taken from https://tc39.es/ecma262/#sec-isvalidintegerindex :
|
|
|
|
|
|
|
|
// Step 3. If index is -0𝔽, return false.
|
|
|
|
|
|
|
|
PropertyKey::String(string) if string == utf16!("-0") => Ok(None), |
|
|
|
|
|
|
|
key => { |
|
|
|
// 2. Return OrdinaryGetOwnProperty(O, P).
|
|
|
|
// 2. Return OrdinaryGetOwnProperty(O, P).
|
|
|
|
super::ordinary_get_own_property(obj, key, context) |
|
|
|
super::ordinary_get_own_property(obj, key, context) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// `[[HasProperty]]` internal method for Integer-Indexed exotic objects.
|
|
|
|
/// `[[HasProperty]]` internal method for Integer-Indexed exotic objects.
|
|
|
|
///
|
|
|
|
///
|
|
|
@ -72,14 +80,20 @@ pub(crate) fn integer_indexed_exotic_has_property( |
|
|
|
) -> JsResult<bool> { |
|
|
|
) -> JsResult<bool> { |
|
|
|
// 1. If Type(P) is String, then
|
|
|
|
// 1. If Type(P) is String, then
|
|
|
|
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
|
|
|
|
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
|
|
|
|
if let PropertyKey::Index(index) = key { |
|
|
|
match key { |
|
|
|
|
|
|
|
PropertyKey::Index(index) => { |
|
|
|
// b. If numericIndex is not undefined, return ! IsValidIntegerIndex(O, numericIndex).
|
|
|
|
// b. If numericIndex is not undefined, return ! IsValidIntegerIndex(O, numericIndex).
|
|
|
|
Ok(is_valid_integer_index(obj, u64::from(*index))) |
|
|
|
Ok(is_valid_integer_index(obj, u64::from(*index))) |
|
|
|
} else { |
|
|
|
} |
|
|
|
|
|
|
|
// The following step is taken from https://tc39.es/ecma262/#sec-isvalidintegerindex :
|
|
|
|
|
|
|
|
// Step 3. If index is -0𝔽, return false.
|
|
|
|
|
|
|
|
PropertyKey::String(string) if string == utf16!("-0") => Ok(false), |
|
|
|
|
|
|
|
key => { |
|
|
|
// 2. Return ? OrdinaryHasProperty(O, P).
|
|
|
|
// 2. Return ? OrdinaryHasProperty(O, P).
|
|
|
|
super::ordinary_has_property(obj, key, context) |
|
|
|
super::ordinary_has_property(obj, key, context) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// `[[DefineOwnProperty]]` internal method for Integer-Indexed exotic objects.
|
|
|
|
/// `[[DefineOwnProperty]]` internal method for Integer-Indexed exotic objects.
|
|
|
|
///
|
|
|
|
///
|
|
|
@ -96,7 +110,8 @@ pub(crate) fn integer_indexed_exotic_define_own_property( |
|
|
|
// 1. If Type(P) is String, then
|
|
|
|
// 1. If Type(P) is String, then
|
|
|
|
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
|
|
|
|
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
|
|
|
|
// b. If numericIndex is not undefined, then
|
|
|
|
// b. If numericIndex is not undefined, then
|
|
|
|
if let &PropertyKey::Index(index) = key { |
|
|
|
match key { |
|
|
|
|
|
|
|
&PropertyKey::Index(index) => { |
|
|
|
// i. If ! IsValidIntegerIndex(O, numericIndex) is false, return false.
|
|
|
|
// i. If ! IsValidIntegerIndex(O, numericIndex) is false, return false.
|
|
|
|
// ii. If Desc has a [[Configurable]] field and if Desc.[[Configurable]] is false, return false.
|
|
|
|
// ii. If Desc has a [[Configurable]] field and if Desc.[[Configurable]] is false, return false.
|
|
|
|
// iii. If Desc has an [[Enumerable]] field and if Desc.[[Enumerable]] is false, return false.
|
|
|
|
// iii. If Desc has an [[Enumerable]] field and if Desc.[[Enumerable]] is false, return false.
|
|
|
@ -120,11 +135,14 @@ pub(crate) fn integer_indexed_exotic_define_own_property( |
|
|
|
|
|
|
|
|
|
|
|
// vii. Return true.
|
|
|
|
// vii. Return true.
|
|
|
|
Ok(true) |
|
|
|
Ok(true) |
|
|
|
} else { |
|
|
|
} |
|
|
|
|
|
|
|
PropertyKey::String(string) if string == utf16!("-0") => Ok(false), |
|
|
|
|
|
|
|
key => { |
|
|
|
// 2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
|
|
|
|
// 2. Return ! OrdinaryDefineOwnProperty(O, P, Desc).
|
|
|
|
super::ordinary_define_own_property(obj, key, desc, context) |
|
|
|
super::ordinary_define_own_property(obj, key, desc, context) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Internal method `[[Get]]` for Integer-Indexed exotic objects.
|
|
|
|
/// Internal method `[[Get]]` for Integer-Indexed exotic objects.
|
|
|
|
///
|
|
|
|
///
|
|
|
@ -141,14 +159,20 @@ pub(crate) fn integer_indexed_exotic_get( |
|
|
|
// 1. If Type(P) is String, then
|
|
|
|
// 1. If Type(P) is String, then
|
|
|
|
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
|
|
|
|
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
|
|
|
|
// b. If numericIndex is not undefined, then
|
|
|
|
// b. If numericIndex is not undefined, then
|
|
|
|
if let PropertyKey::Index(index) = key { |
|
|
|
match key { |
|
|
|
|
|
|
|
PropertyKey::Index(index) => { |
|
|
|
// i. Return ! IntegerIndexedElementGet(O, numericIndex).
|
|
|
|
// i. Return ! IntegerIndexedElementGet(O, numericIndex).
|
|
|
|
Ok(integer_indexed_element_get(obj, u64::from(*index)).unwrap_or_default()) |
|
|
|
Ok(integer_indexed_element_get(obj, u64::from(*index)).unwrap_or_default()) |
|
|
|
} else { |
|
|
|
} |
|
|
|
|
|
|
|
// The following step is taken from https://tc39.es/ecma262/#sec-isvalidintegerindex :
|
|
|
|
|
|
|
|
// Step 3. If index is -0𝔽, return false.
|
|
|
|
|
|
|
|
PropertyKey::String(string) if string == utf16!("-0") => Ok(JsValue::undefined()), |
|
|
|
|
|
|
|
key => { |
|
|
|
// 2. Return ? OrdinaryGet(O, P, Receiver).
|
|
|
|
// 2. Return ? OrdinaryGet(O, P, Receiver).
|
|
|
|
super::ordinary_get(obj, key, receiver, context) |
|
|
|
super::ordinary_get(obj, key, receiver, context) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Internal method `[[Set]]` for Integer-Indexed exotic objects.
|
|
|
|
/// Internal method `[[Set]]` for Integer-Indexed exotic objects.
|
|
|
|
///
|
|
|
|
///
|
|
|
@ -166,17 +190,23 @@ pub(crate) fn integer_indexed_exotic_set( |
|
|
|
// 1. If Type(P) is String, then
|
|
|
|
// 1. If Type(P) is String, then
|
|
|
|
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
|
|
|
|
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
|
|
|
|
// b. If numericIndex is not undefined, then
|
|
|
|
// b. If numericIndex is not undefined, then
|
|
|
|
if let PropertyKey::Index(index) = key { |
|
|
|
match key { |
|
|
|
|
|
|
|
PropertyKey::Index(index) => { |
|
|
|
// i. Perform ? IntegerIndexedElementSet(O, numericIndex, V).
|
|
|
|
// i. Perform ? IntegerIndexedElementSet(O, numericIndex, V).
|
|
|
|
integer_indexed_element_set(obj, index as usize, &value, context)?; |
|
|
|
integer_indexed_element_set(obj, index as usize, &value, context)?; |
|
|
|
|
|
|
|
|
|
|
|
// ii. Return true.
|
|
|
|
// ii. Return true.
|
|
|
|
Ok(true) |
|
|
|
Ok(true) |
|
|
|
} else { |
|
|
|
} |
|
|
|
|
|
|
|
// The following step is taken from https://tc39.es/ecma262/#sec-isvalidintegerindex :
|
|
|
|
|
|
|
|
// Step 3. If index is -0𝔽, return false.
|
|
|
|
|
|
|
|
PropertyKey::String(string) if &string == utf16!("-0") => Ok(false), |
|
|
|
|
|
|
|
key => { |
|
|
|
// 2. Return ? OrdinarySet(O, P, V, Receiver).
|
|
|
|
// 2. Return ? OrdinarySet(O, P, V, Receiver).
|
|
|
|
super::ordinary_set(obj, key, value, receiver, context) |
|
|
|
super::ordinary_set(obj, key, value, receiver, context) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Internal method `[[Delete]]` for Integer-Indexed exotic objects.
|
|
|
|
/// Internal method `[[Delete]]` for Integer-Indexed exotic objects.
|
|
|
|
///
|
|
|
|
///
|
|
|
@ -192,14 +222,35 @@ pub(crate) fn integer_indexed_exotic_delete( |
|
|
|
// 1. If Type(P) is String, then
|
|
|
|
// 1. If Type(P) is String, then
|
|
|
|
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
|
|
|
|
// a. Let numericIndex be ! CanonicalNumericIndexString(P).
|
|
|
|
// b. If numericIndex is not undefined, then
|
|
|
|
// b. If numericIndex is not undefined, then
|
|
|
|
if let PropertyKey::Index(index) = key { |
|
|
|
match key { |
|
|
|
|
|
|
|
PropertyKey::Index(index) => { |
|
|
|
// i. If ! IsValidIntegerIndex(O, numericIndex) is false, return true; else return false.
|
|
|
|
// i. If ! IsValidIntegerIndex(O, numericIndex) is false, return true; else return false.
|
|
|
|
Ok(!is_valid_integer_index(obj, u64::from(*index))) |
|
|
|
Ok(!is_valid_integer_index(obj, u64::from(*index))) |
|
|
|
} else { |
|
|
|
} |
|
|
|
|
|
|
|
// The following step is taken from https://tc39.es/ecma262/#sec-isvalidintegerindex :
|
|
|
|
|
|
|
|
// Step 3. If index is -0𝔽, return false.
|
|
|
|
|
|
|
|
PropertyKey::String(string) if string == utf16!("-0") => { |
|
|
|
|
|
|
|
let obj = obj.borrow(); |
|
|
|
|
|
|
|
let inner = obj.as_typed_array().expect( |
|
|
|
|
|
|
|
"integer indexed exotic method should only be callable from integer indexed objects", |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
// 1. If IsValidIntegerIndex(O, numericIndex) is false, return true; else return false.
|
|
|
|
|
|
|
|
// From IsValidIntegerIndex:
|
|
|
|
|
|
|
|
// 1. If IsDetachedBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
|
|
|
|
|
|
|
|
// 3. If index is -0𝔽, return false.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// NOTE: They are negated, so it should return true.
|
|
|
|
|
|
|
|
if inner.is_detached() { |
|
|
|
|
|
|
|
return Ok(true); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
Ok(true) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
key => { |
|
|
|
// 2. Return ? OrdinaryDelete(O, P).
|
|
|
|
// 2. Return ? OrdinaryDelete(O, P).
|
|
|
|
super::ordinary_delete(obj, key, context) |
|
|
|
super::ordinary_delete(obj, key, context) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Internal method `[[OwnPropertyKeys]]` for Integer-Indexed exotic objects.
|
|
|
|
/// Internal method `[[OwnPropertyKeys]]` for Integer-Indexed exotic objects.
|
|
|
|
///
|
|
|
|
///
|
|
|
@ -263,10 +314,18 @@ pub(crate) fn is_valid_integer_index(obj: &JsObject, index: u64) -> bool { |
|
|
|
"integer indexed exotic method should only be callable from integer indexed objects", |
|
|
|
"integer indexed exotic method should only be callable from integer indexed objects", |
|
|
|
); |
|
|
|
); |
|
|
|
// 1. If IsDetachedBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
|
|
|
|
// 1. If IsDetachedBuffer(O.[[ViewedArrayBuffer]]) is true, return false.
|
|
|
|
// 2. If ! IsIntegralNumber(index) is false, return false.
|
|
|
|
//
|
|
|
|
// 3. If index is -0𝔽, return false.
|
|
|
|
// SKIPPED: 2. If ! IsIntegralNumber(index) is false, return false.
|
|
|
|
|
|
|
|
// NOTE: This step has already been done when we construct a PropertyKey.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// MOVED: 3. If index is -0𝔽, return false.
|
|
|
|
|
|
|
|
// NOTE: This step has been moved into the callers of this functions,
|
|
|
|
|
|
|
|
// once we get the index it is already converted into unsigned integer
|
|
|
|
|
|
|
|
// index, it cannot be `-0`.
|
|
|
|
|
|
|
|
|
|
|
|
// 4. If ℝ(index) < 0 or ℝ(index) ≥ O.[[ArrayLength]], return false.
|
|
|
|
// 4. If ℝ(index) < 0 or ℝ(index) ≥ O.[[ArrayLength]], return false.
|
|
|
|
// 5. Return true.
|
|
|
|
// 5. Return true.
|
|
|
|
|
|
|
|
|
|
|
|
!inner.is_detached() && index < inner.array_length() |
|
|
|
!inner.is_detached() && index < inner.array_length() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|