summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwolfbeast <mcwerewolf@wolfbeast.com>2019-05-19 23:11:17 +0200
committerwolfbeast <mcwerewolf@wolfbeast.com>2019-05-19 23:11:17 +0200
commit162e22a7de3026b676156a2aad29909fe3795dba (patch)
tree5f289528d555a2b7f2906c72591773814d6e0ea4
parentc72afc3c8c3f1df53d241c45dd21aa1b2a6c8e50 (diff)
downloadUXP-162e22a7de3026b676156a2aad29909fe3795dba.tar
UXP-162e22a7de3026b676156a2aad29909fe3795dba.tar.gz
UXP-162e22a7de3026b676156a2aad29909fe3795dba.tar.lz
UXP-162e22a7de3026b676156a2aad29909fe3795dba.tar.xz
UXP-162e22a7de3026b676156a2aad29909fe3795dba.zip
Implement array.flat and array.flatMap
Self-hosted implementation that adds both functions and adds them to @@unscopables as specced in ES2019. Resolves #1095
-rw-r--r--js/src/builtin/Array.js108
-rw-r--r--js/src/jsarray.cpp7
-rw-r--r--js/src/tests/ecma_6/Array/unscopables.js2
-rw-r--r--js/src/vm/CommonPropertyNames.h2
-rw-r--r--js/xpconnect/tests/chrome/test_xrayToJS.xul2
5 files changed, 120 insertions, 1 deletions
diff --git a/js/src/builtin/Array.js b/js/src/builtin/Array.js
index 30e6fb35f..05fc41bc1 100644
--- a/js/src/builtin/Array.js
+++ b/js/src/builtin/Array.js
@@ -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');
diff --git a/js/src/jsarray.cpp b/js/src/jsarray.cpp
index 7a67c0095..3b4c957dc 100644
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -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))
diff --git a/js/src/tests/ecma_6/Array/unscopables.js b/js/src/tests/ecma_6/Array/unscopables.js
index 6685309a0..56b3aa520 100644
--- a/js/src/tests/ecma_6/Array/unscopables.js
+++ b/js/src/tests/ecma_6/Array/unscopables.js
@@ -26,6 +26,8 @@ assertDeepEq(keys, [
"fill",
"find",
"findIndex",
+ "flat",
+ "flatMap",
"includes",
"keys",
"values"
diff --git a/js/src/vm/CommonPropertyNames.h b/js/src/vm/CommonPropertyNames.h
index e971dc844..8a36df083 100644
--- a/js/src/vm/CommonPropertyNames.h
+++ b/js/src/vm/CommonPropertyNames.h
@@ -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") \
diff --git a/js/xpconnect/tests/chrome/test_xrayToJS.xul b/js/xpconnect/tests/chrome/test_xrayToJS.xul
index ed67a34fe..73de267a1 100644
--- a/js/xpconnect/tests/chrome/test_xrayToJS.xul
+++ b/js/xpconnect/tests/chrome/test_xrayToJS.xul
@@ -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
}