diff --git a/rhino/src/main/java/org/mozilla/javascript/ArrayLikeAbstractOperations.java b/rhino/src/main/java/org/mozilla/javascript/ArrayLikeAbstractOperations.java index a23a3a724c..5cffc1695d 100644 --- a/rhino/src/main/java/org/mozilla/javascript/ArrayLikeAbstractOperations.java +++ b/rhino/src/main/java/org/mozilla/javascript/ArrayLikeAbstractOperations.java @@ -26,7 +26,23 @@ public enum ReduceOperation { REDUCE_RIGHT, } - /** Implements the methods "every", "filter", "forEach", "map", and "some". */ + /** + * Implements the methods "every", "filter", "forEach", "map", and "some" without using an + * IdFunctionObject. + */ + public static Object iterativeMethod( + Context cx, + IterativeOperation operation, + Scriptable scope, + Scriptable thisObj, + Object[] args) { + return iterativeMethod(cx, null, operation, scope, thisObj, args, true); + } + + /** + * Implements the methods "every", "filter", "forEach", "map", and "some" using an + * IdFunctionObject. + */ public static Object iterativeMethod( Context cx, IdFunctionObject fun, @@ -34,13 +50,26 @@ public static Object iterativeMethod( Scriptable scope, Scriptable thisObj, Object[] args) { + return iterativeMethod(cx, fun, operation, scope, thisObj, args, false); + } + + private static Object iterativeMethod( + Context cx, + IdFunctionObject fun, + IterativeOperation operation, + Scriptable scope, + Scriptable thisObj, + Object[] args, + boolean skipCoercibleCheck) { Scriptable o = ScriptRuntime.toObject(cx, scope, thisObj); - if (IterativeOperation.FIND == operation - || IterativeOperation.FIND_INDEX == operation - || IterativeOperation.FIND_LAST == operation - || IterativeOperation.FIND_LAST_INDEX == operation) { - requireObjectCoercible(cx, o, fun); + if (!skipCoercibleCheck) { + if (IterativeOperation.FIND == operation + || IterativeOperation.FIND_INDEX == operation + || IterativeOperation.FIND_LAST == operation + || IterativeOperation.FIND_LAST_INDEX == operation) { + requireObjectCoercible(cx, o, fun); + } } long length = getLengthProperty(cx, o); diff --git a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeArrayBuffer.java b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeArrayBuffer.java index d0828af362..1058e7af02 100644 --- a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeArrayBuffer.java +++ b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeArrayBuffer.java @@ -6,18 +6,20 @@ package org.mozilla.javascript.typedarrays; +import org.mozilla.javascript.AbstractEcmaObjectOperations; +import org.mozilla.javascript.Constructable; import org.mozilla.javascript.Context; -import org.mozilla.javascript.IdFunctionObject; -import org.mozilla.javascript.IdScriptableObject; +import org.mozilla.javascript.LambdaConstructor; import org.mozilla.javascript.ScriptRuntime; import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.Undefined; /** * A NativeArrayBuffer is the backing buffer for a typed array. Used inside JavaScript code, it * implements the ArrayBuffer interface. Used directly from Java, it simply holds a byte array. */ -public class NativeArrayBuffer extends IdScriptableObject { +public class NativeArrayBuffer extends ScriptableObject { private static final long serialVersionUID = 3110411773054879549L; public static final String CLASS_NAME = "ArrayBuffer"; @@ -32,8 +34,32 @@ public String getClassName() { } public static void init(Context cx, Scriptable scope, boolean sealed) { - NativeArrayBuffer na = new NativeArrayBuffer(); - na.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); + LambdaConstructor constructor = + new LambdaConstructor( + scope, + "ArrayBuffer", + 1, + LambdaConstructor.CONSTRUCTOR_NEW, + NativeArrayBuffer::js_constructor); + constructor.setPrototypePropertyAttributes(DONTENUM | READONLY | PERMANENT); + + constructor.defineConstructorMethod( + scope, "isView", 1, NativeArrayBuffer::js_isView, DONTENUM, DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "slice", + 2, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + js_slice(lcx, lscope, thisObj, constructor, args), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeProperty( + cx, "byteLength", NativeArrayBuffer::js_byteLength, DONTENUM | READONLY); + + ScriptableObject.defineProperty(scope, CLASS_NAME, constructor, DONTENUM); + if (sealed) { + constructor.sealObject(); + } } /** Create an empty buffer. */ @@ -79,8 +105,6 @@ public byte[] getBuffer() { return buffer; } - // Actual implementations of actual code - /** * Return a new buffer that represents a slice of this buffer's content, starting at position * "start" and ending at position "end". Both values will be "clamped" as per the JavaScript @@ -106,120 +130,68 @@ public NativeArrayBuffer slice(double s, double e) { return newBuf; } - // Function-calling dispatcher - - @Override - public Object execIdCall( - IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { - if (!f.hasTag(CLASS_NAME)) { - return super.execIdCall(f, cx, scope, thisObj, args); - } - int id = f.methodId(); - switch (id) { - case ConstructorId_isView: - return Boolean.valueOf( - (isArg(args, 0) && (args[0] instanceof NativeArrayBufferView))); - - case Id_constructor: - double length = isArg(args, 0) ? ScriptRuntime.toNumber(args[0]) : 0; - return new NativeArrayBuffer(length); - - case Id_slice: - NativeArrayBuffer self = realThis(thisObj, f); - double start = isArg(args, 0) ? ScriptRuntime.toNumber(args[0]) : 0; - double end = isArg(args, 1) ? ScriptRuntime.toNumber(args[1]) : self.buffer.length; - return self.slice(start, end); - } - throw new IllegalArgumentException(String.valueOf(id)); + private static NativeArrayBuffer getSelf(Scriptable thisObj) { + return LambdaConstructor.convertThisObject(thisObj, NativeArrayBuffer.class); } - private static NativeArrayBuffer realThis(Scriptable thisObj, IdFunctionObject f) { - return ensureType(thisObj, NativeArrayBuffer.class, f); + private static NativeArrayBuffer js_constructor(Context cx, Scriptable scope, Object[] args) { + double length = isArg(args, 0) ? ScriptRuntime.toNumber(args[0]) : 0; + return new NativeArrayBuffer(length); } - private static boolean isArg(Object[] args, int i) { - return ((args.length > i) && !Undefined.instance.equals(args[i])); + private static Boolean js_isView( + Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { + return Boolean.valueOf((isArg(args, 0) && (args[0] instanceof NativeArrayBufferView))); } - @Override - protected void initPrototypeId(int id) { - String s; - int arity; - switch (id) { - case Id_constructor: - arity = 1; - s = "constructor"; - break; - case Id_slice: - arity = 2; - s = "slice"; - break; - default: - throw new IllegalArgumentException(String.valueOf(id)); + private static NativeArrayBuffer js_slice( + Context cx, + Scriptable scope, + Scriptable thisObj, + LambdaConstructor defaultConstructor, + Object[] args) { + NativeArrayBuffer self = getSelf(thisObj); + double start = isArg(args, 0) ? ScriptRuntime.toNumber(args[0]) : 0; + double end = isArg(args, 1) ? ScriptRuntime.toNumber(args[1]) : self.getLength(); + int endI = + ScriptRuntime.toInt32( + Math.max( + 0, + Math.min( + self.getLength(), + (end < 0 ? self.getLength() + end : end)))); + int startI = + ScriptRuntime.toInt32( + Math.min( + endI, Math.max(0, (start < 0 ? self.getLength() + start : start)))); + int len = endI - startI; + + Constructable constructor = + AbstractEcmaObjectOperations.speciesConstructor(cx, thisObj, defaultConstructor); + Scriptable newBuf = constructor.construct(cx, scope, new Object[] {len}); + if (!(newBuf instanceof NativeArrayBuffer)) { + throw ScriptRuntime.typeErrorById("msg.species.invalid.ctor"); } - initPrototypeMethod(CLASS_NAME, id, s, arity); - } + NativeArrayBuffer buf = (NativeArrayBuffer) newBuf; - @Override - protected int findPrototypeId(String s) { - int id; - switch (s) { - case "constructor": - id = Id_constructor; - break; - case "slice": - id = Id_slice; - break; - default: - id = 0; - break; + if (buf == self) { + throw ScriptRuntime.typeErrorById("msg.arraybuf.same"); } - return id; - } - - // Table of all functions - private static final int Id_constructor = 1, Id_slice = 2, MAX_PROTOTYPE_ID = Id_slice; - - // Constructor (aka static) functions here - - private static final int ConstructorId_isView = -1; - @Override - protected void fillConstructorProperties(IdFunctionObject ctor) { - addIdFunctionProperty(ctor, CLASS_NAME, ConstructorId_isView, "isView", 1); - } - - // Properties here - - @Override - protected int getMaxInstanceId() { - return MAX_INSTANCE_ID; - } - - @Override - protected String getInstanceIdName(int id) { - if (id == Id_byteLength) { - return "byteLength"; + int actualLength = buf.getLength(); + if (actualLength < len) { + throw ScriptRuntime.typeErrorById("msg.arraybuf.smaller.len", len, actualLength); } - return super.getInstanceIdName(id); - } - @Override - protected Object getInstanceIdValue(int id) { - if (id == Id_byteLength) { - return ScriptRuntime.wrapInt(buffer.length); - } - return super.getInstanceIdValue(id); + System.arraycopy(self.buffer, startI, buf.buffer, 0, len); + return buf; } - @Override - protected int findInstanceIdInfo(String s) { - if ("byteLength".equals(s)) { - return instanceIdInfo(READONLY | PERMANENT, Id_byteLength); - } - return super.findInstanceIdInfo(s); + private static Object js_byteLength(Scriptable thisObj) { + return getSelf(thisObj).getLength(); } - // Table of all properties - private static final int Id_byteLength = 1, MAX_INSTANCE_ID = Id_byteLength; + private static boolean isArg(Object[] args, int i) { + return ((args.length > i) && !Undefined.instance.equals(args[i])); + } } diff --git a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeArrayBufferView.java b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeArrayBufferView.java index a93f498471..eee080a860 100644 --- a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeArrayBufferView.java +++ b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeArrayBufferView.java @@ -7,9 +7,8 @@ package org.mozilla.javascript.typedarrays; import org.mozilla.javascript.Context; -import org.mozilla.javascript.IdScriptableObject; -import org.mozilla.javascript.ScriptRuntime; import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.Symbol; import org.mozilla.javascript.SymbolKey; import org.mozilla.javascript.Undefined; @@ -19,7 +18,7 @@ * NativeArrayBuffer. Many views may simultaneously share the same buffer, and changes to one will * affect all. */ -public abstract class NativeArrayBufferView extends IdScriptableObject { +public abstract class NativeArrayBufferView extends ScriptableObject { private static final long serialVersionUID = 6884475582973958419L; private static Boolean useLittleEndian = null; @@ -76,64 +75,6 @@ protected static boolean isArg(Object[] args, int i) { return ((args.length > i) && !Undefined.instance.equals(args[i])); } - // Property dispatcher - - @Override - protected int getMaxInstanceId() { - return MAX_INSTANCE_ID; - } - - @Override - protected String getInstanceIdName(int id) { - switch (id) { - case Id_buffer: - return "buffer"; - case Id_byteOffset: - return "byteOffset"; - case Id_byteLength: - return "byteLength"; - default: - return super.getInstanceIdName(id); - } - } - - @Override - protected Object getInstanceIdValue(int id) { - switch (id) { - case Id_buffer: - return arrayBuffer; - case Id_byteOffset: - return ScriptRuntime.wrapInt(offset); - case Id_byteLength: - return ScriptRuntime.wrapInt(byteLength); - default: - return super.getInstanceIdValue(id); - } - } - - @Override - protected int findInstanceIdInfo(String s) { - int id; - switch (s) { - case "buffer": - id = Id_buffer; - break; - case "byteOffset": - id = Id_byteOffset; - break; - case "byteLength": - id = Id_byteLength; - break; - default: - id = 0; - break; - } - if (id == 0) { - return super.findInstanceIdInfo(s); - } - return instanceIdInfo(READONLY | PERMANENT, id); - } - @Override public Object get(Symbol key, Scriptable start) { if (SymbolKey.TO_STRING_TAG.equals(key)) { @@ -141,9 +82,4 @@ public Object get(Symbol key, Scriptable start) { } return super.get(key, start); } - - private static final int Id_buffer = 1, Id_byteOffset = 2, Id_byteLength = 3; - - // to be visible by subclasses - protected static final int MAX_INSTANCE_ID = Id_byteLength; } diff --git a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeDataView.java b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeDataView.java index 7d3d02afe9..6873a49735 100644 --- a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeDataView.java +++ b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeDataView.java @@ -7,9 +7,10 @@ package org.mozilla.javascript.typedarrays; import org.mozilla.javascript.Context; -import org.mozilla.javascript.IdFunctionObject; +import org.mozilla.javascript.LambdaConstructor; import org.mozilla.javascript.ScriptRuntime; import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.Undefined; /** @@ -37,8 +38,180 @@ public String getClassName() { } public static void init(Context cx, Scriptable scope, boolean sealed) { - NativeDataView dv = new NativeDataView(); - dv.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); + LambdaConstructor constructor = + new LambdaConstructor( + scope, + CLASS_NAME, + 1, + LambdaConstructor.CONSTRUCTOR_NEW, + NativeDataView::js_constructor); + constructor.setPrototypePropertyAttributes(DONTENUM | READONLY | PERMANENT); + + constructor.definePrototypeProperty( + cx, + "buffer", + (Scriptable thisObj) -> realThis(thisObj).arrayBuffer, + DONTENUM | READONLY); + constructor.definePrototypeProperty( + cx, + "byteLength", + (Scriptable thisObj) -> realThis(thisObj).byteLength, + DONTENUM | READONLY); + constructor.definePrototypeProperty( + cx, + "byteOffset", + (Scriptable thisObj) -> realThis(thisObj).offset, + DONTENUM | READONLY); + + constructor.definePrototypeMethod( + scope, + "getFloat32", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + realThis(thisObj).js_getFloat(4, args), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "getFloat64", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + realThis(thisObj).js_getFloat(8, args), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "getInt8", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + realThis(thisObj).js_getInt(1, true, args), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "getInt16", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + realThis(thisObj).js_getInt(2, true, args), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "getInt32", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + realThis(thisObj).js_getInt(4, true, args), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "getUint8", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + realThis(thisObj).js_getInt(1, false, args), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "getUint16", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + realThis(thisObj).js_getInt(2, false, args), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "getUint32", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + realThis(thisObj).js_getInt(4, false, args), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "setFloat32", + 2, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + realThis(thisObj).js_setFloat(4, args); + return Undefined.instance; + }, + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "setFloat64", + 2, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + realThis(thisObj).js_setFloat(8, args); + return Undefined.instance; + }, + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "setInt8", + 2, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + realThis(thisObj).js_setInt(1, true, args); + return Undefined.instance; + }, + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "setInt16", + 2, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + realThis(thisObj).js_setInt(2, true, args); + return Undefined.instance; + }, + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "setInt32", + 2, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + realThis(thisObj).js_setInt(4, true, args); + return Undefined.instance; + }, + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "setUint8", + 2, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + realThis(thisObj).js_setInt(1, false, args); + return Undefined.instance; + }, + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "setUint16", + 2, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + realThis(thisObj).js_setInt(2, false, args); + return Undefined.instance; + }, + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "setUint32", + 2, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + realThis(thisObj).js_setInt(4, false, args); + return Undefined.instance; + }, + DONTENUM, + DONTENUM | READONLY); + + ScriptableObject.defineProperty(scope, CLASS_NAME, constructor, DONTENUM); + if (sealed) { + constructor.sealObject(); + } } private static int determinePos(Object[] args) { @@ -58,11 +231,11 @@ private void rangeCheck(int pos, int len) { } } - private static NativeDataView realThis(Scriptable thisObj, IdFunctionObject f) { - return ensureType(thisObj, NativeDataView.class, f); + private static NativeDataView realThis(Scriptable thisObj) { + return LambdaConstructor.convertThisObject(thisObj, NativeDataView.class); } - private static NativeDataView js_constructor(Object[] args) { + private static NativeDataView js_constructor(Context cx, Scriptable scope, Object[] args) { if (!isArg(args, 0) || !(args[0] instanceof NativeArrayBuffer)) { throw ScriptRuntime.constructError("TypeError", "Missing parameters"); } @@ -236,220 +409,4 @@ private void js_setFloat(int bytes, Object[] args) { throw new AssertionError(); } } - - // Function dispatcher - - @Override - public Object execIdCall( - IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { - if (!f.hasTag(getClassName())) { - return super.execIdCall(f, cx, scope, thisObj, args); - } - int id = f.methodId(); - switch (id) { - case Id_constructor: - return js_constructor(args); - case Id_getInt8: - return realThis(thisObj, f).js_getInt(1, true, args); - case Id_getUint8: - return realThis(thisObj, f).js_getInt(1, false, args); - case Id_getInt16: - return realThis(thisObj, f).js_getInt(2, true, args); - case Id_getUint16: - return realThis(thisObj, f).js_getInt(2, false, args); - case Id_getInt32: - return realThis(thisObj, f).js_getInt(4, true, args); - case Id_getUint32: - return realThis(thisObj, f).js_getInt(4, false, args); - case Id_getFloat32: - return realThis(thisObj, f).js_getFloat(4, args); - case Id_getFloat64: - return realThis(thisObj, f).js_getFloat(8, args); - case Id_setInt8: - realThis(thisObj, f).js_setInt(1, true, args); - return Undefined.instance; - case Id_setUint8: - realThis(thisObj, f).js_setInt(1, false, args); - return Undefined.instance; - case Id_setInt16: - realThis(thisObj, f).js_setInt(2, true, args); - return Undefined.instance; - case Id_setUint16: - realThis(thisObj, f).js_setInt(2, false, args); - return Undefined.instance; - case Id_setInt32: - realThis(thisObj, f).js_setInt(4, true, args); - return Undefined.instance; - case Id_setUint32: - realThis(thisObj, f).js_setInt(4, false, args); - return Undefined.instance; - case Id_setFloat32: - realThis(thisObj, f).js_setFloat(4, args); - return Undefined.instance; - case Id_setFloat64: - realThis(thisObj, f).js_setFloat(8, args); - return Undefined.instance; - } - throw new IllegalArgumentException(String.valueOf(id)); - } - - @Override - protected void initPrototypeId(int id) { - String s; - int arity; - switch (id) { - case Id_constructor: - arity = 1; - s = "constructor"; - break; - case Id_getInt8: - arity = 1; - s = "getInt8"; - break; - case Id_getUint8: - arity = 1; - s = "getUint8"; - break; - case Id_getInt16: - arity = 1; - s = "getInt16"; - break; - case Id_getUint16: - arity = 1; - s = "getUint16"; - break; - case Id_getInt32: - arity = 1; - s = "getInt32"; - break; - case Id_getUint32: - arity = 1; - s = "getUint32"; - break; - case Id_getFloat32: - arity = 1; - s = "getFloat32"; - break; - case Id_getFloat64: - arity = 1; - s = "getFloat64"; - break; - case Id_setInt8: - arity = 2; - s = "setInt8"; - break; - case Id_setUint8: - arity = 2; - s = "setUint8"; - break; - case Id_setInt16: - arity = 2; - s = "setInt16"; - break; - case Id_setUint16: - arity = 2; - s = "setUint16"; - break; - case Id_setInt32: - arity = 2; - s = "setInt32"; - break; - case Id_setUint32: - arity = 2; - s = "setUint32"; - break; - case Id_setFloat32: - arity = 2; - s = "setFloat32"; - break; - case Id_setFloat64: - arity = 2; - s = "setFloat64"; - break; - default: - throw new IllegalArgumentException(String.valueOf(id)); - } - initPrototypeMethod(getClassName(), id, s, arity); - } - - @Override - protected int findPrototypeId(String s) { - int id; - switch (s) { - case "constructor": - id = Id_constructor; - break; - case "getInt8": - id = Id_getInt8; - break; - case "getUint8": - id = Id_getUint8; - break; - case "getInt16": - id = Id_getInt16; - break; - case "getUint16": - id = Id_getUint16; - break; - case "getInt32": - id = Id_getInt32; - break; - case "getUint32": - id = Id_getUint32; - break; - case "getFloat32": - id = Id_getFloat32; - break; - case "getFloat64": - id = Id_getFloat64; - break; - case "setInt8": - id = Id_setInt8; - break; - case "setUint8": - id = Id_setUint8; - break; - case "setInt16": - id = Id_setInt16; - break; - case "setUint16": - id = Id_setUint16; - break; - case "setInt32": - id = Id_setInt32; - break; - case "setUint32": - id = Id_setUint32; - break; - case "setFloat32": - id = Id_setFloat32; - break; - case "setFloat64": - id = Id_setFloat64; - break; - default: - id = 0; - break; - } - return id; - } - - private static final int Id_constructor = 1, - Id_getInt8 = 2, - Id_getUint8 = 3, - Id_getInt16 = 4, - Id_getUint16 = 5, - Id_getInt32 = 6, - Id_getUint32 = 7, - Id_getFloat32 = 8, - Id_getFloat64 = 9, - Id_setInt8 = 10, - Id_setUint8 = 11, - Id_setInt16 = 12, - Id_setUint16 = 13, - Id_setInt32 = 14, - Id_setUint32 = 15, - Id_setFloat32 = 16, - Id_setFloat64 = 17, - MAX_PROTOTYPE_ID = Id_setFloat64; } diff --git a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeFloat32Array.java b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeFloat32Array.java index cddbc8c02d..de2ab839fa 100644 --- a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeFloat32Array.java +++ b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeFloat32Array.java @@ -7,10 +7,11 @@ package org.mozilla.javascript.typedarrays; import org.mozilla.javascript.Context; -import org.mozilla.javascript.IdFunctionObject; +import org.mozilla.javascript.LambdaConstructor; import org.mozilla.javascript.ScriptRuntime; import org.mozilla.javascript.ScriptRuntimeES6; import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.Undefined; /** @@ -39,14 +40,32 @@ public String getClassName() { } public static void init(Context cx, Scriptable scope, boolean sealed) { - NativeFloat32Array a = new NativeFloat32Array(); - IdFunctionObject constructor = a.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); + LambdaConstructor constructor = + new LambdaConstructor( + scope, + CLASS_NAME, + 3, + LambdaConstructor.CONSTRUCTOR_NEW, + (Context lcx, Scriptable lscope, Object[] args) -> + NativeTypedArrayView.js_constructor( + lcx, + lscope, + args, + NativeFloat32Array::new, + BYTES_PER_ELEMENT)); + constructor.setPrototypePropertyAttributes(DONTENUM | READONLY | PERMANENT); + NativeTypedArrayView.init(cx, scope, constructor, NativeFloat32Array::realThis); + constructor.defineProperty( + "BYTES_PER_ELEMENT", BYTES_PER_ELEMENT, DONTENUM | READONLY | PERMANENT); + constructor.definePrototypeProperty( + "BYTES_PER_ELEMENT", BYTES_PER_ELEMENT, DONTENUM | READONLY | PERMANENT); + ScriptRuntimeES6.addSymbolSpecies(cx, scope, constructor); - } - @Override - protected NativeFloat32Array construct(NativeArrayBuffer ab, int off, int len) { - return new NativeFloat32Array(ab, off, len); + ScriptableObject.defineProperty(scope, CLASS_NAME, constructor, DONTENUM); + if (sealed) { + constructor.sealObject(); + } } @Override @@ -54,9 +73,8 @@ public int getBytesPerElement() { return BYTES_PER_ELEMENT; } - @Override - protected NativeFloat32Array realThis(Scriptable thisObj, IdFunctionObject f) { - return ensureType(thisObj, NativeFloat32Array.class, f); + private static NativeFloat32Array realThis(Scriptable thisObj) { + return LambdaConstructor.convertThisObject(thisObj, NativeFloat32Array.class); } @Override diff --git a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeFloat64Array.java b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeFloat64Array.java index 13f3c7f094..35cb18c8e0 100644 --- a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeFloat64Array.java +++ b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeFloat64Array.java @@ -7,10 +7,11 @@ package org.mozilla.javascript.typedarrays; import org.mozilla.javascript.Context; -import org.mozilla.javascript.IdFunctionObject; +import org.mozilla.javascript.LambdaConstructor; import org.mozilla.javascript.ScriptRuntime; import org.mozilla.javascript.ScriptRuntimeES6; import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.Undefined; /** @@ -39,14 +40,32 @@ public String getClassName() { } public static void init(Context cx, Scriptable scope, boolean sealed) { - NativeFloat64Array a = new NativeFloat64Array(); - IdFunctionObject constructor = a.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); + LambdaConstructor constructor = + new LambdaConstructor( + scope, + CLASS_NAME, + 3, + LambdaConstructor.CONSTRUCTOR_NEW, + (Context lcx, Scriptable lscope, Object[] args) -> + NativeTypedArrayView.js_constructor( + lcx, + lscope, + args, + NativeFloat64Array::new, + BYTES_PER_ELEMENT)); + constructor.setPrototypePropertyAttributes(DONTENUM | READONLY | PERMANENT); + NativeTypedArrayView.init(cx, scope, constructor, NativeFloat64Array::realThis); + constructor.defineProperty( + "BYTES_PER_ELEMENT", BYTES_PER_ELEMENT, DONTENUM | READONLY | PERMANENT); + constructor.definePrototypeProperty( + "BYTES_PER_ELEMENT", BYTES_PER_ELEMENT, DONTENUM | READONLY | PERMANENT); + ScriptRuntimeES6.addSymbolSpecies(cx, scope, constructor); - } - @Override - protected NativeFloat64Array construct(NativeArrayBuffer ab, int off, int len) { - return new NativeFloat64Array(ab, off, len); + ScriptableObject.defineProperty(scope, CLASS_NAME, constructor, DONTENUM); + if (sealed) { + constructor.sealObject(); + } } @Override @@ -54,9 +73,8 @@ public int getBytesPerElement() { return BYTES_PER_ELEMENT; } - @Override - protected NativeFloat64Array realThis(Scriptable thisObj, IdFunctionObject f) { - return ensureType(thisObj, NativeFloat64Array.class, f); + private static NativeFloat64Array realThis(Scriptable thisObj) { + return LambdaConstructor.convertThisObject(thisObj, NativeFloat64Array.class); } @Override diff --git a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeInt16Array.java b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeInt16Array.java index f9a2e336f9..26e8120935 100644 --- a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeInt16Array.java +++ b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeInt16Array.java @@ -7,9 +7,10 @@ package org.mozilla.javascript.typedarrays; import org.mozilla.javascript.Context; -import org.mozilla.javascript.IdFunctionObject; +import org.mozilla.javascript.LambdaConstructor; import org.mozilla.javascript.ScriptRuntimeES6; import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.Undefined; /** @@ -38,14 +39,32 @@ public String getClassName() { } public static void init(Context cx, Scriptable scope, boolean sealed) { - NativeInt16Array a = new NativeInt16Array(); - IdFunctionObject constructor = a.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); + LambdaConstructor constructor = + new LambdaConstructor( + scope, + CLASS_NAME, + 3, + LambdaConstructor.CONSTRUCTOR_NEW, + (Context lcx, Scriptable lscope, Object[] args) -> + NativeTypedArrayView.js_constructor( + lcx, + lscope, + args, + NativeInt16Array::new, + BYTES_PER_ELEMENT)); + constructor.setPrototypePropertyAttributes(DONTENUM | READONLY | PERMANENT); + NativeTypedArrayView.init(cx, scope, constructor, NativeInt16Array::realThis); + constructor.defineProperty( + "BYTES_PER_ELEMENT", BYTES_PER_ELEMENT, DONTENUM | READONLY | PERMANENT); + constructor.definePrototypeProperty( + "BYTES_PER_ELEMENT", BYTES_PER_ELEMENT, DONTENUM | READONLY | PERMANENT); + ScriptRuntimeES6.addSymbolSpecies(cx, scope, constructor); - } - @Override - protected NativeInt16Array construct(NativeArrayBuffer ab, int off, int len) { - return new NativeInt16Array(ab, off, len); + ScriptableObject.defineProperty(scope, CLASS_NAME, constructor, DONTENUM); + if (sealed) { + constructor.sealObject(); + } } @Override @@ -53,9 +72,8 @@ public int getBytesPerElement() { return BYTES_PER_ELEMENT; } - @Override - protected NativeInt16Array realThis(Scriptable thisObj, IdFunctionObject f) { - return ensureType(thisObj, NativeInt16Array.class, f); + private static NativeInt16Array realThis(Scriptable thisObj) { + return LambdaConstructor.convertThisObject(thisObj, NativeInt16Array.class); } @Override diff --git a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeInt32Array.java b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeInt32Array.java index 625bbdf28d..d8254e6275 100644 --- a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeInt32Array.java +++ b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeInt32Array.java @@ -7,10 +7,11 @@ package org.mozilla.javascript.typedarrays; import org.mozilla.javascript.Context; -import org.mozilla.javascript.IdFunctionObject; +import org.mozilla.javascript.LambdaConstructor; import org.mozilla.javascript.ScriptRuntime; import org.mozilla.javascript.ScriptRuntimeES6; import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.Undefined; /** @@ -39,14 +40,32 @@ public String getClassName() { } public static void init(Context cx, Scriptable scope, boolean sealed) { - NativeInt32Array a = new NativeInt32Array(); - IdFunctionObject constructor = a.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); + LambdaConstructor constructor = + new LambdaConstructor( + scope, + CLASS_NAME, + 3, + LambdaConstructor.CONSTRUCTOR_NEW, + (Context lcx, Scriptable lscope, Object[] args) -> + NativeTypedArrayView.js_constructor( + lcx, + lscope, + args, + NativeInt32Array::new, + BYTES_PER_ELEMENT)); + constructor.setPrototypePropertyAttributes(DONTENUM | READONLY | PERMANENT); + NativeTypedArrayView.init(cx, scope, constructor, NativeInt32Array::realThis); + constructor.defineProperty( + "BYTES_PER_ELEMENT", BYTES_PER_ELEMENT, DONTENUM | READONLY | PERMANENT); + constructor.definePrototypeProperty( + "BYTES_PER_ELEMENT", BYTES_PER_ELEMENT, DONTENUM | READONLY | PERMANENT); + ScriptRuntimeES6.addSymbolSpecies(cx, scope, constructor); - } - @Override - protected NativeInt32Array construct(NativeArrayBuffer ab, int off, int len) { - return new NativeInt32Array(ab, off, len); + ScriptableObject.defineProperty(scope, CLASS_NAME, constructor, DONTENUM); + if (sealed) { + constructor.sealObject(); + } } @Override @@ -54,9 +73,8 @@ public int getBytesPerElement() { return BYTES_PER_ELEMENT; } - @Override - protected NativeInt32Array realThis(Scriptable thisObj, IdFunctionObject f) { - return ensureType(thisObj, NativeInt32Array.class, f); + private static NativeInt32Array realThis(Scriptable thisObj) { + return LambdaConstructor.convertThisObject(thisObj, NativeInt32Array.class); } @Override diff --git a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeInt8Array.java b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeInt8Array.java index de3e657fb1..75ae7b119a 100644 --- a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeInt8Array.java +++ b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeInt8Array.java @@ -7,9 +7,10 @@ package org.mozilla.javascript.typedarrays; import org.mozilla.javascript.Context; -import org.mozilla.javascript.IdFunctionObject; +import org.mozilla.javascript.LambdaConstructor; import org.mozilla.javascript.ScriptRuntimeES6; import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.Undefined; /** @@ -37,14 +38,27 @@ public String getClassName() { } public static void init(Context cx, Scriptable scope, boolean sealed) { - NativeInt8Array a = new NativeInt8Array(); - IdFunctionObject constructor = a.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); + LambdaConstructor constructor = + new LambdaConstructor( + scope, + CLASS_NAME, + 3, + LambdaConstructor.CONSTRUCTOR_NEW, + (Context lcx, Scriptable lscope, Object[] args) -> + NativeTypedArrayView.js_constructor( + lcx, lscope, args, NativeInt8Array::new, 1)); + constructor.setPrototypePropertyAttributes(DONTENUM | READONLY | PERMANENT); + NativeTypedArrayView.init(cx, scope, constructor, NativeInt8Array::realThis); + constructor.defineProperty("BYTES_PER_ELEMENT", 1, DONTENUM | READONLY | PERMANENT); + constructor.definePrototypeProperty( + "BYTES_PER_ELEMENT", 1, DONTENUM | READONLY | PERMANENT); + ScriptRuntimeES6.addSymbolSpecies(cx, scope, constructor); - } - @Override - protected NativeInt8Array construct(NativeArrayBuffer ab, int off, int len) { - return new NativeInt8Array(ab, off, len); + ScriptableObject.defineProperty(scope, CLASS_NAME, constructor, DONTENUM); + if (sealed) { + constructor.sealObject(); + } } @Override @@ -52,9 +66,8 @@ public int getBytesPerElement() { return 1; } - @Override - protected NativeInt8Array realThis(Scriptable thisObj, IdFunctionObject f) { - return ensureType(thisObj, NativeInt8Array.class, f); + private static NativeInt8Array realThis(Scriptable thisObj) { + return LambdaConstructor.convertThisObject(thisObj, NativeInt8Array.class); } @Override diff --git a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeTypedArrayView.java b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeTypedArrayView.java index b4feb33dee..64b39ce1ec 100644 --- a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeTypedArrayView.java +++ b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeTypedArrayView.java @@ -24,14 +24,13 @@ import org.mozilla.javascript.Context; import org.mozilla.javascript.ExternalArrayData; import org.mozilla.javascript.Function; -import org.mozilla.javascript.IdFunctionObject; +import org.mozilla.javascript.LambdaConstructor; import org.mozilla.javascript.NativeArray; import org.mozilla.javascript.NativeArrayIterator; import org.mozilla.javascript.NativeArrayIterator.ARRAY_ITERATOR_TYPE; import org.mozilla.javascript.ScriptRuntime; import org.mozilla.javascript.Scriptable; import org.mozilla.javascript.ScriptableObject; -import org.mozilla.javascript.Symbol; import org.mozilla.javascript.SymbolKey; import org.mozilla.javascript.Undefined; import org.mozilla.javascript.Wrapper; @@ -151,6 +150,333 @@ private static int toIndex(double num) { // Actual functions + static void init( + Context cx, Scriptable scope, LambdaConstructor constructor, RealThis realThis) { + constructor.definePrototypeProperty( + cx, + "buffer", + (Scriptable thisObj) -> js_buffer(thisObj, realThis), + DONTENUM | READONLY); + constructor.definePrototypeProperty( + cx, + "byteLength", + (Scriptable thisObj) -> js_byteLength(thisObj, realThis), + DONTENUM | READONLY); + constructor.definePrototypeProperty( + cx, + "byteOffset", + (Scriptable thisObj) -> js_byteOffset(thisObj, realThis), + DONTENUM | READONLY); + constructor.definePrototypeProperty( + cx, + "length", + (Scriptable thisObj) -> js_length(thisObj, realThis), + DONTENUM | READONLY); + + constructor.definePrototypeMethod( + scope, + "at", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + js_at(lcx, lscope, thisObj, args, realThis), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "copyWithin", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + js_copyWithin(lcx, lscope, thisObj, args, realThis), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "entries", + 0, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + NativeTypedArrayView self = realThis.realThis(thisObj); + return new NativeArrayIterator(lscope, self, ARRAY_ITERATOR_TYPE.ENTRIES); + }, + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "every", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + NativeTypedArrayView self = realThis.realThis(thisObj); + return ArrayLikeAbstractOperations.iterativeMethod( + lcx, IterativeOperation.EVERY, lscope, self, args); + }, + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "fill", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + js_fill(lcx, lscope, thisObj, args, realThis), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "filter", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + NativeTypedArrayView self = realThis.realThis(thisObj); + Object array = + ArrayLikeAbstractOperations.iterativeMethod( + lcx, IterativeOperation.FILTER, lscope, self, args); + return self.typedArraySpeciesCreate( + lcx, lscope, new Object[] {array}, "filter"); + }, + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "find", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + NativeTypedArrayView self = realThis.realThis(thisObj); + return ArrayLikeAbstractOperations.iterativeMethod( + lcx, IterativeOperation.FIND, lscope, self, args); + }, + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "findIndex", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + NativeTypedArrayView self = realThis.realThis(thisObj); + return ArrayLikeAbstractOperations.iterativeMethod( + lcx, IterativeOperation.FIND_INDEX, lscope, self, args); + }, + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "findLast", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + NativeTypedArrayView self = realThis.realThis(thisObj); + return ArrayLikeAbstractOperations.iterativeMethod( + lcx, IterativeOperation.FIND_LAST, lscope, self, args); + }, + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "findLastIndex", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + NativeTypedArrayView self = realThis.realThis(thisObj); + return ArrayLikeAbstractOperations.iterativeMethod( + lcx, IterativeOperation.FIND_LAST_INDEX, lscope, self, args); + }, + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "forEach", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + NativeTypedArrayView self = realThis.realThis(thisObj); + return ArrayLikeAbstractOperations.iterativeMethod( + lcx, IterativeOperation.FOR_EACH, lscope, self, args); + }, + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "includes", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + js_includes(lcx, lscope, thisObj, args, realThis), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "indexOf", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + js_indexOf(lcx, lscope, thisObj, args, realThis), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "join", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + js_join(lcx, lscope, thisObj, args, realThis), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "keys", + 0, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + NativeTypedArrayView self = realThis.realThis(thisObj); + return new NativeArrayIterator(lscope, self, ARRAY_ITERATOR_TYPE.KEYS); + }, + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "lastIndexOf", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + js_lastIndexOf(lcx, lscope, thisObj, args, realThis), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "map", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + NativeTypedArrayView self = realThis.realThis(thisObj); + Object array = + ArrayLikeAbstractOperations.iterativeMethod( + lcx, IterativeOperation.MAP, lscope, thisObj, args); + return self.typedArraySpeciesCreate(lcx, lscope, new Object[] {array}, "map"); + }, + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "reduce", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + NativeTypedArrayView self = realThis.realThis(thisObj); + return ArrayLikeAbstractOperations.reduceMethod( + lcx, ReduceOperation.REDUCE, lscope, self, args); + }, + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "reduceRight", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + NativeTypedArrayView self = realThis.realThis(thisObj); + return ArrayLikeAbstractOperations.reduceMethod( + lcx, ReduceOperation.REDUCE_RIGHT, lscope, self, args); + }, + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "reverse", + 0, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + js_reverse(lcx, lscope, thisObj, args, realThis), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "set", + 0, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + js_set(lcx, lscope, thisObj, args, realThis), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "slice", + 2, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + js_slice(lcx, lscope, thisObj, args, realThis), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "some", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + NativeTypedArrayView self = realThis.realThis(thisObj); + return ArrayLikeAbstractOperations.iterativeMethod( + lcx, IterativeOperation.SOME, lscope, self, args); + }, + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "sort", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + js_sort(lcx, lscope, thisObj, args, realThis), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "subarray", + 2, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + js_subarray(lcx, lscope, thisObj, args, realThis), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "toLocaleString", + 0, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + js_toString(lcx, lscope, thisObj, args, realThis, true), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "toReversed", + 0, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + js_toReversed(lcx, lscope, thisObj, args, realThis), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "toSorted", + 1, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + js_toSorted(lcx, lscope, thisObj, args, realThis), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "toString", + 0, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + js_toString(lcx, lscope, thisObj, args, realThis, false), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "values", + 0, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + NativeTypedArrayView self = realThis.realThis(thisObj); + return new NativeArrayIterator(lscope, self, ARRAY_ITERATOR_TYPE.VALUES); + }, + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + "with", + 2, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> + js_with(lcx, lscope, thisObj, args, realThis), + DONTENUM, + DONTENUM | READONLY); + constructor.definePrototypeMethod( + scope, + SymbolKey.ITERATOR, + 0, + (Context lcx, Scriptable lscope, Scriptable thisObj, Object[] args) -> { + NativeTypedArrayView self = realThis.realThis(thisObj); + return new NativeArrayIterator(lscope, self, ARRAY_ITERATOR_TYPE.VALUES); + }, + DONTENUM, + DONTENUM | READONLY); + } + protected boolean checkIndex(int index) { return ((index < 0) || (index >= length)); } @@ -161,45 +487,54 @@ protected boolean checkIndex(int index) { */ public abstract int getBytesPerElement(); - protected abstract NativeTypedArrayView construct(NativeArrayBuffer ab, int off, int len); - protected abstract Object js_get(int index); protected abstract Object js_set(int index, Object c); - protected abstract NativeTypedArrayView realThis(Scriptable thisObj, IdFunctionObject f); - - private NativeArrayBuffer makeArrayBuffer(Context cx, Scriptable scope, int length) { + private static NativeArrayBuffer makeArrayBuffer( + Context cx, Scriptable scope, int length, int bytesPerElement) { return (NativeArrayBuffer) cx.newObject( scope, NativeArrayBuffer.CLASS_NAME, - new Object[] {Double.valueOf((double) length * getBytesPerElement())}); + new Object[] {Double.valueOf((double) length * bytesPerElement)}); } - private NativeTypedArrayView js_constructor(Context cx, Scriptable scope, Object[] args) { + protected interface TypedArrayConstructable { + NativeTypedArrayView construct(NativeArrayBuffer ab, int off, int len); + } + + protected interface RealThis { + NativeTypedArrayView realThis(Scriptable thisObj); + } + + protected static NativeTypedArrayView js_constructor( + Context cx, + Scriptable scope, + Object[] args, + TypedArrayConstructable constructable, + int bytesPerElement) { if (!isArg(args, 0)) { - return construct(new NativeArrayBuffer(), 0, 0); + return constructable.construct(new NativeArrayBuffer(), 0, 0); } final Object arg0 = args[0]; if (arg0 == null) { - return construct(new NativeArrayBuffer(), 0, 0); + return constructable.construct(new NativeArrayBuffer(), 0, 0); } if ((arg0 instanceof Number) || (arg0 instanceof String)) { // Create a zeroed-out array of a certain length int length = ScriptRuntime.toInt32(arg0); - NativeArrayBuffer buffer = makeArrayBuffer(cx, scope, length); - return construct(buffer, 0, length); + NativeArrayBuffer buffer = makeArrayBuffer(cx, scope, length, bytesPerElement); + return constructable.construct(buffer, 0, length); } if (arg0 instanceof NativeTypedArrayView) { // Copy elements from the old array and convert them into our own - @SuppressWarnings("unchecked") - NativeTypedArrayView src = (NativeTypedArrayView) arg0; - NativeArrayBuffer na = makeArrayBuffer(cx, scope, src.length); - NativeTypedArrayView v = construct(na, 0, src.length); + NativeTypedArrayView src = (NativeTypedArrayView) arg0; + NativeArrayBuffer na = makeArrayBuffer(cx, scope, src.length, bytesPerElement); + NativeTypedArrayView v = constructable.construct(na, 0, src.length); for (int i = 0; i < src.length; i++) { v.js_set(i, src.js_get(i)); @@ -214,34 +549,34 @@ private NativeTypedArrayView js_constructor(Context cx, Scriptable scope, Obj int byteLen; if (isArg(args, 2)) { - byteLen = ScriptRuntime.toInt32(args[2]) * getBytesPerElement(); + byteLen = ScriptRuntime.toInt32(args[2]) * bytesPerElement; } else { byteLen = na.getLength() - byteOff; } - if ((byteOff < 0) || (byteOff > na.buffer.length)) { + if ((byteOff < 0) || (byteOff > na.getLength())) { throw ScriptRuntime.rangeError("offset out of range"); } - if ((byteLen < 0) || ((byteOff + byteLen) > na.buffer.length)) { + if ((byteLen < 0) || ((byteOff + byteLen) > na.getLength())) { throw ScriptRuntime.rangeError("length out of range"); } - if ((byteOff % getBytesPerElement()) != 0) { + if ((byteOff % bytesPerElement) != 0) { throw ScriptRuntime.rangeError("offset must be a multiple of the byte size"); } - if ((byteLen % getBytesPerElement()) != 0) { + if ((byteLen % bytesPerElement) != 0) { throw ScriptRuntime.rangeError( "offset and buffer must be a multiple of the byte size"); } - return construct(na, byteOff, byteLen / getBytesPerElement()); + return constructable.construct(na, byteOff, byteLen / bytesPerElement); } if (arg0 instanceof NativeArray) { // Copy elements of the array and convert them to the correct type NativeArray array = (NativeArray) arg0; - NativeArrayBuffer na = makeArrayBuffer(cx, scope, array.size()); - NativeTypedArrayView v = construct(na, 0, array.size()); + NativeArrayBuffer na = makeArrayBuffer(cx, scope, array.size(), bytesPerElement); + NativeTypedArrayView v = constructable.construct(na, 0, array.size()); for (int i = 0; i < array.size(); i++) { // we have to call this here to get the raw value; // null has to be forewoded as null @@ -261,8 +596,9 @@ private NativeTypedArrayView js_constructor(Context cx, Scriptable scope, Obj // Copy elements of the array and convert them to the correct type Object[] arrayElements = ScriptRuntime.getArrayElements((Scriptable) arg0); - NativeArrayBuffer na = makeArrayBuffer(cx, scope, arrayElements.length); - NativeTypedArrayView v = construct(na, 0, arrayElements.length); + NativeArrayBuffer na = + makeArrayBuffer(cx, scope, arrayElements.length, bytesPerElement); + NativeTypedArrayView v = constructable.construct(na, 0, arrayElements.length); for (int i = 0; i < arrayElements.length; i++) { v.js_set(i, arrayElements[i]); } @@ -271,7 +607,7 @@ private NativeTypedArrayView js_constructor(Context cx, Scriptable scope, Obj throw ScriptRuntime.constructError("Error", "invalid argument"); } - private void setRange(NativeTypedArrayView v, int off) { + private void setRange(NativeTypedArrayView v, int off) { if (off >= length) { throw ScriptRuntime.rangeError("offset out of range"); } @@ -311,15 +647,41 @@ private void setRange(NativeArray a, int off) { } } - private String js_toString(Context cx, Scriptable scope, boolean useLocale) { + private static Object js_buffer(Scriptable thisObj, RealThis realThis) { + return realThis.realThis(thisObj).arrayBuffer; + } + + private static Object js_byteLength(Scriptable thisObj, RealThis realThis) { + NativeTypedArrayView o = realThis.realThis(thisObj); + return o.byteLength; + } + + private static Object js_byteOffset(Scriptable thisObj, RealThis realThis) { + NativeTypedArrayView o = realThis.realThis(thisObj); + return o.offset; + } + + private static Object js_length(Scriptable thisObj, RealThis realThis) { + NativeTypedArrayView o = realThis.realThis(thisObj); + return o.length; + } + + private static String js_toString( + Context cx, + Scriptable scope, + Scriptable thisObj, + Object[] args, + RealThis realThis, + boolean useLocale) { + NativeTypedArrayView self = realThis.realThis(thisObj); StringBuilder builder = new StringBuilder(); - if (length > 0) { - Object elem = getElemForToString(cx, scope, 0, useLocale); + if (self.length > 0) { + Object elem = self.getElemForToString(cx, scope, 0, useLocale); builder.append(ScriptRuntime.toString(elem)); } - for (int i = 1; i < length; i++) { + for (int i = 1; i < self.length; i++) { builder.append(','); - Object elem = getElemForToString(cx, scope, i, useLocale); + Object elem = self.getElemForToString(cx, scope, i, useLocale); builder.append(ScriptRuntime.toString(elem)); } return builder.toString(); @@ -336,10 +698,12 @@ private Object getElemForToString(Context cx, Scriptable scope, int index, boole } } - private Boolean js_includes(Object[] args) { + private static Boolean js_includes( + Context cx, Scriptable scope, Scriptable thisObj, Object[] args, RealThis realThis) { + NativeTypedArrayView self = realThis.realThis(thisObj); Object compareTo = args.length > 0 ? args[0] : Undefined.instance; - if (length == 0) return Boolean.FALSE; + if (self.length == 0) return Boolean.FALSE; long start; if (args.length < 2) { @@ -347,13 +711,13 @@ private Boolean js_includes(Object[] args) { } else { start = (long) ScriptRuntime.toInteger(args[1]); if (start < 0) { - start += length; + start += self.length; if (start < 0) start = 0; } - if (start > length - 1) return Boolean.FALSE; + if (start > self.length - 1) return Boolean.FALSE; } - for (int i = (int) start; i < length; i++) { - Object val = js_get(i); + for (int i = (int) start; i < self.length; i++) { + Object val = self.js_get(i); if (ScriptRuntime.sameZero(val, compareTo)) { return Boolean.TRUE; } @@ -361,10 +725,13 @@ private Boolean js_includes(Object[] args) { return Boolean.FALSE; } - private Object js_indexOf(Object[] args) { + private static Object js_indexOf( + Context cx, Scriptable scope, Scriptable thisObj, Object[] args, RealThis realThis) { + NativeTypedArrayView self = realThis.realThis(thisObj); + Object compareTo = args.length > 0 ? args[0] : Undefined.instance; - if (length == 0) return -1; + if (self.length == 0) return -1; long start; if (args.length < 2) { @@ -373,13 +740,13 @@ private Object js_indexOf(Object[] args) { } else { start = (long) ScriptRuntime.toInteger(args[1]); if (start < 0) { - start += length; + start += self.length; if (start < 0) start = 0; } - if (start > length - 1) return -1; + if (start > self.length - 1) return -1; } - for (int i = (int) start; i < length; i++) { - Object val = js_get(i); + for (int i = (int) start; i < self.length; i++) { + Object val = self.js_get(i); if (val != NOT_FOUND && ScriptRuntime.shallowEq(val, compareTo)) { return (long) i; } @@ -387,23 +754,26 @@ private Object js_indexOf(Object[] args) { return -1; } - private Object js_lastIndexOf(Object[] args) { + private static Object js_lastIndexOf( + Context cx, Scriptable scope, Scriptable thisObj, Object[] args, RealThis realThis) { + NativeTypedArrayView self = realThis.realThis(thisObj); + Object compareTo = args.length > 0 ? args[0] : Undefined.instance; - if (length == 0) return -1; + if (self.length == 0) return -1; long start; if (args.length < 2) { // default - start = length - 1L; + start = self.length - 1L; } else { start = (long) ScriptRuntime.toInteger(args[1]); - if (start >= length) start = length - 1L; - else if (start < 0) start += length; + if (start >= self.length) start = self.length - 1L; + else if (start < 0) start += self.length; if (start < 0) return -1; } for (int i = (int) start; i >= 0; i--) { - Object val = js_get(i); + Object val = self.js_get(i); if (val != NOT_FOUND && ScriptRuntime.shallowEq(val, compareTo)) { return (long) i; } @@ -411,21 +781,24 @@ private Object js_lastIndexOf(Object[] args) { return -1; } - private Scriptable js_slice(Context cx, Scriptable scope, Object[] args) { + private static Scriptable js_slice( + Context cx, Scriptable scope, Scriptable thisObj, Object[] args, RealThis realThis) { + NativeTypedArrayView self = realThis.realThis(thisObj); + long begin, end; if (args.length == 0) { begin = 0; - end = length; + end = self.length; } else { begin = ArrayLikeAbstractOperations.toSliceIndex( - ScriptRuntime.toInteger(args[0]), length); + ScriptRuntime.toInteger(args[0]), self.length); if (args.length == 1 || args[1] == Undefined.instance) { - end = length; + end = self.length; } else { end = ArrayLikeAbstractOperations.toSliceIndex( - ScriptRuntime.toInteger(args[1]), length); + ScriptRuntime.toInteger(args[1]), self.length); } } @@ -434,37 +807,42 @@ private Scriptable js_slice(Context cx, Scriptable scope, Object[] args) { throw ScriptRuntime.rangeError(msg); } - return typedArraySpeciesCreate( + long count = Math.max(end - begin, 0); + + return self.typedArraySpeciesCreate( cx, scope, new Object[] { - this.arrayBuffer, begin * this.getBytesPerElement(), Math.max(0, end - begin) + self.arrayBuffer, begin * self.getBytesPerElement(), Math.max(0, end - begin) }, "slice"); } - private String js_join(Object[] args) { + private static String js_join( + Context cx, Scriptable scope, Scriptable thisObj, Object[] args, RealThis realThis) { + NativeTypedArrayView self = realThis.realThis(thisObj); + // if no args, use "," as separator String separator = (args.length < 1 || args[0] == Undefined.instance) ? "," : ScriptRuntime.toString(args[0]); - if (length == 0) { + if (self.length == 0) { return ""; } - String[] buf = new String[length]; + String[] buf = new String[self.length]; int total_size = 0; - for (int i = 0; i != length; i++) { - Object temp = js_get(i); + for (int i = 0; i != self.length; i++) { + Object temp = self.js_get(i); if (temp != null && temp != Undefined.instance) { String str = ScriptRuntime.toString(temp); total_size += str.length(); buf[i] = str; } } - total_size += (length - 1) * separator.length(); + total_size += (self.length - 1) * separator.length(); StringBuilder sb = new StringBuilder(total_size); - for (int i = 0; i != length; i++) { + for (int i = 0; i != self.length; i++) { if (i != 0) { sb.append(separator); } @@ -477,53 +855,66 @@ private String js_join(Object[] args) { return sb.toString(); } - private NativeTypedArrayView js_reverse() { - for (int i = 0, j = length - 1; i < j; i++, j--) { - Object temp = js_get(i); - js_set(i, js_get(j)); - js_set(j, temp); + private static NativeTypedArrayView js_reverse( + Context cx, Scriptable scope, Scriptable thisObj, Object[] args, RealThis realThis) { + NativeTypedArrayView self = realThis.realThis(thisObj); + + for (int i = 0, j = self.length - 1; i < j; i++, j--) { + Object temp = self.js_get(i); + self.js_set(i, self.js_get(j)); + self.js_set(j, temp); } - return this; + return self; } - private NativeTypedArrayView js_fill(Object[] args) { + private static NativeTypedArrayView js_fill( + Context cx, Scriptable scope, Scriptable thisObj, Object[] args, RealThis realThis) { + NativeTypedArrayView self = realThis.realThis(thisObj); + long relativeStart = 0; if (args.length >= 2) { relativeStart = (long) ScriptRuntime.toInteger(args[1]); } final long k; if (relativeStart < 0) { - k = Math.max((length + relativeStart), 0); + k = Math.max((self.length + relativeStart), 0); } else { - k = Math.min(relativeStart, length); + k = Math.min(relativeStart, self.length); } - long relativeEnd = length; + long relativeEnd = self.length; if (args.length >= 3 && !Undefined.isUndefined(args[2])) { relativeEnd = (long) ScriptRuntime.toInteger(args[2]); } final long fin; if (relativeEnd < 0) { - fin = Math.max((length + relativeEnd), 0); + fin = Math.max((self.length + relativeEnd), 0); } else { - fin = Math.min(relativeEnd, length); + fin = Math.min(relativeEnd, self.length); } Object value = args.length > 0 ? args[0] : Undefined.instance; for (int i = (int) k; i < fin; i++) { - js_set(i, value); + self.js_set(i, value); } - return this; + return self; } - private Scriptable js_sort(Context cx, Scriptable scope, Object[] args) { - Object[] working = sortTemporaryArray(cx, scope, args); - for (int i = 0; i < length; ++i) { - js_set(i, working[i]); + private static Scriptable js_sort( + Context cx, Scriptable scope, Scriptable thisObj, Object[] args, RealThis realThis) { + if (isArg(args, 0) && !(args[0] instanceof Callable)) { + throw ScriptRuntime.typeErrorById("msg.function.expected"); } - return this; + NativeTypedArrayView self = realThis.realThis(thisObj); + + Object[] working = self.sortTemporaryArray(cx, scope, args); + for (int i = 0; i < self.length; ++i) { + self.js_set(i, working[i]); + } + + return self; } private Object[] sortTemporaryArray(Context cx, Scriptable scope, Object[] args) { @@ -540,37 +931,40 @@ private Object[] sortTemporaryArray(Context cx, Scriptable scope, Object[] args) return working; } - private Object js_copyWithin(Object[] args) { + private static Object js_copyWithin( + Context cx, Scriptable scope, Scriptable thisObj, Object[] args, RealThis realThis) { + NativeTypedArrayView self = realThis.realThis(thisObj); + Object targetArg = (args.length >= 1) ? args[0] : Undefined.instance; long relativeTarget = (long) ScriptRuntime.toInteger(targetArg); long to; if (relativeTarget < 0) { - to = Math.max((length + relativeTarget), 0); + to = Math.max((self.length + relativeTarget), 0); } else { - to = Math.min(relativeTarget, length); + to = Math.min(relativeTarget, self.length); } Object startArg = (args.length >= 2) ? args[1] : Undefined.instance; long relativeStart = (long) ScriptRuntime.toInteger(startArg); long from; if (relativeStart < 0) { - from = Math.max((length + relativeStart), 0); + from = Math.max((self.length + relativeStart), 0); } else { - from = Math.min(relativeStart, length); + from = Math.min(relativeStart, self.length); } - long relativeEnd = length; + long relativeEnd = self.length; if (args.length >= 3 && !Undefined.isUndefined(args[2])) { relativeEnd = (long) ScriptRuntime.toInteger(args[2]); } final long fin; if (relativeEnd < 0) { - fin = Math.max((length + relativeEnd), 0); + fin = Math.max((self.length + relativeEnd), 0); } else { - fin = Math.min(relativeEnd, length); + fin = Math.min(relativeEnd, self.length); } - long count = Math.min(fin - from, length - to); + long count = Math.min(fin - from, self.length - to); int direction = 1; if (from < to && to < from + count) { direction = -1; @@ -579,38 +973,78 @@ private Object js_copyWithin(Object[] args) { } for (; count > 0; count--) { - final Object temp = js_get((int) from); - js_set((int) to, temp); + final Object temp = self.js_get((int) from); + self.js_set((int) to, temp); from += direction; to += direction; } - return this; + return self; } - private Object js_subarray(Context cx, Scriptable scope, int s, int e) { - int start = (s < 0 ? length + s : s); - int end = (e < 0 ? length + e : e); + private static Object js_set( + Context cx, Scriptable scope, Scriptable thisObj, Object[] args, RealThis realThis) { + NativeTypedArrayView self = realThis.realThis(thisObj); + if (args.length > 0) { + if (args[0] instanceof NativeTypedArrayView) { + int offset = isArg(args, 1) ? ScriptRuntime.toInt32(args[1]) : 0; + NativeTypedArrayView nativeView = (NativeTypedArrayView) args[0]; + self.setRange(nativeView, offset); + return Undefined.instance; + } + if (args[0] instanceof NativeArray) { + int offset = isArg(args, 1) ? ScriptRuntime.toInt32(args[1]) : 0; + self.setRange((NativeArray) args[0], offset); + return Undefined.instance; + } + if (args[0] instanceof Scriptable) { + // Tests show that we need to ignore a non-array object + return Undefined.instance; + } + if (isArg(args, 2)) { + return self.js_set(ScriptRuntime.toInt32(args[0]), args[1]); + } + } + throw ScriptRuntime.constructError("Error", "invalid arguments"); + } + + private static Object js_subarray( + Context cx, Scriptable scope, Scriptable thisObj, Object[] args, RealThis realThis) { + NativeTypedArrayView self = realThis.realThis(thisObj); - // Clamping behavior as described by the spec. - start = Math.max(0, start); - end = Math.min(length, end); - int len = Math.max(0, (end - start)); - int byteOff = - Math.min(getByteOffset() + start * getBytesPerElement(), arrayBuffer.getLength()); + int start = isArg(args, 0) ? ScriptRuntime.toInt32(args[0]) : 0; + int end = isArg(args, 1) ? ScriptRuntime.toInt32(args[1]) : self.length; + if (cx.getLanguageVersion() >= Context.VERSION_ES6 || args.length > 0) { + start = (start < 0 ? self.length + start : start); + end = (end < 0 ? self.length + end : end); - return cx.newObject(scope, getClassName(), new Object[] {arrayBuffer, byteOff, len}); + // Clamping behavior as described by the spec. + start = Math.max(0, start); + end = Math.min(self.length, end); + int len = Math.max(0, (end - start)); + int byteOff = + Math.min( + self.getByteOffset() + start * self.getBytesPerElement(), + self.arrayBuffer.getLength()); + + return cx.newObject( + scope, self.getClassName(), new Object[] {self.arrayBuffer, byteOff, len}); + } + throw ScriptRuntime.constructError("Error", "invalid arguments"); } - private Object js_at(Scriptable thisObj, Object[] args) { + private static Object js_at( + Context cx, Scriptable scope, Scriptable thisObj, Object[] args, RealThis realThis) { + NativeTypedArrayView self = realThis.realThis(thisObj); + long relativeIndex = 0; if (args.length >= 1) { relativeIndex = (long) ScriptRuntime.toInteger(args[0]); } - long k = (relativeIndex >= 0) ? relativeIndex : length + relativeIndex; + long k = (relativeIndex >= 0) ? relativeIndex : self.length + relativeIndex; - if ((k < 0) || (k >= length)) { + if ((k < 0) || (k >= self.length)) { return Undefined.instance; } @@ -632,610 +1066,77 @@ private Scriptable typedArraySpeciesCreate( return newArray; } - private Object js_toReversed(Context cx, Scriptable scope) { - NativeArrayBuffer newBuffer = new NativeArrayBuffer(length * getBytesPerElement()); + private static Object js_toReversed( + Context cx, Scriptable scope, Scriptable thisObj, Object[] args, RealThis realThis) { + NativeTypedArrayView self = realThis.realThis(thisObj); + + NativeArrayBuffer newBuffer = + new NativeArrayBuffer(self.length * self.getBytesPerElement()); Scriptable result = cx.newObject( scope, - getClassName(), - new Object[] {newBuffer, 0, length, getBytesPerElement()}); + self.getClassName(), + new Object[] {newBuffer, 0, self.length, self.getBytesPerElement()}); - for (int k = 0; k < length; ++k) { - int from = length - k - 1; - Object fromValue = js_get(from); + for (int k = 0; k < self.length; ++k) { + int from = self.length - k - 1; + Object fromValue = self.js_get(from); result.put(k, result, fromValue); } return result; } - private Object js_toSorted(Context cx, Scriptable scope, Object[] args) { - Object[] working = sortTemporaryArray(cx, scope, args); + private static Object js_toSorted( + Context cx, Scriptable scope, Scriptable thisObj, Object[] args, RealThis realThis) { + NativeTypedArrayView self = realThis.realThis(thisObj); + + Object[] working = self.sortTemporaryArray(cx, scope, args); // Move value in a new typed array of the same type - NativeArrayBuffer newBuffer = new NativeArrayBuffer(length * getBytesPerElement()); + NativeArrayBuffer newBuffer = + new NativeArrayBuffer(self.length * self.getBytesPerElement()); Scriptable result = cx.newObject( scope, - getClassName(), - new Object[] {newBuffer, 0, length, getBytesPerElement()}); - for (int k = 0; k < length; ++k) { + self.getClassName(), + new Object[] {newBuffer, 0, self.length, self.getBytesPerElement()}); + for (int k = 0; k < self.length; ++k) { result.put(k, result, working[k]); } return result; } - private Object js_with(Context cx, Scriptable scope, Object[] args) { + private static Object js_with( + Context cx, Scriptable scope, Scriptable thisObj, Object[] args, RealThis realThis) { + NativeTypedArrayView self = realThis.realThis(thisObj); + long relativeIndex = args.length > 0 ? (int) ScriptRuntime.toInteger(args[0]) : 0; - long actualIndex = relativeIndex >= 0 ? relativeIndex : length + relativeIndex; + long actualIndex = relativeIndex >= 0 ? relativeIndex : self.length + relativeIndex; Object argsValue = args.length > 1 ? ScriptRuntime.toNumber(args[1]) : 0.0; - if (actualIndex < 0 || actualIndex >= length) { + if (actualIndex < 0 || actualIndex >= self.length) { throw ScriptRuntime.rangeError("index out of range"); } - NativeArrayBuffer newBuffer = new NativeArrayBuffer(length * getBytesPerElement()); + NativeArrayBuffer newBuffer = + new NativeArrayBuffer(self.length * self.getBytesPerElement()); Scriptable result = cx.newObject( scope, - getClassName(), - new Object[] {newBuffer, 0, length, getBytesPerElement()}); + self.getClassName(), + new Object[] {newBuffer, 0, self.length, self.getBytesPerElement()}); - for (int k = 0; k < length; ++k) { - Object fromValue = (k == actualIndex) ? argsValue : js_get(k); + for (int k = 0; k < self.length; ++k) { + Object fromValue = (k == actualIndex) ? argsValue : self.js_get(k); result.put(k, result, fromValue); } return result; } - // Dispatcher - - @Override - public Object execIdCall( - IdFunctionObject f, Context cx, Scriptable scope, Scriptable thisObj, Object[] args) { - if (!f.hasTag(getClassName())) { - return super.execIdCall(f, cx, scope, thisObj, args); - } - int id = f.methodId(); - switch (id) { - case Id_constructor: - if (thisObj != null && cx.getLanguageVersion() >= Context.VERSION_ES6) { - throw ScriptRuntime.typeErrorById("msg.only.from.new", getClassName()); - } - return js_constructor(cx, scope, args); - - case Id_toString: - return realThis(thisObj, f).js_toString(cx, scope, false); - case Id_toLocaleString: - return realThis(thisObj, f).js_toString(cx, scope, true); - case Id_includes: - return realThis(thisObj, f).js_includes(args); - case Id_indexOf: - return realThis(thisObj, f).js_indexOf(args); - case Id_lastIndexOf: - return realThis(thisObj, f).js_lastIndexOf(args); - case Id_slice: - return realThis(thisObj, f).js_slice(cx, scope, args); - case Id_join: - return realThis(thisObj, f).js_join(args); - case Id_reverse: - return realThis(thisObj, f).js_reverse(); - case Id_fill: - return realThis(thisObj, f).js_fill(args); - case Id_sort: - return realThis(thisObj, f).js_sort(cx, scope, args); - case Id_copyWithin: - return realThis(thisObj, f).js_copyWithin(args); - - case Id_get: - if (args.length > 0) { - return realThis(thisObj, f).js_get(ScriptRuntime.toInt32(args[0])); - } - throw ScriptRuntime.constructError("Error", "invalid arguments"); - - case Id_set: - if (args.length > 0) { - NativeTypedArrayView self = realThis(thisObj, f); - if (args[0] instanceof NativeTypedArrayView) { - int offset = isArg(args, 1) ? ScriptRuntime.toInt32(args[1]) : 0; - @SuppressWarnings("unchecked") - NativeTypedArrayView nativeView = (NativeTypedArrayView) args[0]; - self.setRange(nativeView, offset); - return Undefined.instance; - } - if (args[0] instanceof NativeArray) { - int offset = isArg(args, 1) ? ScriptRuntime.toInt32(args[1]) : 0; - self.setRange((NativeArray) args[0], offset); - return Undefined.instance; - } - if (args[0] instanceof Scriptable) { - // Tests show that we need to ignore a non-array object - return Undefined.instance; - } - if (isArg(args, 2)) { - return self.js_set(ScriptRuntime.toInt32(args[0]), args[1]); - } - } - throw ScriptRuntime.constructError("Error", "invalid arguments"); - - case Id_subarray: - { - NativeTypedArrayView self = realThis(thisObj, f); - int start = isArg(args, 0) ? ScriptRuntime.toInt32(args[0]) : 0; - int end = isArg(args, 1) ? ScriptRuntime.toInt32(args[1]) : self.length; - if (cx.getLanguageVersion() >= Context.VERSION_ES6 || args.length > 0) { - return self.js_subarray(cx, scope, start, end); - } - throw ScriptRuntime.constructError("Error", "invalid arguments"); - } - - case Id_at: - { - NativeTypedArrayView self = realThis(thisObj, f); - if (cx.getLanguageVersion() >= Context.VERSION_ES6 || args.length > 0) { - return self.js_at(thisObj, args); - } - throw ScriptRuntime.constructError("Error", "invalid arguments"); - } - - case Id_entries: - { - NativeTypedArrayView self = realThis(thisObj, f); - return new NativeArrayIterator(scope, self, ARRAY_ITERATOR_TYPE.ENTRIES); - } - - case Id_keys: - { - NativeTypedArrayView self = realThis(thisObj, f); - return new NativeArrayIterator(scope, self, ARRAY_ITERATOR_TYPE.KEYS); - } - - case Id_values: - { - NativeTypedArrayView self = realThis(thisObj, f); - return new NativeArrayIterator(scope, self, ARRAY_ITERATOR_TYPE.VALUES); - } - - case Id_every: - return ArrayLikeAbstractOperations.iterativeMethod( - cx, f, IterativeOperation.EVERY, scope, thisObj, args); - case Id_filter: - { - // We first create an array and then we wrap it in a TypedArray. This could be - // more efficient. - Object array = - ArrayLikeAbstractOperations.iterativeMethod( - cx, f, IterativeOperation.FILTER, scope, thisObj, args); - return realThis(thisObj, f) - .typedArraySpeciesCreate(cx, scope, new Object[] {array}, "filter"); - } - case Id_forEach: - return ArrayLikeAbstractOperations.iterativeMethod( - cx, f, IterativeOperation.FOR_EACH, scope, thisObj, args); - case Id_map: - { - // We first create an array and then we wrap it in a TypedArray. This could be - // more efficient. - Object array = - ArrayLikeAbstractOperations.iterativeMethod( - cx, f, IterativeOperation.MAP, scope, thisObj, args); - return realThis(thisObj, f) - .typedArraySpeciesCreate(cx, scope, new Object[] {array}, "map"); - } - case Id_some: - return ArrayLikeAbstractOperations.iterativeMethod( - cx, f, IterativeOperation.SOME, scope, thisObj, args); - case Id_find: - return ArrayLikeAbstractOperations.iterativeMethod( - cx, f, IterativeOperation.FIND, scope, thisObj, args); - case Id_findIndex: - return ArrayLikeAbstractOperations.iterativeMethod( - cx, f, IterativeOperation.FIND_INDEX, scope, thisObj, args); - case Id_findLast: - return ArrayLikeAbstractOperations.iterativeMethod( - cx, f, IterativeOperation.FIND_LAST, scope, thisObj, args); - case Id_findLastIndex: - return ArrayLikeAbstractOperations.iterativeMethod( - cx, f, IterativeOperation.FIND_LAST_INDEX, scope, thisObj, args); - case Id_reduce: - return ArrayLikeAbstractOperations.reduceMethod( - cx, ReduceOperation.REDUCE, scope, thisObj, args); - case Id_reduceRight: - return ArrayLikeAbstractOperations.reduceMethod( - cx, ReduceOperation.REDUCE_RIGHT, scope, thisObj, args); - case Id_toReversed: - return realThis(thisObj, f).js_toReversed(cx, scope); - case Id_toSorted: - return realThis(thisObj, f).js_toSorted(cx, scope, args); - case Id_with: - return realThis(thisObj, f).js_with(cx, scope, args); - - case SymbolId_iterator: - return new NativeArrayIterator(scope, thisObj, ARRAY_ITERATOR_TYPE.VALUES); - } - throw new IllegalArgumentException(String.valueOf(id)); - } - - @Override - protected void initPrototypeId(int id) { - if (id == SymbolId_iterator) { - initPrototypeMethod(getClassName(), id, SymbolKey.ITERATOR, "[Symbol.iterator]", 0); - return; - } - - String s, fnName = null; - int arity; - switch (id) { - case Id_constructor: - arity = 3; - s = "constructor"; - break; - case Id_toString: - arity = 0; - s = "toString"; - break; - case Id_toLocaleString: - arity = 0; - s = "toLocaleString"; - break; - case Id_includes: - arity = 1; - s = "includes"; - break; - case Id_indexOf: - arity = 1; - s = "indexOf"; - break; - case Id_lastIndexOf: - arity = 1; - s = "lastIndexOf"; - break; - case Id_slice: - arity = 2; - s = "slice"; - break; - case Id_join: - arity = 1; - s = "join"; - break; - case Id_reverse: - arity = 0; - s = "reverse"; - break; - case Id_fill: - arity = 1; - s = "fill"; - break; - case Id_sort: - arity = 1; - s = "sort"; - break; - case Id_copyWithin: - arity = 2; - s = "copyWithin"; - break; - case Id_get: - arity = 1; - s = "get"; - break; - case Id_set: - arity = 2; - s = "set"; - break; - case Id_subarray: - arity = 2; - s = "subarray"; - break; - case Id_at: - arity = 1; - s = "at"; - break; - case Id_entries: - arity = 0; - s = "entries"; - break; - case Id_keys: - arity = 0; - s = "keys"; - break; - case Id_values: - arity = 0; - s = "values"; - break; - case Id_every: - arity = 1; - s = "every"; - break; - case Id_filter: - arity = 1; - s = "filter"; - break; - case Id_forEach: - arity = 1; - s = "forEach"; - break; - case Id_map: - arity = 1; - s = "map"; - break; - case Id_some: - arity = 1; - s = "some"; - break; - case Id_find: - arity = 1; - s = "find"; - break; - case Id_findIndex: - arity = 1; - s = "findIndex"; - break; - case Id_findLast: - arity = 1; - s = "findLast"; - break; - case Id_findLastIndex: - arity = 1; - s = "findLastIndex"; - break; - case Id_reduce: - arity = 1; - s = "reduce"; - break; - case Id_reduceRight: - arity = 1; - s = "reduceRight"; - break; - case Id_toSorted: - arity = 1; - s = "toSorted"; - break; - case Id_toReversed: - arity = 0; - s = "toReversed"; - break; - case Id_with: - arity = 2; - s = "with"; - break; - default: - throw new IllegalArgumentException(String.valueOf(id)); - } - initPrototypeMethod(getClassName(), id, s, fnName, arity); - } - - @Override - protected int findPrototypeId(Symbol k) { - if (SymbolKey.ITERATOR.equals(k)) { - return SymbolId_iterator; - } - return 0; - } - - @Override - protected int findPrototypeId(String s) { - int id; - switch (s) { - case "constructor": - id = Id_constructor; - break; - case "toString": - id = Id_toString; - break; - case "toLocaleString": - id = Id_toLocaleString; - break; - case "includes": - id = Id_includes; - break; - case "indexOf": - id = Id_indexOf; - break; - case "lastIndexOf": - id = Id_lastIndexOf; - break; - case "slice": - id = Id_slice; - break; - case "join": - id = Id_join; - break; - case "reverse": - id = Id_reverse; - break; - case "fill": - id = Id_fill; - break; - case "sort": - id = Id_sort; - break; - case "copyWithin": - id = Id_copyWithin; - break; - case "get": - id = Id_get; - break; - case "set": - id = Id_set; - break; - case "subarray": - id = Id_subarray; - break; - case "at": - id = Id_at; - break; - case "entries": - id = Id_entries; - break; - case "keys": - id = Id_keys; - break; - case "values": - id = Id_values; - break; - case "every": - id = Id_every; - break; - case "filter": - id = Id_filter; - break; - case "forEach": - id = Id_forEach; - break; - case "map": - id = Id_map; - break; - case "some": - id = Id_some; - break; - case "find": - id = Id_find; - break; - case "findIndex": - id = Id_findIndex; - break; - case "findLast": - id = Id_findLast; - break; - case "findLastIndex": - id = Id_findLastIndex; - break; - case "reduce": - id = Id_reduce; - break; - case "reduceRight": - id = Id_reduceRight; - break; - case "toSorted": - id = Id_toSorted; - break; - case "toReversed": - id = Id_toReversed; - break; - case "with": - id = Id_with; - break; - default: - id = 0; - break; - } - return id; - } - - // Table of all functions - private static final int Id_constructor = 1, - Id_toString = 2, - Id_toLocaleString = 3, - Id_includes = 4, - Id_indexOf = 5, - Id_lastIndexOf = 6, - Id_slice = 7, - Id_join = 8, - Id_reverse = 9, - Id_fill = 10, - Id_sort = 11, - Id_copyWithin = 12, - Id_get = 13, - Id_set = 14, - Id_subarray = 15, - Id_at = 16, - Id_entries = 17, - Id_keys = 18, - Id_values = 19, - Id_every = 20, - Id_filter = 21, - Id_forEach = 22, - Id_map = 23, - Id_some = 24, - Id_find = 25, - Id_findIndex = 26, - Id_findLast = 27, - Id_findLastIndex = 28, - Id_reduce = 29, - Id_reduceRight = 30, - Id_toReversed = 31, - Id_toSorted = 32, - Id_with = 33, - SymbolId_iterator = 34; - - protected static final int MAX_PROTOTYPE_ID = SymbolId_iterator; - - // Constructor properties - - @Override - protected void fillConstructorProperties(IdFunctionObject ctor) { - ctor.defineProperty( - "BYTES_PER_ELEMENT", - ScriptRuntime.wrapInt(getBytesPerElement()), - DONTENUM | PERMANENT | READONLY); - - super.fillConstructorProperties(ctor); - } - - // Property dispatcher - - @Override - protected int getMaxInstanceId() { - return MAX_INSTANCE_ID; - } - - @Override - protected String getInstanceIdName(int id) { - switch (id) { - case Id_length: - return "length"; - case Id_BYTES_PER_ELEMENT: - return "BYTES_PER_ELEMENT"; - default: - return super.getInstanceIdName(id); - } - } - - @Override - protected Object getInstanceIdValue(int id) { - switch (id) { - case Id_length: - return ScriptRuntime.wrapInt(length); - case Id_BYTES_PER_ELEMENT: - return ScriptRuntime.wrapInt(getBytesPerElement()); - default: - return super.getInstanceIdValue(id); - } - } - - @Override - protected int findInstanceIdInfo(String s) { - int id; - switch (s) { - case "length": - id = Id_length; - break; - case "BYTES_PER_ELEMENT": - id = Id_BYTES_PER_ELEMENT; - break; - default: - id = 0; - break; - } - if (id == 0) { - return super.findInstanceIdInfo(s); - } - if (id == Id_BYTES_PER_ELEMENT) { - return instanceIdInfo(DONTENUM | READONLY | PERMANENT, id); - } - return instanceIdInfo(READONLY | PERMANENT, id); - } - - /* - * These must not conflict with ids in the parent since we delegate there for property dispatching. - */ - private static final int Id_length = NativeArrayBufferView.MAX_INSTANCE_ID + 1, - Id_BYTES_PER_ELEMENT = Id_length + 1, - MAX_INSTANCE_ID = Id_BYTES_PER_ELEMENT; - // External Array implementation @Override diff --git a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeUint16Array.java b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeUint16Array.java index bf264a0520..43f187fd81 100644 --- a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeUint16Array.java +++ b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeUint16Array.java @@ -7,9 +7,10 @@ package org.mozilla.javascript.typedarrays; import org.mozilla.javascript.Context; -import org.mozilla.javascript.IdFunctionObject; +import org.mozilla.javascript.LambdaConstructor; import org.mozilla.javascript.ScriptRuntimeES6; import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.Undefined; /** @@ -38,14 +39,32 @@ public String getClassName() { } public static void init(Context cx, Scriptable scope, boolean sealed) { - NativeUint16Array a = new NativeUint16Array(); - IdFunctionObject constructor = a.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); + LambdaConstructor constructor = + new LambdaConstructor( + scope, + CLASS_NAME, + 3, + LambdaConstructor.CONSTRUCTOR_NEW, + (Context lcx, Scriptable lscope, Object[] args) -> + NativeTypedArrayView.js_constructor( + lcx, + lscope, + args, + NativeUint16Array::new, + BYTES_PER_ELEMENT)); + constructor.setPrototypePropertyAttributes(DONTENUM | READONLY | PERMANENT); + NativeTypedArrayView.init(cx, scope, constructor, NativeUint16Array::realThis); + constructor.defineProperty( + "BYTES_PER_ELEMENT", BYTES_PER_ELEMENT, DONTENUM | READONLY | PERMANENT); + constructor.definePrototypeProperty( + "BYTES_PER_ELEMENT", BYTES_PER_ELEMENT, DONTENUM | READONLY | PERMANENT); + ScriptRuntimeES6.addSymbolSpecies(cx, scope, constructor); - } - @Override - protected NativeUint16Array construct(NativeArrayBuffer ab, int off, int len) { - return new NativeUint16Array(ab, off, len); + ScriptableObject.defineProperty(scope, CLASS_NAME, constructor, DONTENUM); + if (sealed) { + constructor.sealObject(); + } } @Override @@ -53,9 +72,8 @@ public int getBytesPerElement() { return BYTES_PER_ELEMENT; } - @Override - protected NativeUint16Array realThis(Scriptable thisObj, IdFunctionObject f) { - return ensureType(thisObj, NativeUint16Array.class, f); + private static NativeUint16Array realThis(Scriptable thisObj) { + return LambdaConstructor.convertThisObject(thisObj, NativeUint16Array.class); } @Override diff --git a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeUint32Array.java b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeUint32Array.java index 0b05cb55a9..fe22774332 100644 --- a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeUint32Array.java +++ b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeUint32Array.java @@ -7,9 +7,10 @@ package org.mozilla.javascript.typedarrays; import org.mozilla.javascript.Context; -import org.mozilla.javascript.IdFunctionObject; +import org.mozilla.javascript.LambdaConstructor; import org.mozilla.javascript.ScriptRuntimeES6; import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.Undefined; /** @@ -38,14 +39,32 @@ public String getClassName() { } public static void init(Context cx, Scriptable scope, boolean sealed) { - NativeUint32Array a = new NativeUint32Array(); - IdFunctionObject constructor = a.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); + LambdaConstructor constructor = + new LambdaConstructor( + scope, + CLASS_NAME, + 3, + LambdaConstructor.CONSTRUCTOR_NEW, + (Context lcx, Scriptable lscope, Object[] args) -> + NativeTypedArrayView.js_constructor( + lcx, + lscope, + args, + NativeUint32Array::new, + BYTES_PER_ELEMENT)); + constructor.setPrototypePropertyAttributes(DONTENUM | READONLY | PERMANENT); + NativeTypedArrayView.init(cx, scope, constructor, NativeUint32Array::realThis); + constructor.defineProperty( + "BYTES_PER_ELEMENT", BYTES_PER_ELEMENT, DONTENUM | READONLY | PERMANENT); + constructor.definePrototypeProperty( + "BYTES_PER_ELEMENT", BYTES_PER_ELEMENT, DONTENUM | READONLY | PERMANENT); + ScriptRuntimeES6.addSymbolSpecies(cx, scope, constructor); - } - @Override - protected NativeUint32Array construct(NativeArrayBuffer ab, int off, int len) { - return new NativeUint32Array(ab, off, len); + ScriptableObject.defineProperty(scope, CLASS_NAME, constructor, DONTENUM); + if (sealed) { + constructor.sealObject(); + } } @Override @@ -53,9 +72,8 @@ public int getBytesPerElement() { return BYTES_PER_ELEMENT; } - @Override - protected NativeUint32Array realThis(Scriptable thisObj, IdFunctionObject f) { - return ensureType(thisObj, NativeUint32Array.class, f); + private static NativeUint32Array realThis(Scriptable thisObj) { + return LambdaConstructor.convertThisObject(thisObj, NativeUint32Array.class); } @Override diff --git a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeUint8Array.java b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeUint8Array.java index 86140a3fe9..313b328af2 100644 --- a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeUint8Array.java +++ b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeUint8Array.java @@ -7,9 +7,10 @@ package org.mozilla.javascript.typedarrays; import org.mozilla.javascript.Context; -import org.mozilla.javascript.IdFunctionObject; +import org.mozilla.javascript.LambdaConstructor; import org.mozilla.javascript.ScriptRuntimeES6; import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.Undefined; /** @@ -37,14 +38,27 @@ public String getClassName() { } public static void init(Context cx, Scriptable scope, boolean sealed) { - NativeUint8Array a = new NativeUint8Array(); - IdFunctionObject constructor = a.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); + LambdaConstructor constructor = + new LambdaConstructor( + scope, + CLASS_NAME, + 3, + LambdaConstructor.CONSTRUCTOR_NEW, + (Context lcx, Scriptable lscope, Object[] args) -> + NativeTypedArrayView.js_constructor( + lcx, lscope, args, NativeUint8Array::new, 1)); + constructor.setPrototypePropertyAttributes(DONTENUM | READONLY | PERMANENT); + NativeTypedArrayView.init(cx, scope, constructor, NativeUint8Array::realThis); + constructor.defineProperty("BYTES_PER_ELEMENT", 1, DONTENUM | READONLY | PERMANENT); + constructor.definePrototypeProperty( + "BYTES_PER_ELEMENT", 1, DONTENUM | READONLY | PERMANENT); + ScriptRuntimeES6.addSymbolSpecies(cx, scope, constructor); - } - @Override - protected NativeUint8Array construct(NativeArrayBuffer ab, int off, int len) { - return new NativeUint8Array(ab, off, len); + ScriptableObject.defineProperty(scope, CLASS_NAME, constructor, DONTENUM); + if (sealed) { + constructor.sealObject(); + } } @Override @@ -52,9 +66,8 @@ public int getBytesPerElement() { return 1; } - @Override - protected NativeUint8Array realThis(Scriptable thisObj, IdFunctionObject f) { - return ensureType(thisObj, NativeUint8Array.class, f); + private static NativeUint8Array realThis(Scriptable thisObj) { + return LambdaConstructor.convertThisObject(thisObj, NativeUint8Array.class); } @Override diff --git a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeUint8ClampedArray.java b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeUint8ClampedArray.java index c6b1428a72..b0d34bc25e 100644 --- a/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeUint8ClampedArray.java +++ b/rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeUint8ClampedArray.java @@ -7,9 +7,10 @@ package org.mozilla.javascript.typedarrays; import org.mozilla.javascript.Context; -import org.mozilla.javascript.IdFunctionObject; +import org.mozilla.javascript.LambdaConstructor; import org.mozilla.javascript.ScriptRuntimeES6; import org.mozilla.javascript.Scriptable; +import org.mozilla.javascript.ScriptableObject; import org.mozilla.javascript.Undefined; /** @@ -39,14 +40,27 @@ public String getClassName() { } public static void init(Context cx, Scriptable scope, boolean sealed) { - NativeUint8ClampedArray a = new NativeUint8ClampedArray(); - IdFunctionObject constructor = a.exportAsJSClass(MAX_PROTOTYPE_ID, scope, sealed); + LambdaConstructor constructor = + new LambdaConstructor( + scope, + CLASS_NAME, + 3, + LambdaConstructor.CONSTRUCTOR_NEW, + (Context lcx, Scriptable lscope, Object[] args) -> + NativeTypedArrayView.js_constructor( + lcx, lscope, args, NativeUint8ClampedArray::new, 1)); + constructor.setPrototypePropertyAttributes(DONTENUM | READONLY | PERMANENT); + NativeTypedArrayView.init(cx, scope, constructor, NativeUint8ClampedArray::realThis); + constructor.defineProperty("BYTES_PER_ELEMENT", 1, DONTENUM | READONLY | PERMANENT); + constructor.definePrototypeProperty( + "BYTES_PER_ELEMENT", 1, DONTENUM | READONLY | PERMANENT); + ScriptRuntimeES6.addSymbolSpecies(cx, scope, constructor); - } - @Override - protected NativeUint8ClampedArray construct(NativeArrayBuffer ab, int off, int len) { - return new NativeUint8ClampedArray(ab, off, len); + ScriptableObject.defineProperty(scope, CLASS_NAME, constructor, DONTENUM); + if (sealed) { + constructor.sealObject(); + } } @Override @@ -54,9 +68,8 @@ public int getBytesPerElement() { return 1; } - @Override - protected NativeUint8ClampedArray realThis(Scriptable thisObj, IdFunctionObject f) { - return ensureType(thisObj, NativeUint8ClampedArray.class, f); + private static NativeUint8ClampedArray realThis(Scriptable thisObj) { + return LambdaConstructor.convertThisObject(thisObj, NativeUint8ClampedArray.class); } @Override diff --git a/rhino/src/main/resources/org/mozilla/javascript/resources/Messages.properties b/rhino/src/main/resources/org/mozilla/javascript/resources/Messages.properties index b3fcce45b9..b121f7e670 100644 --- a/rhino/src/main/resources/org/mozilla/javascript/resources/Messages.properties +++ b/rhino/src/main/resources/org/mozilla/javascript/resources/Messages.properties @@ -985,6 +985,16 @@ msg.promise.any.toobig =\ msg.typed.array.ctor.incompatible = \ Method %TypedArray%.prototype.{0} called on incompatible receiver -# NativeError +# Error msg.iterable.expected =\ Expected the first argument to be iterable + +# ArrayBuffer +msg.species.invalid.ctor =\ + The [Symbol.species] property of object's constructor is not a constructor + +msg.arraybuf.smaller.len =\ + Expected ArrayBuffer with at least {0} bytes, but got {1} bytes instead + +msg.arraybuf.same =\ + Expected different ArrayBuffer diff --git a/tests/testsrc/jstests/harmony/external-array.js b/tests/testsrc/jstests/harmony/external-array.js index 83994edf5f..d74e2f97d3 100644 --- a/tests/testsrc/jstests/harmony/external-array.js +++ b/tests/testsrc/jstests/harmony/external-array.js @@ -29,83 +29,85 @@ load("testsrc/assert.js"); -// Flags: --allow-natives-syntax --expose-gc +// Flags: --allow-natives-syntax + +// Helper +function assertInstance(o, f) { + assertSame(o.constructor, f); + assertInstanceof(o, f); +} + // This is a regression test for overlapping key and value registers. function f(a) { a[0] = 0; a[1] = 0; } +//%PrepareFunctionForOptimization(f); var a = new Int32Array(2); for (var i = 0; i < 5; i++) { f(a); } - +//%OptimizeFunctionOnNextCall(f); f(a); assertEquals(0, a[0]); assertEquals(0, a[1]); -// No-parameter constructor should fail right now. -function abfunc1() { - return new ArrayBuffer(); -} -//TODO assertThrows(abfunc1); - // Test derivation from an ArrayBuffer var ab = new ArrayBuffer(12); -assertInstanceof(ab, ArrayBuffer); +assertInstance(ab, ArrayBuffer); var derived_uint8 = new Uint8Array(ab); -assertInstanceof(derived_uint8, Uint8Array); +assertInstance(derived_uint8, Uint8Array); assertSame(ab, derived_uint8.buffer); assertEquals(12, derived_uint8.length); assertEquals(12, derived_uint8.byteLength); assertEquals(0, derived_uint8.byteOffset); assertEquals(1, derived_uint8.BYTES_PER_ELEMENT); var derived_uint8_2 = new Uint8Array(ab,7); -assertInstanceof(derived_uint8_2, Uint8Array); +assertInstance(derived_uint8_2, Uint8Array); assertSame(ab, derived_uint8_2.buffer); assertEquals(5, derived_uint8_2.length); assertEquals(5, derived_uint8_2.byteLength); assertEquals(7, derived_uint8_2.byteOffset); assertEquals(1, derived_uint8_2.BYTES_PER_ELEMENT); var derived_int16 = new Int16Array(ab); -assertInstanceof(derived_int16, Int16Array); +assertInstance(derived_int16, Int16Array); assertSame(ab, derived_int16.buffer); assertEquals(6, derived_int16.length); assertEquals(12, derived_int16.byteLength); assertEquals(0, derived_int16.byteOffset); assertEquals(2, derived_int16.BYTES_PER_ELEMENT); var derived_int16_2 = new Int16Array(ab,6); -assertInstanceof(derived_int16_2, Int16Array); +assertInstance(derived_int16_2, Int16Array); assertSame(ab, derived_int16_2.buffer); assertEquals(3, derived_int16_2.length); assertEquals(6, derived_int16_2.byteLength); assertEquals(6, derived_int16_2.byteOffset); assertEquals(2, derived_int16_2.BYTES_PER_ELEMENT); var derived_uint32 = new Uint32Array(ab); -assertInstanceof(derived_uint32, Uint32Array); +assertInstance(derived_uint32, Uint32Array); assertSame(ab, derived_uint32.buffer); assertEquals(3, derived_uint32.length); assertEquals(12, derived_uint32.byteLength); assertEquals(0, derived_uint32.byteOffset); assertEquals(4, derived_uint32.BYTES_PER_ELEMENT); var derived_uint32_2 = new Uint32Array(ab,4); -assertInstanceof(derived_uint32_2, Uint32Array); +assertInstance(derived_uint32_2, Uint32Array); assertSame(ab, derived_uint32_2.buffer); assertEquals(2, derived_uint32_2.length); assertEquals(8, derived_uint32_2.byteLength); assertEquals(4, derived_uint32_2.byteOffset); assertEquals(4, derived_uint32_2.BYTES_PER_ELEMENT); var derived_uint32_3 = new Uint32Array(ab,4,1); -assertInstanceof(derived_uint32_3, Uint32Array); +assertInstance(derived_uint32_3, Uint32Array); assertSame(ab, derived_uint32_3.buffer); assertEquals(1, derived_uint32_3.length); assertEquals(4, derived_uint32_3.byteLength); assertEquals(4, derived_uint32_3.byteOffset); assertEquals(4, derived_uint32_3.BYTES_PER_ELEMENT); var derived_float64 = new Float64Array(ab,0,1); -assertInstanceof(derived_float64, Float64Array); +assertInstance(derived_float64, Float64Array); assertSame(ab, derived_float64.buffer); assertEquals(1, derived_float64.length); assertEquals(8, derived_float64.byteLength); @@ -156,15 +158,12 @@ a = new Float64Array(7); assertSame(a.buffer, (new Uint16Array(a.buffer)).buffer); assertSame(a.buffer, (new Float32Array(a.buffer,4)).buffer); assertSame(a.buffer, (new Int8Array(a.buffer,3,51)).buffer); -assertInstanceof(a.buffer, ArrayBuffer); -assertTrue(a.buffer instanceof ArrayBuffer); +assertInstance(a.buffer, ArrayBuffer); -// Test the correct behavior of the |BYTES_PER_ELEMENT| property (which is -// "constant", but not read-only). +// Test the correct behavior of the |BYTES_PER_ELEMENT| property a = new Int32Array(2); assertEquals(4, a.BYTES_PER_ELEMENT); a.BYTES_PER_ELEMENT = 42; -// TODO assertEquals(42, a.BYTES_PER_ELEMENT); a = new Uint8Array(2); assertEquals(1, a.BYTES_PER_ELEMENT); a = new Int16Array(2); @@ -173,48 +172,39 @@ assertEquals(2, a.BYTES_PER_ELEMENT); // Test Float64Arrays. function get(a, index) { return a[index]; -} +}; +//%PrepareFunctionForOptimization(get); function set(a, index, value) { a[index] = value; -} +}; +//%PrepareFunctionForOptimization(set); function temp() { -var array = new Float64Array(2); -for (var i = 0; i < 5; i++) { + var array = new Float64Array(2); + for (var i = 0; i < 5; i++) { + set(array, 0, 2.5); + assertEquals(2.5, array[0]); + } +//%OptimizeFunctionOnNextCall(set); set(array, 0, 2.5); assertEquals(2.5, array[0]); -} -//%OptimizeFunctionOnNextCall(set); -set(array, 0, 2.5); -assertEquals(2.5, array[0]); -set(array, 1, 3.5); -assertEquals(3.5, array[1]); -for (var i = 0; i < 5; i++) { - assertEquals(2.5, get(array, 0)); + set(array, 1, 3.5); assertEquals(3.5, array[1]); -} + for (var i = 0; i < 5; i++) { + assertEquals(2.5, get(array, 0)); + assertEquals(3.5, array[1]); + } //%OptimizeFunctionOnNextCall(get); -assertEquals(2.5, get(array, 0)); -assertEquals(3.5, get(array, 1)); + assertEquals(2.5, get(array, 0)); + assertEquals(3.5, get(array, 1)); } // Test non-number parameters. -/* TODO doesn't work on regular node var array_with_length_from_non_number = new Int32Array("2"); assertEquals(2, array_with_length_from_non_number.length); -array_with_length_from_non_number = new Int32Array(undefined); -assertEquals(0, array_with_length_from_non_number.length); -var foo = { valueOf: function() { return 3; } }; -array_with_length_from_non_number = new Int32Array(foo); -assertEquals(3, array_with_length_from_non_number.length); -foo = { toString: function() { return "4"; } }; -array_with_length_from_non_number = new Int32Array(foo); -assertEquals(4, array_with_length_from_non_number.length); -*/ - // Test loads and stores. types = [Array, Int8Array, Uint8Array, Int16Array, Uint16Array, Int32Array, - Uint32Array, Uint8ClampedArray, Float32Array, Float64Array]; + Uint32Array, Uint8ClampedArray, Float32Array, Float64Array]; test_result_nan = [NaN, 0, 0, 0, 0, 0, 0, 0, NaN, NaN]; test_result_low_int = [-1, -1, 255, -1, 65535, -1, 0xFFFFFFFF, 0, -1, -1]; @@ -310,15 +300,16 @@ function test_store_nan(array, sum) { const kRuns = 10; function run_test(test_func, array, expected_result) { +//%PrepareFunctionForOptimization(test_func); for (var i = 0; i < 5; i++) test_func(array, 0); - //%OptimizeFunctionOnNextCall(test_func); +//%OptimizeFunctionOnNextCall(test_func); var sum = 0; for (var i = 0; i < kRuns; i++) { sum = test_func(array, sum); } assertEquals(expected_result, sum); - //%DeoptimizeFunction(test_func); - //gc(); // Makes V8 forget about type information for test_func. +//%DeoptimizeFunction(test_func); +//%ClearFunctionFeedback(test_func); } function run_bounds_test(test_func, array, expected_result) { @@ -348,30 +339,27 @@ for (var t = 0; t < types.length; t++) { run_test(test_store_low_tagged, a, test_result_low_double[t]); run_test(test_store_high_int, a, test_result_high_int[t]); run_test(test_store_nan, a, test_result_nan[t]); - // Rhino: seems to be expecting floating-point to work a certain way - //run_test(test_store_middle_double, a, test_result_middle[t]); - //run_test(test_store_middle_tagged, a, test_result_middle[t]); - //run_test(test_store_high_double, a, test_result_high_double[t]); - //run_test(test_store_high_tagged, a, test_result_high_double[t]); + run_test(test_store_middle_double, a, test_result_middle[t]); + run_test(test_store_middle_tagged, a, test_result_middle[t]); + run_test(test_store_high_double, a, test_result_high_double[t]); + run_test(test_store_high_tagged, a, test_result_high_double[t]); // Test the correct behavior of the |length| property (which is read-only). if (t != 0) { assertEquals(kElementCount, a.length); a.length = 2; assertEquals(kElementCount, a.length); - // TODO assertTrue(delete a.length); - a.length = 2; - // TODO assertEquals(2, a.length); + assertTrue(delete a.length); // Make sure bounds checks are handled correctly for external arrays. + //%PrepareFunctionForOptimization(run_bounds_test); run_bounds_test(a); run_bounds_test(a); run_bounds_test(a); - //%OptimizeFunctionOnNextCall(run_bounds_test); + //%OptimizeFunctionOnNextCall(run_bounds_test); run_bounds_test(a); - //%DeoptimizeFunction(run_bounds_test); - //gc(); // Makes V8 forget about type information for test_func. - + //%DeoptimizeFunction(run_bounds_test); + //%ClearFunctionFeedback(run_bounds_test); } function array_load_set_smi_check(a) { @@ -385,12 +373,13 @@ for (var t = 0; t < types.length; t++) { return a[0] = a[0] = 1; } +//%PrepareFunctionForOptimization(array_load_set_smi_check2); array_load_set_smi_check2(a); - //%OptimizeFunctionOnNextCall(array_load_set_smi_check2); +//%OptimizeFunctionOnNextCall(array_load_set_smi_check2); array_load_set_smi_check2(a); array_load_set_smi_check2(0); - //%DeoptimizeFunction(array_load_set_smi_check2); - //gc(); // Makes V8 forget about type information for array_load_set_smi_check. +//%DeoptimizeFunction(array_load_set_smi_check2); +//%ClearFunctionFeedback(array_load_set_smi_check2); } // Check handling of undefined in 32- and 64-bit external float arrays. @@ -399,6 +388,7 @@ function store_float32_undefined(ext_array) { ext_array[0] = undefined; } +//%PrepareFunctionForOptimization(store_float32_undefined); var float32_array = new Float32Array(1); // Make sure runtime does it right store_float32_undefined(float32_array); @@ -415,6 +405,7 @@ function store_float64_undefined(ext_array) { ext_array[0] = undefined; } +//%PrepareFunctionForOptimization(store_float64_undefined); var float64_array = new Float64Array(1); // Make sure runtime does it right store_float64_undefined(float64_array); @@ -430,109 +421,108 @@ assertTrue(isNaN(float64_array[0])); // Check handling of 0-sized buffers and arrays. ab = new ArrayBuffer(0); -assertInstanceof(ab, ArrayBuffer); +assertInstance(ab, ArrayBuffer); assertEquals(0, ab.byteLength); a = new Int8Array(ab); -assertInstanceof(a, Int8Array); +assertInstance(a, Int8Array); assertEquals(0, a.byteLength); assertEquals(0, a.length); a[0] = 1; assertEquals(undefined, a[0]); ab = new ArrayBuffer(16); -assertInstanceof(ab, ArrayBuffer); +assertInstance(ab, ArrayBuffer); a = new Float32Array(ab,4,0); -assertInstanceof(a, Float32Array); +assertInstance(a, Float32Array); assertEquals(0, a.byteLength); assertEquals(0, a.length); a[0] = 1; assertEquals(undefined, a[0]); a = new Uint16Array(0); -assertInstanceof(a, Uint16Array); +assertInstance(a, Uint16Array); assertEquals(0, a.byteLength); assertEquals(0, a.length); a[0] = 1; assertEquals(undefined, a[0]); - // Check construction from arrays. a = new Uint32Array([]); -assertInstanceof(a, Uint32Array); +assertInstance(a, Uint32Array); assertEquals(0, a.length); assertEquals(0, a.byteLength); assertEquals(0, a.buffer.byteLength); assertEquals(4, a.BYTES_PER_ELEMENT); -assertInstanceof(a.buffer, ArrayBuffer); +assertInstance(a.buffer, ArrayBuffer); a = new Uint16Array([1,2,3]); -assertInstanceof(a, Uint16Array); +assertInstance(a, Uint16Array); assertEquals(3, a.length); assertEquals(6, a.byteLength); assertEquals(6, a.buffer.byteLength); assertEquals(2, a.BYTES_PER_ELEMENT); assertEquals(1, a[0]); assertEquals(3, a[2]); -assertInstanceof(a.buffer, ArrayBuffer); +assertInstance(a.buffer, ArrayBuffer); a = new Uint32Array(a); -assertInstanceof(a, Uint32Array); +assertInstance(a, Uint32Array); assertEquals(3, a.length); assertEquals(12, a.byteLength); assertEquals(12, a.buffer.byteLength); assertEquals(4, a.BYTES_PER_ELEMENT); assertEquals(1, a[0]); assertEquals(3, a[2]); -assertInstanceof(a.buffer, ArrayBuffer); +assertInstance(a.buffer, ArrayBuffer); // Check subarrays. a = new Uint16Array([1,2,3,4,5,6]); aa = a.subarray(3); -assertInstanceof(aa, Uint16Array); +assertInstance(aa, Uint16Array); assertEquals(3, aa.length); assertEquals(6, aa.byteLength); assertEquals(2, aa.BYTES_PER_ELEMENT); assertSame(a.buffer, aa.buffer); aa = a.subarray(3,5); -assertInstanceof(aa, Uint16Array); +assertInstance(aa, Uint16Array); assertEquals(2, aa.length); assertEquals(4, aa.byteLength); assertEquals(2, aa.BYTES_PER_ELEMENT); assertSame(a.buffer, aa.buffer); aa = a.subarray(4,8); -assertInstanceof(aa, Uint16Array); +assertInstance(aa, Uint16Array); assertEquals(2, aa.length); assertEquals(4, aa.byteLength); assertEquals(2, aa.BYTES_PER_ELEMENT); assertSame(a.buffer, aa.buffer); aa = a.subarray(9); -assertInstanceof(aa, Uint16Array); +assertInstance(aa, Uint16Array); assertEquals(0, aa.length); assertEquals(0, aa.byteLength); assertEquals(2, aa.BYTES_PER_ELEMENT); assertSame(a.buffer, aa.buffer); aa = a.subarray(-4); -assertInstanceof(aa, Uint16Array); +assertInstance(aa, Uint16Array); assertEquals(4, aa.length); assertEquals(8, aa.byteLength); assertEquals(2, aa.BYTES_PER_ELEMENT); assertSame(a.buffer, aa.buffer); aa = a.subarray(-3,-1); -assertInstanceof(aa, Uint16Array); +assertInstance(aa, Uint16Array); assertEquals(2, aa.length); assertEquals(4, aa.byteLength); assertEquals(2, aa.BYTES_PER_ELEMENT); assertSame(a.buffer, aa.buffer); aa = a.subarray(3,2); -assertInstanceof(aa, Uint16Array); +assertInstance(aa, Uint16Array); assertEquals(0, aa.length); assertEquals(0, aa.byteLength); assertEquals(2, aa.BYTES_PER_ELEMENT); assertSame(a.buffer, aa.buffer); aa = a.subarray(-3,-4); -assertInstanceof(aa, Uint16Array); +assertInstance(aa, Uint16Array); assertEquals(0, aa.length); assertEquals(0, aa.byteLength); assertEquals(2, aa.BYTES_PER_ELEMENT); assertSame(a.buffer, aa.buffer); aa = a.subarray(0,-8); -assertInstanceof(aa, Uint16Array); +assertInstance(aa, Uint16Array); assertEquals(0, aa.length); assertEquals(0, aa.byteLength); assertEquals(2, aa.BYTES_PER_ELEMENT); @@ -540,36 +530,20 @@ assertSame(a.buffer, aa.buffer); assertThrows(function(){ a.subarray.call({}, 0) }); assertThrows(function(){ a.subarray.call([], 0) }); -// TODO assertThrows(function(){ a.subarray.call(a) }); - - -// Call constructors directly as functions, and through .call and .apply - -b = ArrayBuffer(100) -a = Int8Array(b, 5, 77) -// Rhino: seems to work differently -//assertInstanceof(b, ArrayBuffer) -//assertInstanceof(a, Int8Array) -assertSame(b, a.buffer) -assertEquals(5, a.byteOffset) -assertEquals(77, a.byteLength) -b = ArrayBuffer.call(null, 10) -a = Uint16Array.call(null, b, 2, 4) -//assertInstanceof(b, ArrayBuffer) -//assertInstanceof(a, Uint16Array) -assertSame(b, a.buffer) -assertEquals(2, a.byteOffset) -assertEquals(8, a.byteLength) -b = ArrayBuffer.apply(null, [1000]) -a = Float32Array.apply(null, [b, 128, 1]) -//assertInstanceof(b, ArrayBuffer) -//assertInstanceof(a, Float32Array) -assertSame(b, a.buffer) -assertEquals(128, a.byteOffset) -assertEquals(4, a.byteLength) +// Try to call constructors directly as functions, and through .call +// and .apply. Should fail. + +assertThrows(function() { ArrayBuffer(100); }, TypeError); +assertThrows(function() { Int8Array(b, 5, 77); }, TypeError); +assertThrows(function() { ArrayBuffer.call(null, 10); }, TypeError); +assertThrows(function() { Uint16Array.call(null, b, 2, 4); }, TypeError); +assertThrows(function() { ArrayBuffer.apply(null, [1000]); }, TypeError); +assertThrows(function() { Float32Array.apply(null, [b, 128, 1]); }, TypeError); // Test array.set in different combinations. +var b = new ArrayBuffer(4) + function assertArrayPrefix(expected, array) { for (var i = 0; i < expected.length; ++i) { assertEquals(expected[i], array[i]); @@ -621,11 +595,11 @@ assertArrayPrefix([0x50, 0x50, 0x0a, 0x0a], a50) a50.set([0x50, 0x50, 0x0a, 0x0a]) a53.set(a5) -// TODO assertArrayPrefix([0x50, 0x50, 0x50, 0x0a], a50) +assertArrayPrefix([0x50, 0x50, 0x50, 0x0a], a50) a50.set([0x50, 0x51, 0x0a, 0x0b]) a5.set(a51) -// TODO assertArrayPrefix([0x0050, 0x0051], a5) +assertArrayPrefix([0x0050, 0x0051], a5) a50.set([0x50, 0x51, 0x0a, 0x0b]) a5.set(a52) @@ -644,8 +618,12 @@ a61.set(a62) assertArrayPrefix([1, 12], a61) // Invalid source -// TODO assertThrows(function() { a.set(0) }) -// TODO assertThrows(function() { a.set({}) }) +// TODO: rhino +// a.set(0); // does not throw +assertArrayPrefix([1,2,3,4,5,6], a); +// TODO: rhino +// a.set({}); // does not throw +assertArrayPrefix([1,2,3,4,5,6], a); // Test arraybuffer.slice @@ -655,15 +633,15 @@ var b0 = a0.buffer var b1 = b0.slice(0) assertEquals(b0.byteLength, b1.byteLength) -assertArrayPrefix([1, 2, 3, 4, 5, 6], Int8Array(b1)) +assertArrayPrefix([1, 2, 3, 4, 5, 6], new Int8Array(b1)) var b2 = b0.slice(3) assertEquals(b0.byteLength - 3, b2.byteLength) -assertArrayPrefix([4, 5, 6], Int8Array(b2)) +assertArrayPrefix([4, 5, 6], new Int8Array(b2)) var b3 = b0.slice(2, 4) assertEquals(2, b3.byteLength) -assertArrayPrefix([3, 4], Int8Array(b3)) +assertArrayPrefix([3, 4], new Int8Array(b3)) function goo(a, i) { return a[i]; @@ -675,16 +653,18 @@ function boo(a, i, v) { function do_tagged_index_external_array_test(constructor) { var t_array = new constructor([1, 2, 3, 4, 5, 6]); +//%PrepareFunctionForOptimization(goo); +//%PrepareFunctionForOptimization(boo); assertEquals(1, goo(t_array, 0)); assertEquals(1, goo(t_array, 0)); boo(t_array, 0, 13); assertEquals(13, goo(t_array, 0)); - //%OptimizeFunctionOnNextCall(goo); - //%OptimizeFunctionOnNextCall(boo); +//%OptimizeFunctionOnNextCall(goo); +//%OptimizeFunctionOnNextCall(boo); boo(t_array, 0, 15); assertEquals(15, goo(t_array, 0)); - //%ClearFunctionTypeFeedback(goo); - //%ClearFunctionTypeFeedback(boo); +//%ClearFunctionFeedback(goo); +//%ClearFunctionFeedback(boo); } do_tagged_index_external_array_test(Int8Array); @@ -697,23 +677,61 @@ do_tagged_index_external_array_test(Float32Array); do_tagged_index_external_array_test(Float64Array); var built_in_array = new Array(1, 2, 3, 4, 5, 6); +//%PrepareFunctionForOptimization(goo); +//%PrepareFunctionForOptimization(boo); assertEquals(1, goo(built_in_array, 0)); assertEquals(1, goo(built_in_array, 0)); //%OptimizeFunctionOnNextCall(goo); //%OptimizeFunctionOnNextCall(boo); boo(built_in_array, 0, 11); assertEquals(11, goo(built_in_array, 0)); -//%ClearFunctionTypeFeedback(goo); -//%ClearFunctionTypeFeedback(boo); +//%ClearFunctionFeedback(goo); +//%ClearFunctionFeedback(boo); built_in_array = new Array(1.5, 2, 3, 4, 5, 6); +//%PrepareFunctionForOptimization(goo); +//%PrepareFunctionForOptimization(boo); assertEquals(1.5, goo(built_in_array, 0)); assertEquals(1.5, goo(built_in_array, 0)); //%OptimizeFunctionOnNextCall(goo); //%OptimizeFunctionOnNextCall(boo); boo(built_in_array, 0, 2.5); assertEquals(2.5, goo(built_in_array, 0)); -//%ClearFunctionTypeFeedback(goo); -//%ClearFunctionTypeFeedback(boo); +//%ClearFunctionFeedback(goo); +//%ClearFunctionFeedback(boo); + +// Check all int range edge cases +function checkRange() { + var e32 = Math.pow(2,32); var e31 = Math.pow(2,31); + var e16 = Math.pow(2,16); var e15 = Math.pow(2,15); + var e8 = Math.pow(2,8); var e7 = Math.pow(2,7); + var a7 = new Uint32Array(2); var a71 = new Int32Array(2); + var a72 = new Uint16Array(2); var a73 = new Int16Array(2); + var a74 = new Uint8Array(2); var a75 = new Int8Array(2); + for (i = 1; i <= Math.pow(2,33); i *= 2) { + var j = i-1; + a7[0] = i; a71[0] = i; a72[0] = i; a73[0] = i; a74[0] = i; a75[0] = i; + a7[1] = j; a71[1] = j; a72[1] = j; a73[1] = j; a74[1] = j; a75[1] = j; + + if (i < e32) { assertEquals(a7[0], i); } else { assertEquals(a7[0], 0); } + if (j < e32) { assertEquals(a7[1], j); } else { assertEquals(a7[1],e32-1); } + if (i < e31) { assertEquals(a71[0], i); } else { + assertEquals(a71[0], (i < e32) ? -e31 : 0 ); } + if (j < e31) { assertEquals(a71[1], j); } else { assertEquals(a71[1], -1); } + + if (i < e16) { assertEquals(a72[0], i); } else { assertEquals(a72[0], 0); } + if (j < e16) { assertEquals(a72[1], j); } else { assertEquals(a72[1], e16-1); } + if (i < e15) { assertEquals(a73[0], i); } else { + assertEquals(a73[0], (i < e16) ? -e15 : 0 ); } + if (j < e15) { assertEquals(a73[1], j); } else { assertEquals(a73[1], -1); } + + if (i < e8) { assertEquals(a74[0], i); } else { assertEquals(a74[0], 0); } + if (j < e8) { assertEquals(a74[1], j); } else { assertEquals(a74[1], e8-1); } + if (i < e7) { assertEquals(a75[0], i); } else { + assertEquals(a75[0], (i < e8) ? -e7 : 0); } + if (j < e7) { assertEquals(a75[1], j); } else { assertEquals(a75[1], -1); } + } +} +checkRange(); "success"; diff --git a/tests/testsrc/test262.properties b/tests/testsrc/test262.properties index fe3c0c336a..3602bd10b1 100644 --- a/tests/testsrc/test262.properties +++ b/tests/testsrc/test262.properties @@ -27,7 +27,7 @@ harness 23/115 (20.0%) isConstructor.js {unsupported: [Reflect.construct]} nativeFunctionMatcher.js -built-ins/Array 382/3074 (12.43%) +built-ins/Array 380/3074 (12.36%) fromAsync 94/94 (100.0%) from/calling-from-valid-1-noStrict.js non-strict Spec pretty clearly says this should be undefined from/elements-deleted-after.js Checking to see if length changed, but spec says it should not @@ -53,9 +53,7 @@ built-ins/Array 382/3074 (12.43%) prototype/at/coerced-index-resize.js {unsupported: [resizable-arraybuffer]} prototype/at/typed-array-resizable-buffer.js {unsupported: [resizable-arraybuffer]} prototype/concat/arg-length-exceeding-integer-limit.js {unsupported: [Proxy]} - prototype/concat/Array.prototype.concat_large-typed-array.js new prototype/concat/Array.prototype.concat_non-array.js - prototype/concat/Array.prototype.concat_small-typed-array.js prototype/concat/create-ctor-non-object.js prototype/concat/create-ctor-poisoned.js prototype/concat/create-proto-from-ctor-realm-non-array.js @@ -318,15 +316,11 @@ built-ins/Array 382/3074 (12.43%) proto-from-ctor-realm-two.js {unsupported: [Reflect]} proto-from-ctor-realm-zero.js {unsupported: [Reflect]} -built-ins/ArrayBuffer 142/191 (74.35%) +built-ins/ArrayBuffer 126/191 (65.97%) isView/arg-is-dataview-subclass-instance.js {unsupported: [class]} isView/arg-is-typedarray-subclass-instance.js {unsupported: [class]} isView/not-a-constructor.js {unsupported: [Reflect.construct]} prototype/byteLength/detached-buffer.js - prototype/byteLength/invoked-as-accessor.js - prototype/byteLength/length.js - prototype/byteLength/name.js - prototype/byteLength/prop-desc.js prototype/byteLength/this-is-sharedarraybuffer.js {unsupported: [SharedArrayBuffer]} prototype/detached 11/11 (100.0%) prototype/maxByteLength 11/11 (100.0%) @@ -334,17 +328,6 @@ built-ins/ArrayBuffer 142/191 (74.35%) prototype/resize 20/20 (100.0%) prototype/slice/nonconstructor.js {unsupported: [Reflect.construct]} prototype/slice/not-a-constructor.js {unsupported: [Reflect.construct]} - prototype/slice/species.js - prototype/slice/species-constructor-is-not-object.js - prototype/slice/species-constructor-is-undefined.js - prototype/slice/species-is-not-constructor.js - prototype/slice/species-is-not-object.js - prototype/slice/species-is-null.js - prototype/slice/species-is-undefined.js - prototype/slice/species-returns-larger-arraybuffer.js - prototype/slice/species-returns-not-arraybuffer.js - prototype/slice/species-returns-same-arraybuffer.js - prototype/slice/species-returns-smaller-arraybuffer.js prototype/slice/this-is-sharedarraybuffer.js {unsupported: [SharedArrayBuffer]} prototype/transferToFixedLength 23/23 (100.0%) prototype/transfer 23/23 (100.0%) @@ -365,7 +348,6 @@ built-ins/ArrayBuffer 142/191 (74.35%) options-non-object.js {unsupported: [resizable-arraybuffer]} proto-from-ctor-realm.js {unsupported: [Reflect]} prototype-from-newtarget.js {unsupported: [Reflect.construct]} - undefined-newtarget-throws.js built-ins/ArrayIteratorPrototype 1/27 (3.7%) next/detach-typedarray-in-progress.js @@ -404,29 +386,17 @@ built-ins/Boolean 4/51 (7.84%) is-a-constructor.js {unsupported: [Reflect.construct]} proto-from-ctor-realm.js {unsupported: [Reflect]} -built-ins/DataView 254/550 (46.18%) +built-ins/DataView 241/550 (43.82%) prototype/buffer/detached-buffer.js - prototype/buffer/invoked-as-accessor.js - prototype/buffer/length.js - prototype/buffer/name.js - prototype/buffer/prop-desc.js prototype/buffer/return-buffer-sab.js {unsupported: [SharedArrayBuffer]} prototype/buffer/this-has-no-dataview-internal-sab.js {unsupported: [SharedArrayBuffer]} prototype/byteLength/detached-buffer.js prototype/byteLength/instance-has-detached-buffer.js - prototype/byteLength/invoked-as-accessor.js - prototype/byteLength/length.js - prototype/byteLength/name.js - prototype/byteLength/prop-desc.js prototype/byteLength/resizable-array-buffer-auto.js {unsupported: [resizable-arraybuffer]} prototype/byteLength/resizable-array-buffer-fixed.js {unsupported: [resizable-arraybuffer]} prototype/byteLength/return-bytelength-sab.js {unsupported: [SharedArrayBuffer]} prototype/byteLength/this-has-no-dataview-internal-sab.js {unsupported: [SharedArrayBuffer]} prototype/byteOffset/detached-buffer.js - prototype/byteOffset/invoked-as-accessor.js - prototype/byteOffset/length.js - prototype/byteOffset/name.js - prototype/byteOffset/prop-desc.js prototype/byteOffset/resizable-array-buffer-auto.js {unsupported: [resizable-arraybuffer]} prototype/byteOffset/resizable-array-buffer-fixed.js {unsupported: [resizable-arraybuffer]} prototype/byteOffset/return-byteoffset-sab.js {unsupported: [SharedArrayBuffer]} @@ -647,7 +617,6 @@ built-ins/DataView 254/550 (46.18%) is-a-constructor.js {unsupported: [Reflect.construct]} negative-bytelength-throws-sab.js {unsupported: [SharedArrayBuffer]} negative-byteoffset-throws-sab.js {unsupported: [SharedArrayBuffer]} - newtarget-undefined-throws.js newtarget-undefined-throws-sab.js {unsupported: [SharedArrayBuffer]} proto-from-ctor-realm.js {unsupported: [Reflect]} proto-from-ctor-realm-sab.js {unsupported: [SharedArrayBuffer, Reflect]} @@ -2915,7 +2884,7 @@ built-ins/TypedArray 1091/1422 (76.72%) resizable-buffer-length-tracking-1.js {unsupported: [resizable-arraybuffer]} resizable-buffer-length-tracking-2.js {unsupported: [resizable-arraybuffer]} -built-ins/TypedArrayConstructors 595/735 (80.95%) +built-ins/TypedArrayConstructors 586/735 (79.73%) BigInt64Array/prototype 4/4 (100.0%) BigInt64Array 8/8 (100.0%) BigUint64Array/prototype 4/4 (100.0%) @@ -2999,10 +2968,8 @@ built-ins/TypedArrayConstructors 595/735 (80.95%) ctors/typedarray-arg/use-custom-proto-if-object.js {unsupported: [Reflect]} ctors/typedarray-arg/use-default-proto-if-custom-proto-is-not-object.js ctors/no-species.js - Float32Array/prototype/not-typedarray-object.js Float32Array/prototype/proto.js Float32Array/is-a-constructor.js {unsupported: [Reflect.construct]} - Float64Array/prototype/not-typedarray-object.js Float64Array/prototype/proto.js Float64Array/is-a-constructor.js {unsupported: [Reflect.construct]} from/BigInt 28/28 (100.0%) @@ -3029,13 +2996,10 @@ built-ins/TypedArrayConstructors 595/735 (80.95%) from/new-instance-without-mapfn.js from/property-abrupt-completion.js from/set-value-abrupt-completion.js - Int16Array/prototype/not-typedarray-object.js Int16Array/prototype/proto.js Int16Array/is-a-constructor.js {unsupported: [Reflect.construct]} - Int32Array/prototype/not-typedarray-object.js Int32Array/prototype/proto.js Int32Array/is-a-constructor.js {unsupported: [Reflect.construct]} - Int8Array/prototype/not-typedarray-object.js Int8Array/prototype/proto.js Int8Array/is-a-constructor.js {unsupported: [Reflect.construct]} internals/DefineOwnProperty/BigInt 26/26 (100.0%) @@ -3173,16 +3137,12 @@ built-ins/TypedArrayConstructors 595/735 (80.95%) prototype/toString 2/2 (100.0%) prototype/values 2/2 (100.0%) prototype 2/2 (100.0%) - Uint16Array/prototype/not-typedarray-object.js Uint16Array/prototype/proto.js Uint16Array/is-a-constructor.js {unsupported: [Reflect.construct]} - Uint32Array/prototype/not-typedarray-object.js Uint32Array/prototype/proto.js Uint32Array/is-a-constructor.js {unsupported: [Reflect.construct]} - Uint8Array/prototype/not-typedarray-object.js Uint8Array/prototype/proto.js Uint8Array/is-a-constructor.js {unsupported: [Reflect.construct]} - Uint8ClampedArray/prototype/not-typedarray-object.js Uint8ClampedArray/prototype/proto.js Uint8ClampedArray/is-a-constructor.js {unsupported: [Reflect.construct]}