Bug 1120503 - Fix seal/freeze for typed arrays. r=Waldo

This commit is contained in:
Tom Schuster 2015-02-18 13:04:12 +01:00
parent 9cbdf3d75e
commit 22c358bee4
2 changed files with 54 additions and 18 deletions

View File

@ -1098,7 +1098,7 @@ js::SetIntegrityLevel(JSContext *cx, HandleObject obj, IntegrityLevel level)
return true;
}
/* ES6 rev 29 (6 Dec 2014) 7.3.14. */
// ES6 draft rev33 (12 Feb 2015) 7.3.15
bool
js::TestIntegrityLevel(JSContext *cx, HandleObject obj, IntegrityLevel level, bool *result)
{
@ -1111,38 +1111,26 @@ js::TestIntegrityLevel(JSContext *cx, HandleObject obj, IntegrityLevel level, bo
return true;
}
if (IsAnyTypedArray(obj)) {
if (level == IntegrityLevel::Sealed) {
// Typed arrays are considered sealed (bug 1120503).
*result = true;
} else {
// Typed arrays cannot be frozen, but an empty typed array is
// considered frozen (bug 1120503).
*result = (AnyTypedArrayLength(obj) == 0);
}
return true;
}
// Steps 7-8.
AutoIdVector props(cx);
if (!GetPropertyKeys(cx, obj, JSITER_HIDDEN | JSITER_OWNONLY | JSITER_SYMBOLS, &props))
return false;
// Step 11.
// Step 9.
RootedId id(cx);
Rooted<PropertyDescriptor> desc(cx);
for (size_t i = 0, len = props.length(); i < len; i++) {
id = props[i];
// Steps 11.a-b.
// Steps 9.a-b.
if (!GetOwnPropertyDescriptor(cx, obj, id, &desc))
return false;
// Step 11.c.
// Step 9.c.
if (!desc.object())
continue;
// Steps 11.c.i-ii.
// Steps 9.c.i-ii.
if (!desc.isPermanent() ||
(level == IntegrityLevel::Frozen && desc.isDataDescriptor() && desc.isWritable()))
{
@ -1151,7 +1139,7 @@ js::TestIntegrityLevel(JSContext *cx, HandleObject obj, IntegrityLevel level, bo
}
}
// Step 12.
// Step 10.
*result = true;
return true;
}

View File

@ -0,0 +1,48 @@
"use strict";
// Seal
assertEq(Object.isSealed(new Int32Array(2)), false);
assertEq(Object.isSealed(new Int32Array(0)), false);
var array = new Int32Array(0);
Object.preventExtensions(array);
assertEq(Object.isSealed(array), true);
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);
array = new Int32Array(2);
array.b = "test";
Object.seal(array);
assertEq(Object.isSealed(array), true);
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
var array = new Int32Array(0);
Object.preventExtensions(array);
assertEq(Object.isFrozen(array), true);
array = new Int32Array(0);
array.b = "test";
assertEq(Object.isFrozen(array), false);
Object.preventExtensions(array);
assertEq(Object.isFrozen(array), false);
Object.defineProperty(array, "b", {configurable: false, writable: false});
assertEq(Object.isFrozen(array), true);
// Non-empty typed arrays can never be frozen, because the elements stay writable
array = new Int32Array(1);
assertThrowsInstanceOf(() => Object.freeze(array), TypeError);
assertEq(Object.isExtensible(array), false);
assertEq(Object.isFrozen(array), false);
if (typeof reportCompare === "function")
reportCompare(true, true);