Implement array.flat and array.flatMap

master
Fedor 2019-07-08 13:08:34 +03:00
parent 8ac840e319
commit 7fd9c4b7e3
5 changed files with 120 additions and 1 deletions

View File

@ -1073,6 +1073,114 @@ function ArrayConcat(arg1) {
return A; return A;
} }
// https://tc39.github.io/proposal-flatMap/
// January 4, 2019
function ArrayFlatMap(mapperFunction/*, thisArg*/) {
// Step 1.
var O = ToObject(this);
// Step 2.
var sourceLen = ToLength(O.length);
// Step 3.
if (!IsCallable(mapperFunction))
ThrowTypeError(JSMSG_NOT_FUNCTION, DecompileArg(0, mapperFunction));
// Step 4.
var T = arguments.length > 1 ? arguments[1] : undefined;
// Step 5.
var A = ArraySpeciesCreate(O, 0);
// Step 6.
FlattenIntoArray(A, O, sourceLen, 0, 1, mapperFunction, T);
// Step 7.
return A;
}
// https://tc39.github.io/proposal-flatMap/
// January 4, 2019
function ArrayFlat(/* depth */) {
// Step 1.
var O = ToObject(this);
// Step 2.
var sourceLen = ToLength(O.length);
// Step 3.
var depthNum = 1;
// Step 4.
if (arguments.length > 0 && arguments[0] !== undefined)
depthNum = ToInteger(arguments[0]);
// Step 5.
var A = ArraySpeciesCreate(O, 0);
// Step 6.
FlattenIntoArray(A, O, sourceLen, 0, depthNum);
// Step 7.
return A;
}
// https://tc39.github.io/proposal-flatMap/
// January 4, 2019
function FlattenIntoArray(target, source, sourceLen, start, depth, mapperFunction, thisArg) {
// Step 1.
var targetIndex = start;
// Steps 2-3.
for (var sourceIndex = 0; sourceIndex < sourceLen; sourceIndex++) {
// Steps 3.a-c.
if (sourceIndex in source) {
// Step 3.c.i.
var element = source[sourceIndex];
if (mapperFunction) {
// Step 3.c.ii.1.
assert(arguments.length === 7, "thisArg is present");
// Step 3.c.ii.2.
element = callContentFunction(mapperFunction, thisArg, element, sourceIndex, source);
}
// Step 3.c.iii.
var shouldFlatten = false;
// Step 3.c.iv.
if (depth > 0) {
// Step 3.c.iv.1.
shouldFlatten = IsArray(element);
}
// Step 3.c.v.
if (shouldFlatten) {
// Step 3.c.v.1.
var elementLen = ToLength(element.length);
// Step 3.c.v.2.
// Recursive call to walk the depth.
targetIndex = FlattenIntoArray(target, element, elementLen, targetIndex, depth - 1);
} else {
// Step 3.c.vi.1.
if (targetIndex >= MAX_NUMERIC_INDEX)
ThrowTypeError(JSMSG_TOO_LONG_ARRAY);
// Step 3.c.vi.2.
_DefineDataProperty(target, targetIndex, element);
// Step 3.c.vi.3.
targetIndex++;
}
}
}
// Step 4.
return targetIndex;
}
function ArrayStaticConcat(arr, arg1) { function ArrayStaticConcat(arr, arg1) {
if (arguments.length < 1) if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'Array.concat'); ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'Array.concat');

View File

@ -3169,6 +3169,11 @@ static const JSFunctionSpec array_methods[] = {
/* ES7 additions */ /* ES7 additions */
JS_SELF_HOSTED_FN("includes", "ArrayIncludes", 2,0), JS_SELF_HOSTED_FN("includes", "ArrayIncludes", 2,0),
/* ES2019 additions */
JS_SELF_HOSTED_FN("flat", "ArrayFlat", 0,0),
JS_SELF_HOSTED_FN("flatMap", "ArrayFlatMap", 1,0),
JS_FS_END JS_FS_END
}; };
@ -3333,6 +3338,8 @@ array_proto_finish(JSContext* cx, JS::HandleObject ctor, JS::HandleObject proto)
!DefineProperty(cx, unscopables, cx->names().fill, value) || !DefineProperty(cx, unscopables, cx->names().fill, value) ||
!DefineProperty(cx, unscopables, cx->names().find, value) || !DefineProperty(cx, unscopables, cx->names().find, value) ||
!DefineProperty(cx, unscopables, cx->names().findIndex, value) || !DefineProperty(cx, unscopables, cx->names().findIndex, value) ||
!DefineProperty(cx, unscopables, cx->names().flat, value) ||
!DefineProperty(cx, unscopables, cx->names().flatMap, value) ||
!DefineProperty(cx, unscopables, cx->names().includes, value) || !DefineProperty(cx, unscopables, cx->names().includes, value) ||
!DefineProperty(cx, unscopables, cx->names().keys, value) || !DefineProperty(cx, unscopables, cx->names().keys, value) ||
!DefineProperty(cx, unscopables, cx->names().values, value)) !DefineProperty(cx, unscopables, cx->names().values, value))

View File

@ -26,6 +26,8 @@ assertDeepEq(keys, [
"fill", "fill",
"find", "find",
"findIndex", "findIndex",
"flat",
"flatMap",
"includes", "includes",
"keys", "keys",
"values" "values"

View File

@ -115,6 +115,8 @@
macro(firstDayOfWeek, firstDayOfWeek, "firstDayOfWeek") \ macro(firstDayOfWeek, firstDayOfWeek, "firstDayOfWeek") \
macro(fix, fix, "fix") \ macro(fix, fix, "fix") \
macro(flags, flags, "flags") \ macro(flags, flags, "flags") \
macro(flat, flat, "flat") \
macro(flatMap, flatMap, "flatMap") \
macro(float32, float32, "float32") \ macro(float32, float32, "float32") \
macro(Float32x4, Float32x4, "Float32x4") \ macro(Float32x4, Float32x4, "Float32x4") \
macro(float64, float64, "float64") \ macro(float64, float64, "float64") \

View File

@ -198,7 +198,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681
"pop", "shift", "unshift", "splice", "concat", "slice", "lastIndexOf", "indexOf", "pop", "shift", "unshift", "splice", "concat", "slice", "lastIndexOf", "indexOf",
"includes", "forEach", "map", "reduce", "reduceRight", "filter", "some", "every", "find", "includes", "forEach", "map", "reduce", "reduceRight", "filter", "some", "every", "find",
"findIndex", "copyWithin", "fill", Symbol.iterator, Symbol.unscopables, "entries", "keys", "findIndex", "copyWithin", "fill", Symbol.iterator, Symbol.unscopables, "entries", "keys",
"values", "constructor"]; "values", "constructor", "flat", "flatMap"];
if (isNightlyBuild) { if (isNightlyBuild) {
// ...nothing now // ...nothing now
} }