Bug 905947 - Don't assert when redefining an array's length to be configurable via the JSAPI. r=jorendorff

--HG--
extra : rebase_source : 4729e0aca6ea7addb56fd12a280eb2b1b4469ad7
This commit is contained in:
Jeff Walden 2013-08-20 17:06:51 -07:00
parent 118513d78a
commit a4b90e86b2
2 changed files with 61 additions and 2 deletions

View File

@ -435,8 +435,6 @@ js::ArraySetLength(JSContext *cx, Handle<ArrayObject*> arr, HandleId id, unsigne
HandleValue value, bool setterIsStrict) HandleValue value, bool setterIsStrict)
{ {
MOZ_ASSERT(id == NameToId(cx->names().length)); MOZ_ASSERT(id == NameToId(cx->names().length));
MOZ_ASSERT(attrs & JSPROP_PERMANENT);
MOZ_ASSERT(!(attrs & JSPROP_ENUMERATE));
/* Steps 1-2 are irrelevant in our implementation. */ /* Steps 1-2 are irrelevant in our implementation. */
@ -445,6 +443,21 @@ js::ArraySetLength(JSContext *cx, Handle<ArrayObject*> arr, HandleId id, unsigne
if (!CanonicalizeArrayLengthValue(cx, value, &newLen)) if (!CanonicalizeArrayLengthValue(cx, value, &newLen))
return false; return false;
// Abort if we're being asked to change enumerability or configurability.
// (The length property of arrays is non-configurable, so such attempts
// must fail.) This behavior is spread throughout the ArraySetLength spec
// algorithm, but we only need check it once as our array implementation
// is internally so different from the spec algorithm. (ES5 and ES6 define
// behavior by delegating to the default define-own-property algorithm --
// OrdinaryDefineOwnProperty in ES6, the default [[DefineOwnProperty]] in
// ES5 -- but we reimplement all the conflict-detection bits ourselves here
// so that we can use a customized length representation.)
if (!(attrs & JSPROP_PERMANENT) || (attrs & JSPROP_ENUMERATE)) {
if (!setterIsStrict)
return true;
return Throw(cx, id, JSMSG_CANT_REDEFINE_PROP);
}
/* Steps 6-7. */ /* Steps 6-7. */
bool lengthIsWritable = arr->lengthIsWritable(); bool lengthIsWritable = arr->lengthIsWritable();
#ifdef DEBUG #ifdef DEBUG

View File

@ -0,0 +1,46 @@
/*
* Any copyright is dedicated to the Public Domain.
* http://creativecommons.org/licenses/publicdomain/
*/
var gTestfile = 'proxy-array-target-length-definition.js';
var BUGNUMBER = 905947;
var summary =
"Redefining an array's |length| property when redefining the |length| " +
"property on a proxy with an array as target";
print(BUGNUMBER + ": " + summary);
/**************
* BEGIN TEST *
**************/
var arr = [];
var p = new Proxy(arr, {});
// This really should throw a TypeError, but we're buggy just yet, and this
// silently does nothing.
Object.defineProperty(p, "length", { value: 17, configurable: true });
// Same here.
Object.defineProperty(p, "length", { value: 42, enumerable: true });
// But at least we can check the property went unchanged.
var pd = Object.getOwnPropertyDescriptor(p, "length");
assertEq(pd.value, 0);
assertEq(pd.writable, true);
assertEq(pd.enumerable, false);
assertEq(pd.configurable, false);
var ad = Object.getOwnPropertyDescriptor(arr, "length");
assertEq(ad.value, 0);
assertEq(ad.writable, true);
assertEq(ad.enumerable, false);
assertEq(ad.configurable, false);
/******************************************************************************/
if (typeof reportCompare === "function")
reportCompare(true, true);
print("Tests complete");