Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -651,8 +651,17 @@ public static Object TO_ARRAY(final Object object, final Object from) {
}

all = values.toArray();
} else if (object instanceof Object[]) {
// A Java array of a reference type. toApplyArgs hands back the very array it
// was given and Global.allocate wraps rather than copies, so the result would
// share storage with the source: writing to the spread copy would write
// through to the Java array. Copying to an Object[] also drops the component
// type, which would otherwise make an ordinary assignment of an unrelated
// value throw ArrayStoreException out of script code.
final Object[] array = (Object[]) object;
all = Arrays.copyOf(array, array.length, Object[].class);
} else {
// Arrays, array-like script objects, the arguments object and Lists.
// Array-like script objects, the arguments object and Lists.
all = NativeFunction.toApplyArgs(object);
}

Expand Down
36 changes: 36 additions & 0 deletions test/script/basic/es6/spread.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,39 @@ print(add3(...nums.map(function (x) { return x * 2; })));
print([...[]].length);
print(add3(...[1, 2, 3], ...[]));
print([1, ...[], 2].join(","));

// Spreading a Java array copies it. The result must not share storage with the
// source, and must not keep the source's component type either: both would show
// up as an ArrayStoreException out of an ordinary assignment.
var StringArray = Java.type("java.lang.String[]");
var javaArray = new StringArray(2);
javaArray[0] = "x";
javaArray[1] = "y";

var copy = [...javaArray];
print(copy.join(","));

copy[0] = "changed";
print(javaArray[0] + "," + javaArray[1]);

copy[0] = 42;
copy[1] = true;
print(copy.join(","));

// A Java array of a primitive type goes through reflection and was never shared.
var IntArray = Java.type("int[]");
var primitives = new IntArray(2);
primitives[0] = 1;
primitives[1] = 2;

var primitiveCopy = [...primitives];
primitiveCopy[0] = "s";
print(primitiveCopy.join(","));

// A List is copied by toArray, and the copy is detached from it.
var list = new (Java.type("java.util.ArrayList"))();
list.add("q");

var listCopy = [...list];
listCopy[0] = 9;
print(listCopy[0] + "," + list.get(0));
5 changes: 5 additions & 0 deletions test/script/basic/es6/spread.js.EXPECTED
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,8 @@ x,y
0
6
1,2
x,y
x,y
42,true
s,2
9,q