Skip to content

Commit c212ac8

Browse files
committed
[GR-24687] Corrections of ArraySetLength().
PullRequest: js/1576
2 parents 79fd504 + 501bf15 commit c212ac8

File tree

3 files changed

+71
-36
lines changed

3 files changed

+71
-36
lines changed
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright (c) 2020, 2020, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl.
6+
*/
7+
8+
load('assert.js');
9+
10+
// valueOf() should be invoked twice (from ToUint32() and ToNumber())
11+
var valueOfCalls = 0;
12+
Object.defineProperty([0, 1, 2], 'length', {
13+
value: {
14+
valueOf: function () {
15+
valueOfCalls++;
16+
return 3;
17+
}
18+
}
19+
});
20+
assertSame(2, valueOfCalls);
21+
22+
// length should remain writable when its re-definition is refused
23+
var array = [42, 211];
24+
assertThrows(function () {
25+
Object.defineProperty(array, 'length', {
26+
writable: false,
27+
configurable: true
28+
});
29+
}, TypeError);
30+
array.length = 5;
31+
assertSame(5, array.length);
32+
33+
// length should be constant after re-definition with "writable: false"
34+
var array = [0, 1, 2];
35+
Object.defineProperty(array, 'length', {
36+
value: 3,
37+
writable: false
38+
});
39+
assertThrows(function () {
40+
array.splice(1, 2, 4);
41+
}, TypeError);
42+
assertSame(3, array.length);
43+
assertSame(array[0], 0);
44+
assertSame(array[1], 4);
45+
assertSame(array[2], undefined);
46+
47+
true;

graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/builtins/JSAbstractArray.java

