mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-10-28 18:17:29 +09:00
Issue #2089 - Implement AggregateError
Based-on: m-c 1568903/4,1641355(partial),1652148,1643397
This commit is contained in:
parent
209c8e06a2
commit
61c99bf6cd
11 changed files with 259 additions and 55 deletions
5
js/src/jit-test/tests/auto-regress/bug1652148.js
Normal file
5
js/src/jit-test/tests/auto-regress/bug1652148.js
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
// |jit-test| skip-if: !('oomTest' in this)
|
||||||
|
|
||||||
|
oomTest(() => {
|
||||||
|
new AggregateError([]);
|
||||||
|
});
|
||||||
|
|
@ -642,6 +642,7 @@ typedef enum JSExnType {
|
||||||
JSEXN_ERR,
|
JSEXN_ERR,
|
||||||
JSEXN_FIRST = JSEXN_ERR,
|
JSEXN_FIRST = JSEXN_ERR,
|
||||||
JSEXN_INTERNALERR,
|
JSEXN_INTERNALERR,
|
||||||
|
JSEXN_AGGREGATEERR,
|
||||||
JSEXN_EVALERR,
|
JSEXN_EVALERR,
|
||||||
JSEXN_RANGEERR,
|
JSEXN_RANGEERR,
|
||||||
JSEXN_REFERENCEERR,
|
JSEXN_REFERENCEERR,
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ CopyErrorObject(JSContext* cx, JS::Handle<ErrorObject*> errobj);
|
||||||
|
|
||||||
static_assert(JSEXN_ERR == 0 &&
|
static_assert(JSEXN_ERR == 0 &&
|
||||||
JSProto_Error + JSEXN_INTERNALERR == JSProto_InternalError &&
|
JSProto_Error + JSEXN_INTERNALERR == JSProto_InternalError &&
|
||||||
|
JSProto_Error + JSEXN_AGGREGATEERR == JSProto_AggregateError &&
|
||||||
JSProto_Error + JSEXN_EVALERR == JSProto_EvalError &&
|
JSProto_Error + JSEXN_EVALERR == JSProto_EvalError &&
|
||||||
JSProto_Error + JSEXN_RANGEERR == JSProto_RangeError &&
|
JSProto_Error + JSEXN_RANGEERR == JSProto_RangeError &&
|
||||||
JSProto_Error + JSEXN_REFERENCEERR == JSProto_ReferenceError &&
|
JSProto_Error + JSEXN_REFERENCEERR == JSProto_ReferenceError &&
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@
|
||||||
real(RegExp, InitViaClassSpec, OCLASP(RegExp)) \
|
real(RegExp, InitViaClassSpec, OCLASP(RegExp)) \
|
||||||
real(Error, InitViaClassSpec, ERROR_CLASP(JSEXN_ERR)) \
|
real(Error, InitViaClassSpec, ERROR_CLASP(JSEXN_ERR)) \
|
||||||
real(InternalError, InitViaClassSpec, ERROR_CLASP(JSEXN_INTERNALERR)) \
|
real(InternalError, InitViaClassSpec, ERROR_CLASP(JSEXN_INTERNALERR)) \
|
||||||
|
real(AggregateError, InitViaClassSpec, ERROR_CLASP(JSEXN_AGGREGATEERR)) \
|
||||||
real(EvalError, InitViaClassSpec, ERROR_CLASP(JSEXN_EVALERR)) \
|
real(EvalError, InitViaClassSpec, ERROR_CLASP(JSEXN_EVALERR)) \
|
||||||
real(RangeError, InitViaClassSpec, ERROR_CLASP(JSEXN_RANGEERR)) \
|
real(RangeError, InitViaClassSpec, ERROR_CLASP(JSEXN_RANGEERR)) \
|
||||||
real(ReferenceError, InitViaClassSpec, ERROR_CLASP(JSEXN_REFERENCEERR)) \
|
real(ReferenceError, InitViaClassSpec, ERROR_CLASP(JSEXN_REFERENCEERR)) \
|
||||||
|
|
|
||||||
82
js/src/tests/non262/Error/AggregateError.js
Normal file
82
js/src/tests/non262/Error/AggregateError.js
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
// |reftest| skip-if(release_or_beta)
|
||||||
|
|
||||||
|
assertEq(typeof AggregateError, "function");
|
||||||
|
assertEq(Object.getPrototypeOf(AggregateError), Error);
|
||||||
|
assertEq(AggregateError.name, "AggregateError");
|
||||||
|
assertEq(AggregateError.length, 2);
|
||||||
|
|
||||||
|
assertEq(Object.getPrototypeOf(AggregateError.prototype), Error.prototype);
|
||||||
|
assertEq(AggregateError.prototype.name, "AggregateError");
|
||||||
|
assertEq(AggregateError.prototype.message, "");
|
||||||
|
|
||||||
|
// The |errors| argument is mandatory.
|
||||||
|
assertThrowsInstanceOf(() => new AggregateError(), TypeError);
|
||||||
|
assertThrowsInstanceOf(() => AggregateError(), TypeError);
|
||||||
|
|
||||||
|
// The .errors data property is an array object.
|
||||||
|
{
|
||||||
|
let err = new AggregateError([]);
|
||||||
|
|
||||||
|
let {errors} = err;
|
||||||
|
assertEq(Array.isArray(errors), true);
|
||||||
|
assertEq(errors.length, 0);
|
||||||
|
|
||||||
|
// The errors object is modifiable.
|
||||||
|
errors.push(123);
|
||||||
|
assertEq(errors.length, 1);
|
||||||
|
assertEq(errors[0], 123);
|
||||||
|
assertEq(err.errors[0], 123);
|
||||||
|
|
||||||
|
// The property is writable.
|
||||||
|
err.errors = undefined;
|
||||||
|
assertEq(err.errors, undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The errors argument can be any iterable.
|
||||||
|
{
|
||||||
|
function* g() { yield* [1, 2, 3]; }
|
||||||
|
|
||||||
|
let {errors} = new AggregateError(g());
|
||||||
|
assertEqArray(errors, [1, 2, 3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The message property is populated by the second argument.
|
||||||
|
{
|
||||||
|
let err;
|
||||||
|
|
||||||
|
err = new AggregateError([]);
|
||||||
|
assertEq(err.message, "");
|
||||||
|
|
||||||
|
err = new AggregateError([], "my message");
|
||||||
|
assertEq(err.message, "my message");
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
assertEq("errors" in AggregateError.prototype, false);
|
||||||
|
|
||||||
|
const {
|
||||||
|
configurable,
|
||||||
|
enumerable,
|
||||||
|
value,
|
||||||
|
writable
|
||||||
|
} = Object.getOwnPropertyDescriptor(new AggregateError([]), "errors");
|
||||||
|
assertEq(configurable, true);
|
||||||
|
assertEq(enumerable, false);
|
||||||
|
assertEq(writable, true);
|
||||||
|
assertEq(value.length, 0);
|
||||||
|
|
||||||
|
const g = newGlobal();
|
||||||
|
|
||||||
|
let obj = {};
|
||||||
|
let errors = new g.AggregateError([obj]).errors;
|
||||||
|
|
||||||
|
assertEq(errors.length, 1);
|
||||||
|
assertEq(errors[0], obj);
|
||||||
|
|
||||||
|
// The prototype is |g.Array.prototype| in the cross-compartment case.
|
||||||
|
let proto = Object.getPrototypeOf(errors);
|
||||||
|
assertEq(proto === g.Array.prototype, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof reportCompare === "function")
|
||||||
|
reportCompare(0, 0);
|
||||||
|
|
@ -116,6 +116,7 @@
|
||||||
macro(enumerate, enumerate, "enumerate") \
|
macro(enumerate, enumerate, "enumerate") \
|
||||||
macro(era, era, "era") \
|
macro(era, era, "era") \
|
||||||
macro(ErrorToStringWithTrailingNewline, ErrorToStringWithTrailingNewline, "ErrorToStringWithTrailingNewline") \
|
macro(ErrorToStringWithTrailingNewline, ErrorToStringWithTrailingNewline, "ErrorToStringWithTrailingNewline") \
|
||||||
|
macro(errors, errors, "errors") \
|
||||||
macro(escape, escape, "escape") \
|
macro(escape, escape, "escape") \
|
||||||
macro(eval, eval, "eval") \
|
macro(eval, eval, "eval") \
|
||||||
macro(exec, exec, "exec") \
|
macro(exec, exec, "exec") \
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,11 @@
|
||||||
|
|
||||||
#include "vm/ErrorObject-inl.h"
|
#include "vm/ErrorObject-inl.h"
|
||||||
|
|
||||||
|
#include "mozilla/DebugOnly.h"
|
||||||
#include "mozilla/Range.h"
|
#include "mozilla/Range.h"
|
||||||
|
|
||||||
|
#include "jsapi.h"
|
||||||
|
#include "jsarray.h"
|
||||||
#include "jsexn.h"
|
#include "jsexn.h"
|
||||||
|
|
||||||
#include "js/CallArgs.h"
|
#include "js/CallArgs.h"
|
||||||
|
|
@ -18,6 +21,7 @@
|
||||||
|
|
||||||
#include "jsobjinlines.h"
|
#include "jsobjinlines.h"
|
||||||
|
|
||||||
|
#include "vm/ArrayObject-inl.h"
|
||||||
#include "vm/NativeObject-inl.h"
|
#include "vm/NativeObject-inl.h"
|
||||||
#include "vm/SavedStacks-inl.h"
|
#include "vm/SavedStacks-inl.h"
|
||||||
#include "vm/Shape-inl.h"
|
#include "vm/Shape-inl.h"
|
||||||
|
|
@ -37,6 +41,7 @@ ErrorObject::protoClasses[JSEXN_ERROR_LIMIT] = {
|
||||||
IMPLEMENT_ERROR_PROTO_CLASS(Error),
|
IMPLEMENT_ERROR_PROTO_CLASS(Error),
|
||||||
|
|
||||||
IMPLEMENT_ERROR_PROTO_CLASS(InternalError),
|
IMPLEMENT_ERROR_PROTO_CLASS(InternalError),
|
||||||
|
IMPLEMENT_ERROR_PROTO_CLASS(AggregateError),
|
||||||
IMPLEMENT_ERROR_PROTO_CLASS(EvalError),
|
IMPLEMENT_ERROR_PROTO_CLASS(EvalError),
|
||||||
IMPLEMENT_ERROR_PROTO_CLASS(RangeError),
|
IMPLEMENT_ERROR_PROTO_CLASS(RangeError),
|
||||||
IMPLEMENT_ERROR_PROTO_CLASS(ReferenceError),
|
IMPLEMENT_ERROR_PROTO_CLASS(ReferenceError),
|
||||||
|
|
@ -60,33 +65,37 @@ static const JSFunctionSpec error_methods[] = {
|
||||||
JS_FS_END
|
JS_FS_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Error.prototype and NativeError.prototype have own .message and .name
|
||||||
|
// properties.
|
||||||
|
#define COMMON_ERROR_PROPERTIES(name) \
|
||||||
|
JS_STRING_PS("message", "", 0), \
|
||||||
|
JS_STRING_PS("name", #name, 0)
|
||||||
|
|
||||||
static const JSPropertySpec error_properties[] = {
|
static const JSPropertySpec error_properties[] = {
|
||||||
JS_STRING_PS("message", "", 0),
|
COMMON_ERROR_PROPERTIES(Error),
|
||||||
JS_STRING_PS("name", "Error", 0),
|
|
||||||
// Only Error.prototype has .stack!
|
// Only Error.prototype has .stack!
|
||||||
JS_PSGS("stack", ErrorObject::getStack, ErrorObject::setStack, 0),
|
JS_PSGS("stack", ErrorObject::getStack, ErrorObject::setStack, 0),
|
||||||
JS_PS_END
|
JS_PS_END
|
||||||
};
|
};
|
||||||
|
|
||||||
#define IMPLEMENT_ERROR_PROPERTIES(name) \
|
#define IMPLEMENT_NATIVE_ERROR_PROPERTIES(name) \
|
||||||
{ \
|
static const JSPropertySpec name##_properties[] = { \
|
||||||
JS_STRING_PS("message", "", 0), \
|
COMMON_ERROR_PROPERTIES(name), \
|
||||||
JS_STRING_PS("name", #name, 0), \
|
|
||||||
JS_PS_END \
|
JS_PS_END \
|
||||||
}
|
};
|
||||||
|
|
||||||
static const JSPropertySpec other_error_properties[JSEXN_ERROR_LIMIT - 1][3] = {
|
IMPLEMENT_NATIVE_ERROR_PROPERTIES(InternalError)
|
||||||
IMPLEMENT_ERROR_PROPERTIES(InternalError),
|
IMPLEMENT_NATIVE_ERROR_PROPERTIES(AggregateError)
|
||||||
IMPLEMENT_ERROR_PROPERTIES(EvalError),
|
IMPLEMENT_NATIVE_ERROR_PROPERTIES(EvalError)
|
||||||
IMPLEMENT_ERROR_PROPERTIES(RangeError),
|
IMPLEMENT_NATIVE_ERROR_PROPERTIES(RangeError)
|
||||||
IMPLEMENT_ERROR_PROPERTIES(ReferenceError),
|
IMPLEMENT_NATIVE_ERROR_PROPERTIES(ReferenceError)
|
||||||
IMPLEMENT_ERROR_PROPERTIES(SyntaxError),
|
IMPLEMENT_NATIVE_ERROR_PROPERTIES(SyntaxError)
|
||||||
IMPLEMENT_ERROR_PROPERTIES(TypeError),
|
IMPLEMENT_NATIVE_ERROR_PROPERTIES(TypeError)
|
||||||
IMPLEMENT_ERROR_PROPERTIES(URIError),
|
IMPLEMENT_NATIVE_ERROR_PROPERTIES(URIError)
|
||||||
IMPLEMENT_ERROR_PROPERTIES(DebuggeeWouldRun),
|
IMPLEMENT_NATIVE_ERROR_PROPERTIES(DebuggeeWouldRun)
|
||||||
IMPLEMENT_ERROR_PROPERTIES(CompileError),
|
IMPLEMENT_NATIVE_ERROR_PROPERTIES(CompileError)
|
||||||
IMPLEMENT_ERROR_PROPERTIES(RuntimeError)
|
IMPLEMENT_NATIVE_ERROR_PROPERTIES(LinkError)
|
||||||
};
|
IMPLEMENT_NATIVE_ERROR_PROPERTIES(RuntimeError)
|
||||||
|
|
||||||
#define IMPLEMENT_NATIVE_ERROR_SPEC(name) \
|
#define IMPLEMENT_NATIVE_ERROR_SPEC(name) \
|
||||||
{ \
|
{ \
|
||||||
|
|
@ -95,7 +104,7 @@ static const JSPropertySpec other_error_properties[JSEXN_ERROR_LIMIT - 1][3] = {
|
||||||
nullptr, \
|
nullptr, \
|
||||||
nullptr, \
|
nullptr, \
|
||||||
nullptr, \
|
nullptr, \
|
||||||
other_error_properties[JSProto_##name - JSProto_Error - 1], \
|
name##_properties, \
|
||||||
nullptr, \
|
nullptr, \
|
||||||
JSProto_Error \
|
JSProto_Error \
|
||||||
}
|
}
|
||||||
|
|
@ -107,7 +116,7 @@ static const JSPropertySpec other_error_properties[JSEXN_ERROR_LIMIT - 1][3] = {
|
||||||
nullptr, \
|
nullptr, \
|
||||||
nullptr, \
|
nullptr, \
|
||||||
nullptr, \
|
nullptr, \
|
||||||
other_error_properties[JSProto_##name - JSProto_Error - 1], \
|
name##_properties, \
|
||||||
nullptr, \
|
nullptr, \
|
||||||
JSProto_Error | ClassSpec::DontDefineConstructor \
|
JSProto_Error | ClassSpec::DontDefineConstructor \
|
||||||
}
|
}
|
||||||
|
|
@ -124,6 +133,7 @@ ErrorObject::classSpecs[JSEXN_ERROR_LIMIT] = {
|
||||||
},
|
},
|
||||||
|
|
||||||
IMPLEMENT_NATIVE_ERROR_SPEC(InternalError),
|
IMPLEMENT_NATIVE_ERROR_SPEC(InternalError),
|
||||||
|
IMPLEMENT_NATIVE_ERROR_SPEC(AggregateError),
|
||||||
IMPLEMENT_NATIVE_ERROR_SPEC(EvalError),
|
IMPLEMENT_NATIVE_ERROR_SPEC(EvalError),
|
||||||
IMPLEMENT_NATIVE_ERROR_SPEC(RangeError),
|
IMPLEMENT_NATIVE_ERROR_SPEC(RangeError),
|
||||||
IMPLEMENT_NATIVE_ERROR_SPEC(ReferenceError),
|
IMPLEMENT_NATIVE_ERROR_SPEC(ReferenceError),
|
||||||
|
|
@ -168,6 +178,7 @@ const Class
|
||||||
ErrorObject::classes[JSEXN_ERROR_LIMIT] = {
|
ErrorObject::classes[JSEXN_ERROR_LIMIT] = {
|
||||||
IMPLEMENT_ERROR_CLASS(Error),
|
IMPLEMENT_ERROR_CLASS(Error),
|
||||||
IMPLEMENT_ERROR_CLASS(InternalError),
|
IMPLEMENT_ERROR_CLASS(InternalError),
|
||||||
|
IMPLEMENT_ERROR_CLASS(AggregateError),
|
||||||
IMPLEMENT_ERROR_CLASS(EvalError),
|
IMPLEMENT_ERROR_CLASS(EvalError),
|
||||||
IMPLEMENT_ERROR_CLASS(RangeError),
|
IMPLEMENT_ERROR_CLASS(RangeError),
|
||||||
IMPLEMENT_ERROR_CLASS(ReferenceError),
|
IMPLEMENT_ERROR_CLASS(ReferenceError),
|
||||||
|
|
@ -188,22 +199,16 @@ exn_finalize(FreeOp* fop, JSObject* obj)
|
||||||
fop->delete_(report);
|
fop->delete_(report);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
static ErrorObject* CreateErrorObject(JSContext* cx, const CallArgs& args,
|
||||||
Error(JSContext* cx, unsigned argc, Value* vp)
|
unsigned messageArg, JSExnType exnType,
|
||||||
|
HandleObject proto)
|
||||||
{
|
{
|
||||||
CallArgs args = CallArgsFromVp(argc, vp);
|
|
||||||
|
|
||||||
// ES6 19.5.1.1 mandates the .prototype lookup happens before the toString
|
|
||||||
RootedObject proto(cx);
|
|
||||||
if (!GetPrototypeFromCallableConstructor(cx, args, &proto))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
/* Compute the error message, if any. */
|
/* Compute the error message, if any. */
|
||||||
RootedString message(cx, nullptr);
|
RootedString message(cx, nullptr);
|
||||||
if (args.hasDefined(0)) {
|
if (args.hasDefined(messageArg)) {
|
||||||
message = ToString<CanGC>(cx, args[0]);
|
message = ToString<CanGC>(cx, args[messageArg]);
|
||||||
if (!message)
|
if (!message)
|
||||||
return false;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the scripted caller, but only ones we're allowed to know about. */
|
/* Find the scripted caller, but only ones we're allowed to know about. */
|
||||||
|
|
@ -211,8 +216,8 @@ Error(JSContext* cx, unsigned argc, Value* vp)
|
||||||
|
|
||||||
/* Set the 'fileName' property. */
|
/* Set the 'fileName' property. */
|
||||||
RootedString fileName(cx);
|
RootedString fileName(cx);
|
||||||
if (args.length() > 1) {
|
if (args.length() > messageArg + 1) {
|
||||||
fileName = ToString<CanGC>(cx, args[1]);
|
fileName = ToString<CanGC>(cx, args[messageArg + 1]);
|
||||||
} else {
|
} else {
|
||||||
fileName = cx->runtime()->emptyString;
|
fileName = cx->runtime()->emptyString;
|
||||||
if (!iter.done()) {
|
if (!iter.done()) {
|
||||||
|
|
@ -221,13 +226,13 @@ Error(JSContext* cx, unsigned argc, Value* vp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!fileName)
|
if (!fileName)
|
||||||
return false;
|
return nullptr;
|
||||||
|
|
||||||
/* Set the 'lineNumber' property. */
|
/* Set the 'lineNumber' property. */
|
||||||
uint32_t lineNumber, columnNumber = 0;
|
uint32_t lineNumber, columnNumber = 0;
|
||||||
if (args.length() > 2) {
|
if (args.length() > messageArg + 2) {
|
||||||
if (!ToUint32(cx, args[2], &lineNumber))
|
if (!ToUint32(cx, args[messageArg + 2], &lineNumber))
|
||||||
return false;
|
return nullptr;
|
||||||
} else {
|
} else {
|
||||||
lineNumber = iter.done() ? 0 : iter.computeLine(&columnNumber);
|
lineNumber = iter.done() ? 0 : iter.computeLine(&columnNumber);
|
||||||
// XXX: Make the column 1-based as in other browsers, instead of 0-based
|
// XXX: Make the column 1-based as in other browsers, instead of 0-based
|
||||||
|
|
@ -238,7 +243,15 @@ Error(JSContext* cx, unsigned argc, Value* vp)
|
||||||
|
|
||||||
RootedObject stack(cx);
|
RootedObject stack(cx);
|
||||||
if (!CaptureStack(cx, &stack))
|
if (!CaptureStack(cx, &stack))
|
||||||
return false;
|
return nullptr;
|
||||||
|
|
||||||
|
return ErrorObject::create(cx, exnType, stack, fileName, lineNumber,
|
||||||
|
columnNumber, nullptr, message, proto);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool Error(JSContext* cx, unsigned argc, Value* vp)
|
||||||
|
{
|
||||||
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ECMA ed. 3, 15.11.1 requires Error, etc., to construct even when
|
* ECMA ed. 3, 15.11.1 requires Error, etc., to construct even when
|
||||||
|
|
@ -248,8 +261,15 @@ Error(JSContext* cx, unsigned argc, Value* vp)
|
||||||
*/
|
*/
|
||||||
JSExnType exnType = JSExnType(args.callee().as<JSFunction>().getExtendedSlot(0).toInt32());
|
JSExnType exnType = JSExnType(args.callee().as<JSFunction>().getExtendedSlot(0).toInt32());
|
||||||
|
|
||||||
RootedObject obj(cx, ErrorObject::create(cx, exnType, stack, fileName,
|
MOZ_ASSERT(exnType != JSEXN_AGGREGATEERR,
|
||||||
lineNumber, columnNumber, nullptr, message, proto));
|
"AggregateError has its own constructor function");
|
||||||
|
|
||||||
|
// ES6 19.5.1.1 mandates the .prototype lookup happens before the toString
|
||||||
|
RootedObject proto(cx);
|
||||||
|
if (!GetPrototypeFromCallableConstructor(cx, args, &proto))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto* obj = CreateErrorObject(cx, args, 0, exnType, proto);
|
||||||
if (!obj)
|
if (!obj)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
|
@ -257,6 +277,80 @@ Error(JSContext* cx, unsigned argc, Value* vp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ArrayObject* IterableToArray(JSContext* cx, HandleValue iterable)
|
||||||
|
{
|
||||||
|
JS::ForOfIterator iterator(cx);
|
||||||
|
if (!iterator.init(iterable, JS::ForOfIterator::ThrowOnNonIterable)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
RootedArrayObject array(cx, NewDenseEmptyArray(cx));
|
||||||
|
if (!array) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
RootedValue nextValue(cx);
|
||||||
|
while (true) {
|
||||||
|
bool done;
|
||||||
|
if (!iterator.next(&nextValue, &done)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (done) {
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!NewbornArrayPush(cx, array, nextValue)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// AggregateError ( errors, message )
|
||||||
|
static bool AggregateError(JSContext* cx, unsigned argc, Value* vp)
|
||||||
|
{
|
||||||
|
CallArgs args = CallArgsFromVp(argc, vp);
|
||||||
|
|
||||||
|
mozilla::DebugOnly<JSExnType> exnType =
|
||||||
|
JSExnType(args.callee().as<JSFunction>().getExtendedSlot(0).toInt32());
|
||||||
|
|
||||||
|
MOZ_ASSERT(exnType == JSEXN_AGGREGATEERR);
|
||||||
|
|
||||||
|
// Steps 1-2. (9.1.13 OrdinaryCreateFromConstructor, steps 1-2).
|
||||||
|
RootedObject proto(cx);
|
||||||
|
if (!GetPrototypeFromCallableConstructor(cx, args, &proto)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TypeError anyway, but this gives a better error message.
|
||||||
|
if (!args.requireAtLeast(cx, "AggregateError", 1)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 9.1.13 OrdinaryCreateFromConstructor, step 3.
|
||||||
|
// Step 3.
|
||||||
|
Rooted<ErrorObject*> obj(
|
||||||
|
cx, CreateErrorObject(cx, args, 1, JSEXN_AGGREGATEERR, proto));
|
||||||
|
if (!obj) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4.
|
||||||
|
RootedArrayObject errorsList(cx, IterableToArray(cx, args.get(0)));
|
||||||
|
if (!errorsList) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 5.
|
||||||
|
RootedValue errorsVal(cx, JS::ObjectValue(*errorsList));
|
||||||
|
if (!NativeDefineDataProperty(cx, obj, cx->names().errors, errorsVal, 0)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 6.
|
||||||
|
args.rval().setObject(*obj);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* static */ JSObject*
|
/* static */ JSObject*
|
||||||
ErrorObject::createProto(JSContext* cx, JSProtoKey key)
|
ErrorObject::createProto(JSContext* cx, JSProtoKey key)
|
||||||
{
|
{
|
||||||
|
|
@ -289,9 +383,20 @@ ErrorObject::createConstructor(JSContext* cx, JSProtoKey key)
|
||||||
if (!proto)
|
if (!proto)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
ctor = NewFunctionWithProto(cx, Error, 1, JSFunction::NATIVE_CTOR, nullptr,
|
Native native;
|
||||||
ClassName(key, cx), proto, gc::AllocKind::FUNCTION_EXTENDED,
|
unsigned nargs;
|
||||||
SingletonObject);
|
if (type == JSEXN_AGGREGATEERR) {
|
||||||
|
native = AggregateError;
|
||||||
|
nargs = 2;
|
||||||
|
} else {
|
||||||
|
native = Error;
|
||||||
|
nargs = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctor =
|
||||||
|
NewFunctionWithProto(cx, native, nargs, JSFunction::NATIVE_CTOR,
|
||||||
|
nullptr, ClassName(key, cx), proto,
|
||||||
|
gc::AllocKind::FUNCTION_EXTENDED, SingletonObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ctor)
|
if (!ctor)
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
#include "vm/Shape.h"
|
#include "vm/Shape.h"
|
||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
class ArrayObject;
|
||||||
|
|
||||||
class ErrorObject : public NativeObject
|
class ErrorObject : public NativeObject
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,7 @@ const char* const XPCJSContext::mStrings[] = {
|
||||||
"columnNumber", // IDX_COLUMNNUMBER
|
"columnNumber", // IDX_COLUMNNUMBER
|
||||||
"stack", // IDX_STACK
|
"stack", // IDX_STACK
|
||||||
"message", // IDX_MESSAGE
|
"message", // IDX_MESSAGE
|
||||||
|
"errors", // IDX_ERRORS
|
||||||
"lastIndex" // IDX_LASTINDEX
|
"lastIndex" // IDX_LASTINDEX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -495,6 +495,7 @@ public:
|
||||||
IDX_COLUMNNUMBER ,
|
IDX_COLUMNNUMBER ,
|
||||||
IDX_STACK ,
|
IDX_STACK ,
|
||||||
IDX_MESSAGE ,
|
IDX_MESSAGE ,
|
||||||
|
IDX_ERRORS ,
|
||||||
IDX_LASTINDEX ,
|
IDX_LASTINDEX ,
|
||||||
IDX_TOTAL_COUNT // just a count of the above
|
IDX_TOTAL_COUNT // just a count of the above
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -41,11 +41,11 @@ using namespace XrayUtils;
|
||||||
|
|
||||||
#define Between(x, a, b) (a <= x && x <= b)
|
#define Between(x, a, b) (a <= x && x <= b)
|
||||||
|
|
||||||
static_assert(JSProto_URIError - JSProto_Error == 7, "New prototype added in error object range");
|
static_assert(JSProto_URIError - JSProto_Error == 8, "New prototype added in error object range");
|
||||||
#define AssertErrorObjectKeyInBounds(key) \
|
#define AssertErrorObjectKeyInBounds(key) \
|
||||||
static_assert(Between(key, JSProto_Error, JSProto_URIError), "We depend on jsprototypes.h ordering here");
|
static_assert(Between(key, JSProto_Error, JSProto_URIError), "We depend on jsprototypes.h ordering here");
|
||||||
MOZ_FOR_EACH(AssertErrorObjectKeyInBounds, (),
|
MOZ_FOR_EACH(AssertErrorObjectKeyInBounds, (),
|
||||||
(JSProto_Error, JSProto_InternalError, JSProto_EvalError, JSProto_RangeError,
|
(JSProto_Error, JSProto_InternalError, JSProto_AggregateError, JSProto_EvalError, JSProto_RangeError,
|
||||||
JSProto_ReferenceError, JSProto_SyntaxError, JSProto_TypeError, JSProto_URIError));
|
JSProto_ReferenceError, JSProto_SyntaxError, JSProto_TypeError, JSProto_URIError));
|
||||||
|
|
||||||
static_assert(JSProto_Uint8ClampedArray - JSProto_Int8Array == 8, "New prototype added in typed array range");
|
static_assert(JSProto_Uint8ClampedArray - JSProto_Int8Array == 8, "New prototype added in typed array range");
|
||||||
|
|
@ -608,6 +608,11 @@ JSXrayTraits::resolveOwnProperty(JSContext* cx, const Wrapper& jsWrapper,
|
||||||
FillPropertyDescriptor(desc, nullptr, 0, UndefinedValue());
|
FillPropertyDescriptor(desc, nullptr, 0, UndefinedValue());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (key == JSProto_AggregateError &&
|
||||||
|
id == GetJSIDByIndex(cx, XPCJSContext::IDX_ERRORS)) {
|
||||||
|
return getOwnPropertyFromWrapperIfSafe(cx, wrapper, id, desc);
|
||||||
|
}
|
||||||
} else if (key == JSProto_RegExp) {
|
} else if (key == JSProto_RegExp) {
|
||||||
if (id == GetJSIDByIndex(cx, XPCJSContext::IDX_LASTINDEX))
|
if (id == GetJSIDByIndex(cx, XPCJSContext::IDX_LASTINDEX))
|
||||||
return getOwnPropertyFromWrapperIfSafe(cx, wrapper, id, desc);
|
return getOwnPropertyFromWrapperIfSafe(cx, wrapper, id, desc);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue