summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartok <martok@martoks-place.de>2023-01-27 19:45:13 +0100
committerMartok <martok@martoks-place.de>2023-02-01 00:02:44 +0100
commit0148ae5a60655a36d5664a961419defa34295fa9 (patch)
tree9849ad90afa93b50f8ec526e6ec96b81a6aac68b
parentec38c883c6f2ecda97b43cb585970f76e70d239a (diff)
downloaduxp-0148ae5a60655a36d5664a961419defa34295fa9.tar.gz
Issue #2089 - Implement AggregateError
Based-on: m-c 1568903/4,1641355(partial),1652148,1643397
-rw-r--r--js/src/jit-test/tests/auto-regress/bug1652148.js5
-rw-r--r--js/src/jsapi.h1
-rw-r--r--js/src/jsexn.h1
-rw-r--r--js/src/jsprototypes.h1
-rw-r--r--js/src/tests/non262/Error/AggregateError.js82
-rw-r--r--js/src/vm/CommonPropertyNames.h1
-rw-r--r--js/src/vm/ErrorObject.cpp211
-rw-r--r--js/src/vm/ErrorObject.h1
-rw-r--r--js/xpconnect/src/XPCJSContext.cpp1
-rw-r--r--js/xpconnect/src/xpcprivate.h1
-rw-r--r--js/xpconnect/wrappers/XrayWrapper.cpp9
11 files changed, 259 insertions, 55 deletions
diff --git a/js/src/jit-test/tests/auto-regress/bug1652148.js b/js/src/jit-test/tests/auto-regress/bug1652148.js
new file mode 100644
index 0000000000..232957edb6
--- /dev/null
+++ b/js/src/jit-test/tests/auto-regress/bug1652148.js
@@ -0,0 +1,5 @@
+// |jit-test| skip-if: !('oomTest' in this)
+
+oomTest(() => {
+ new AggregateError([]);
+});
diff --git a/js/src/jsapi.h b/js/src/jsapi.h
index b93353f223..42f80952e6 100644
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -642,6 +642,7 @@ typedef enum JSExnType {
JSEXN_ERR,
JSEXN_FIRST = JSEXN_ERR,
JSEXN_INTERNALERR,
+ JSEXN_AGGREGATEERR,
JSEXN_EVALERR,
JSEXN_RANGEERR,
JSEXN_REFERENCEERR,
diff --git a/js/src/jsexn.h b/js/src/jsexn.h
index a1ed55b4a1..e3601e0276 100644
--- a/js/src/jsexn.h
+++ b/js/src/jsexn.h
@@ -62,6 +62,7 @@ CopyErrorObject(JSContext* cx, JS::Handle<ErrorObject*> errobj);
static_assert(JSEXN_ERR == 0 &&
JSProto_Error + JSEXN_INTERNALERR == JSProto_InternalError &&
+ JSProto_Error + JSEXN_AGGREGATEERR == JSProto_AggregateError &&
JSProto_Error + JSEXN_EVALERR == JSProto_EvalError &&
JSProto_Error + JSEXN_RANGEERR == JSProto_RangeError &&
JSProto_Error + JSEXN_REFERENCEERR == JSProto_ReferenceError &&
diff --git a/js/src/jsprototypes.h b/js/src/jsprototypes.h
index 880fc1054e..7de6b0245a 100644
--- a/js/src/jsprototypes.h
+++ b/js/src/jsprototypes.h
@@ -69,6 +69,7 @@
real(RegExp, InitViaClassSpec, OCLASP(RegExp)) \
real(Error, InitViaClassSpec, ERROR_CLASP(JSEXN_ERR)) \
real(InternalError, InitViaClassSpec, ERROR_CLASP(JSEXN_INTERNALERR)) \
+ real(AggregateError, InitViaClassSpec, ERROR_CLASP(JSEXN_AGGREGATEERR)) \
real(EvalError, InitViaClassSpec, ERROR_CLASP(JSEXN_EVALERR)) \
real(RangeError, InitViaClassSpec, ERROR_CLASP(JSEXN_RANGEERR)) \
real(ReferenceError, InitViaClassSpec, ERROR_CLASP(JSEXN_REFERENCEERR)) \
diff --git a/js/src/tests/non262/Error/AggregateError.js b/js/src/tests/non262/Error/AggregateError.js
new file mode 100644
index 0000000000..81cf04e9d1
--- /dev/null
+++ b/js/src/tests/non262/Error/AggregateError.js
@@ -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);
diff --git a/js/src/vm/CommonPropertyNames.h b/js/src/vm/CommonPropertyNames.h
index 57ec80669c..171920447e 100644
--- a/js/src/vm/CommonPropertyNames.h
+++ b/js/src/vm/CommonPropertyNames.h
@@ -116,6 +116,7 @@
macro(enumerate, enumerate, "enumerate") \
macro(era, era, "era") \
macro(ErrorToStringWithTrailingNewline, ErrorToStringWithTrailingNewline, "ErrorToStringWithTrailingNewline") \
+ macro(errors, errors, "errors") \
macro(escape, escape, "escape") \
macro(eval, eval, "eval") \
macro(exec, exec, "exec") \
diff --git a/js/src/vm/ErrorObject.cpp b/js/src/vm/ErrorObject.cpp
index 192b0758db..2fa36089ed 100644
--- a/js/src/vm/ErrorObject.cpp
+++ b/js/src/vm/ErrorObject.cpp
@@ -6,8 +6,11 @@
#include "vm/ErrorObject-inl.h"
+#include "mozilla/DebugOnly.h"
#include "mozilla/Range.h"
+#include "jsapi.h"
+#include "jsarray.h"
#include "jsexn.h"
#include "js/CallArgs.h"
@@ -18,6 +21,7 @@
#include "jsobjinlines.h"
+#include "vm/ArrayObject-inl.h"
#include "vm/NativeObject-inl.h"
#include "vm/SavedStacks-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(InternalError),
+ IMPLEMENT_ERROR_PROTO_CLASS(AggregateError),
IMPLEMENT_ERROR_PROTO_CLASS(EvalError),
IMPLEMENT_ERROR_PROTO_CLASS(RangeError),
IMPLEMENT_ERROR_PROTO_CLASS(ReferenceError),
@@ -60,33 +65,37 @@ static const JSFunctionSpec error_methods[] = {
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[] = {
- JS_STRING_PS("message", "", 0),
- JS_STRING_PS("name", "Error", 0),
+ COMMON_ERROR_PROPERTIES(Error),
// Only Error.prototype has .stack!
JS_PSGS("stack", ErrorObject::getStack, ErrorObject::setStack, 0),
JS_PS_END
};
-#define IMPLEMENT_ERROR_PROPERTIES(name) \
- { \
- JS_STRING_PS("message", "", 0), \
- JS_STRING_PS("name", #name, 0), \
- JS_PS_END \
- }
-
-static const JSPropertySpec other_error_properties[JSEXN_ERROR_LIMIT - 1][3] = {
- IMPLEMENT_ERROR_PROPERTIES(InternalError),
- IMPLEMENT_ERROR_PROPERTIES(EvalError),
- IMPLEMENT_ERROR_PROPERTIES(RangeError),
- IMPLEMENT_ERROR_PROPERTIES(ReferenceError),
- IMPLEMENT_ERROR_PROPERTIES(SyntaxError),
- IMPLEMENT_ERROR_PROPERTIES(TypeError),
- IMPLEMENT_ERROR_PROPERTIES(URIError),
- IMPLEMENT_ERROR_PROPERTIES(DebuggeeWouldRun),
- IMPLEMENT_ERROR_PROPERTIES(CompileError),
- IMPLEMENT_ERROR_PROPERTIES(RuntimeError)
-};
+#define IMPLEMENT_NATIVE_ERROR_PROPERTIES(name) \
+ static const JSPropertySpec name##_properties[] = { \
+ COMMON_ERROR_PROPERTIES(name), \
+ JS_PS_END \
+ };
+
+IMPLEMENT_NATIVE_ERROR_PROPERTIES(InternalError)
+IMPLEMENT_NATIVE_ERROR_PROPERTIES(AggregateError)
+IMPLEMENT_NATIVE_ERROR_PROPERTIES(EvalError)
+IMPLEMENT_NATIVE_ERROR_PROPERTIES(RangeError)
+IMPLEMENT_NATIVE_ERROR_PROPERTIES(ReferenceError)
+IMPLEMENT_NATIVE_ERROR_PROPERTIES(SyntaxError)
+IMPLEMENT_NATIVE_ERROR_PROPERTIES(TypeError)
+IMPLEMENT_NATIVE_ERROR_PROPERTIES(URIError)
+IMPLEMENT_NATIVE_ERROR_PROPERTIES(DebuggeeWouldRun)
+IMPLEMENT_NATIVE_ERROR_PROPERTIES(CompileError)
+IMPLEMENT_NATIVE_ERROR_PROPERTIES(LinkError)
+IMPLEMENT_NATIVE_ERROR_PROPERTIES(RuntimeError)
#define IMPLEMENT_NATIVE_ERROR_SPEC(name) \
{ \
@@ -95,7 +104,7 @@ static const JSPropertySpec other_error_properties[JSEXN_ERROR_LIMIT - 1][3] = {
nullptr, \
nullptr, \
nullptr, \
- other_error_properties[JSProto_##name - JSProto_Error - 1], \
+ name##_properties, \
nullptr, \
JSProto_Error \
}
@@ -107,7 +116,7 @@ static const JSPropertySpec other_error_properties[JSEXN_ERROR_LIMIT - 1][3] = {
nullptr, \
nullptr, \
nullptr, \
- other_error_properties[JSProto_##name - JSProto_Error - 1], \
+ name##_properties, \
nullptr, \
JSProto_Error | ClassSpec::DontDefineConstructor \
}
@@ -124,6 +133,7 @@ ErrorObject::classSpecs[JSEXN_ERROR_LIMIT] = {
},
IMPLEMENT_NATIVE_ERROR_SPEC(InternalError),
+ IMPLEMENT_NATIVE_ERROR_SPEC(AggregateError),
IMPLEMENT_NATIVE_ERROR_SPEC(EvalError),
IMPLEMENT_NATIVE_ERROR_SPEC(RangeError),
IMPLEMENT_NATIVE_ERROR_SPEC(ReferenceError),
@@ -136,13 +146,13 @@ ErrorObject::classSpecs[JSEXN_ERROR_LIMIT] = {
IMPLEMENT_NONGLOBAL_ERROR_SPEC(RuntimeError)
};
-#define IMPLEMENT_ERROR_CLASS(name) \
- { \
- js_Error_str, /* yes, really */ \
- JSCLASS_HAS_CACHED_PROTO(JSProto_##name) | \
+#define IMPLEMENT_ERROR_CLASS(name) \
+ { \
+ js_Error_str, /* yes, really */ \
+ JSCLASS_HAS_CACHED_PROTO(JSProto_##name) | \
JSCLASS_HAS_RESERVED_SLOTS(ErrorObject::RESERVED_SLOTS) | \
- JSCLASS_BACKGROUND_FINALIZE, \
- &ErrorObjectClassOps, \
+ JSCLASS_BACKGROUND_FINALIZE, \
+ &ErrorObjectClassOps, \
&ErrorObject::classSpecs[JSProto_##name - JSProto_Error ] \
}
@@ -168,6 +178,7 @@ const Class
ErrorObject::classes[JSEXN_ERROR_LIMIT] = {
IMPLEMENT_ERROR_CLASS(Error),
IMPLEMENT_ERROR_CLASS(InternalError),
+ IMPLEMENT_ERROR_CLASS(AggregateError),
IMPLEMENT_ERROR_CLASS(EvalError),
IMPLEMENT_ERROR_CLASS(RangeError),
IMPLEMENT_ERROR_CLASS(ReferenceError),
@@ -188,22 +199,16 @@ exn_finalize(FreeOp* fop, JSObject* obj)
fop->delete_(report);
}
-bool
-Error(JSContext* cx, unsigned argc, Value* vp)
+static ErrorObject* CreateErrorObject(JSContext* cx, const CallArgs& args,
+ 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. */
RootedString message(cx, nullptr);
- if (args.hasDefined(0)) {
- message = ToString<CanGC>(cx, args[0]);
+ if (args.hasDefined(messageArg)) {
+ message = ToString<CanGC>(cx, args[messageArg]);
if (!message)
- return false;
+ return nullptr;
}
/* 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. */
RootedString fileName(cx);
- if (args.length() > 1) {
- fileName = ToString<CanGC>(cx, args[1]);
+ if (args.length() > messageArg + 1) {
+ fileName = ToString<CanGC>(cx, args[messageArg + 1]);
} else {
fileName = cx->runtime()->emptyString;
if (!iter.done()) {
@@ -221,13 +226,13 @@ Error(JSContext* cx, unsigned argc, Value* vp)
}
}
if (!fileName)
- return false;
+ return nullptr;
/* Set the 'lineNumber' property. */
uint32_t lineNumber, columnNumber = 0;
- if (args.length() > 2) {
- if (!ToUint32(cx, args[2], &lineNumber))
- return false;
+ if (args.length() > messageArg + 2) {
+ if (!ToUint32(cx, args[messageArg + 2], &lineNumber))
+ return nullptr;
} else {
lineNumber = iter.done() ? 0 : iter.computeLine(&columnNumber);
// 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);
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
@@ -248,8 +261,15 @@ Error(JSContext* cx, unsigned argc, Value* vp)
*/
JSExnType exnType = JSExnType(args.callee().as<JSFunction>().getExtendedSlot(0).toInt32());
- RootedObject obj(cx, ErrorObject::create(cx, exnType, stack, fileName,
- lineNumber, columnNumber, nullptr, message, proto));
+ MOZ_ASSERT(exnType != JSEXN_AGGREGATEERR,
+ "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)
return false;
@@ -257,6 +277,80 @@ Error(JSContext* cx, unsigned argc, Value* vp)
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*
ErrorObject::createProto(JSContext* cx, JSProtoKey key)
{
@@ -289,9 +383,20 @@ ErrorObject::createConstructor(JSContext* cx, JSProtoKey key)
if (!proto)
return nullptr;
- ctor = NewFunctionWithProto(cx, Error, 1, JSFunction::NATIVE_CTOR, nullptr,
- ClassName(key, cx), proto, gc::AllocKind::FUNCTION_EXTENDED,
- SingletonObject);
+ Native native;
+ unsigned nargs;
+ 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)
diff --git a/js/src/vm/ErrorObject.h b/js/src/vm/ErrorObject.h
index 6e99dfa2c6..7842bbfa09 100644
--- a/js/src/vm/ErrorObject.h
+++ b/js/src/vm/ErrorObject.h
@@ -13,6 +13,7 @@
#include "vm/Shape.h"
namespace js {
+class ArrayObject;
class ErrorObject : public NativeObject
{
diff --git a/js/xpconnect/src/XPCJSContext.cpp b/js/xpconnect/src/XPCJSContext.cpp
index d918880a49..551bfb681f 100644
--- a/js/xpconnect/src/XPCJSContext.cpp
+++ b/js/xpconnect/src/XPCJSContext.cpp
@@ -108,6 +108,7 @@ const char* const XPCJSContext::mStrings[] = {
"columnNumber", // IDX_COLUMNNUMBER
"stack", // IDX_STACK
"message", // IDX_MESSAGE
+ "errors", // IDX_ERRORS
"lastIndex" // IDX_LASTINDEX
};
diff --git a/js/xpconnect/src/xpcprivate.h b/js/xpconnect/src/xpcprivate.h
index c6b8cf0cc2..724c8db3a9 100644
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -495,6 +495,7 @@ public:
IDX_COLUMNNUMBER ,
IDX_STACK ,
IDX_MESSAGE ,
+ IDX_ERRORS ,
IDX_LASTINDEX ,
IDX_TOTAL_COUNT // just a count of the above
};
diff --git a/js/xpconnect/wrappers/XrayWrapper.cpp b/js/xpconnect/wrappers/XrayWrapper.cpp
index e63a1d6d4d..499e22d245 100644
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -41,11 +41,11 @@ using namespace XrayUtils;
#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) \
static_assert(Between(key, JSProto_Error, JSProto_URIError), "We depend on jsprototypes.h ordering here");
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));
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());
return true;
}
+
+ if (key == JSProto_AggregateError &&
+ id == GetJSIDByIndex(cx, XPCJSContext::IDX_ERRORS)) {
+ return getOwnPropertyFromWrapperIfSafe(cx, wrapper, id, desc);
+ }
} else if (key == JSProto_RegExp) {
if (id == GetJSIDByIndex(cx, XPCJSContext::IDX_LASTINDEX))
return getOwnPropertyFromWrapperIfSafe(cx, wrapper, id, desc);