import changes from rmottola/Arctic-Fox:

- Bug 1113369, part 1 - Introduce JS::ObjectOpResult and use it in js::StandardDefineProperty. (15663c476)
- Bug 1113369, part 1½ - Avoid regressing error messages by adding obj to the ObjectOpResult methods that could throw a TypeError. (e063faf08)
- Bug 1113369, part 2 - js::SetArrayLength ObjectOpResult support. (cf8326017)
- Bug 1113369, part 3 - [[DefineOwnProperty]] ObjectOpResult support. (e16605a90)
- Bug 1113369, part 4 - [[Set]] ObjectOpResult support. (6f94604d4)
This commit is contained in:
2019-02-07 18:42:28 +08:00
parent 26882c6ce0
commit fbd797d49d
86 changed files with 1464 additions and 925 deletions
+22 -62
View File
@@ -363,7 +363,7 @@ SetArrayElement(JSContext* cx, HandleObject obj, double index, HandleValue v)
return false;
RootedValue tmp(cx, v);
return SetProperty(cx, obj, obj, id, &tmp, true);
return SetProperty(cx, obj, obj, id, &tmp);
}
/*
@@ -433,7 +433,7 @@ bool
js::SetLengthProperty(JSContext* cx, HandleObject obj, double length)
{
RootedValue v(cx, NumberValue(length));
return SetProperty(cx, obj, obj, cx->names().length, &v, true);
return SetProperty(cx, obj, obj, cx->names().length, &v);
}
/*
@@ -459,7 +459,8 @@ array_length_getter(JSContext* cx, HandleObject obj_, HandleId id, MutableHandle
}
static bool
array_length_setter(JSContext* cx, HandleObject obj, HandleId id, bool strict, MutableHandleValue vp)
array_length_setter(JSContext *cx, HandleObject obj, HandleId id, MutableHandleValue vp,
ObjectOpResult &result)
{
if (!obj->is<ArrayObject>()) {
// This array .length property was found on the prototype
@@ -467,13 +468,14 @@ array_length_setter(JSContext* cx, HandleObject obj, HandleId id, bool strict, M
// we're here, do an impression of SetPropertyByDefining.
const Class* clasp = obj->getClass();
return DefineProperty(cx, obj, cx->names().length, vp,
clasp->getProperty, clasp->setProperty, JSPROP_ENUMERATE);
clasp->getProperty, clasp->setProperty, JSPROP_ENUMERATE, result);
}
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
MOZ_ASSERT(arr->lengthIsWritable(),
"setter shouldn't be called if property is non-writable");
return ArraySetLength(cx, arr, id, JSPROP_PERMANENT, vp, strict);
return ArraySetLength(cx, arr, id, JSPROP_PERMANENT, vp, result);
}
struct ReverseIndexComparator
@@ -506,7 +508,7 @@ js::CanonicalizeArrayLengthValue(JSContext* cx, HandleValue v, uint32_t* newLen)
/* ES6 20130308 draft 8.4.2.4 ArraySetLength */
bool
js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
unsigned attrs, HandleValue value, bool setterIsStrict)
unsigned attrs, HandleValue value, ObjectOpResult &result)
{
MOZ_ASSERT(id == NameToId(cx->names().length));
@@ -529,11 +531,8 @@ js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
// 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);
}
if (!(attrs & JSPROP_PERMANENT) || (attrs & JSPROP_ENUMERATE))
return result.fail(JSMSG_CANT_REDEFINE_PROP);
/* Steps 6-7. */
bool lengthIsWritable = arr->lengthIsWritable();
@@ -550,14 +549,9 @@ js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
/* Steps 8-9 for arrays with non-writable length. */
if (!lengthIsWritable) {
if (newLen == oldLen)
return true;
return result.succeed();
if (setterIsStrict) {
return JS_ReportErrorFlagsAndNumber(cx, JSREPORT_ERROR, GetErrorMessage, nullptr,
JSMSG_CANT_REDEFINE_ARRAY_LENGTH);
}
return JSObject::reportReadOnly(cx, id, JSREPORT_STRICT | JSREPORT_WARNING);
return result.fail(JSMSG_CANT_REDEFINE_ARRAY_LENGTH);
}
/* Step 8. */
@@ -738,53 +732,20 @@ js::ArraySetLength(JSContext* cx, Handle<ArrayObject*> arr, HandleId id,
}
}
if (setterIsStrict && !succeeded) {
RootedId elementId(cx);
if (!IndexToId(cx, newLen - 1, &elementId))
return false;
return arr->reportNotConfigurable(cx, elementId);
}
if (!succeeded)
return result.fail(JSMSG_CANT_TRUNCATE_ARRAY);
return true;
return result.succeed();
}
bool
js::WouldDefinePastNonwritableLength(ExclusiveContext* cx,
HandleObject obj, uint32_t index, bool strict,
bool* definesPast)
js::WouldDefinePastNonwritableLength(HandleNativeObject obj, uint32_t index)
{
if (!obj->is<ArrayObject>()) {
*definesPast = false;
return true;
}
if (!obj->is<ArrayObject>())
return false;
Rooted<ArrayObject*> arr(cx, &obj->as<ArrayObject>());
uint32_t length = arr->length();
if (index < length) {
*definesPast = false;
return true;
}
if (arr->lengthIsWritable()) {
*definesPast = false;
return true;
}
*definesPast = true;
// Error in strict mode code or warn with strict option.
unsigned flags = strict ? JSREPORT_ERROR : (JSREPORT_STRICT | JSREPORT_WARNING);
if (!cx->isJSContext())
return true;
JSContext* ncx = cx->asJSContext();
if (!strict && !ncx->compartment()->options().extraWarnings(ncx))
return true;
// XXX include the index and maybe array length in the error message
return JS_ReportErrorFlagsAndNumber(ncx, flags, GetErrorMessage, nullptr,
JSMSG_CANT_DEFINE_PAST_ARRAY_LENGTH);
ArrayObject *arr = &obj->as<ArrayObject>();
return !arr->lengthIsWritable() && index >= arr->length();
}
static bool
@@ -1308,7 +1269,7 @@ InitArrayElements(JSContext* cx, HandleObject obj, uint32_t start, uint32_t coun
value = *vector++;
indexv = DoubleValue(index);
if (!ValueToId<CanGC>(cx, indexv, &id) ||
!SetProperty(cx, obj, obj, id, &value, true))
!SetProperty(cx, obj, obj, id, &value))
{
return false;
}
@@ -3112,8 +3073,7 @@ array_of(JSContext* cx, unsigned argc, Value* vp)
}
// Steps 9-10.
RootedValue v(cx, NumberValue(args.length()));
if (!SetProperty(cx, obj, obj, cx->names().length, &v, true))
if (!SetLengthProperty(cx, obj, args.length()))
return false;
// Step 11.