fix: copy a Java array when spreading it - #55
Merged
Conversation
Spreading a Java array of a reference type produced an array that shared storage
with it, against the "a new array holding the elements" the method documents:
var StringArray = Java.type("java.lang.String[]");
var a = new StringArray(2); a[0] = "x"; a[1] = "y";
var js = [...a];
js[0] = "changed"; a is now changed,y
js[0] = 42; java.lang.ArrayStoreException: java.lang.Integer
js[1] = {}; java.lang.ArrayStoreException: ...JO4
Both come out of an ordinary assignment as raw Java exceptions, which script code
cannot recover from.
toApplyArgs returns the very array it is given when that array is an Object[],
and Global.allocate wraps rather than copies - ArrayData.allocate(Object[]) makes
an ObjectArrayData over the same storage. Every other branch of TO_ARRAY builds a
fresh array, and the start > 0 path already copied with Arrays.copyOfRange; only
this one aliased.
Copying with Arrays.copyOf(array, length, Object[].class) rather than clone()
because a String[] clones to a String[]: the component type has to go too, or the
second and third lines above still throw.
./gradlew build testOptimistic testPessimistic:
suite before after
test 665, 0 fail 665, 0 fail
testOptimistic 1717, 0 fail 1717, 0 fail
testPessimistic 1717, 0 fail 1717, 0 fail
marevol
force-pushed
the
es6/fix-spread-array-copy
branch
from
August 28, 2026 05:11
51aa880 to
58d5ab9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #54.
Spreading a Java array of a reference type produced an array that shared storage with it, against the "a new array holding the elements" the method documents:
Both come out of an ordinary assignment as raw Java exceptions, which script code cannot recover from.
Cause
toApplyArgsreturns the very array it is given when that array is anObject[], andGlobal.allocatewraps rather than copies —ArrayData.allocate(Object[])makes anObjectArrayDataover the same storage. Every other branch ofTO_ARRAYbuilds a fresh array, and thestart > 0path already copied withArrays.copyOfRange; only this one aliased.Fix
Copy with
Arrays.copyOf(array, length, Object[].class)rather thanclone(), because aString[]clones to aString[]: the component type has to go too, or the second and third lines above still throw.Verification
./gradlew build testOptimistic testPessimistic