diff --git a/graal-js/src/com.oracle.truffle.js.test/js/GR-51680.js b/graal-js/src/com.oracle.truffle.js.test/js/GR-51680.js new file mode 100644 index 00000000000..8d0a6d49c54 --- /dev/null +++ b/graal-js/src/com.oracle.truffle.js.test/js/GR-51680.js @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. + */ + +/** + * Regression test checking successful transition from sealed JSObjectArray to ObjectArray strategy. + * + * @option debug-builtin + */ + +load("assert.js"); + +const o = {}; +const x = 42; + +for (const jsobjectArrayType of ["ZeroBasedJSObjectArray", "ContiguousJSObjectArray", "HolesJSObjectArray"]) { + const objectArrayType = jsobjectArrayType.replace("JS", ""); + switch (jsobjectArrayType) { + case "ZeroBasedJSObjectArray": { + let a = []; + for (let i = 0; i < 8; i++) { + a[i] = o; + } + Object.seal(a); + assertArrayType(a, jsobjectArrayType); + + a[5] = x; + + assertArrayType(a, objectArrayType); + assertSameContent([o,o,o,o,o,x,o,o], a); + assertTrue(Object.isSealed(a)); + break; + } + case "ContiguousJSObjectArray": { + let a = []; + for (let i = 1; i < 8; i++) { + a[i] = o; + } + Object.seal(a); + assertArrayType(a, jsobjectArrayType); + + a[0] = x; + assertArrayType(a, jsobjectArrayType); + + a[5] = x; + assertArrayType(a, objectArrayType); + assertSameContent([ ,o,o,o,o,x,o,o], a); + assertTrue(Object.isSealed(a)); + break; + } + case "HolesJSObjectArray": { + let a = []; + for (let i = 0; i < 8; i++) { + if (i == 4) { + continue; + } + a[i] = o; + } + Object.seal(a); + assertArrayType(a, jsobjectArrayType); + + a[4] = x; + assertArrayType(a, jsobjectArrayType); + a[5] = x; + + assertArrayType(a, objectArrayType); + assertSameContent([o,o,o,o, ,x,o,o], a); + assertTrue(Object.isSealed(a)); + break; + } + default: throw new TypeError(jsobjectArrayType); + } +} + +function assertArrayType(array, expected) { + assertSame(expected, Debug.arraytype(array)) +} diff --git a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/nodes/interop/ArrayElementInfoNode.java b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/nodes/interop/ArrayElementInfoNode.java index a3deb7f8cbc..f93efe2f354 100644 --- a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/nodes/interop/ArrayElementInfoNode.java +++ b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/nodes/interop/ArrayElementInfoNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -49,6 +49,7 @@ import com.oracle.truffle.js.nodes.JavaScriptBaseNode; import com.oracle.truffle.js.runtime.JSRuntime; import com.oracle.truffle.js.runtime.array.ScriptArray; +import com.oracle.truffle.js.runtime.builtins.JSAbstractArray; import com.oracle.truffle.js.runtime.builtins.JSArrayBase; /** @@ -99,7 +100,7 @@ static TriState doCached(JSArrayBase target, long index, int query, return TriState.UNDEFINED; } } - if (index >= 0 && index < arrayType.length(target)) { + if (index >= 0 && index < JSAbstractArray.arrayGetLength(target)) { if ((query & READABLE) != 0) { return TriState.TRUE; } diff --git a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/array/dyn/AbstractJSObjectArray.java b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/array/dyn/AbstractJSObjectArray.java index dd9c2ba7d77..b605531db45 100644 --- a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/array/dyn/AbstractJSObjectArray.java +++ b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/array/dyn/AbstractJSObjectArray.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -78,10 +78,15 @@ public final ScriptArray setElementImpl(JSDynamicObject object, long index, Obje } private ScriptArray rewrite(JSDynamicObject object, long index, Object value) { - if (isSupportedContiguous(object, index)) { - return toContiguous(object, index, value); - } else if (isSupportedHoles(object, index)) { - return toHoles(object, index, value); + if (JSDynamicObject.isJSDynamicObject(value)) { + assert !isSupported(object, index); + if (isSupportedContiguous(object, index)) { + return toContiguous(object, index, value); + } else if (isSupportedHoles(object, index)) { + return toHoles(object, index, value); + } else { + return toSparse(object, index, value); + } } else { return toObject(object, index, value); }