implement Array/String/TypedArray item methods

Bug: v8:10961
Change-Id: I79f8410cac1c949100231d4c57dbea0379e88475
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2441128
Commit-Queue: Gus Caplan <snek@chromium.org>
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
Reviewed-by: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#71279}
This commit is contained in:
Gus Caplan 2020-11-19 01:01:31 -06:00 committed by Commit Bot
parent 9e111d3f28
commit b91f929dbc
9 changed files with 194 additions and 22 deletions

View File

@ -1134,6 +1134,7 @@ action("postmortem-metadata") {
torque_files = [
"src/builtins/aggregate-error.tq",
"src/builtins/array-at.tq",
"src/builtins/array-copywithin.tq",
"src/builtins/array-every.tq",
"src/builtins/array-filter.tq",
@ -1216,6 +1217,7 @@ torque_files = [
"src/builtins/regexp-split.tq",
"src/builtins/regexp-test.tq",
"src/builtins/regexp.tq",
"src/builtins/string-at.tq",
"src/builtins/string-endswith.tq",
"src/builtins/string-html.tq",
"src/builtins/string-iterator.tq",
@ -1229,6 +1231,7 @@ torque_files = [
"src/builtins/string-trim.tq",
"src/builtins/symbol.tq",
"src/builtins/torque-internal.tq",
"src/builtins/typed-array-at.tq",
"src/builtins/typed-array-createtypedarray.tq",
"src/builtins/typed-array-every.tq",
"src/builtins/typed-array-entries.tq",

27
src/builtins/array-at.tq Normal file
View File

@ -0,0 +1,27 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
namespace array {
// https://tc39.es/proposal-item-method/#sec-array.prototype.at
transitioning javascript builtin ArrayPrototypeAt(
js-implicit context: NativeContext, receiver: JSAny)(index: JSAny): JSAny {
// 1. Let O be ? ToObject(this value).
const o = ToObject_Inline(context, receiver);
// 2. Let len be ? LengthOfArrayLike(O).
const len = GetLengthProperty(o);
// 3. Let relativeIndex be ? ToInteger(index).
const relativeIndex = ToInteger_Inline(index);
// 4. If relativeIndex ≥ 0, then
// a. Let k be relativeIndex.
// 5. Else,
// a. Let k be len + relativeIndex.
const k = relativeIndex >= 0 ? relativeIndex : len + relativeIndex;
// 6. If k < 0 or k ≥ len, then return undefined.
if (k < 0 || k >= len) {
return Undefined;
}
// 7. Return ? Get(O, ! ToString(k)).
return GetProperty(o, k);
}
}

29
src/builtins/string-at.tq Normal file
View File

@ -0,0 +1,29 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
namespace string {
// https://tc39.es/proposal-item-method/#sec-string.prototype.at
transitioning javascript builtin StringPrototypeAt(
js-implicit context: NativeContext, receiver: JSAny)(index: JSAny): JSAny {
// 1. Let O be ? RequireObjectCoercible(this value).
// 2. Let S be ? ToString(O).
const s = ToThisString(receiver, 'String.prototype.at');
// 3. Let len be the length of S.
const len = s.length_smi;
// 4. Let relativeIndex be ? ToInteger(index).
const relativeIndex = ToInteger_Inline(index);
// 5. If relativeIndex ≥ 0, then
// a. Let k be relativeIndex.
// 6. Else,
// a. Let k be len + relativeIndex.
const k = relativeIndex >= 0 ? relativeIndex : len + relativeIndex;
// 7. If k < 0 or k ≥ len, then return undefined.
if (k < 0 || k >= len) {
return Undefined;
}
// 8. Return the String value consisting of only the code unit at position k
// in S.
return StringFromSingleCharCode(StringCharCodeAt(s, Convert<uintptr>(k)));
}
}

View File

@ -0,0 +1,28 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
namespace typed_array {
// https://tc39.es/proposal-item-method/#sec-%typedarray%.prototype.at
transitioning javascript builtin TypedArrayPrototypeAt(
js-implicit context: NativeContext, receiver: JSAny)(index: JSAny): JSAny {
// 1. Let O be the this value.
// 2. Perform ? ValidateTypedArray(O).
const o = ValidateTypedArray(context, receiver, '%TypedArray%.prototype.at');
// 3. Let len be O.[[ArrayLength]].
const len = Convert<Number>(o.length);
// 4. Let relativeIndex be ? ToInteger(index).
const relativeIndex = ToInteger_Inline(index);
// 5. If relativeIndex ≥ 0, then
// a. Let k be relativeIndex.
// 6. Else,
// a. Let k be len + relativeIndex.
const k = relativeIndex >= 0 ? relativeIndex : len + relativeIndex;
// 7. If k < 0 or k ≥ len, then return undefined.
if (k < 0 || k >= len) {
return Undefined;
}
// 8. Return ? Get(O, ! ToString(k)).
return GetProperty(o, k);
}
}

View File

@ -567,6 +567,7 @@ DebugInfo::SideEffectState BuiltinGetSideEffectState(Builtins::Name id) {
case Builtins::kArrayIndexOf:
case Builtins::kArrayPrototypeValues:
case Builtins::kArrayIncludes:
case Builtins::kArrayPrototypeAt:
case Builtins::kArrayPrototypeEntries:
case Builtins::kArrayPrototypeFill:
case Builtins::kArrayPrototypeFind:
@ -592,6 +593,7 @@ DebugInfo::SideEffectState BuiltinGetSideEffectState(Builtins::Name id) {
case Builtins::kTrace:
// TypedArray builtins.
case Builtins::kTypedArrayConstructor:
case Builtins::kTypedArrayPrototypeAt:
case Builtins::kTypedArrayPrototypeBuffer:
case Builtins::kTypedArrayPrototypeByteLength:
case Builtins::kTypedArrayPrototypeByteOffset:
@ -759,6 +761,7 @@ DebugInfo::SideEffectState BuiltinGetSideEffectState(Builtins::Name id) {
case Builtins::kStringFromCodePoint:
case Builtins::kStringConstructor:
case Builtins::kStringPrototypeAnchor:
case Builtins::kStringPrototypeAt:
case Builtins::kStringPrototypeBig:
case Builtins::kStringPrototypeBlink:
case Builtins::kStringPrototypeBold:

View File

@ -253,7 +253,8 @@ DEFINE_IMPLICATION(harmony_weak_refs_with_cleanup_some, harmony_weak_refs)
V(harmony_weak_refs_with_cleanup_some, \
"harmony weak references with FinalizationRegistry.prototype.cleanupSome") \
V(harmony_regexp_match_indices, "harmony regexp match indices") \
V(harmony_import_assertions, "harmony import assertions")
V(harmony_import_assertions, "harmony import assertions") \
V(harmony_relative_indexing_methods, "harmony relative indexing methods")
#ifdef V8_INTL_SUPPORT
#define HARMONY_INPROGRESS(V) \

View File

@ -4391,6 +4391,40 @@ void Genesis::InitializeGlobal_regexp_linear_flag() {
native_context()->set_regexp_prototype_map(regexp_prototype->map());
}
void Genesis::InitializeGlobal_harmony_relative_indexing_methods() {
if (!FLAG_harmony_relative_indexing_methods) return;
{
Handle<JSFunction> array_function(native_context()->array_function(),
isolate());
Handle<JSObject> array_prototype(
JSObject::cast(array_function->instance_prototype()), isolate());
SimpleInstallFunction(isolate(), array_prototype, "at",
Builtins::kArrayPrototypeAt, 1, true);
}
{
Handle<JSFunction> string_function(native_context()->string_function(),
isolate());
Handle<JSObject> string_prototype(
JSObject::cast(string_function->instance_prototype()), isolate());
SimpleInstallFunction(isolate(), string_prototype, "at",
Builtins::kStringPrototypeAt, 1, true);
}
{
Handle<JSFunction> typed_array_function(
native_context()->typed_array_function(), isolate());
Handle<JSObject> typed_array_prototype(
JSObject::cast(typed_array_function->instance_prototype()), isolate());
SimpleInstallFunction(isolate(), typed_array_prototype, "at",
Builtins::kTypedArrayPrototypeAt, 1, true);
}
}
#ifdef V8_INTL_SUPPORT
void Genesis::InitializeGlobal_harmony_intl_segmenter() {

View File

@ -0,0 +1,47 @@
// Copyright 2020 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --harmony-relative-indexing-methods --allow-natives-syntax
'use strict';
[
[1, 2, 3],
'123',
new Uint8Array([1, 2, 3]),
].forEach((v) => {
assertEquals(v.at(0), v[0]);
assertEquals(v.at(-1), v[2]);
assertEquals(v.at(-4), undefined);
assertEquals(v.at(3), undefined);
assertEquals(v.at(1337), undefined);
assertEquals(v.at(-Infinity), undefined);
assertEquals(v.at(Infinity), undefined);
assertEquals(v.at(NaN), v[0]);
assertEquals(v.at(undefined), v[0])
assertEquals(v.at(), v[0]);
});
{
const props = ['length', '2'];
const proxy = new Proxy([1, 2, 3], {
get(t, p, r) {
assertEquals(p, props.shift());
return Reflect.get(t, p, r);
}
});
assertEquals(Array.prototype.at.call(proxy, -1), 3);
}
assertThrows(() => {
Uint8Array.prototype.at.call({});
}, TypeError);
{
const a = new Uint8Array([1, 2, 3]);
%ArrayBufferDetach(a.buffer);
assertThrows(() => {
a.at(0);
}, TypeError);
}

View File

@ -449,27 +449,27 @@ KNOWN_OBJECTS = {
("old_space", 0x02a71): "StringSplitCache",
("old_space", 0x02e79): "RegExpMultipleCache",
("old_space", 0x03281): "BuiltinsConstantsTable",
("old_space", 0x03661): "AsyncFunctionAwaitRejectSharedFun",
("old_space", 0x03689): "AsyncFunctionAwaitResolveSharedFun",
("old_space", 0x036b1): "AsyncGeneratorAwaitRejectSharedFun",
("old_space", 0x036d9): "AsyncGeneratorAwaitResolveSharedFun",
("old_space", 0x03701): "AsyncGeneratorYieldResolveSharedFun",
("old_space", 0x03729): "AsyncGeneratorReturnResolveSharedFun",
("old_space", 0x03751): "AsyncGeneratorReturnClosedRejectSharedFun",
("old_space", 0x03779): "AsyncGeneratorReturnClosedResolveSharedFun",
("old_space", 0x037a1): "AsyncIteratorValueUnwrapSharedFun",
("old_space", 0x037c9): "PromiseAllResolveElementSharedFun",
("old_space", 0x037f1): "PromiseAllSettledResolveElementSharedFun",
("old_space", 0x03819): "PromiseAllSettledRejectElementSharedFun",
("old_space", 0x03841): "PromiseAnyRejectElementSharedFun",
("old_space", 0x03869): "PromiseCapabilityDefaultRejectSharedFun",
("old_space", 0x03891): "PromiseCapabilityDefaultResolveSharedFun",
("old_space", 0x038b9): "PromiseCatchFinallySharedFun",
("old_space", 0x038e1): "PromiseGetCapabilitiesExecutorSharedFun",
("old_space", 0x03909): "PromiseThenFinallySharedFun",
("old_space", 0x03931): "PromiseThrowerFinallySharedFun",
("old_space", 0x03959): "PromiseValueThunkFinallySharedFun",
("old_space", 0x03981): "ProxyRevokeSharedFun",
("old_space", 0x03669): "AsyncFunctionAwaitRejectSharedFun",
("old_space", 0x03691): "AsyncFunctionAwaitResolveSharedFun",
("old_space", 0x036b9): "AsyncGeneratorAwaitRejectSharedFun",
("old_space", 0x036e1): "AsyncGeneratorAwaitResolveSharedFun",
("old_space", 0x03709): "AsyncGeneratorYieldResolveSharedFun",
("old_space", 0x03731): "AsyncGeneratorReturnResolveSharedFun",
("old_space", 0x03759): "AsyncGeneratorReturnClosedRejectSharedFun",
("old_space", 0x03781): "AsyncGeneratorReturnClosedResolveSharedFun",
("old_space", 0x037a9): "AsyncIteratorValueUnwrapSharedFun",
("old_space", 0x037d1): "PromiseAllResolveElementSharedFun",
("old_space", 0x037f9): "PromiseAllSettledResolveElementSharedFun",
("old_space", 0x03821): "PromiseAllSettledRejectElementSharedFun",
("old_space", 0x03849): "PromiseAnyRejectElementSharedFun",
("old_space", 0x03871): "PromiseCapabilityDefaultRejectSharedFun",
("old_space", 0x03899): "PromiseCapabilityDefaultResolveSharedFun",
("old_space", 0x038c1): "PromiseCatchFinallySharedFun",
("old_space", 0x038e9): "PromiseGetCapabilitiesExecutorSharedFun",
("old_space", 0x03911): "PromiseThenFinallySharedFun",
("old_space", 0x03939): "PromiseThrowerFinallySharedFun",
("old_space", 0x03961): "PromiseValueThunkFinallySharedFun",
("old_space", 0x03989): "ProxyRevokeSharedFun",
}
# Lower 32 bits of first page addresses for various heap spaces.