From 300d6df4b466b0c161eeb63ff9e8aafbcaae7965 Mon Sep 17 00:00:00 2001 From: nename0 Date: Sun, 23 Jun 2019 15:57:26 +0200 Subject: [PATCH] implement Array.includes to align to specs --- src/org/mozilla/javascript/NativeArray.java | 55 ++++++++++++++++++++- testsrc/test262.properties | 16 ------ 2 files changed, 54 insertions(+), 17 deletions(-) diff --git a/src/org/mozilla/javascript/NativeArray.java b/src/org/mozilla/javascript/NativeArray.java index 883a4584b0..e986757ff5 100644 --- a/src/org/mozilla/javascript/NativeArray.java +++ b/src/org/mozilla/javascript/NativeArray.java @@ -351,7 +351,7 @@ public Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope, return js_lastIndexOf(cx, scope, thisObj, args); case Id_includes: - return Boolean.valueOf(((long) js_indexOf(cx, scope, thisObj, args)) > -1); + return js_includes(cx, scope, thisObj, args); case Id_fill: return js_fill(cx, scope, thisObj, args); @@ -1711,6 +1711,59 @@ else if (start < 0) return NEGATIVE_ONE; } + /* + See ECMA-262 22.1.3.13 + */ + private static Boolean js_includes(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { + Object compareTo = args.length > 0 ? args[0] : Undefined.instance; + + Scriptable o = ScriptRuntime.toObject(cx, scope, thisObj); + long len = ScriptRuntime.toLength(new Object[]{getProperty(thisObj, "length")}, 0); + if (len == 0) return Boolean.FALSE; + + long k; + if (args.length < 2) { + k = 0; + } else { + k = (long) ScriptRuntime.toInteger(args[1]); + if (k < 0) { + k += len; + if (k < 0) + k = 0; + } + if (k > len - 1) return Boolean.FALSE; + } + if (o instanceof NativeArray) { + NativeArray na = (NativeArray) o; + if (na.denseOnly) { + Scriptable proto = na.getPrototype(); + for (int i = (int) k; i < len; i++) { + Object elementK = na.dense[i]; + if (elementK == NOT_FOUND && proto != null) { + elementK = ScriptableObject.getProperty(proto, i); + } + if (elementK == NOT_FOUND) { + elementK = Undefined.instance; + } + if (ScriptRuntime.sameZero(elementK, compareTo)) { + return Boolean.TRUE; + } + } + return Boolean.FALSE; + } + } + for (; k < len; k++) { + Object elementK = getRawElem(o, k); + if (elementK == NOT_FOUND) { + elementK = Undefined.instance; + } + if (ScriptRuntime.sameZero(elementK, compareTo)) { + return Boolean.TRUE; + } + } + return Boolean.FALSE; + } + private static Object js_fill(Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { Scriptable o = ScriptRuntime.toObject(cx, scope, thisObj); diff --git a/testsrc/test262.properties b/testsrc/test262.properties index d8cab04c27..0c3a655c3f 100644 --- a/testsrc/test262.properties +++ b/testsrc/test262.properties @@ -90,22 +90,6 @@ built-ins/Array ! prototype/Symbol.unscopables/value.js # Not throwing properly on unwritable ! prototype/copyWithin/return-abrupt-from-delete-target.js - # No "valueOf" yet. - ! prototype/includes/fromIndex-equal-or-greater-length-returns-false.js - ! prototype/includes/fromIndex-infinity.js - ! prototype/includes/fromIndex-minus-zero.js - ! prototype/includes/get-prop.js - ! prototype/includes/length-boundaries.js - ! prototype/includes/length-zero-returns-false.js - ! prototype/includes/no-arg.js - ! prototype/includes/samevaluezero.js - ! prototype/includes/search-found-returns-true.js - ! prototype/includes/search-not-found-returns-false.js - ! prototype/includes/sparse.js - ! prototype/includes/tointeger-fromindex.js - ! prototype/includes/tolength-length.js - ! prototype/includes/using-fromindex.js - ! prototype/includes/values-are-not-cached.js # Expects a particular string value ! prototype/Symbol.iterator.js