Skip to content

Commit f02349c

Browse files
authored
Add ArrayBuffer detach
This passes pretty much every test related to detached array buffers, with the only ones failing being methods we don't support yet.
1 parent e3f133a commit f02349c

24 files changed

Lines changed: 555 additions & 633 deletions

rhino/src/main/java/org/mozilla/javascript/AbstractEcmaObjectOperations.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,7 @@ static List<Object> createListFromArrayLike(
361361
* <p><a href="https://262.ecma-international.org/12.0/#sec-lengthofarraylike">7.3.18
362362
* LengthOfArrayLike (obj)</a>
363363
*/
364-
static long lengthOfArrayLike(Context cx, Scriptable o) {
364+
public static long lengthOfArrayLike(Context cx, Scriptable o) {
365365
Object value = ScriptableObject.getProperty(o, "length");
366366
long len = ScriptRuntime.toLength(new Object[] {value}, 0);
367367
return len;

rhino/src/main/java/org/mozilla/javascript/NativeArrayIterator.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
package org.mozilla.javascript;
88

9+
import org.mozilla.javascript.typedarrays.NativeTypedArrayView;
10+
911
public final class NativeArrayIterator extends ES6Iterator {
1012
public enum ARRAY_ITERATOR_TYPE {
1113
ENTRIES,
@@ -41,6 +43,12 @@ public String getClassName() {
4143

4244
@Override
4345
protected boolean isDone(Context cx, Scriptable scope) {
46+
if (arrayLike instanceof NativeTypedArrayView) {
47+
NativeTypedArrayView<?> typedArray = (NativeTypedArrayView<?>) arrayLike;
48+
if (typedArray.isTypedArrayOutOfBounds()) {
49+
throw ScriptRuntime.typeErrorById("msg.typed.array.out.of.bounds");
50+
}
51+
}
4452
return index >= NativeArray.getLengthProperty(cx, arrayLike);
4553
}
4654

rhino/src/main/java/org/mozilla/javascript/NativeReflect.java

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,18 @@ private static Object defineProperty(
216216
ScriptableObject target = checkTarget(args);
217217
ScriptableObject desc = ScriptableObject.ensureScriptableObject(args[2]);
218218

219+
Object key = args[1];
220+
219221
try {
220-
return target.defineOwnProperty(cx, args[1], desc);
222+
if (key instanceof Symbol) {
223+
return target.defineOwnProperty(cx, key, desc);
224+
} else {
225+
String propertyKey =
226+
ScriptRuntime.toString(
227+
ScriptRuntime.toPrimitive(key, ScriptRuntime.StringClass));
228+
return target.defineOwnProperty(cx, propertyKey, desc);
229+
}
230+
221231
} catch (EcmaError e) {
222232
return false;
223233
}

rhino/src/main/java/org/mozilla/javascript/ScriptRuntime.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -821,12 +821,12 @@ public static int toIndex(Object val) {
821821
}
822822
double integerIndex = toInteger(val);
823823
if (integerIndex < 0) {
824-
throw rangeError("index out of range");
824+
throw rangeErrorById("msg.out.of.range.index", integerIndex);
825825
}
826826
// ToLength
827827
double index = Math.min(integerIndex, NativeNumber.MAX_SAFE_INTEGER);
828828
if (integerIndex != index) {
829-
throw rangeError("index out of range");
829+
throw rangeErrorById("msg.out.of.range.index", integerIndex);
830830
}
831831
return (int) index;
832832
}

rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeArrayBuffer.java

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public class NativeArrayBuffer extends ScriptableObject {
2727

2828
private static final byte[] EMPTY_BUF = new byte[0];
2929

30-
final byte[] buffer;
30+
byte[] buffer;
3131

3232
@Override
3333
public String getClassName() {
@@ -56,6 +56,8 @@ public static Object init(Context cx, Scriptable scope, boolean sealed) {
5656
DONTENUM | READONLY);
5757
constructor.definePrototypeProperty(
5858
cx, "byteLength", NativeArrayBuffer::js_byteLength, DONTENUM | READONLY);
59+
constructor.definePrototypeProperty(
60+
cx, "detached", NativeArrayBuffer::js_detached, DONTENUM | READONLY);
5961
constructor.definePrototypeProperty(
6062
SymbolKey.TO_STRING_TAG, "ArrayBuffer", DONTENUM | READONLY);
6163

@@ -97,7 +99,7 @@ public NativeArrayBuffer(double len) {
9799

98100
/** Get the number of bytes in the buffer. */
99101
public int getLength() {
100-
return buffer.length;
102+
return buffer != null ? buffer.length : 0;
101103
}
102104

103105
/**
@@ -108,6 +110,14 @@ public byte[] getBuffer() {
108110
return buffer;
109111
}
110112

113+
public void detach() {
114+
buffer = null;
115+
}
116+
117+
public boolean isDetached() {
118+
return buffer == null;
119+
}
120+
111121
/**
112122
* Return a new buffer that represents a slice of this buffer's content, starting at position
113123
* "start" and ending at position "end". Both values will be "clamped" as per the JavaScript
@@ -123,9 +133,9 @@ public NativeArrayBuffer slice(double s, double e) {
123133
// Clamp as per the spec to between 0 and length
124134
int end =
125135
ScriptRuntime.toInt32(
126-
Math.max(0, Math.min(buffer.length, (e < 0 ? buffer.length + e : e))));
136+
Math.max(0, Math.min(getLength(), (e < 0 ? getLength() + e : e))));
127137
int start =
128-
ScriptRuntime.toInt32(Math.min(end, Math.max(0, (s < 0 ? buffer.length + s : s))));
138+
ScriptRuntime.toInt32(Math.min(end, Math.max(0, (s < 0 ? getLength() + s : s))));
129139
int len = end - start;
130140

131141
NativeArrayBuffer newBuf = new NativeArrayBuffer(len);
@@ -154,6 +164,11 @@ private static NativeArrayBuffer js_slice(
154164
LambdaConstructor defaultConstructor,
155165
Object[] args) {
156166
NativeArrayBuffer self = getSelf(thisObj);
167+
168+
if (self.isDetached()) {
169+
throw ScriptRuntime.typeErrorById("msg.arraybuf.detached");
170+
}
171+
157172
double start = isArg(args, 0) ? ScriptRuntime.toNumber(args[0]) : 0;
158173
double end = isArg(args, 1) ? ScriptRuntime.toNumber(args[1]) : self.getLength();
159174
int endI =
@@ -194,6 +209,10 @@ private static Object js_byteLength(Scriptable thisObj) {
194209
return getSelf(thisObj).getLength();
195210
}
196211

212+
private static Object js_detached(Scriptable thisObj) {
213+
return getSelf(thisObj).isDetached();
214+
}
215+
197216
private static boolean isArg(Object[] args, int i) {
198217
return ((args.length > i) && !Undefined.instance.equals(args[i]));
199218
}

rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeArrayBufferView.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,24 @@ public abstract class NativeArrayBufferView extends ScriptableObject {
2929
/** The length, in bytes, of the portion of the backing array that we use */
3030
protected final int byteLength;
3131

32+
protected final boolean outOfRange;
33+
3234
public NativeArrayBufferView() {
3335
arrayBuffer = new NativeArrayBuffer();
3436
offset = 0;
3537
byteLength = 0;
38+
outOfRange = false;
3639
}
3740

3841
protected NativeArrayBufferView(NativeArrayBuffer ab, int offset, int byteLength) {
3942
this.offset = offset;
4043
this.byteLength = byteLength;
4144
this.arrayBuffer = ab;
45+
46+
int bufferByteLength = arrayBuffer.getLength();
47+
int byteOffsetEnd = offset + byteLength;
48+
49+
outOfRange = offset > bufferByteLength || byteOffsetEnd > bufferByteLength;
4250
}
4351

4452
/** Return the buffer that backs this view. */

rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeBigInt64Array.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* An array view that stores 64-bit quantities and implements the JavaScript "Float64Array"
1919
* interface. It also implements List&lt;Double&gt; for direct manipulation in Java.
2020
*/
21-
public class NativeBigInt64Array extends NativeTypedArrayView<BigInteger> {
21+
public class NativeBigInt64Array extends NativeBigIntArrayView {
2222
private static final long serialVersionUID = -1255405650050639335L;
2323

2424
private static final String CLASS_NAME = "BigInt64Array";
@@ -91,10 +91,10 @@ protected Object js_get(int index) {
9191

9292
@Override
9393
protected Object js_set(int index, Object c) {
94+
var val = ScriptRuntime.toBigInt(c);
9495
if (checkIndex(index)) {
9596
return Undefined.instance;
9697
}
97-
var val = ScriptRuntime.toBigInt(c);
9898

9999
long base = val.longValue();
100100

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package org.mozilla.javascript.typedarrays;
2+
3+
import java.math.BigInteger;
4+
import org.mozilla.javascript.ScriptRuntime;
5+
6+
public abstract class NativeBigIntArrayView extends NativeTypedArrayView<BigInteger> {
7+
private static final long serialVersionUID = -3349222145964894609L;
8+
9+
protected NativeBigIntArrayView() {}
10+
11+
protected NativeBigIntArrayView(NativeArrayBuffer ab, int off, int len, int byteLen) {
12+
super(ab, off, len, byteLen);
13+
}
14+
15+
@Override
16+
protected Object toNumeric(Object num) {
17+
return ScriptRuntime.toBigInt(num);
18+
}
19+
}

rhino/src/main/java/org/mozilla/javascript/typedarrays/NativeBigUint64Array.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
* An array view that stores 64-bit quantities and implements the JavaScript "Float64Array"
1919
* interface. It also implements List&lt;Double&gt; for direct manipulation in Java.
2020
*/
21-
public class NativeBigUint64Array extends NativeTypedArrayView<BigInteger> {
21+
public class NativeBigUint64Array extends NativeBigIntArrayView {
2222
private static final long serialVersionUID = -1255405650050639335L;
2323

2424
private static final String CLASS_NAME = "BigUint64Array";
@@ -98,10 +98,10 @@ protected Object js_get(int index) {
9898

9999
@Override
100100
protected Object js_set(int index, Object c) {
101+
var val = ScriptRuntime.toBigInt(c);
101102
if (checkIndex(index)) {
102103
return Undefined.instance;
103104
}
104-
var val = ScriptRuntime.toBigInt(c);
105105

106106
long base = val.longValue();
107107

0 commit comments

Comments
 (0)