From 5f182e7470aff314688d2662f8c493d7b7265be2 Mon Sep 17 00:00:00 2001 From: Jan Stola Date: Thu, 6 Feb 2025 22:36:29 +0100 Subject: [PATCH 1/7] Non-extensible object can be sealed/frozen even without the corresponding flag. --- .../truffle/js/runtime/builtins/JSNonProxy.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/JSNonProxy.java b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/JSNonProxy.java index 12ce6ef4955..cf7bb26ffbe 100644 --- a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/JSNonProxy.java +++ b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/JSNonProxy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, 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 @@ -532,9 +532,18 @@ public static boolean setIntegrityLevelFast(JSDynamicObject thisObj, boolean fre public static boolean testIntegrityLevelFast(JSDynamicObject obj, boolean frozen) { int objectFlags = JSDynamicObject.getObjectFlags(obj); if (frozen) { - return (objectFlags & JSShape.FROZEN_FLAG) != 0; + if ((objectFlags & JSShape.FROZEN_FLAG) != 0) { + return true; + } } else { - return (objectFlags & JSShape.SEALED_FLAG) != 0; + if ((objectFlags & JSShape.SEALED_FLAG) != 0) { + return true; + } + } + if ((objectFlags & JSShape.NOT_EXTENSIBLE_FLAG) != 0) { + return testSealedProperties(obj) && (!frozen || testFrozenProperties(obj)); + } else { + return false; } } @@ -565,10 +574,12 @@ public static boolean ordinaryPreventExtensions(JSDynamicObject thisObj, int ext return true; } + @TruffleBoundary private static boolean testSealedProperties(JSDynamicObject thisObj) { return JSDynamicObject.testProperties(thisObj, p -> p.isHidden() || (p.getFlags() & JSAttributes.NOT_CONFIGURABLE) != 0); } + @TruffleBoundary private static boolean testFrozenProperties(JSDynamicObject thisObj) { return JSDynamicObject.testProperties(thisObj, p -> p.isHidden() || (p.getFlags() & JSProperty.ACCESSOR) != 0 || (p.getFlags() & JSAttributes.NOT_WRITABLE) != 0); } From bf795c2bd5c568232ef9c130a542b322d5d1cc2d Mon Sep 17 00:00:00 2001 From: Jan Stola Date: Thu, 6 Feb 2025 22:37:50 +0100 Subject: [PATCH 2/7] Non-empty typed array cannot be sealed. --- .../truffle/js/runtime/builtins/JSTypedArrayObject.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/JSTypedArrayObject.java b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/JSTypedArrayObject.java index 8438604859a..c5dcf3e8d22 100644 --- a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/JSTypedArrayObject.java +++ b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/JSTypedArrayObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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 @@ -180,7 +180,7 @@ public boolean isArrayElementInsertable(@SuppressWarnings("unused") long index) @Override public boolean testIntegrityLevel(boolean frozen) { - if (frozen && getArraySize() > 0) { + if (getArraySize() > 0) { return false; } return JSNonProxy.testIntegrityLevelFast(this, frozen); @@ -189,7 +189,7 @@ public boolean testIntegrityLevel(boolean frozen) { @Override public boolean setIntegrityLevel(boolean freeze, boolean doThrow) { preventExtensions(doThrow); - if (freeze && getArraySize() > 0) { + if (getArraySize() > 0) { throw Errors.createTypeErrorCannotRedefineTypedArrayElement(); } JSNonProxy.setIntegrityLevelFast(this, freeze); From 176ee2510b6ddcf1dea07b436cd52d9b079434a1 Mon Sep 17 00:00:00 2001 From: Jan Stola Date: Thu, 6 Feb 2025 22:38:48 +0100 Subject: [PATCH 3/7] Updating the status of Test262 test-suite. --- graal-js/test/test262.json | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/graal-js/test/test262.json b/graal-js/test/test262.json index 64734770c55..d5596b65577 100644 --- a/graal-js/test/test262.json +++ b/graal-js/test/test262.json @@ -3644,6 +3644,10 @@ "COMPILE_IMMEDIATELY" : "SKIP" }, "comment" : "Long-running in compile mode" + }, { + "filePath" : "staging/built-ins/Object/seal/seal-variable-length-typed-arrays.js", + "status" : "FAIL", + "comment" : "Off-spec: expects Object.seal(fixed length TA backed by GSAB) not to throw. It throws because it has configurable integer properties that cannot be redefined to be non-configurable." }, { "filePath" : "staging/Intl402/Temporal/old/addition-across-lunisolar-leap-months.js", "status" : "FAIL", @@ -3978,10 +3982,6 @@ "minVersion" : 24 }, "comment" : "requires Unicode 16.0" - }, { - "filePath" : "staging/sm/Symbol/property-reflection.js", - "status" : "FAIL", - "comment" : "new failures 2025-01-23" }, { "filePath" : "staging/sm/Temporal/Calendar/compare-to-datetimeformat.js", "status" : "FAIL", @@ -4040,10 +4040,6 @@ "minVersion" : 16 }, "comment" : "expects uint8array-base64 to be enabled" - }, { - "filePath" : "staging/sm/TypedArray/seal-and-freeze.js", - "status" : "FAIL", - "comment" : "new failures 2025-01-23" }, { "filePath" : "staging/sm/TypedArray/sort-negative-nan.js", "ecmaVersion" : { @@ -4060,10 +4056,6 @@ "filePath" : "staging/sm/TypedArray/test-integrity-level-detached.js", "status" : "FAIL", "comment" : "new failures 2025-01-23" - }, { - "filePath" : "staging/sm/TypedArray/test-integrity-level.js", - "status" : "FAIL", - "comment" : "new failures 2025-01-23" }, { "filePath" : "staging/sm/TypedArray/toString.js", "ecmaVersion" : { From 132535a3d02771645e68456dc9117fd2fdfd3dc8 Mon Sep 17 00:00:00 2001 From: Jan Stola Date: Fri, 7 Feb 2025 23:14:34 +0100 Subject: [PATCH 4/7] Updating the status of TestV8 test-suite. --- graal-js/test/testV8.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/graal-js/test/testV8.json b/graal-js/test/testV8.json index ba6490e0b67..d0b7653cb35 100644 --- a/graal-js/test/testV8.json +++ b/graal-js/test/testV8.json @@ -881,6 +881,10 @@ }, { "filePath" : "mjsunit/number-tostring-big-integer.js", "status" : "FAIL" + }, { + "filePath" : "mjsunit/object-seal.js", + "status" : "FAIL", + "comment" : "Obsolete test, see https://github.com/v8/v8/commit/58fe43dd2fbb2b3c4fad55f8c40bd0daa78612a7#diff-8c4973d7623f46ba59c9c0fa41083040ac0b33cf160ebfc89ecf2151f12309a1" }, { "filePath" : "mjsunit/opt-elements-kind.js", "status" : "SKIP", @@ -1363,6 +1367,10 @@ "filePath" : "mjsunit/regress/regress-948307.js", "runInIsolation" : true, "comment" : "test with (expected) high memory usage that might influence other tests" + }, { + "filePath" : "mjsunit/regress/regress-95920.js", + "status" : "FAIL", + "comment" : "Obsolete test, see https://github.com/v8/v8/commit/58fe43dd2fbb2b3c4fad55f8c40bd0daa78612a7#diff-3463c63ce3409b70aa17c9e8cd3af8429d2dd1764c57219229b28d3f6aa31d6e" }, { "filePath" : "mjsunit/regress/regress-crbug-100859.js", "runInIsolation" : true, From e8421e3b0aff861241d3f4877f5f4c78ed1a0ce6 Mon Sep 17 00:00:00 2001 From: Jan Stola Date: Fri, 7 Feb 2025 23:36:26 +0100 Subject: [PATCH 5/7] Updating object_freeze_seal test. --- .../js/object_freeze_seal.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/graal-js/src/com.oracle.truffle.js.test/js/object_freeze_seal.js b/graal-js/src/com.oracle.truffle.js.test/js/object_freeze_seal.js index c33915c1ce4..da1fbe21569 100644 --- a/graal-js/src/com.oracle.truffle.js.test/js/object_freeze_seal.js +++ b/graal-js/src/com.oracle.truffle.js.test/js/object_freeze_seal.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, 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. @@ -82,15 +82,15 @@ assertTrue(Object.isExtensible(ta)); assertFalse(Object.isSealed(ta)); assertFalse(Object.isFrozen(ta)); -Object.seal(ta); +try { Object.seal(ta); } catch {} assertFalse(Object.isExtensible(ta)); -assertTrue(Object.isSealed(ta)); +assertFalse(Object.isSealed(ta)); assertFalse(Object.isFrozen(ta)); assertEqual(JSON.stringify(Object.getOwnPropertyDescriptor(ta, "0")), `{"value":0,"writable":true,"enumerable":true,"configurable":true}`); try { Object.freeze(ta); } catch {} assertFalse(Object.isExtensible(ta)); -assertTrue(Object.isSealed(ta)); +assertFalse(Object.isSealed(ta)); assertFalse(Object.isFrozen(ta)); assertEqual(JSON.stringify(Object.getOwnPropertyDescriptor(ta, "0")), `{"value":0,"writable":true,"enumerable":true,"configurable":true}`); @@ -101,16 +101,16 @@ assertTrue(Object.isExtensible(ta)); assertFalse(Object.isSealed(ta)); assertFalse(Object.isFrozen(ta)); -Object.seal(ta); +try { Object.seal(ta); } catch {} assertFalse(Object.isExtensible(ta)); -assertTrue(Object.isSealed(ta)); +assertFalse(Object.isSealed(ta)); assertFalse(Object.isFrozen(ta)); assertEqual(JSON.stringify(Object.getOwnPropertyDescriptor(ta, "0")), `{"value":0,"writable":true,"enumerable":true,"configurable":true}`); -assertEqual(JSON.stringify(Object.getOwnPropertyDescriptor(ta, "x")), `{"value":42,"writable":true,"enumerable":true,"configurable":false}`); +assertEqual(JSON.stringify(Object.getOwnPropertyDescriptor(ta, "x")), `{"value":42,"writable":true,"enumerable":true,"configurable":true}`); try { Object.freeze(ta); } catch {} assertFalse(Object.isExtensible(ta)); -assertTrue(Object.isSealed(ta)); +assertFalse(Object.isSealed(ta)); assertFalse(Object.isFrozen(ta)); assertEqual(JSON.stringify(Object.getOwnPropertyDescriptor(ta, "0")), `{"value":0,"writable":true,"enumerable":true,"configurable":true}`); -assertEqual(JSON.stringify(Object.getOwnPropertyDescriptor(ta, "x")), `{"value":42,"writable":true,"enumerable":true,"configurable":false}`); +assertEqual(JSON.stringify(Object.getOwnPropertyDescriptor(ta, "x")), `{"value":42,"writable":true,"enumerable":true,"configurable":true}`); From 33088c033ebdc04d127a751c792c8fcfdc8d60a1 Mon Sep 17 00:00:00 2001 From: Jan Stola Date: Sun, 9 Feb 2025 23:53:58 +0100 Subject: [PATCH 6/7] Non-extensible array can be sealed/frozen even without the corresponding flag. --- .../com/oracle/truffle/js/runtime/builtins/JSArrayBase.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/JSArrayBase.java b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/JSArrayBase.java index 9af92b2bcca..506a0f7ff61 100644 --- a/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/JSArrayBase.java +++ b/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/JSArrayBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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 @@ -107,7 +107,8 @@ public final void setArray(Object array) { @Override public final boolean testIntegrityLevel(boolean frozen) { DynamicArray array = (DynamicArray) getArrayType(); - boolean arrayIs = frozen ? array.isFrozen() : array.isSealed(); + boolean arrayIs = (frozen ? array.isFrozen() : array.isSealed()) || + (!array.isExtensible() && array.firstElementIndex(this) > array.lastElementIndex(this)); return arrayIs && JSNonProxy.testIntegrityLevelFast(this, frozen); } From 4ce91e75a3885bfb44ccc952696dd0598a3705e1 Mon Sep 17 00:00:00 2001 From: Jan Stola Date: Sun, 9 Feb 2025 23:55:11 +0100 Subject: [PATCH 7/7] Testing the integrity level of non-extensible arrays. --- .../js/array_integrity_level.js | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 graal-js/src/com.oracle.truffle.js.test/js/array_integrity_level.js diff --git a/graal-js/src/com.oracle.truffle.js.test/js/array_integrity_level.js b/graal-js/src/com.oracle.truffle.js.test/js/array_integrity_level.js new file mode 100644 index 00000000000..417f840be32 --- /dev/null +++ b/graal-js/src/com.oracle.truffle.js.test/js/array_integrity_level.js @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2025, 2025, 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. + */ + +load("assert.js"); + +[[], new Array(100)].forEach(function (array) { + assertFalse(Object.isSealed(array)); + assertFalse(Object.isFrozen(array)); + + Object.preventExtensions(array); + + assertTrue(Object.isSealed(array)); + assertFalse(Object.isFrozen(array)); // length is writable still + + Object.defineProperty(array, 'length', { writable: false }); + + assertTrue(Object.isSealed(array)); + assertTrue(Object.isFrozen(array)); +}); + +var array = [,42]; +Object.preventExtensions(array); +assertFalse(Object.isSealed(array)); // has array[1] +assertFalse(Object.isFrozen(array)); +delete array[1]; +assertTrue(Object.isSealed(array)); +assertFalse(Object.isFrozen(array)); // length is writable still +Object.defineProperty(array, 'length', { length: 2, writable: false }); +assertTrue(Object.isSealed(array)); +assertTrue(Object.isFrozen(array));