mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 03:37:43 +00:00
LibJS: Update spec numbers / text for the Change Array by Copy proposal
This proposal has been merged into the main ECMA-262 spec. See:
4a32716
Note this includes some editorial changes made when the proposal was
merged into the main spec, but are not in the proposal spec.
This commit is contained in:
parent
f794b08548
commit
e945994877
5 changed files with 133 additions and 128 deletions
|
@ -156,7 +156,60 @@ ThrowCompletionOr<bool> Array::set_length(PropertyDescriptor const& property_des
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1.1.1.2 CompareArrayElements ( x, y, comparefn ), https://tc39.es/proposal-change-array-by-copy/#sec-comparearrayelements
|
// 23.1.3.30.1 SortIndexedProperties ( obj, len, SortCompare, holes ), https://tc39.es/ecma262/#sec-sortindexedproperties
|
||||||
|
ThrowCompletionOr<MarkedVector<Value>> sort_indexed_properties(VM& vm, Object const& object, size_t length, Function<ThrowCompletionOr<double>(Value, Value)> const& sort_compare, Holes holes)
|
||||||
|
{
|
||||||
|
// 1. Let items be a new empty List.
|
||||||
|
auto items = MarkedVector<Value> { vm.heap() };
|
||||||
|
|
||||||
|
// 2. Let k be 0.
|
||||||
|
// 3. Repeat, while k < len,
|
||||||
|
for (size_t k = 0; k < length; ++k) {
|
||||||
|
// a. Let Pk be ! ToString(𝔽(k)).
|
||||||
|
auto property_key = PropertyKey { k };
|
||||||
|
|
||||||
|
bool k_read;
|
||||||
|
|
||||||
|
// b. If holes is skip-holes, then
|
||||||
|
if (holes == Holes::SkipHoles) {
|
||||||
|
// i. Let kRead be ? HasProperty(obj, Pk).
|
||||||
|
k_read = TRY(object.has_property(property_key));
|
||||||
|
}
|
||||||
|
// c. Else,
|
||||||
|
else {
|
||||||
|
// i. Assert: holes is read-through-holes.
|
||||||
|
VERIFY(holes == Holes::ReadThroughHoles);
|
||||||
|
|
||||||
|
// ii. Let kRead be true.
|
||||||
|
k_read = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// d. If kRead is true, then
|
||||||
|
if (k_read) {
|
||||||
|
// i. Let kValue be ? Get(obj, Pk).
|
||||||
|
auto k_value = TRY(object.get(property_key));
|
||||||
|
|
||||||
|
// ii. Append kValue to items.
|
||||||
|
items.append(k_value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// e. Set k to k + 1.
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Sort items using an implementation-defined sequence of calls to SortCompare. If any such call returns an abrupt completion, stop before performing any further calls to SortCompare or steps in this algorithm and return that Completion Record.
|
||||||
|
|
||||||
|
// Perform sorting by merge sort. This isn't as efficient compared to quick sort, but
|
||||||
|
// quicksort can't be used in all cases because the spec requires Array.prototype.sort()
|
||||||
|
// to be stable. FIXME: when initially scanning through the array, maintain a flag
|
||||||
|
// for if an unstable sort would be indistinguishable from a stable sort (such as just
|
||||||
|
// just strings or numbers), and in that case use quick sort instead for better performance.
|
||||||
|
TRY(array_merge_sort(vm, sort_compare, items));
|
||||||
|
|
||||||
|
// 5. Return items.
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 23.1.3.30.2 CompareArrayElements ( x, y, comparefn ), https://tc39.es/ecma262/#sec-comparearrayelements
|
||||||
ThrowCompletionOr<double> compare_array_elements(VM& vm, Value x, Value y, FunctionObject* comparefn)
|
ThrowCompletionOr<double> compare_array_elements(VM& vm, Value x, Value y, FunctionObject* comparefn)
|
||||||
{
|
{
|
||||||
// 1. If x and y are both undefined, return +0𝔽.
|
// 1. If x and y are both undefined, return +0𝔽.
|
||||||
|
@ -209,56 +262,6 @@ ThrowCompletionOr<double> compare_array_elements(VM& vm, Value x, Value y, Funct
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1.1.1.3 SortIndexedProperties ( obj, len, SortCompare, skipHoles ), https://tc39.es/proposal-change-array-by-copy/#sec-sortindexedproperties
|
|
||||||
ThrowCompletionOr<MarkedVector<Value>> sort_indexed_properties(VM& vm, Object const& object, size_t length, Function<ThrowCompletionOr<double>(Value, Value)> const& sort_compare, bool skip_holes)
|
|
||||||
{
|
|
||||||
// 1. Let items be a new empty List.
|
|
||||||
auto items = MarkedVector<Value> { vm.heap() };
|
|
||||||
|
|
||||||
// 2. Let k be 0.
|
|
||||||
// 3. Repeat, while k < len,
|
|
||||||
for (size_t k = 0; k < length; ++k) {
|
|
||||||
// a. Let Pk be ! ToString(𝔽(k)).
|
|
||||||
auto property_key = PropertyKey { k };
|
|
||||||
|
|
||||||
bool k_read;
|
|
||||||
|
|
||||||
// b. If skipHoles is true, then
|
|
||||||
if (skip_holes) {
|
|
||||||
// i. Let kRead be ? HasProperty(obj, Pk).
|
|
||||||
k_read = TRY(object.has_property(property_key));
|
|
||||||
}
|
|
||||||
// c. Else,
|
|
||||||
else {
|
|
||||||
// i. Let kRead be true.
|
|
||||||
k_read = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// d. If kRead is true, then
|
|
||||||
if (k_read) {
|
|
||||||
// i. Let kValue be ? Get(obj, Pk).
|
|
||||||
auto k_value = TRY(object.get(property_key));
|
|
||||||
|
|
||||||
// ii. Append kValue to items.
|
|
||||||
items.append(k_value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// e. Set k to k + 1.
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Sort items using an implementation-defined sequence of calls to SortCompare. If any such call returns an abrupt completion, stop before performing any further calls to SortCompare or steps in this algorithm and return that Completion Record.
|
|
||||||
|
|
||||||
// Perform sorting by merge sort. This isn't as efficient compared to quick sort, but
|
|
||||||
// quicksort can't be used in all cases because the spec requires Array.prototype.sort()
|
|
||||||
// to be stable. FIXME: when initially scanning through the array, maintain a flag
|
|
||||||
// for if an unstable sort would be indistinguishable from a stable sort (such as just
|
|
||||||
// just strings or numbers), and in that case use quick sort instead for better performance.
|
|
||||||
TRY(array_merge_sort(vm, sort_compare, items));
|
|
||||||
|
|
||||||
// 5. Return items.
|
|
||||||
return items;
|
|
||||||
}
|
|
||||||
|
|
||||||
// NON-STANDARD: Used to return the value of the ephemeral length property
|
// NON-STANDARD: Used to return the value of the ephemeral length property
|
||||||
ThrowCompletionOr<Optional<PropertyDescriptor>> Array::internal_get_own_property(PropertyKey const& property_key) const
|
ThrowCompletionOr<Optional<PropertyDescriptor>> Array::internal_get_own_property(PropertyKey const& property_key) const
|
||||||
{
|
{
|
||||||
|
|
|
@ -69,7 +69,12 @@ private:
|
||||||
bool m_length_writable { true };
|
bool m_length_writable { true };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class Holes {
|
||||||
|
SkipHoles,
|
||||||
|
ReadThroughHoles,
|
||||||
|
};
|
||||||
|
|
||||||
|
ThrowCompletionOr<MarkedVector<Value>> sort_indexed_properties(VM&, Object const&, size_t length, Function<ThrowCompletionOr<double>(Value, Value)> const& sort_compare, Holes holes);
|
||||||
ThrowCompletionOr<double> compare_array_elements(VM&, Value x, Value y, FunctionObject* comparefn);
|
ThrowCompletionOr<double> compare_array_elements(VM&, Value x, Value y, FunctionObject* comparefn);
|
||||||
ThrowCompletionOr<MarkedVector<Value>> sort_indexed_properties(VM&, Object const&, size_t length, Function<ThrowCompletionOr<double>(Value, Value)> const& sort_compare, bool skip_holes);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,12 +83,11 @@ ThrowCompletionOr<void> ArrayPrototype::initialize(Realm& realm)
|
||||||
// Use define_direct_property here instead of define_native_function so that
|
// Use define_direct_property here instead of define_native_function so that
|
||||||
// Object.is(Array.prototype[Symbol.iterator], Array.prototype.values)
|
// Object.is(Array.prototype[Symbol.iterator], Array.prototype.values)
|
||||||
// evaluates to true
|
// evaluates to true
|
||||||
// 23.1.3.36 Array.prototype [ @@iterator ] ( ), https://tc39.es/ecma262/#sec-array.prototype-@@iterator
|
// 23.1.3.40 Array.prototype [ @@iterator ] ( ), https://tc39.es/ecma262/#sec-array.prototype-@@iterator
|
||||||
define_direct_property(*vm.well_known_symbol_iterator(), get_without_side_effects(vm.names.values), attr);
|
define_direct_property(*vm.well_known_symbol_iterator(), get_without_side_effects(vm.names.values), attr);
|
||||||
|
|
||||||
// 23.1.3.37 Array.prototype [ @@unscopables ], https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
|
// 23.1.3.41 Array.prototype [ @@unscopables ], https://tc39.es/ecma262/#sec-array.prototype-@@unscopables
|
||||||
// With array grouping proposal, https://tc39.es/proposal-array-grouping/#sec-array.prototype-@@unscopables
|
// With array grouping proposal, https://tc39.es/proposal-array-grouping/#sec-array.prototype-@@unscopables
|
||||||
// With change array by copy proposal, https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype-@@unscopables
|
|
||||||
auto unscopable_list = Object::create(realm, nullptr);
|
auto unscopable_list = Object::create(realm, nullptr);
|
||||||
MUST(unscopable_list->create_data_property_or_throw(vm.names.at, Value(true)));
|
MUST(unscopable_list->create_data_property_or_throw(vm.names.at, Value(true)));
|
||||||
MUST(unscopable_list->create_data_property_or_throw(vm.names.copyWithin, Value(true)));
|
MUST(unscopable_list->create_data_property_or_throw(vm.names.copyWithin, Value(true)));
|
||||||
|
@ -1558,7 +1557,6 @@ ThrowCompletionOr<void> array_merge_sort(VM& vm, Function<ThrowCompletionOr<doub
|
||||||
}
|
}
|
||||||
|
|
||||||
// 23.1.3.30 Array.prototype.sort ( comparefn ), https://tc39.es/ecma262/#sec-array.prototype.sort
|
// 23.1.3.30 Array.prototype.sort ( comparefn ), https://tc39.es/ecma262/#sec-array.prototype.sort
|
||||||
// 1.1.1.1 Array.prototype.sort ( comparefn ), https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.sort
|
|
||||||
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::sort)
|
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::sort)
|
||||||
{
|
{
|
||||||
// 1. If comparefn is not undefined and IsCallable(comparefn) is false, throw a TypeError exception.
|
// 1. If comparefn is not undefined and IsCallable(comparefn) is false, throw a TypeError exception.
|
||||||
|
@ -1578,31 +1576,31 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::sort)
|
||||||
return TRY(compare_array_elements(vm, x, y, comparefn.is_undefined() ? nullptr : &comparefn.as_function()));
|
return TRY(compare_array_elements(vm, x, y, comparefn.is_undefined() ? nullptr : &comparefn.as_function()));
|
||||||
};
|
};
|
||||||
|
|
||||||
// 6. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, true).
|
// 5. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, skip-holes).
|
||||||
auto sorted_list = TRY(sort_indexed_properties(vm, *object, length, sort_compare, true));
|
auto sorted_list = TRY(sort_indexed_properties(vm, *object, length, sort_compare, Holes::SkipHoles));
|
||||||
|
|
||||||
// 7. Let itemCount be the number of elements in sortedList.
|
// 6. Let itemCount be the number of elements in sortedList.
|
||||||
auto item_count = sorted_list.size();
|
auto item_count = sorted_list.size();
|
||||||
|
|
||||||
// 8. Let j be 0.
|
// 7. Let j be 0.
|
||||||
size_t j = 0;
|
size_t j = 0;
|
||||||
|
|
||||||
// 9. Repeat, while j < itemCount,
|
// 8. Repeat, while j < itemCount,
|
||||||
for (; j < item_count; ++j) {
|
for (; j < item_count; ++j) {
|
||||||
// a. Perform ? Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
|
// a. Perform ? Set(obj, ! ToString(𝔽(j)), sortedList[j], true).
|
||||||
TRY(object->set(j, sorted_list[j], Object::ShouldThrowExceptions::Yes));
|
TRY(object->set(j, sorted_list[j], Object::ShouldThrowExceptions::Yes));
|
||||||
// b. Set j to j + 1.
|
// b. Set j to j + 1.
|
||||||
}
|
}
|
||||||
|
|
||||||
// 10. NOTE: The call to SortIndexedProperties in step 6 has the skipHoles parameter set to true. The remaining indexes are deleted to preserve the number of holes that were detected and excluded from the sort.
|
// 9. NOTE: The call to SortIndexedProperties in step 5 uses skip-holes. The remaining indices are deleted to preserve the number of holes that were detected and excluded from the sort.
|
||||||
// 11. Repeat, while j < len,
|
// 10. Repeat, while j < len,
|
||||||
for (; j < length; ++j) {
|
for (; j < length; ++j) {
|
||||||
// a. Perform ? DeletePropertyOrThrow(obj, ! ToString(𝔽(j))).
|
// a. Perform ? DeletePropertyOrThrow(obj, ! ToString(𝔽(j))).
|
||||||
TRY(object->delete_property_or_throw(j));
|
TRY(object->delete_property_or_throw(j));
|
||||||
// b. Set j to j + 1.
|
// b. Set j to j + 1.
|
||||||
}
|
}
|
||||||
|
|
||||||
// 12. Return obj.
|
// 11. Return obj.
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1748,7 +1746,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_locale_string)
|
||||||
return PrimitiveString::create(vm, builder.to_deprecated_string());
|
return PrimitiveString::create(vm, builder.to_deprecated_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1.1.1.4 Array.prototype.toReversed ( ), https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.toReversed
|
// 23.1.3.33 Array.prototype.toReversed ( ), https://tc39.es/ecma262/#sec-array.prototype.toreversed
|
||||||
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_reversed)
|
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_reversed)
|
||||||
{
|
{
|
||||||
auto& realm = *vm.current_realm();
|
auto& realm = *vm.current_realm();
|
||||||
|
@ -1784,7 +1782,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_reversed)
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1.1.1.5 Array.prototype.toSorted ( comparefn ), https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.toSorted
|
// 23.1.3.34 Array.prototype.toSorted ( comparefn ), https://tc39.es/ecma262/#sec-array.prototype.tosorted
|
||||||
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_sorted)
|
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_sorted)
|
||||||
{
|
{
|
||||||
auto& realm = *vm.current_realm();
|
auto& realm = *vm.current_realm();
|
||||||
|
@ -1810,8 +1808,8 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_sorted)
|
||||||
return TRY(compare_array_elements(vm, x, y, comparefn.is_undefined() ? nullptr : &comparefn.as_function()));
|
return TRY(compare_array_elements(vm, x, y, comparefn.is_undefined() ? nullptr : &comparefn.as_function()));
|
||||||
};
|
};
|
||||||
|
|
||||||
// 6. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, false).
|
// 6. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
|
||||||
auto sorted_list = TRY(sort_indexed_properties(vm, *object, length, sort_compare, false));
|
auto sorted_list = TRY(sort_indexed_properties(vm, *object, length, sort_compare, Holes::ReadThroughHoles));
|
||||||
|
|
||||||
// 7. Let j be 0.
|
// 7. Let j be 0.
|
||||||
// 8. Repeat, while j < len,
|
// 8. Repeat, while j < len,
|
||||||
|
@ -1826,13 +1824,13 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_sorted)
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1.1.1.6 Array.prototype.toSpliced ( start, deleteCount, ...items ), https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.toSpliced
|
// 23.1.3.35 Array.prototype.toSpliced ( start, skipCount, ...items ), https://tc39.es/ecma262/#sec-array.prototype.tospliced
|
||||||
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_spliced)
|
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_spliced)
|
||||||
{
|
{
|
||||||
auto& realm = *vm.current_realm();
|
auto& realm = *vm.current_realm();
|
||||||
|
|
||||||
auto start = vm.argument(0);
|
auto start = vm.argument(0);
|
||||||
auto delete_count = vm.argument(1);
|
auto skip_count = vm.argument(1);
|
||||||
|
|
||||||
// 1. Let O be ? ToObject(this value).
|
// 1. Let O be ? ToObject(this value).
|
||||||
auto* object = TRY(vm.this_value().to_object(vm));
|
auto* object = TRY(vm.this_value().to_object(vm));
|
||||||
|
@ -1861,32 +1859,32 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_spliced)
|
||||||
// 7. Let insertCount be the number of elements in items.
|
// 7. Let insertCount be the number of elements in items.
|
||||||
auto insert_count = vm.argument_count() >= 2 ? vm.argument_count() - 2 : 0;
|
auto insert_count = vm.argument_count() >= 2 ? vm.argument_count() - 2 : 0;
|
||||||
|
|
||||||
size_t actual_delete_count;
|
size_t actual_skip_count;
|
||||||
|
|
||||||
// 8. If start is not present, then
|
// 8. If start is not present, then
|
||||||
if (vm.argument_count() == 0) {
|
if (vm.argument_count() == 0) {
|
||||||
// a. Let actualDeleteCount be 0.
|
// a. Let actualSkipCount be 0.
|
||||||
actual_delete_count = 0;
|
actual_skip_count = 0;
|
||||||
}
|
}
|
||||||
// 9. Else if deleteCount is not present, then
|
// 9. Else if deleteCount is not present, then
|
||||||
else if (vm.argument_count() == 1) {
|
else if (vm.argument_count() == 1) {
|
||||||
// a. Let actualDeleteCount be len - actualStart.
|
// a. Let actualSkipCount be len - actualStart.
|
||||||
actual_delete_count = length - actual_start;
|
actual_skip_count = length - actual_start;
|
||||||
}
|
}
|
||||||
// 10. Else,
|
// 10. Else,
|
||||||
else {
|
else {
|
||||||
// a. Let dc be ? ToIntegerOrInfinity(deleteCount).
|
// a. Let sc be ? ToIntegerOrInfinity(skipCount).
|
||||||
auto dc = TRY(delete_count.to_integer_or_infinity(vm));
|
auto sc = TRY(skip_count.to_integer_or_infinity(vm));
|
||||||
|
|
||||||
// b. Let actualDeleteCount be the result of clamping dc between 0 and len - actualStart.
|
// b. Let actualSkipCount be the result of clamping sc between 0 and len - actualStart.
|
||||||
actual_delete_count = static_cast<size_t>(clamp(dc, 0, static_cast<double>(length - actual_start)));
|
actual_skip_count = static_cast<size_t>(clamp(sc, 0, static_cast<double>(length - actual_start)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sanity check
|
// Sanity check
|
||||||
VERIFY(actual_delete_count <= (length - actual_start));
|
VERIFY(actual_skip_count <= (length - actual_start));
|
||||||
|
|
||||||
// 11. Let newLen be len + insertCount - actualDeleteCount.
|
// 11. Let newLen be len + insertCount - actualSkipCount.
|
||||||
auto new_length_double = static_cast<double>(length) + static_cast<double>(insert_count) - static_cast<double>(actual_delete_count);
|
auto new_length_double = static_cast<double>(length) + static_cast<double>(insert_count) - static_cast<double>(actual_skip_count);
|
||||||
|
|
||||||
// 12. If newLen > 2^53 - 1, throw a TypeError exception.
|
// 12. If newLen > 2^53 - 1, throw a TypeError exception.
|
||||||
if (new_length_double > MAX_ARRAY_LIKE_INDEX)
|
if (new_length_double > MAX_ARRAY_LIKE_INDEX)
|
||||||
|
@ -1900,8 +1898,8 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_spliced)
|
||||||
// 14. Let i be 0.
|
// 14. Let i be 0.
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
|
||||||
// 15. Let r be actualStart + actualDeleteCount.
|
// 15. Let r be actualStart + actualSkipCount.
|
||||||
auto r = actual_start + actual_delete_count;
|
auto r = actual_start + actual_skip_count;
|
||||||
|
|
||||||
// 16. Repeat, while i < actualStart,
|
// 16. Repeat, while i < actualStart,
|
||||||
while (i < actual_start) {
|
while (i < actual_start) {
|
||||||
|
@ -1957,7 +1955,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_spliced)
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 23.1.3.33 Array.prototype.toString ( ), https://tc39.es/ecma262/#sec-array.prototype.tostring
|
// 23.1.3.36 Array.prototype.toString ( ), https://tc39.es/ecma262/#sec-array.prototype.tostring
|
||||||
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_string)
|
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_string)
|
||||||
{
|
{
|
||||||
auto& realm = *vm.current_realm();
|
auto& realm = *vm.current_realm();
|
||||||
|
@ -1976,7 +1974,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::to_string)
|
||||||
return TRY(call(vm, func.as_function(), array));
|
return TRY(call(vm, func.as_function(), array));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 23.1.3.34 Array.prototype.unshift ( ...items ), https://tc39.es/ecma262/#sec-array.prototype.unshift
|
// 23.1.3.37 Array.prototype.unshift ( ...items ), https://tc39.es/ecma262/#sec-array.prototype.unshift
|
||||||
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::unshift)
|
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::unshift)
|
||||||
{
|
{
|
||||||
auto* this_object = TRY(vm.this_value().to_object(vm));
|
auto* this_object = TRY(vm.this_value().to_object(vm));
|
||||||
|
@ -2008,7 +2006,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::unshift)
|
||||||
return Value(new_length);
|
return Value(new_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 23.1.3.35 Array.prototype.values ( ), https://tc39.es/ecma262/#sec-array.prototype.values
|
// 23.1.3.38 Array.prototype.values ( ), https://tc39.es/ecma262/#sec-array.prototype.values
|
||||||
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::values)
|
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::values)
|
||||||
{
|
{
|
||||||
auto& realm = *vm.current_realm();
|
auto& realm = *vm.current_realm();
|
||||||
|
@ -2018,7 +2016,7 @@ JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::values)
|
||||||
return ArrayIterator::create(realm, this_object, Object::PropertyKind::Value);
|
return ArrayIterator::create(realm, this_object, Object::PropertyKind::Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1.1.1.7 Array.prototype.with ( index, value ), https://tc39.es/proposal-change-array-by-copy/#sec-array.prototype.with
|
// 23.1.3.39 Array.prototype.with ( index, value ), https://tc39.es/ecma262/#sec-array.prototype.with
|
||||||
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::with)
|
JS_DEFINE_NATIVE_FUNCTION(ArrayPrototype::with)
|
||||||
{
|
{
|
||||||
auto& realm = *vm.current_realm();
|
auto& realm = *vm.current_realm();
|
||||||
|
|
|
@ -27,7 +27,7 @@ ThrowCompletionOr<TypedArrayBase*> typed_array_from(VM& vm, Value typed_array_va
|
||||||
return static_cast<TypedArrayBase*>(this_object);
|
return static_cast<TypedArrayBase*>(this_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 23.2.4.3 ValidateTypedArray ( O ), https://tc39.es/ecma262/#sec-validatetypedarray
|
// 23.2.4.4 ValidateTypedArray ( O ), https://tc39.es/ecma262/#sec-validatetypedarray
|
||||||
ThrowCompletionOr<void> validate_typed_array(VM& vm, TypedArrayBase& typed_array)
|
ThrowCompletionOr<void> validate_typed_array(VM& vm, TypedArrayBase& typed_array)
|
||||||
{
|
{
|
||||||
// 1. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
|
// 1. Perform ? RequireInternalSlot(O, [[TypedArrayName]]).
|
||||||
|
@ -340,25 +340,24 @@ ThrowCompletionOr<TypedArrayBase*> typed_array_create(VM& vm, FunctionObject& co
|
||||||
return &typed_array;
|
return &typed_array;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1.2.1.1 TypedArrayCreateSameType ( exemplar, argumentList ) https://tc39.es/proposal-change-array-by-copy/#typedarray-create-same-type
|
// 23.2.4.3 TypedArrayCreateSameType ( exemplar, argumentList ), https://tc39.es/ecma262/#sec-typedarray-create-same-type
|
||||||
ThrowCompletionOr<TypedArrayBase*> typed_array_create_same_type(VM& vm, TypedArrayBase const& exemplar, MarkedVector<Value> arguments)
|
ThrowCompletionOr<TypedArrayBase*> typed_array_create_same_type(VM& vm, TypedArrayBase const& exemplar, MarkedVector<Value> arguments)
|
||||||
{
|
{
|
||||||
auto& realm = *vm.current_realm();
|
auto& realm = *vm.current_realm();
|
||||||
|
|
||||||
// 1. Assert: exemplar is an Object that has [[TypedArrayName]] and [[ContentType]] internal slots.
|
// 1. Let constructor be the intrinsic object associated with the constructor name exemplar.[[TypedArrayName]] in Table 68.
|
||||||
// 2. Let constructor be the intrinsic object listed in column one of Table 63 (points to Table 72) for exemplar.[[TypedArrayName]].
|
|
||||||
auto* constructor = (realm.intrinsics().*exemplar.intrinsic_constructor())();
|
auto* constructor = (realm.intrinsics().*exemplar.intrinsic_constructor())();
|
||||||
|
|
||||||
// 3. Let result be ? TypedArrayCreate(constructor, argumentList).
|
// 2. Let result be ? TypedArrayCreate(constructor, argumentList).
|
||||||
auto* result = TRY(typed_array_create(vm, *constructor, move(arguments)));
|
auto* result = TRY(typed_array_create(vm, *constructor, move(arguments)));
|
||||||
|
|
||||||
// 4. Assert: result has [[TypedArrayName]] and [[ContentType]] internal slots.
|
// 3. Assert: result has [[TypedArrayName]] and [[ContentType]] internal slots.
|
||||||
// 5. Assert: result.[[ContentType]] is exemplar.[[ContentType]].
|
// 4. Assert: result.[[ContentType]] is exemplar.[[ContentType]].
|
||||||
// 6. Return result.
|
// 5. Return result.
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1.2.2.1.2 CompareTypedArrayElements ( x, y, comparefn ), https://tc39.es/proposal-change-array-by-copy/#sec-comparetypedarrayelements
|
// 23.2.4.7 CompareTypedArrayElements ( x, y, comparefn ), https://tc39.es/ecma262/#sec-typedarray-create-same-type
|
||||||
ThrowCompletionOr<double> compare_typed_array_elements(VM& vm, Value x, Value y, FunctionObject* comparefn)
|
ThrowCompletionOr<double> compare_typed_array_elements(VM& vm, Value x, Value y, FunctionObject* comparefn)
|
||||||
{
|
{
|
||||||
// 1. Assert: x is a Number and y is a Number, or x is a BigInt and y is a BigInt.
|
// 1. Assert: x is a Number and y is a Number, or x is a BigInt and y is a BigInt.
|
||||||
|
|
|
@ -65,10 +65,10 @@ ThrowCompletionOr<void> TypedArrayPrototype::initialize(Realm& realm)
|
||||||
|
|
||||||
define_native_accessor(realm, *vm.well_known_symbol_to_string_tag(), to_string_tag_getter, nullptr, Attribute::Configurable);
|
define_native_accessor(realm, *vm.well_known_symbol_to_string_tag(), to_string_tag_getter, nullptr, Attribute::Configurable);
|
||||||
|
|
||||||
// 23.2.3.32 %TypedArray%.prototype.toString ( ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.tostring
|
// 23.2.3.34 %TypedArray%.prototype.toString ( ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.tostring
|
||||||
define_direct_property(vm.names.toString, realm.intrinsics().array_prototype()->get_without_side_effects(vm.names.toString), attr);
|
define_direct_property(vm.names.toString, realm.intrinsics().array_prototype()->get_without_side_effects(vm.names.toString), attr);
|
||||||
|
|
||||||
// 23.2.3.34 %TypedArray%.prototype [ @@iterator ] ( ), https://tc39.es/ecma262/#sec-%typedarray%.prototype-@@iterator
|
// 23.2.3.37 %TypedArray%.prototype [ @@iterator ] ( ), https://tc39.es/ecma262/#sec-%typedarray%.prototype-@@iterator
|
||||||
define_direct_property(*vm.well_known_symbol_iterator(), get_without_side_effects(vm.names.values), attr);
|
define_direct_property(*vm.well_known_symbol_iterator(), get_without_side_effects(vm.names.values), attr);
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -1404,7 +1404,6 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::some)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 23.2.3.29 %TypedArray%.prototype.sort ( comparefn ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.sort
|
// 23.2.3.29 %TypedArray%.prototype.sort ( comparefn ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.sort
|
||||||
// 1.2.2.1.1 %TypedArray%.prototype.sort ( comparefn ), https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.sort
|
|
||||||
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::sort)
|
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::sort)
|
||||||
{
|
{
|
||||||
// 1. If comparefn is not undefined and IsCallable(comparefn) is false, throw a TypeError exception.
|
// 1. If comparefn is not undefined and IsCallable(comparefn) is false, throw a TypeError exception.
|
||||||
|
@ -1426,8 +1425,8 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::sort)
|
||||||
return TRY(compare_typed_array_elements(vm, x, y, compare_fn.is_undefined() ? nullptr : &compare_fn.as_function()));
|
return TRY(compare_typed_array_elements(vm, x, y, compare_fn.is_undefined() ? nullptr : &compare_fn.as_function()));
|
||||||
};
|
};
|
||||||
|
|
||||||
// 7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, false).
|
// 7. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, read-through-holes).
|
||||||
auto sorted_list = TRY(sort_indexed_properties(vm, *typed_array, length, sort_compare, false));
|
auto sorted_list = TRY(sort_indexed_properties(vm, *typed_array, length, sort_compare, Holes::ReadThroughHoles));
|
||||||
|
|
||||||
// 8. Let j be 0.
|
// 8. Let j be 0.
|
||||||
// 9. Repeat, while j < len,
|
// 9. Repeat, while j < len,
|
||||||
|
@ -1571,7 +1570,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_locale_string)
|
||||||
return PrimitiveString::create(vm, builder.to_deprecated_string());
|
return PrimitiveString::create(vm, builder.to_deprecated_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1.2.2.1.3 %TypedArray%.prototype.toReversed ( ), https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.toReversed
|
// 23.2.3.32 %TypedArray%.prototype.toReversed ( ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.toreversed
|
||||||
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_reversed)
|
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_reversed)
|
||||||
{
|
{
|
||||||
// 1. Let O be the this value.
|
// 1. Let O be the this value.
|
||||||
|
@ -1608,7 +1607,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_reversed)
|
||||||
return return_array;
|
return return_array;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1.2.2.1.4 %TypedArray%.prototype.toSorted ( comparefn ), https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.toSorted
|
// 23.2.3.33 %TypedArray%.prototype.toSorted ( comparefn ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.tosorted
|
||||||
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_sorted)
|
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_sorted)
|
||||||
{
|
{
|
||||||
auto comparefn = vm.argument(0);
|
auto comparefn = vm.argument(0);
|
||||||
|
@ -1637,8 +1636,8 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_sorted)
|
||||||
return TRY(compare_typed_array_elements(vm, x, y, comparefn.is_undefined() ? nullptr : &comparefn.as_function()));
|
return TRY(compare_typed_array_elements(vm, x, y, comparefn.is_undefined() ? nullptr : &comparefn.as_function()));
|
||||||
};
|
};
|
||||||
|
|
||||||
// 8. Let sortedList be ? SortIndexedProperties(obj, len, SortCompare, false).
|
// 8. Let sortedList be ? SortIndexedProperties(O, len, SortCompare, read-through-holes).
|
||||||
auto sorted_list = TRY(sort_indexed_properties(vm, *object, length, sort_compare, false));
|
auto sorted_list = TRY(sort_indexed_properties(vm, *object, length, sort_compare, Holes::ReadThroughHoles));
|
||||||
|
|
||||||
// 9. Let j be 0.
|
// 9. Let j be 0.
|
||||||
// 10. Repeat, while j < len,
|
// 10. Repeat, while j < len,
|
||||||
|
@ -1651,7 +1650,20 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_sorted)
|
||||||
return return_array;
|
return return_array;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1.2.2.1.5 %TypedArray%.prototype.with ( index, value ), https://tc39.es/proposal-change-array-by-copy/#sec-%typedarray%.prototype.with
|
// 23.2.3.35 %TypedArray%.prototype.values ( ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.values
|
||||||
|
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::values)
|
||||||
|
{
|
||||||
|
auto& realm = *vm.current_realm();
|
||||||
|
|
||||||
|
// 1. Let O be the this value.
|
||||||
|
// 2. Perform ? ValidateTypedArray(O).
|
||||||
|
auto* typed_array = TRY(validate_typed_array_from_this(vm));
|
||||||
|
|
||||||
|
// 3. Return CreateArrayIterator(O, value).
|
||||||
|
return ArrayIterator::create(realm, typed_array, Object::PropertyKind::Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 23.2.3.36 %TypedArray%.prototype.with ( index, value ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.with
|
||||||
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::with)
|
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::with)
|
||||||
{
|
{
|
||||||
auto index = vm.argument(0);
|
auto index = vm.argument(0);
|
||||||
|
@ -1674,14 +1686,15 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::with)
|
||||||
else
|
else
|
||||||
actual_index = length + relative_index;
|
actual_index = length + relative_index;
|
||||||
|
|
||||||
// 7. If O.[[ContentType]] is BigInt, set value to ? ToBigInt(value).
|
Value numeric_value;
|
||||||
|
// 7. If O.[[ContentType]] is BigInt, let numericValue be ? ToBigInt(value).
|
||||||
if (typed_array->content_type() == TypedArrayBase::ContentType::BigInt)
|
if (typed_array->content_type() == TypedArrayBase::ContentType::BigInt)
|
||||||
value = TRY(value.to_bigint(vm));
|
numeric_value = TRY(value.to_bigint(vm));
|
||||||
// 8. Else, set value to ? ToNumber(value).
|
// 8. Else, let numericValue be ? ToNumber(value).
|
||||||
else
|
else
|
||||||
value = TRY(value.to_number(vm));
|
numeric_value = TRY(value.to_number(vm));
|
||||||
|
|
||||||
// 9. If ! IsValidIntegerIndex(O, 𝔽(actualIndex)) is false, throw a RangeError exception.
|
// 9. If IsValidIntegerIndex(O, 𝔽(actualIndex)) is false, throw a RangeError exception.
|
||||||
if (!is_valid_integer_index(*typed_array, TRY(CanonicalIndex::from_double(vm, CanonicalIndex::Type::Index, actual_index))))
|
if (!is_valid_integer_index(*typed_array, TRY(CanonicalIndex::from_double(vm, CanonicalIndex::Type::Index, actual_index))))
|
||||||
return vm.throw_completion<RangeError>(ErrorType::TypedArrayInvalidIntegerIndex, actual_index);
|
return vm.throw_completion<RangeError>(ErrorType::TypedArrayInvalidIntegerIndex, actual_index);
|
||||||
|
|
||||||
|
@ -1697,9 +1710,9 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::with)
|
||||||
auto property_key = PropertyKey { k };
|
auto property_key = PropertyKey { k };
|
||||||
|
|
||||||
Value from_value;
|
Value from_value;
|
||||||
// b. If k is actualIndex, let fromValue be value.
|
// b. If k is actualIndex, let fromValue be numericValue.
|
||||||
if (k == actual_index)
|
if (k == actual_index)
|
||||||
from_value = value;
|
from_value = numeric_value;
|
||||||
// c. Else, let fromValue be ! Get(O, Pk).
|
// c. Else, let fromValue be ! Get(O, Pk).
|
||||||
else
|
else
|
||||||
from_value = MUST(typed_array->get(property_key));
|
from_value = MUST(typed_array->get(property_key));
|
||||||
|
@ -1714,20 +1727,7 @@ JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::with)
|
||||||
return return_array;
|
return return_array;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 23.2.3.33 %TypedArray%.prototype.values ( ), https://tc39.es/ecma262/#sec-%typedarray%.prototype.values
|
// 23.2.3.38 get %TypedArray%.prototype [ @@toStringTag ], https://tc39.es/ecma262/#sec-get-%typedarray%.prototype-@@tostringtag
|
||||||
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::values)
|
|
||||||
{
|
|
||||||
auto& realm = *vm.current_realm();
|
|
||||||
|
|
||||||
// 1. Let O be the this value.
|
|
||||||
// 2. Perform ? ValidateTypedArray(O).
|
|
||||||
auto* typed_array = TRY(validate_typed_array_from_this(vm));
|
|
||||||
|
|
||||||
// 3. Return CreateArrayIterator(O, value).
|
|
||||||
return ArrayIterator::create(realm, typed_array, Object::PropertyKind::Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 23.2.3.35 get %TypedArray%.prototype [ @@toStringTag ], https://tc39.es/ecma262/#sec-get-%typedarray%.prototype-@@tostringtag
|
|
||||||
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_string_tag_getter)
|
JS_DEFINE_NATIVE_FUNCTION(TypedArrayPrototype::to_string_tag_getter)
|
||||||
{
|
{
|
||||||
auto this_value = vm.this_value();
|
auto this_value = vm.this_value();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue