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;
}
// 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) {
if (arguments.length < 1)
ThrowTypeError(JSMSG_MISSING_FUN_ARG, 0, 'Array.concat');

View File

@ -3169,6 +3169,11 @@ static const JSFunctionSpec array_methods[] = {
/* ES7 additions */
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
};
@ -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().find, 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().keys, value) ||
!DefineProperty(cx, unscopables, cx->names().values, value))

View File

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

View File

@ -115,6 +115,8 @@
macro(firstDayOfWeek, firstDayOfWeek, "firstDayOfWeek") \
macro(fix, fix, "fix") \
macro(flags, flags, "flags") \
macro(flat, flat, "flat") \
macro(flatMap, flatMap, "flatMap") \
macro(float32, float32, "float32") \
macro(Float32x4, Float32x4, "Float32x4") \
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",
"includes", "forEach", "map", "reduce", "reduceRight", "filter", "some", "every", "find",
"findIndex", "copyWithin", "fill", Symbol.iterator, Symbol.unscopables, "entries", "keys",
"values", "constructor"];
"values", "constructor", "flat", "flatMap"];
if (isNightlyBuild) {
// ...nothing now
}