Lines changed: 24 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -637,7 +637,7 @@ public static long toArrayIndexOrRangeError(Number len, Number len32, BranchProf
637637
@TruffleBoundary
638638
public boolean defineOwnProperty(DynamicObject thisObj, Object key, PropertyDescriptor descriptor, boolean doThrow) {
639639
if (key.equals(LENGTH)) {
640-
return defineOwnPropertyLength(thisObj, key, descriptor, doThrow);
640+
return defineOwnPropertyLength(thisObj, descriptor, doThrow);
641641
} else if (key instanceof String && JSRuntime.isArrayIndex((String) key)) {
642642
return defineOwnPropertyIndex(thisObj, (String) key, descriptor, doThrow);
643643
} else {
@@ -651,17 +651,18 @@ public boolean defineOwnProperty(DynamicObject thisObj, Object key, PropertyDesc
651651
*
652652
* @return whether the operation was successful
653653
*/
654-
private boolean defineOwnPropertyLength(DynamicObject thisObj, Object key, PropertyDescriptor descriptor, boolean doThrow) {
654+
private boolean defineOwnPropertyLength(DynamicObject thisObj, PropertyDescriptor descriptor, boolean doThrow) {
655655
if (!descriptor.hasValue()) {
656-
if (descriptor.hasWritable() && !descriptor.getWritable()) {
656+
boolean success = DefinePropertyUtil.ordinaryDefineOwnProperty(thisObj, LENGTH, descriptor, doThrow);
657+
if (success && descriptor.hasWritable() && !descriptor.getWritable()) {
657658
setLengthNotWritable(thisObj);
658659
}
659-
return DefinePropertyUtil.ordinaryDefineOwnProperty(thisObj, key, descriptor, doThrow);
660+
return success;
660661
}
661662

662-
Number newLenNum = JSRuntime.toNumber(descriptor.getValue());
663-
long newLen = JSRuntime.toUInt32(newLenNum);
664-
if (JSRuntime.doubleValue(newLenNum) != newLen) {
663+
long newLen = JSRuntime.toUInt32(descriptor.getValue());
664+
Number numberLen = JSRuntime.toNumber(descriptor.getValue());
665+
if (JSRuntime.doubleValue(numberLen) != newLen) {
665666
throw Errors.createRangeErrorInvalidArrayLength();
666667
}
667668
PropertyDescriptor lenDesc = getOwnProperty(thisObj, LENGTH);
@@ -715,32 +716,26 @@ private boolean deleteElementsAfterShortening(DynamicObject thisObj, PropertyDes
715716

716717
private boolean definePropertyLength(DynamicObject thisObj, PropertyDescriptor descriptor, PropertyDescriptor currentDesc, long len, boolean doThrow) {
717718
assert JSRuntime.isValidArrayLength(len);
719+
assert !currentDesc.getConfigurable();
718720
boolean currentWritable = currentDesc.getWritable();
719721
boolean currentEnumerable = currentDesc.getEnumerable();
720-
boolean currentConfigurable = currentDesc.getConfigurable();
721722

722723
boolean newWritable = descriptor.getIfHasWritable(currentWritable);
723724
boolean newEnumerable = descriptor.getIfHasEnumerable(currentEnumerable);
724-
boolean newConfigurable = descriptor.getIfHasConfigurable(currentConfigurable);
725+
boolean newConfigurable = descriptor.getIfHasConfigurable(false);
725726

726-
if (currentConfigurable) {
727-
if (!currentWritable && !newWritable) {
728-
return DefinePropertyUtil.reject(doThrow, LENGTH_PROPERTY_NOT_WRITABLE);
729-
}
730-
} else {
731-
if (descriptor.getConfigurable() || (newEnumerable != currentEnumerable)) {
732-
// ES2020 9.1.6.3, 4.a and 4.b
733-
return DefinePropertyUtil.reject(doThrow, CANNOT_REDEFINE_PROPERTY_LENGTH);
734-
}
735-
if (currentWritable == newWritable && currentEnumerable == newEnumerable) {
736-
if (!descriptor.hasValue() || len == getLength(thisObj)) {
737-
return true; // nothing changed
738-
}
739-
}
740-
if (!currentWritable) {
741-
return DefinePropertyUtil.reject(doThrow, LENGTH_PROPERTY_NOT_WRITABLE);
727+
if (newConfigurable || (newEnumerable != currentEnumerable)) {
728+
// ES2020 9.1.6.3, 4.a and 4.b
729+
return DefinePropertyUtil.reject(doThrow, CANNOT_REDEFINE_PROPERTY_LENGTH);
730+
}
731+
if (currentWritable == newWritable && currentEnumerable == newEnumerable) {
732+
if (!descriptor.hasValue() || len == getLength(thisObj)) {
733+
return true; // nothing changed
742734
}
743735
}
736+
if (!currentWritable) {
737+
return DefinePropertyUtil.reject(doThrow, LENGTH_PROPERTY_NOT_WRITABLE);
738+
}
744739

745740
try {
746741
setLength(thisObj, len, doThrow);
@@ -749,6 +744,10 @@ private boolean definePropertyLength(DynamicObject thisObj, PropertyDescriptor d
749744
JSObjectUtil.changeFlags(thisObj, LENGTH, newAttr);
750745
}
751746

747+
if (!newWritable) {
748+
setLengthNotWritable(thisObj);
749+
}
750+
752751
return true;
753752
}
754753

graal-js/test/testV8.json

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1077,9 +1077,6 @@
10771077
"filePath" : "mjsunit/regress/regress-5638b.js",
10781078
"status" : "FAIL",
10791079
"comment" : "TODO: evaluate (V8 tests update 2017-07-07)"
1080-
}, {
1081-
"filePath" : "mjsunit/regress/regress-5669.js",
1082-
"status" : "FAIL"
10831080
}, {
10841081
"filePath" : "mjsunit/regress/regress-575364.js",
10851082
"status" : "SKIP",
@@ -1580,10 +1577,6 @@
15801577
"filePath" : "mjsunit/regress/regress-crbug-816961.js",
15811578
"status" : "FAIL",
15821579
"comment" : "TODO: evaluate (V8 tests update 2018-10-29)"
1583-
}, {
1584-
"filePath" : "mjsunit/regress/regress-crbug-823069.js",
1585-
"status" : "FAIL",
1586-
"comment" : "TODO: evaluate (V8 tests update 2018-10-29)"
15871580
}, {
15881581
"filePath" : "mjsunit/regress/regress-crbug-865892.js",
15891582
"status" : "FAIL",
@@ -1733,10 +1726,6 @@
17331726
"filePath" : "mjsunit/regress/regress-wasm-crbug-618602.js",
17341727
"status" : "SKIP",
17351728
"comment" : "WASM (GR-6494)"
1736-
}, {
1737-
"filePath" : "mjsunit/regress/regress_967104.js",
1738-
"status" : "FAIL",
1739-
"comment" : "TODO: evaluate (V8 tests update 2019-10-15)"
17401729
}, {
17411730
"filePath" : "mjsunit/regress/wasm/loop-stack-check.js",
17421731
"status" : "SKIP",

0 commit comments

Comments
 (0)