Bug 1317307: Throw a TypeError when attempting to change array.length to accessor property. r=till

This commit is contained in:
André Bargull 2016-11-14 12:27:52 -08:00
Родитель 6ff62e4d56
Коммит ae832a8e94
3 изменённых файлов: 50 добавлений и 4 удалений

Просмотреть файл

@ -551,6 +551,8 @@ js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
// Step 1.
uint32_t newLen;
if (attrs & JSPROP_IGNORE_VALUE) {
MOZ_ASSERT(value.isUndefined());
// The spec has us calling OrdinaryDefineOwnProperty if
// Desc.[[Value]] is absent, but our implementation is so different that
// this is impossible. Instead, set newLen to the current length and
@ -560,7 +562,6 @@ js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
// Step 2 is irrelevant in our implementation.
// Steps 3-7.
MOZ_ASSERT_IF(attrs & JSPROP_IGNORE_VALUE, value.isUndefined());
if (!CanonicalizeArrayLengthValue(cx, value, &newLen))
return false;

Просмотреть файл

@ -0,0 +1,42 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
var absent = {};
var getterValues = [absent, undefined, function(){}];
var setterValues = [absent, undefined, function(){}];
var configurableValues = [absent, true, false];
var enumerableValues = [absent, true, false];
function CreateDescriptor(getter, setter, enumerable, configurable) {
var descriptor = {};
if (getter !== absent)
descriptor.get = getter;
if (setter !== absent)
descriptor.set = setter;
if (configurable !== absent)
descriptor.configurable = configurable;
if (enumerable !== absent)
descriptor.enumerable = enumerable;
return descriptor;
}
getterValues.forEach(function(getter) {
setterValues.forEach(function(setter) {
enumerableValues.forEach(function(enumerable) {
configurableValues.forEach(function(configurable) {
var descriptor = CreateDescriptor(getter, setter, enumerable, configurable);
if (!("get" in descriptor || "set" in descriptor))
return;
assertThrowsInstanceOf(function() {
Object.defineProperty([], "length", descriptor);
}, TypeError);
});
});
});
});
if (typeof reportCompare === "function")
reportCompare(0, 0);

Просмотреть файл

@ -1372,8 +1372,7 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
{
desc_.assertValid();
// Section numbers and step numbers below refer to ES6 draft rev 36
// (17 March 2015).
// Section numbers and step numbers below refer to ES2016.
//
// This function aims to implement 9.1.6 [[DefineOwnProperty]] as well as
// the [[DefineOwnProperty]] methods described in 9.4.2.1 (arrays), 9.4.4.2
@ -1384,6 +1383,10 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
// 9.4.2.1 step 2. Redefining an array's length is very special.
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
if (id == NameToId(cx->names().length)) {
// 9.1.6.3 ValidateAndApplyPropertyDescriptor, step 7.a.
if (desc_.isAccessorDescriptor())
return result.fail(JSMSG_CANT_REDEFINE_PROP);
if (!cx->shouldBeJSContext())
return false;
return ArraySetLength(cx->asJSContext(), arr, id, desc_.attributes(), desc_.value(),
@ -1423,7 +1426,7 @@ js::NativeDefineProperty(ExclusiveContext* cx, HandleNativeObject obj, HandleId
}
}
// 9.1.6.1 OrdinaryDefineOwnProperty steps 1-2.
// 9.1.6.1 OrdinaryDefineOwnProperty step 1.
RootedShape shape(cx);
if (desc_.attributes() & JSPROP_RESOLVING) {
// We are being called from a resolve or enumerate hook to reify a