Skip to content

Commit

Permalink
Bug 1672862 - Part 1: Change TypedArray indexed properties to report …
Browse files Browse the repository at this point in the history
…as configurable. r=tcampbell

Implements the changes from <tc39/ecma262#2164> and
<tc39/ecma262#2210> for [[GetOwnProperty]]. Part 3
will update [[DefineOwnProperty]] and part 5 updates [[Set]].

A side-effect of this change is that non-extensible, non-empty TypedArrays are
no longer considered as sealed by `Object.isSealed()`.

A later patch in this series will update test262 to enable more currently
skipped TypedArray tests.

Differential Revision: https://phabricator.services.mozilla.com/D99380
  • Loading branch information
anba committed Dec 22, 2020
1 parent 3fa05e5 commit be0125b
Show file tree
Hide file tree
Showing 6 changed files with 19 additions and 17 deletions.
2 changes: 1 addition & 1 deletion js/src/tests/non262/TypedArray/object-defineproperty.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ Object.defineProperty(obj, 0, {value: 18});
assertEq(obj[0], 18);

var desc = Object.getOwnPropertyDescriptor(obj, 0);
assertEq(desc.configurable, false);
assertEq(desc.configurable, true);
assertEq(desc.enumerable, true);
assertEq(desc.writable, true);
assertEq(desc.value, 18);
Expand Down
7 changes: 4 additions & 3 deletions js/src/tests/non262/TypedArray/seal-and-freeze.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,25 @@ var array = new Int32Array(0);
Object.preventExtensions(array);
assertEq(Object.isSealed(array), true);

// Non-empty typed arrays can never be sealed, because the elements stay configurable.
array = new Int32Array(1);
array.b = "test";
Object.preventExtensions(array);
assertEq(Object.isSealed(array), false);
Object.defineProperty(array, "b", {configurable: false});
assertEq(Object.isSealed(array), true);
assertEq(Object.isSealed(array), false);

array = new Int32Array(2);
array.b = "test";
Object.seal(array);
assertEq(Object.isSealed(array), true);
assertEq(Object.isSealed(array), false);
assertThrowsInstanceOf(() => array.c = 15, TypeError);

// Freeze
assertEq(Object.isFrozen(new Int32Array(2)), false);
assertEq(Object.isFrozen(new Int32Array(0)), false);

// Empty non-extensible typed-array is trvially frozen
// Empty non-extensible typed-array is trivially frozen
var array = new Int32Array(0);
Object.preventExtensions(array);
assertEq(Object.isFrozen(array), true);
Expand Down
10 changes: 5 additions & 5 deletions js/src/tests/non262/TypedArray/test-integrity-level.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ const NON_INLINE_STORAGE = 1024;
assertEq(Object.isFrozen(ta), true);
}

// Non-empty typed arrays can be sealed.
// Non-empty typed arrays cannot be sealed.
for (let length of [INLINE_STORAGE, NON_INLINE_STORAGE]) {
let ta = new Int32Array(length);
Object.seal(ta);

assertEq(Object.isExtensible(ta), false);
assertEq(Object.isSealed(ta), true);
assertEq(Object.isSealed(ta), false);
assertEq(Object.isFrozen(ta), false);
}

Expand All @@ -38,7 +38,7 @@ for (let length of [INLINE_STORAGE, NON_INLINE_STORAGE]) {
assertThrowsInstanceOf(() => Object.freeze(ta), TypeError);

assertEq(Object.isExtensible(ta), false);
assertEq(Object.isSealed(ta), true);
assertEq(Object.isSealed(ta), false);
assertEq(Object.isFrozen(ta), false);
}

Expand All @@ -52,13 +52,13 @@ for (let length of [INLINE_STORAGE, NON_INLINE_STORAGE]) {
assertEq(Object.isFrozen(ta), true);
}

// Non-extensible non-empty typed arrays are sealed, but aren't frozen.
// Non-extensible non-empty typed arrays are neither sealed nor frozen.
for (let length of [INLINE_STORAGE, NON_INLINE_STORAGE]) {
let ta = new Int32Array(length);
Object.preventExtensions(ta);

assertEq(Object.isExtensible(ta), false);
assertEq(Object.isSealed(ta), true);
assertEq(Object.isSealed(ta), false);
assertEq(Object.isFrozen(ta), false);
}

Expand Down
7 changes: 3 additions & 4 deletions js/src/vm/JSObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -673,11 +673,10 @@ bool js::TestIntegrityLevel(JSContext* cx, HandleObject obj,
return false;
}

// Typed array elements are non-configurable, writable properties, so
// if any elements are present, the typed array cannot be frozen.
// Typed array elements are configurable, writable properties, so if any
// elements are present, the typed array can neither be sealed nor frozen.
if (nobj->is<TypedArrayObject>() &&
nobj->as<TypedArrayObject>().length().get() > 0 &&
level == IntegrityLevel::Frozen) {
nobj->as<TypedArrayObject>().length().get() > 0) {
*result = false;
return true;
}
Expand Down
8 changes: 5 additions & 3 deletions js/src/vm/NativeObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2770,6 +2770,11 @@ bool js::NativeDeleteProperty(JSContext* cx, HandleNativeObject obj,
return result.failCantDelete();
}

// Typed array elements are configurable, but can't be deleted.
if (prop.isTypedArrayElement()) {
return result.failCantDelete();
}

if (!CallJSDeletePropertyOp(cx, obj->getClass()->getDelProperty(), obj, id,
result)) {
return false;
Expand All @@ -2778,9 +2783,6 @@ bool js::NativeDeleteProperty(JSContext* cx, HandleNativeObject obj,
return true;
}

// Typed array elements are non-configurable.
MOZ_ASSERT(!prop.isTypedArrayElement());

// Step 5.
if (prop.isDenseElement()) {
obj->setDenseElementHole(prop.denseElementIndex());
Expand Down
2 changes: 1 addition & 1 deletion js/src/vm/Shape-inl.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ static inline uint8_t GetPropertyAttributes(JSObject* obj,
return obj->as<NativeObject>().getElementsHeader()->elementAttributes();
}
if (prop.isTypedArrayElement()) {
return JSPROP_ENUMERATE | JSPROP_PERMANENT;
return JSPROP_ENUMERATE;
}

return prop.shape()->attributes();
Expand Down

0 comments on commit be0125b

Please sign in to comment.