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:
parent
9e111d3f28
commit
b91f929dbc
3
BUILD.gn
3
BUILD.gn
@ -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
27
src/builtins/array-at.tq
Normal 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
29
src/builtins/string-at.tq
Normal 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)));
|
||||
}
|
||||
}
|
28
src/builtins/typed-array-at.tq
Normal file
28
src/builtins/typed-array-at.tq
Normal 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);
|
||||
}
|
||||
}
|
@ -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:
|
||||
|
@ -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) \
|
||||
|
@ -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() {
|
||||
|
47
test/mjsunit/harmony/relative-indexing-methods.js
Normal file
47
test/mjsunit/harmony/relative-indexing-methods.js
Normal 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);
|
||||
}
|
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user