Commit 697d39ab authored by Mathias Bynens's avatar Mathias Bynens Committed by Commit Bot

[esnext] Implement Array.prototype.{flatten,flatMap} 🥙

Proposal repo: https://tc39.github.io/proposal-flatMap/

Bug: v8:7220
Cq-Include-Trybots: luci.v8.try:v8_linux_noi18n_rel_ng
Change-Id: I61661fc6d5c39d084ce5c96a9e150e5c26799e2d
Also-By: bmeurer@chromium.org
Reviewed-on: https://chromium-review.googlesource.com/957043
Commit-Queue: Mathias Bynens <mathias@chromium.org>
Reviewed-by: 's avatarSathya Gunasekaran <gsathya@chromium.org>
Reviewed-by: 's avatarBenedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#51967}
parent f8fb4a5c
......@@ -4251,6 +4251,17 @@ void Genesis::InitializeGlobal_harmony_array_prototype_values() {
NONE);
}
void Genesis::InitializeGlobal_harmony_array_flatten() {
if (!FLAG_harmony_array_flatten) return;
Handle<JSFunction> array_constructor(native_context()->array_function());
Handle<JSObject> array_prototype(
JSObject::cast(array_constructor->instance_prototype()));
SimpleInstallFunction(array_prototype, "flatten",
Builtins::kArrayPrototypeFlatten, 0, false, DONT_ENUM);
SimpleInstallFunction(array_prototype, "flatMap",
Builtins::kArrayPrototypeFlatMap, 1, false, DONT_ENUM);
}
void Genesis::InitializeGlobal_harmony_promise_finally() {
if (!FLAG_harmony_promise_finally) return;
......
This diff is collapsed.
......@@ -367,6 +367,14 @@ namespace internal {
TFJ(ArrayPrototypeValues, 0) \
/* ES6 #sec-%arrayiteratorprototype%.next */ \
TFJ(ArrayIteratorPrototypeNext, 0) \
/* https://tc39.github.io/proposal-flatMap/#sec-FlattenIntoArray */ \
TFS(FlattenIntoArray, kTarget, kSource, kSourceLength, kStart, kDepth) \
TFS(FlatMapIntoArray, kTarget, kSource, kSourceLength, kStart, kDepth, \
kMapperFunction, kThisArg) \
/* https://tc39.github.io/proposal-flatMap/#sec-Array.prototype.flatten */ \
TFJ(ArrayPrototypeFlatten, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* https://tc39.github.io/proposal-flatMap/#sec-Array.prototype.flatMap */ \
TFJ(ArrayPrototypeFlatMap, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
\
/* ArrayBuffer */ \
/* ES #sec-arraybuffer-constructor */ \
......
......@@ -6174,7 +6174,8 @@ TNode<Number> CodeStubAssembler::ToLength_Inline(SloppyTNode<Context> context,
}
TNode<Number> CodeStubAssembler::ToInteger_Inline(
TNode<Context> context, TNode<Object> input, ToIntegerTruncationMode mode) {
SloppyTNode<Context> context, SloppyTNode<Object> input,
ToIntegerTruncationMode mode) {
Builtins::Name builtin = (mode == kNoTruncation)
? Builtins::kToInteger
: Builtins::kToInteger_TruncateMinusZero;
......@@ -10022,7 +10023,7 @@ void CodeStubAssembler::BranchIfSameValue(Node* lhs, Node* rhs, Label* if_true,
}
TNode<Oddball> CodeStubAssembler::HasProperty(SloppyTNode<HeapObject> object,
SloppyTNode<Name> key,
SloppyTNode<Object> key,
SloppyTNode<Context> context,
HasPropertyLookupMode mode) {
Label call_runtime(this, Label::kDeferred), return_true(this),
......
......@@ -1315,7 +1315,8 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
SloppyTNode<Object> input);
// ES6 7.1.4 ToInteger ( argument )
TNode<Number> ToInteger_Inline(TNode<Context> context, TNode<Object> input,
TNode<Number> ToInteger_Inline(SloppyTNode<Context> context,
SloppyTNode<Object> input,
ToIntegerTruncationMode mode = kNoTruncation);
TNode<Number> ToInteger(SloppyTNode<Context> context,
SloppyTNode<Object> input,
......@@ -1910,7 +1911,7 @@ class V8_EXPORT_PRIVATE CodeStubAssembler : public compiler::CodeAssembler {
enum HasPropertyLookupMode { kHasProperty, kForInHasProperty };
TNode<Oddball> HasProperty(SloppyTNode<HeapObject> object,
SloppyTNode<Name> key,
SloppyTNode<Object> key,
SloppyTNode<Context> context,
HasPropertyLookupMode mode);
......
......@@ -212,7 +212,8 @@ DEFINE_IMPLICATION(harmony_class_fields, harmony_private_fields)
V(harmony_array_prototype_values, "harmony Array.prototype.values") \
V(harmony_do_expressions, "harmony do-expressions") \
V(harmony_class_fields, "harmony fields in class literals") \
V(harmony_static_fields, "harmony static fields in class literals")
V(harmony_static_fields, "harmony static fields in class literals") \
V(harmony_array_flatten, "harmony Array.prototype.flat{ten,Map}")
// Features that are complete (but still behind --harmony/es-staging flag).
#define HARMONY_STAGED(V) \
......
......@@ -343,6 +343,7 @@ class ErrorUtils : public AllStatic {
T(IteratorSymbolNonCallable, "Found non-callable @@iterator") \
T(IteratorValueNotAnObject, "Iterator value % is not an entry object") \
T(LanguageID, "Language ID should be string or object.") \
T(MapperFunctionNonCallable, "flatMap mapper function is not callable") \
T(MethodCalledOnWrongObject, \
"Method % called on a non-object or on a wrong type of object.") \
T(MethodInvokedOnNullOrUndefined, \
......@@ -643,6 +644,9 @@ class ErrorUtils : public AllStatic {
T(NoCatchOrFinally, "Missing catch or finally after try") \
T(NotIsvar, "builtin %%IS_VAR: not a variable") \
T(ParamAfterRest, "Rest parameter must be last formal parameter") \
T(FlattenPastSafeLength, \
"Flattening % elements on an array-like of length % " \
"is disallowed, as the total surpasses 2**53-1") \
T(PushPastSafeLength, \
"Pushing % elements on an array-like of length % " \
"is disallowed, as the total surpasses 2**53-1") \
......
......@@ -367,7 +367,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(146),
B(Wide), B(LdaSmi), I16(147),
B(Star), R(18),
B(LdaConstant), U8(15),
B(Star), R(19),
......
......@@ -124,7 +124,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(146),
B(Wide), B(LdaSmi), I16(147),
B(Star), R(19),
B(LdaConstant), U8(12),
B(Star), R(20),
......@@ -378,7 +378,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(146),
B(Wide), B(LdaSmi), I16(147),
B(Star), R(19),
B(LdaConstant), U8(12),
B(Star), R(20),
......@@ -654,7 +654,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(146),
B(Wide), B(LdaSmi), I16(147),
B(Star), R(19),
B(LdaConstant), U8(12),
B(Star), R(20),
......@@ -886,7 +886,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(146),
B(Wide), B(LdaSmi), I16(147),
B(Star), R(17),
B(LdaConstant), U8(10),
B(Star), R(18),
......
......@@ -86,7 +86,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(146),
B(Wide), B(LdaSmi), I16(147),
B(Star), R(12),
B(LdaConstant), U8(8),
B(Star), R(13),
......@@ -220,7 +220,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(146),
B(Wide), B(LdaSmi), I16(147),
B(Star), R(13),
B(LdaConstant), U8(8),
B(Star), R(14),
......@@ -366,7 +366,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(146),
B(Wide), B(LdaSmi), I16(147),
B(Star), R(12),
B(LdaConstant), U8(8),
B(Star), R(13),
......@@ -502,7 +502,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(146),
B(Wide), B(LdaSmi), I16(147),
B(Star), R(11),
B(LdaConstant), U8(10),
B(Star), R(12),
......
......@@ -90,7 +90,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(146),
B(Wide), B(LdaSmi), I16(147),
B(Star), R(14),
B(LdaConstant), U8(7),
B(Star), R(15),
......@@ -261,7 +261,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(146),
B(Wide), B(LdaSmi), I16(147),
B(Star), R(14),
B(LdaConstant), U8(11),
B(Star), R(15),
......@@ -408,7 +408,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(146),
B(Wide), B(LdaSmi), I16(147),
B(Star), R(12),
B(LdaConstant), U8(9),
B(Star), R(13),
......@@ -503,7 +503,7 @@ bytecodes: [
B(JumpIfUndefined), U8(6),
B(Ldar), R(6),
B(JumpIfNotNull), U8(16),
B(LdaSmi), I8(76),
B(LdaSmi), I8(77),
B(Star), R(18),
B(LdaConstant), U8(4),
B(Star), R(19),
......@@ -559,7 +559,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(146),
B(Wide), B(LdaSmi), I16(147),
B(Star), R(17),
B(LdaConstant), U8(9),
B(Star), R(18),
......@@ -713,7 +713,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(146),
B(Wide), B(LdaSmi), I16(147),
B(Star), R(16),
B(LdaConstant), U8(10),
B(Star), R(17),
......@@ -882,7 +882,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(146),
B(Wide), B(LdaSmi), I16(147),
B(Star), R(15),
B(LdaConstant), U8(13),
B(Star), R(16),
......@@ -1037,7 +1037,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(146),
B(Wide), B(LdaSmi), I16(147),
B(Star), R(21),
B(LdaConstant), U8(7),
B(Star), R(22),
......@@ -1253,7 +1253,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(146),
B(Wide), B(LdaSmi), I16(147),
B(Star), R(20),
B(LdaConstant), U8(8),
B(Star), R(21),
......
......@@ -204,7 +204,7 @@ bytecodes: [
B(TestTypeOf), U8(6),
B(JumpIfFalse), U8(4),
B(Jump), U8(18),
B(Wide), B(LdaSmi), I16(146),
B(Wide), B(LdaSmi), I16(147),
B(Star), R(14),
B(LdaConstant), U8(14),
B(Star), R(15),
......
......@@ -231,7 +231,7 @@ bytecodes: [
B(JumpIfUndefined), U8(6),
B(Ldar), R(3),
B(JumpIfNotNull), U8(16),
B(LdaSmi), I8(76),
B(LdaSmi), I8(77),
B(Star), R(4),
B(LdaConstant), U8(1),
B(Star), R(5),
......
// Copyright 2018 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-array-flatten --allow-natives-syntax
assertEquals(Array.prototype.flatMap.length, 1);
assertEquals(Array.prototype.flatMap.name, 'flatMap');
assertEquals(
[1, 2, 3, 4].flatMap((element) => [element, element ** 2]),
[1, 1, 2, 4, 3, 9, 4, 16]
);
assertEquals(
[1, 2, 3, 4].flatMap((element) => [[element, element ** 2]]),
[[1, 1], [2, 4], [3, 9], [4, 16]]
);
const elements = new Set([
-Infinity,
-1,
-0,
+0,
+1,
Infinity,
null,
undefined,
true,
false,
'',
'foo',
/./,
[],
{},
Object.create(null),
new Proxy({}, {}),
Symbol(),
x => x ** 2,
String
]);
for (const value of elements) {
assertEquals(
[value].flatMap((element) => [element, element]),
[value, value]
);
}
const array = [42];
assertEquals(
[array].flatMap((element) => [element, element]),
[array, array]
);
const nonCallables = new Set([
-Infinity,
-1,
-0,
+0,
+1,
Infinity,
null,
undefined,
true,
false,
'',
'foo',
/./,
[],
{},
Object.create(null),
new Proxy({}, {}),
Symbol(),
]);
for (const nonCallable of nonCallables) {
assertThrows(() => {
[].flatMap(nonCallable);
}, TypeError);
}
const object = {
foo: 42,
get length() {
object.foo = 0;
}
};
const result = [object].flatMap((element) => [element, element]);
%HeapObjectVerify(result);
assertEquals(result, [object, object]);
assertEquals(result[0].foo, 42);
assertThrows(() => {
Array.prototype.flatMap.call(null, (element) => element);
}, TypeError);
assertThrows(() => {
Array.prototype.flatMap.call(undefined, (element) => element);
}, TypeError);
assertEquals(
Array.prototype.flatMap.call(
{
length: 1,
0: 'a',
1: 'b',
},
(element) => element
),
['a']
);
assertEquals(
Array.prototype.flatMap.call(
{
length: 2,
0: 'a',
1: 'b',
},
(element) => element
),
['a', 'b']
);
// Copyright 2018 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-array-flatten
assertEquals(Array.prototype.flatten.length, 0);
assertEquals(Array.prototype.flatten.name, 'flatten');
const input = [1, [2], [[3]]];
assertEquals(input.flatten(), [1, 2, [3]]);
assertEquals(input.flatten(1), [1, 2, [3]]);
assertEquals(input.flatten(true), [1, 2, [3]]);
assertEquals(input.flatten(undefined), [1, 2, [3]]);
assertEquals(input.flatten(-Infinity), [1, [2], [[3]]]);
assertEquals(input.flatten(-1), [1, [2], [[3]]]);
assertEquals(input.flatten(-0), [1, [2], [[3]]]);
assertEquals(input.flatten(0), [1, [2], [[3]]]);
assertEquals(input.flatten(false), [1, [2], [[3]]]);
assertEquals(input.flatten(null), [1, [2], [[3]]]);
assertEquals(input.flatten(''), [1, [2], [[3]]]);
assertEquals(input.flatten('foo'), [1, [2], [[3]]]);
assertEquals(input.flatten(/./), [1, [2], [[3]]]);
assertEquals(input.flatten([]), [1, [2], [[3]]]);
assertEquals(input.flatten({}), [1, [2], [[3]]]);
assertEquals(
input.flatten(new Proxy({}, {})), [1, [2], [[3]]]);
assertEquals(input.flatten((x) => x), [1, [2], [[3]]]);
assertEquals(
input.flatten(String), [1, [2], [[3]]]);
assertEquals(input.flatten(2), [1, 2, 3]);
assertEquals(input.flatten(Infinity), [1, 2, 3]);
assertThrows(() => { input.flatten(Symbol()); }, TypeError);
assertThrows(() => { input.flatten(Object.create(null)); }, TypeError);
......@@ -50,11 +50,12 @@ FEATURE_FLAGS = {
'class-fields-public': '--harmony-public-fields',
'optional-catch-binding': '--harmony-optional-catch-binding',
'class-fields-private': '--harmony-private-fields',
'Array.prototype.flatten': '--harmony-array-flatten',
'Array.prototype.flatMap': '--harmony-array-flatten',
'numeric-separator-literal': '--harmony-numeric-separator',
}
SKIPPED_FEATURES = set(['Array.prototype.flatten',
'Array.prototype.flatMap'])
SKIPPED_FEATURES = set([])
DATA = os.path.join(os.path.dirname(os.path.abspath(__file__)), "data")
ARCHIVE = DATA + ".tar"
......
......@@ -60,7 +60,9 @@ LINT_RULES = """
-build/header_guard
-build/include_what_you_use
-readability/fn_size
-readability/multiline_comment
-runtime/references
-whitespace/comments
""".split()
LINT_OUTPUT_PATTERN = re.compile(r'^.+[:(]\d+[:)]|^Done processing')
......
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