зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 10 changesets (bug 1568903) for causing mochitest failures
Backed out changeset 76ad398222a6 (bug 1568903) Backed out changeset f4d9fda6d7f2 (bug 1568903) Backed out changeset 379d0f2de211 (bug 1568903) Backed out changeset 3f4aee7f2893 (bug 1568903) Backed out changeset 595accbef95e (bug 1568903) Backed out changeset 567d497a39f4 (bug 1568903) Backed out changeset 127a44494b67 (bug 1568903) Backed out changeset 27c54b414c35 (bug 1568903) Backed out changeset d2b01a1ad0a9 (bug 1568903) Backed out changeset 58c002a9cb78 (bug 1568903)
This commit is contained in:
Родитель
0152c2ed16
Коммит
0165e36c21
|
@ -46,7 +46,6 @@ enum JSExnType {
|
|||
JSEXN_ERR,
|
||||
JSEXN_FIRST = JSEXN_ERR,
|
||||
JSEXN_INTERNALERR,
|
||||
JSEXN_AGGREGATEERR,
|
||||
JSEXN_EVALERR,
|
||||
JSEXN_RANGEERR,
|
||||
JSEXN_REFERENCEERR,
|
||||
|
|
|
@ -62,7 +62,6 @@
|
|||
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)) \
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "vm/AsyncFunction.h"
|
||||
#include "vm/DateObject.h"
|
||||
#include "vm/EqualityOperations.h" // js::SameValue
|
||||
#include "vm/ErrorObject.h"
|
||||
#include "vm/JSContext.h"
|
||||
#include "vm/RegExpObject.h"
|
||||
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -69,7 +69,6 @@
|
|||
#include "util/Text.h"
|
||||
#include "vm/AsyncFunction.h"
|
||||
#include "vm/AsyncIteration.h"
|
||||
#include "vm/ErrorObject.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/Interpreter.h"
|
||||
#include "vm/Iteration.h"
|
||||
|
|
|
@ -177,15 +177,6 @@ function GetTypeError(msg) {
|
|||
assert(false, "the catch block should've returned from this function.");
|
||||
}
|
||||
|
||||
function GetAggregateError(msg) {
|
||||
try {
|
||||
FUN_APPLY(ThrowAggregateError, undefined, arguments);
|
||||
} catch (e) {
|
||||
return e;
|
||||
}
|
||||
assert(false, "the catch block should've returned from this function.");
|
||||
}
|
||||
|
||||
function GetInternalError(msg) {
|
||||
try {
|
||||
FUN_APPLY(ThrowInternalError, undefined, arguments);
|
||||
|
|
|
@ -1,58 +0,0 @@
|
|||
// |jit-test| skip-if: !Promise.any
|
||||
|
||||
function newPromiseCapability() {
|
||||
var resolve, reject, promise = new Promise(function(r1, r2) {
|
||||
resolve = r1;
|
||||
reject = r2;
|
||||
});
|
||||
return {promise, resolve, reject};
|
||||
}
|
||||
|
||||
function neverCalled() {
|
||||
// Quit with non-zero exit code to ensure a test suite error is shown,
|
||||
// even when this function is called within promise handlers which normally
|
||||
// swallow any exceptions.
|
||||
quit(1);
|
||||
}
|
||||
|
||||
var {promise, resolve} = newPromiseCapability();
|
||||
|
||||
var getterCount = 0;
|
||||
|
||||
class P extends Promise {
|
||||
constructor(executor) {
|
||||
var {promise, resolve, reject} = newPromiseCapability();
|
||||
|
||||
executor(function(v) {
|
||||
// Resolve the promise.
|
||||
resolve(v);
|
||||
|
||||
// But then return an object from the resolve function. This object
|
||||
// must be treated as the resolution value for the otherwise
|
||||
// skipped promise which gets created when Promise.prototype.then is
|
||||
// called in PerformPromiseRace.
|
||||
return {
|
||||
get then() {
|
||||
getterCount++;
|
||||
}
|
||||
};
|
||||
}, neverCalled);
|
||||
|
||||
return promise;
|
||||
}
|
||||
|
||||
// Default to the standard Promise.resolve function, so we don't create
|
||||
// another instance of this class when resolving the passed promise objects
|
||||
// in Promise.race.
|
||||
static resolve(v) {
|
||||
return Promise.resolve(v);
|
||||
}
|
||||
}
|
||||
|
||||
P.any([promise]);
|
||||
|
||||
resolve(0);
|
||||
|
||||
drainJobQueue();
|
||||
|
||||
assertEq(getterCount, 1);
|
|
@ -11,8 +11,6 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#include "jsnum.h"
|
||||
|
||||
#include "jit/Ion.h"
|
||||
#include "jit/IonAnalysis.h"
|
||||
#include "jit/JitSpewer.h"
|
||||
|
|
|
@ -644,7 +644,6 @@ MSG_DEF(JSMSG_PROMISE_CAPABILITY_HAS_SOMETHING_ALREADY, 0, JSEXN_TYPEERR, "GetCa
|
|||
MSG_DEF(JSMSG_PROMISE_RESOLVE_FUNCTION_NOT_CALLABLE, 0, JSEXN_TYPEERR, "A Promise subclass passed a non-callable value as the resolve function.")
|
||||
MSG_DEF(JSMSG_PROMISE_REJECT_FUNCTION_NOT_CALLABLE, 0, JSEXN_TYPEERR, "A Promise subclass passed a non-callable value as the reject function.")
|
||||
MSG_DEF(JSMSG_PROMISE_ERROR_IN_WRAPPED_REJECTION_REASON,0, JSEXN_INTERNALERR, "Promise rejection value is a non-unwrappable cross-compartment wrapper.")
|
||||
MSG_DEF(JSMSG_PROMISE_ANY_REJECTION, 0, JSEXN_AGGREGATEERR, "No Promise in Promise.any was resolved")
|
||||
|
||||
// Iterator
|
||||
MSG_DEF(JSMSG_RETURN_NOT_CALLABLE, 0, JSEXN_TYPEERR, "property 'return' of iterator is not callable")
|
||||
|
|
368
js/src/jsexn.cpp
368
js/src/jsexn.cpp
|
@ -10,51 +10,161 @@
|
|||
|
||||
#include "jsexn.h"
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/ScopeExit.h"
|
||||
#include "mozilla/Sprintf.h"
|
||||
|
||||
#include <new>
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <utility>
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "jsnum.h"
|
||||
#include "jstypes.h"
|
||||
|
||||
#include "gc/Rooting.h"
|
||||
#include "gc/FreeOp.h"
|
||||
#include "gc/Marking.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "js/Class.h"
|
||||
#include "js/Conversions.h"
|
||||
#include "js/PropertySpec.h"
|
||||
#include "js/UniquePtr.h"
|
||||
#include "js/Value.h"
|
||||
#include "js/Warnings.h" // JS::{,Set}WarningReporter
|
||||
#include "js/Wrapper.h"
|
||||
#include "util/Memory.h"
|
||||
#include "util/StringBuffer.h"
|
||||
#include "vm/Compartment.h"
|
||||
#include "vm/ErrorObject.h"
|
||||
#include "vm/FrameIter.h" // js::NonBuiltinFrameIter
|
||||
#include "vm/JSAtom.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/JSContext.h"
|
||||
#include "vm/JSFunction.h"
|
||||
#include "vm/JSObject.h"
|
||||
#include "vm/JSScript.h"
|
||||
#include "vm/Realm.h"
|
||||
#include "vm/SavedFrame.h"
|
||||
#include "vm/SavedStacks.h"
|
||||
#include "vm/SelfHosting.h"
|
||||
#include "vm/Stack.h"
|
||||
#include "vm/StringType.h"
|
||||
#include "vm/SymbolType.h"
|
||||
|
||||
#include "vm/ErrorObject-inl.h"
|
||||
#include "vm/JSContext-inl.h"
|
||||
#include "vm/JSObject-inl.h"
|
||||
#include "vm/SavedStacks-inl.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
static void exn_finalize(JSFreeOp* fop, JSObject* obj);
|
||||
|
||||
static bool exn_toSource(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
#define IMPLEMENT_ERROR_PROTO_CLASS(name) \
|
||||
{ \
|
||||
js_Object_str, JSCLASS_HAS_CACHED_PROTO(JSProto_##name), \
|
||||
JS_NULL_CLASS_OPS, \
|
||||
&ErrorObject::classSpecs[JSProto_##name - JSProto_Error] \
|
||||
}
|
||||
|
||||
const JSClass ErrorObject::protoClasses[JSEXN_ERROR_LIMIT] = {
|
||||
IMPLEMENT_ERROR_PROTO_CLASS(Error),
|
||||
|
||||
IMPLEMENT_ERROR_PROTO_CLASS(InternalError),
|
||||
IMPLEMENT_ERROR_PROTO_CLASS(EvalError),
|
||||
IMPLEMENT_ERROR_PROTO_CLASS(RangeError),
|
||||
IMPLEMENT_ERROR_PROTO_CLASS(ReferenceError),
|
||||
IMPLEMENT_ERROR_PROTO_CLASS(SyntaxError),
|
||||
IMPLEMENT_ERROR_PROTO_CLASS(TypeError),
|
||||
IMPLEMENT_ERROR_PROTO_CLASS(URIError),
|
||||
|
||||
IMPLEMENT_ERROR_PROTO_CLASS(DebuggeeWouldRun),
|
||||
IMPLEMENT_ERROR_PROTO_CLASS(CompileError),
|
||||
IMPLEMENT_ERROR_PROTO_CLASS(LinkError),
|
||||
IMPLEMENT_ERROR_PROTO_CLASS(RuntimeError)};
|
||||
|
||||
static const JSFunctionSpec error_methods[] = {
|
||||
JS_FN(js_toSource_str, exn_toSource, 0, 0),
|
||||
JS_SELF_HOSTED_FN(js_toString_str, "ErrorToString", 0, 0), JS_FS_END};
|
||||
|
||||
static const JSPropertySpec error_properties[] = {
|
||||
JS_STRING_PS("message", "", 0), JS_STRING_PS("name", "Error", 0),
|
||||
// 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(LinkError),
|
||||
IMPLEMENT_ERROR_PROPERTIES(RuntimeError)};
|
||||
|
||||
#define IMPLEMENT_NATIVE_ERROR_SPEC(name) \
|
||||
{ \
|
||||
ErrorObject::createConstructor, ErrorObject::createProto, nullptr, \
|
||||
nullptr, nullptr, \
|
||||
other_error_properties[JSProto_##name - JSProto_Error - 1], nullptr, \
|
||||
JSProto_Error \
|
||||
}
|
||||
|
||||
#define IMPLEMENT_NONGLOBAL_ERROR_SPEC(name) \
|
||||
{ \
|
||||
ErrorObject::createConstructor, ErrorObject::createProto, nullptr, \
|
||||
nullptr, nullptr, \
|
||||
other_error_properties[JSProto_##name - JSProto_Error - 1], nullptr, \
|
||||
JSProto_Error | ClassSpec::DontDefineConstructor \
|
||||
}
|
||||
|
||||
const ClassSpec ErrorObject::classSpecs[JSEXN_ERROR_LIMIT] = {
|
||||
{ErrorObject::createConstructor, ErrorObject::createProto, nullptr, nullptr,
|
||||
error_methods, error_properties},
|
||||
|
||||
IMPLEMENT_NATIVE_ERROR_SPEC(InternalError),
|
||||
IMPLEMENT_NATIVE_ERROR_SPEC(EvalError),
|
||||
IMPLEMENT_NATIVE_ERROR_SPEC(RangeError),
|
||||
IMPLEMENT_NATIVE_ERROR_SPEC(ReferenceError),
|
||||
IMPLEMENT_NATIVE_ERROR_SPEC(SyntaxError),
|
||||
IMPLEMENT_NATIVE_ERROR_SPEC(TypeError),
|
||||
IMPLEMENT_NATIVE_ERROR_SPEC(URIError),
|
||||
|
||||
IMPLEMENT_NONGLOBAL_ERROR_SPEC(DebuggeeWouldRun),
|
||||
IMPLEMENT_NONGLOBAL_ERROR_SPEC(CompileError),
|
||||
IMPLEMENT_NONGLOBAL_ERROR_SPEC(LinkError),
|
||||
IMPLEMENT_NONGLOBAL_ERROR_SPEC(RuntimeError)};
|
||||
|
||||
#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, \
|
||||
&ErrorObject::classSpecs[JSProto_##name - JSProto_Error] \
|
||||
}
|
||||
|
||||
static const JSClassOps ErrorObjectClassOps = {
|
||||
nullptr, /* addProperty */
|
||||
nullptr, /* delProperty */
|
||||
nullptr, /* enumerate */
|
||||
nullptr, /* newEnumerate */
|
||||
nullptr, /* resolve */
|
||||
nullptr, /* mayResolve */
|
||||
exn_finalize, nullptr, /* call */
|
||||
nullptr, /* hasInstance */
|
||||
nullptr, /* construct */
|
||||
nullptr, /* trace */
|
||||
};
|
||||
|
||||
const JSClass ErrorObject::classes[JSEXN_ERROR_LIMIT] = {
|
||||
IMPLEMENT_ERROR_CLASS(Error), IMPLEMENT_ERROR_CLASS(InternalError),
|
||||
IMPLEMENT_ERROR_CLASS(EvalError), IMPLEMENT_ERROR_CLASS(RangeError),
|
||||
IMPLEMENT_ERROR_CLASS(ReferenceError), IMPLEMENT_ERROR_CLASS(SyntaxError),
|
||||
IMPLEMENT_ERROR_CLASS(TypeError), IMPLEMENT_ERROR_CLASS(URIError),
|
||||
// These Error subclasses are not accessible via the global object:
|
||||
IMPLEMENT_ERROR_CLASS(DebuggeeWouldRun),
|
||||
IMPLEMENT_ERROR_CLASS(CompileError), IMPLEMENT_ERROR_CLASS(LinkError),
|
||||
IMPLEMENT_ERROR_CLASS(RuntimeError)};
|
||||
|
||||
size_t ExtraMallocSize(JSErrorReport* report) {
|
||||
if (report->linebuf()) {
|
||||
/*
|
||||
|
@ -207,7 +317,7 @@ struct SuppressErrorsGuard {
|
|||
// errors).
|
||||
static const size_t MAX_REPORTED_STACK_DEPTH = 1u << 7;
|
||||
|
||||
bool js::CaptureStack(JSContext* cx, MutableHandleObject stack) {
|
||||
static bool CaptureStack(JSContext* cx, MutableHandleObject stack) {
|
||||
return CaptureCurrentStack(
|
||||
cx, stack, JS::StackCapture(JS::MaxFrames(MAX_REPORTED_STACK_DEPTH)));
|
||||
}
|
||||
|
@ -228,6 +338,14 @@ JSString* js::ComputeStackString(JSContext* cx) {
|
|||
return str.get();
|
||||
}
|
||||
|
||||
static void exn_finalize(JSFreeOp* fop, JSObject* obj) {
|
||||
MOZ_ASSERT(fop->maybeOnHelperThread());
|
||||
if (JSErrorReport* report = obj->as<ErrorObject>().getErrorReport()) {
|
||||
// Bug 1560019: This allocation is not currently tracked.
|
||||
fop->deleteUntracked(report);
|
||||
}
|
||||
}
|
||||
|
||||
JSErrorReport* js::ErrorFromException(JSContext* cx, HandleObject objArg) {
|
||||
// It's ok to UncheckedUnwrap here, since all we do is get the
|
||||
// JSErrorReport, and consumers are careful with the information they get
|
||||
|
@ -271,6 +389,212 @@ JS_PUBLIC_API uint64_t JS::ExceptionTimeWarpTarget(JS::HandleValue value) {
|
|||
return obj->timeWarpTarget();
|
||||
}
|
||||
|
||||
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
|
||||
// called as functions, without operator new. But as we do not give
|
||||
// each constructor a distinct JSClass, we must get the exception type
|
||||
// ourselves.
|
||||
JSExnType exnType =
|
||||
JSExnType(args.callee().as<JSFunction>().getExtendedSlot(0).toInt32());
|
||||
|
||||
JSProtoKey protoKey =
|
||||
JSCLASS_CACHED_PROTO_KEY(&ErrorObject::classes[exnType]);
|
||||
|
||||
// ES6 19.5.1.1 mandates the .prototype lookup happens before the toString
|
||||
RootedObject proto(cx);
|
||||
if (!GetPrototypeFromBuiltinConstructor(cx, args, protoKey, &proto)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compute the error message, if any.
|
||||
RootedString message(cx, nullptr);
|
||||
if (args.hasDefined(0)) {
|
||||
message = ToString<CanGC>(cx, args[0]);
|
||||
if (!message) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the scripted caller, but only ones we're allowed to know about.
|
||||
NonBuiltinFrameIter iter(cx, cx->realm()->principals());
|
||||
|
||||
RootedString fileName(cx);
|
||||
uint32_t sourceId = 0;
|
||||
if (args.length() > 1) {
|
||||
fileName = ToString<CanGC>(cx, args[1]);
|
||||
} else {
|
||||
fileName = cx->runtime()->emptyString;
|
||||
if (!iter.done()) {
|
||||
if (const char* cfilename = iter.filename()) {
|
||||
fileName = JS_NewStringCopyZ(cx, cfilename);
|
||||
}
|
||||
if (iter.hasScript()) {
|
||||
sourceId = iter.script()->scriptSource()->id();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!fileName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t lineNumber, columnNumber = 0;
|
||||
if (args.length() > 2) {
|
||||
if (!ToUint32(cx, args[2], &lineNumber)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
lineNumber = iter.done() ? 0 : iter.computeLine(&columnNumber);
|
||||
columnNumber = FixupColumnForDisplay(columnNumber);
|
||||
}
|
||||
|
||||
RootedObject stack(cx);
|
||||
if (!CaptureStack(cx, &stack)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedObject obj(cx, ErrorObject::create(cx, exnType, stack, fileName,
|
||||
sourceId, lineNumber, columnNumber,
|
||||
nullptr, message, proto));
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
args.rval().setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a string that may eval to something similar to the original object.
|
||||
*/
|
||||
static bool exn_toSource(JSContext* cx, unsigned argc, Value* vp) {
|
||||
if (!CheckRecursionLimit(cx)) {
|
||||
return false;
|
||||
}
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
RootedObject obj(cx, ToObject(cx, args.thisv()));
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedValue nameVal(cx);
|
||||
RootedString name(cx);
|
||||
if (!GetProperty(cx, obj, obj, cx->names().name, &nameVal) ||
|
||||
!(name = ToString<CanGC>(cx, nameVal))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedValue messageVal(cx);
|
||||
RootedString message(cx);
|
||||
if (!GetProperty(cx, obj, obj, cx->names().message, &messageVal) ||
|
||||
!(message = ValueToSource(cx, messageVal))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedValue filenameVal(cx);
|
||||
RootedString filename(cx);
|
||||
if (!GetProperty(cx, obj, obj, cx->names().fileName, &filenameVal) ||
|
||||
!(filename = ValueToSource(cx, filenameVal))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedValue linenoVal(cx);
|
||||
uint32_t lineno;
|
||||
if (!GetProperty(cx, obj, obj, cx->names().lineNumber, &linenoVal) ||
|
||||
!ToUint32(cx, linenoVal, &lineno)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSStringBuilder sb(cx);
|
||||
if (!sb.append("(new ") || !sb.append(name) || !sb.append("(")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sb.append(message)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!filename->empty()) {
|
||||
if (!sb.append(", ") || !sb.append(filename)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (lineno != 0) {
|
||||
/* We have a line, but no filename, add empty string */
|
||||
if (filename->empty() && !sb.append(", \"\"")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSString* linenumber = ToString<CanGC>(cx, linenoVal);
|
||||
if (!linenumber) {
|
||||
return false;
|
||||
}
|
||||
if (!sb.append(", ") || !sb.append(linenumber)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sb.append("))")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSString* str = sb.finishString();
|
||||
if (!str) {
|
||||
return false;
|
||||
}
|
||||
args.rval().setString(str);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
JSObject* ErrorObject::createProto(JSContext* cx, JSProtoKey key) {
|
||||
JSExnType type = ExnTypeFromProtoKey(key);
|
||||
|
||||
if (type == JSEXN_ERR) {
|
||||
return GlobalObject::createBlankPrototype(
|
||||
cx, cx->global(), &ErrorObject::protoClasses[JSEXN_ERR]);
|
||||
}
|
||||
|
||||
RootedObject protoProto(
|
||||
cx, GlobalObject::getOrCreateErrorPrototype(cx, cx->global()));
|
||||
if (!protoProto) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return GlobalObject::createBlankPrototypeInheriting(
|
||||
cx, &ErrorObject::protoClasses[type], protoProto);
|
||||
}
|
||||
|
||||
/* static */
|
||||
JSObject* ErrorObject::createConstructor(JSContext* cx, JSProtoKey key) {
|
||||
JSExnType type = ExnTypeFromProtoKey(key);
|
||||
RootedObject ctor(cx);
|
||||
|
||||
if (type == JSEXN_ERR) {
|
||||
ctor = GenericCreateConstructor<Error, 1, gc::AllocKind::FUNCTION_EXTENDED>(
|
||||
cx, key);
|
||||
} else {
|
||||
RootedFunction proto(
|
||||
cx, GlobalObject::getOrCreateErrorConstructor(cx, cx->global()));
|
||||
if (!proto) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ctor = NewFunctionWithProto(
|
||||
cx, Error, 1, FunctionFlags::NATIVE_CTOR, nullptr, ClassName(key, cx),
|
||||
proto, gc::AllocKind::FUNCTION_EXTENDED, SingletonObject);
|
||||
}
|
||||
|
||||
if (!ctor) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ctor->as<JSFunction>().setExtendedSlot(0, Int32Value(type));
|
||||
return ctor;
|
||||
}
|
||||
|
||||
JS_FRIEND_API JSLinearString* js::GetErrorTypeName(JSContext* cx,
|
||||
int16_t exnType) {
|
||||
/*
|
||||
|
@ -791,11 +1115,3 @@ bool js::GetTypeError(JSContext* cx, unsigned errorNumber,
|
|||
return CallSelfHostedFunction(cx, cx->names().GetTypeError, NullHandleValue,
|
||||
args, error);
|
||||
}
|
||||
|
||||
bool js::GetAggregateError(JSContext* cx, unsigned errorNumber,
|
||||
MutableHandleValue error) {
|
||||
FixedInvokeArgs<1> args(cx);
|
||||
args[0].set(Int32Value(errorNumber));
|
||||
return CallSelfHostedFunction(cx, cx->names().GetAggregateError,
|
||||
NullHandleValue, args, error);
|
||||
}
|
||||
|
|
|
@ -11,18 +11,11 @@
|
|||
#ifndef jsexn_h
|
||||
#define jsexn_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jspubtd.h"
|
||||
#include "jstypes.h"
|
||||
#include "NamespaceImports.h"
|
||||
|
||||
#include "js/ErrorReport.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "js/UniquePtr.h"
|
||||
#include "js/Utility.h"
|
||||
#include "vm/JSContext.h"
|
||||
|
||||
namespace js {
|
||||
class ErrorObject;
|
||||
|
@ -32,8 +25,6 @@ UniquePtr<JSErrorNotes::Note> CopyErrorNote(JSContext* cx,
|
|||
|
||||
UniquePtr<JSErrorReport> CopyErrorReport(JSContext* cx, JSErrorReport* report);
|
||||
|
||||
bool CaptureStack(JSContext* cx, MutableHandleObject stack);
|
||||
|
||||
JSString* ComputeStackString(JSContext* cx);
|
||||
|
||||
/*
|
||||
|
@ -68,7 +59,6 @@ extern JSObject* CopyErrorObject(JSContext* cx,
|
|||
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 &&
|
||||
|
@ -119,8 +109,6 @@ bool GetInternalError(JSContext* cx, unsigned errorNumber,
|
|||
MutableHandleValue error);
|
||||
bool GetTypeError(JSContext* cx, unsigned errorNumber,
|
||||
MutableHandleValue error);
|
||||
bool GetAggregateError(JSContext* cx, unsigned errorNumber,
|
||||
MutableHandleValue error);
|
||||
|
||||
} // namespace js
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include "util/Poison.h"
|
||||
#include "vm/ArgumentsObject.h"
|
||||
#include "vm/DateObject.h"
|
||||
#include "vm/ErrorObject.h"
|
||||
#include "vm/FrameIter.h" // js::FrameIter
|
||||
#include "vm/JSContext.h"
|
||||
#include "vm/JSObject.h"
|
||||
|
|
|
@ -1,82 +0,0 @@
|
|||
// |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, "");
|
||||
|
||||
// AggregateError.prototype isn't an AggregateError instance.
|
||||
assertThrowsInstanceOf(() => AggregateError.prototype.errors, TypeError);
|
||||
|
||||
// The |errors| argument is mandatory.
|
||||
assertThrowsInstanceOf(() => new AggregateError(), TypeError);
|
||||
assertThrowsInstanceOf(() => AggregateError(), TypeError);
|
||||
|
||||
// The .errors getter returns an array object.
|
||||
{
|
||||
let err = new AggregateError([]);
|
||||
|
||||
let {errors} = err;
|
||||
assertEq(Array.isArray(errors), true);
|
||||
assertEq(errors.length, 0);
|
||||
|
||||
// A fresh object is returned each time calling the getter.
|
||||
assertEq(errors === err.errors, false);
|
||||
|
||||
// The errors object is modifiable.
|
||||
errors.push(123);
|
||||
assertEq(errors.length, 1);
|
||||
assertEq(errors[0], 123);
|
||||
}
|
||||
|
||||
// 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");
|
||||
}
|
||||
|
||||
{
|
||||
const {
|
||||
get: getErrors,
|
||||
set: setErrors,
|
||||
} = Object.getOwnPropertyDescriptor(AggregateError.prototype, "errors");
|
||||
assertEq(typeof getErrors, "function");
|
||||
assertEq(typeof setErrors, "undefined");
|
||||
|
||||
// The |this| argument must be an AggregateError instance.
|
||||
assertThrowsInstanceOf(() => getErrors.call(null), TypeError);
|
||||
assertThrowsInstanceOf(() => getErrors.call({}), TypeError);
|
||||
assertThrowsInstanceOf(() => getErrors.call(new Error), TypeError);
|
||||
|
||||
const g = newGlobal();
|
||||
|
||||
let obj = {};
|
||||
let errors = getErrors.call(new g.AggregateError([obj]));
|
||||
|
||||
assertEq(errors.length, 1);
|
||||
assertEq(errors[0], obj);
|
||||
|
||||
// The prototype is (incorrectly) |g.Array.prototype| in the cross-compartment case.
|
||||
let proto = Object.getPrototypeOf(errors);
|
||||
assertEq(proto === Array.prototype || proto === g.Array.prototype, true);
|
||||
}
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(0, 0);
|
|
@ -1,69 +0,0 @@
|
|||
// |reftest| skip-if(!Promise.any)
|
||||
|
||||
function toMessage(stack) {
|
||||
// Provide the stack string in the error message for debugging.
|
||||
return `[stack: ${stack.replace(/\n/g, "\\n")}]`;
|
||||
}
|
||||
|
||||
// Test when AggregateError isn't created from a Promise Job.
|
||||
{
|
||||
let p = Promise.any([]); // line 10
|
||||
|
||||
p.then(v => {
|
||||
reportCompare(0, 1, "expected error");
|
||||
}, e => {
|
||||
assertEq(e.name, "AggregateError");
|
||||
var {stack} = e;
|
||||
|
||||
assertEq(/^@.+any-stack.js:10/m.test(stack), true, toMessage(stack));
|
||||
});
|
||||
}
|
||||
|
||||
// Same as above, but now with surrounding function context.
|
||||
function testNoJobQueue() {
|
||||
let p = Promise.any([]); // line 24
|
||||
|
||||
p.then(v => {
|
||||
reportCompare(0, 1, "expected error");
|
||||
}, e => {
|
||||
assertEq(e.name, "AggregateError");
|
||||
var {stack} = e;
|
||||
|
||||
assertEq(/^testNoJobQueue@.+any-stack.js:24/m.test(stack), true, toMessage(stack));
|
||||
});
|
||||
}
|
||||
testNoJobQueue();
|
||||
|
||||
// Test when AggregateError is created from a Promise Job.
|
||||
{
|
||||
let rejected = Promise.reject(0);
|
||||
let p = Promise.any([rejected]); // line 40
|
||||
|
||||
p.then(v => {
|
||||
reportCompare(0, 1, "expected error");
|
||||
}, e => {
|
||||
assertEq(e.name, "AggregateError");
|
||||
var {stack} = e;
|
||||
|
||||
assertEq(/^Promise.any\*@.+any-stack.js:40/m.test(stack), true, toMessage(stack));
|
||||
});
|
||||
}
|
||||
|
||||
// Same as above, but now with surrounding function context.
|
||||
function testFromJobQueue() {
|
||||
let rejected = Promise.reject(0);
|
||||
let p = Promise.any([rejected]); // line 55
|
||||
|
||||
p.then(v => {
|
||||
reportCompare(0, 1, "expected error");
|
||||
}, e => {
|
||||
assertEq(e.name, "AggregateError");
|
||||
var {stack} = e;
|
||||
|
||||
assertEq(/^Promise.any\*testFromJobQueue@.+any-stack.js:55/m.test(stack), true, toMessage(stack));
|
||||
});
|
||||
}
|
||||
testFromJobQueue();
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(0, 0);
|
|
@ -1,78 +0,0 @@
|
|||
// |reftest| skip-if(!Promise.any)
|
||||
|
||||
// Smoke test for `Promise.any`, test262 should cover the function in
|
||||
// more detail.
|
||||
|
||||
function expectedError() {
|
||||
reportCompare(true, false, "expected error");
|
||||
}
|
||||
|
||||
// Empty elements.
|
||||
Promise.any([]).then(expectedError, e => {
|
||||
assertEq(e instanceof AggregateError, true);
|
||||
assertEq(e.errors.length, 0);
|
||||
});
|
||||
|
||||
// Single element.
|
||||
Promise.any([Promise.resolve(0)]).then(v => {
|
||||
assertEq(v, 0);
|
||||
});
|
||||
Promise.any([Promise.reject(1)]).then(expectedError, e => {
|
||||
assertEq(e instanceof AggregateError, true);
|
||||
assertEq(e.errors.length, 1);
|
||||
assertEq(e.errors[0], 1);
|
||||
});
|
||||
|
||||
// Multiple elements.
|
||||
Promise.any([Promise.resolve(1), Promise.resolve(2)]).then(v => {
|
||||
assertEq(v, 1);
|
||||
});
|
||||
Promise.any([Promise.resolve(3), Promise.reject(4)]).then(v => {
|
||||
assertEq(v, 3);
|
||||
});
|
||||
Promise.any([Promise.reject(5), Promise.resolve(6)]).then(v => {
|
||||
assertEq(v, 6);
|
||||
});
|
||||
Promise.any([Promise.reject(7), Promise.reject(8)]).then(expectedError, e => {
|
||||
assertEq(e instanceof AggregateError, true);
|
||||
assertEq(e.errors.length, 2);
|
||||
assertEq(e.errors[0], 7);
|
||||
assertEq(e.errors[1], 8);
|
||||
});
|
||||
|
||||
// Cross-Realm tests.
|
||||
//
|
||||
// Note: When |g| is a cross-compartment global, Promise.any creates the errors
|
||||
// array and the AggregateError in |g|'s Realm. This doesn't follow the spec, but
|
||||
// the code in js/src/builtin/Promise.cpp claims this is useful when the Promise
|
||||
// compartment is less-privileged. This means for this test we can't use
|
||||
// assertDeepEq below, because the result array/error may have the wrong prototype.
|
||||
let g = newGlobal();
|
||||
|
||||
if (typeof isSameCompartment !== "function") {
|
||||
var isSameCompartment = SpecialPowers.Cu.getJSTestingFunctions().isSameCompartment;
|
||||
}
|
||||
|
||||
// Test wrapping when no `Promise.any Reject Element Function` is called.
|
||||
Promise.any.call(g.Promise, []).then(expectedError, e => {
|
||||
assertEq(e.name, "AggregateError");
|
||||
|
||||
assertEq(isSameCompartment(e, g), true);
|
||||
assertEq(isSameCompartment(e.errors, g), true);
|
||||
|
||||
assertEq(e.errors.length, 0);
|
||||
});
|
||||
|
||||
// Test wrapping in `Promise.any Reject Element Function`.
|
||||
Promise.any.call(g.Promise, [Promise.reject("err")]).then(expectedError, e => {
|
||||
assertEq(e.name, "AggregateError");
|
||||
|
||||
assertEq(isSameCompartment(e, g), true);
|
||||
assertEq(isSameCompartment(e.errors, g), true);
|
||||
|
||||
assertEq(e.errors.length, 1);
|
||||
assertEq(e.errors[0], "err");
|
||||
});
|
||||
|
||||
if (typeof reportCompare === "function")
|
||||
reportCompare(0, 0);
|
|
@ -185,7 +185,6 @@
|
|||
MACRO(GeneratorReturn, GeneratorReturn, "GeneratorReturn") \
|
||||
MACRO(GeneratorThrow, GeneratorThrow, "GeneratorThrow") \
|
||||
MACRO(get, get, "get") \
|
||||
MACRO(GetAggregateError, GetAggregateError, "GetAggregateError") \
|
||||
MACRO(GetInternalError, GetInternalError, "GetInternalError") \
|
||||
MACRO(getBigInt64, getBigInt64, "getBigInt64") \
|
||||
MACRO(getBigUint64, getBigUint64, "getBigUint64") \
|
||||
|
|
|
@ -7,409 +7,25 @@
|
|||
|
||||
#include "vm/ErrorObject-inl.h"
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/RecordReplay.h"
|
||||
#include "mozilla/Range.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsexn.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "jsnum.h"
|
||||
#include "jspubtd.h"
|
||||
#include "NamespaceImports.h"
|
||||
|
||||
#include "builtin/Array.h"
|
||||
#include "gc/AllocKind.h"
|
||||
#include "gc/FreeOp.h"
|
||||
#include "gc/Rooting.h"
|
||||
#include "js/CallArgs.h"
|
||||
#include "js/CallNonGenericMethod.h"
|
||||
#include "js/CharacterEncoding.h"
|
||||
#include "js/Class.h"
|
||||
#include "js/Conversions.h"
|
||||
#include "js/ErrorReport.h"
|
||||
#include "js/ForOfIterator.h"
|
||||
#include "js/PropertySpec.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "js/Utility.h"
|
||||
#include "js/Value.h"
|
||||
#include "js/Wrapper.h"
|
||||
#include "util/StringBuffer.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/JSAtom.h"
|
||||
#include "vm/JSFunction.h"
|
||||
#include "vm/JSObject.h"
|
||||
#include "vm/NativeObject.h"
|
||||
#include "vm/ObjectGroup.h"
|
||||
#include "vm/ObjectOperations.h"
|
||||
#include "vm/SavedStacks.h"
|
||||
#include "vm/SelfHosting.h"
|
||||
#include "vm/Shape.h"
|
||||
#include "vm/Stack.h"
|
||||
#include "vm/StringType.h"
|
||||
|
||||
#include "vm/ArrayObject-inl.h"
|
||||
#include "vm/JSContext-inl.h"
|
||||
#include "vm/JSObject-inl.h"
|
||||
#include "vm/NativeObject-inl.h"
|
||||
#include "vm/ObjectOperations-inl.h"
|
||||
#include "vm/SavedStacks-inl.h"
|
||||
#include "vm/Shape-inl.h"
|
||||
|
||||
using namespace js;
|
||||
|
||||
#define IMPLEMENT_ERROR_PROTO_CLASS(name) \
|
||||
{ \
|
||||
js_Object_str, JSCLASS_HAS_CACHED_PROTO(JSProto_##name), \
|
||||
JS_NULL_CLASS_OPS, \
|
||||
&ErrorObject::classSpecs[JSProto_##name - JSProto_Error] \
|
||||
}
|
||||
|
||||
const JSClass 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),
|
||||
IMPLEMENT_ERROR_PROTO_CLASS(SyntaxError),
|
||||
IMPLEMENT_ERROR_PROTO_CLASS(TypeError),
|
||||
IMPLEMENT_ERROR_PROTO_CLASS(URIError),
|
||||
|
||||
IMPLEMENT_ERROR_PROTO_CLASS(DebuggeeWouldRun),
|
||||
IMPLEMENT_ERROR_PROTO_CLASS(CompileError),
|
||||
IMPLEMENT_ERROR_PROTO_CLASS(LinkError),
|
||||
IMPLEMENT_ERROR_PROTO_CLASS(RuntimeError)};
|
||||
|
||||
static bool exn_toSource(JSContext* cx, unsigned argc, Value* vp);
|
||||
|
||||
static const JSFunctionSpec error_methods[] = {
|
||||
JS_FN(js_toSource_str, exn_toSource, 0, 0),
|
||||
JS_SELF_HOSTED_FN(js_toString_str, "ErrorToString", 0, 0), 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[] = {
|
||||
COMMON_ERROR_PROPERTIES(Error),
|
||||
// Only Error.prototype has .stack!
|
||||
JS_PSGS("stack", ErrorObject::getStack, ErrorObject::setStack, 0),
|
||||
JS_PS_END};
|
||||
|
||||
static const JSPropertySpec AggregateError_properties[] = {
|
||||
COMMON_ERROR_PROPERTIES(AggregateError),
|
||||
// Only AggregateError.prototype has .errors!
|
||||
JS_PSG("errors", AggregateErrorObject::getErrors, 0), JS_PS_END};
|
||||
|
||||
#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(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) \
|
||||
{ \
|
||||
ErrorObject::createConstructor, ErrorObject::createProto, nullptr, \
|
||||
nullptr, nullptr, name##_properties, nullptr, JSProto_Error \
|
||||
}
|
||||
|
||||
#define IMPLEMENT_NONGLOBAL_ERROR_SPEC(name) \
|
||||
{ \
|
||||
ErrorObject::createConstructor, ErrorObject::createProto, nullptr, \
|
||||
nullptr, nullptr, name##_properties, nullptr, \
|
||||
JSProto_Error | ClassSpec::DontDefineConstructor \
|
||||
}
|
||||
|
||||
const ClassSpec ErrorObject::classSpecs[JSEXN_ERROR_LIMIT] = {
|
||||
{ErrorObject::createConstructor, ErrorObject::createProto, nullptr, nullptr,
|
||||
error_methods, error_properties},
|
||||
|
||||
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),
|
||||
IMPLEMENT_NATIVE_ERROR_SPEC(SyntaxError),
|
||||
IMPLEMENT_NATIVE_ERROR_SPEC(TypeError),
|
||||
IMPLEMENT_NATIVE_ERROR_SPEC(URIError),
|
||||
|
||||
IMPLEMENT_NONGLOBAL_ERROR_SPEC(DebuggeeWouldRun),
|
||||
IMPLEMENT_NONGLOBAL_ERROR_SPEC(CompileError),
|
||||
IMPLEMENT_NONGLOBAL_ERROR_SPEC(LinkError),
|
||||
IMPLEMENT_NONGLOBAL_ERROR_SPEC(RuntimeError)};
|
||||
|
||||
#define IMPLEMENT_ERROR_CLASS_FROM(clazz, name) \
|
||||
{ \
|
||||
js_Error_str, /* yes, really */ \
|
||||
JSCLASS_HAS_CACHED_PROTO(JSProto_##name) | \
|
||||
JSCLASS_HAS_RESERVED_SLOTS(clazz::RESERVED_SLOTS) | \
|
||||
JSCLASS_BACKGROUND_FINALIZE, \
|
||||
&ErrorObjectClassOps, \
|
||||
&ErrorObject::classSpecs[JSProto_##name - JSProto_Error] \
|
||||
}
|
||||
|
||||
#define IMPLEMENT_ERROR_CLASS(name) \
|
||||
IMPLEMENT_ERROR_CLASS_FROM(ErrorObject, name)
|
||||
|
||||
static void exn_finalize(JSFreeOp* fop, JSObject* obj);
|
||||
|
||||
static const JSClassOps ErrorObjectClassOps = {
|
||||
nullptr, /* addProperty */
|
||||
nullptr, /* delProperty */
|
||||
nullptr, /* enumerate */
|
||||
nullptr, /* newEnumerate */
|
||||
nullptr, /* resolve */
|
||||
nullptr, /* mayResolve */
|
||||
exn_finalize, nullptr, /* call */
|
||||
nullptr, /* hasInstance */
|
||||
nullptr, /* construct */
|
||||
nullptr, /* trace */
|
||||
};
|
||||
|
||||
const JSClass ErrorObject::classes[JSEXN_ERROR_LIMIT] = {
|
||||
IMPLEMENT_ERROR_CLASS(Error), IMPLEMENT_ERROR_CLASS(InternalError),
|
||||
IMPLEMENT_ERROR_CLASS_FROM(AggregateErrorObject, AggregateError),
|
||||
IMPLEMENT_ERROR_CLASS(EvalError), IMPLEMENT_ERROR_CLASS(RangeError),
|
||||
IMPLEMENT_ERROR_CLASS(ReferenceError), IMPLEMENT_ERROR_CLASS(SyntaxError),
|
||||
IMPLEMENT_ERROR_CLASS(TypeError), IMPLEMENT_ERROR_CLASS(URIError),
|
||||
// These Error subclasses are not accessible via the global object:
|
||||
IMPLEMENT_ERROR_CLASS(DebuggeeWouldRun),
|
||||
IMPLEMENT_ERROR_CLASS(CompileError), IMPLEMENT_ERROR_CLASS(LinkError),
|
||||
IMPLEMENT_ERROR_CLASS(RuntimeError)};
|
||||
|
||||
static void exn_finalize(JSFreeOp* fop, JSObject* obj) {
|
||||
MOZ_ASSERT(fop->maybeOnHelperThread());
|
||||
if (JSErrorReport* report = obj->as<ErrorObject>().getErrorReport()) {
|
||||
// Bug 1560019: This allocation is not currently tracked.
|
||||
fop->deleteUntracked(report);
|
||||
}
|
||||
}
|
||||
|
||||
static ErrorObject* CreateErrorObject(JSContext* cx, const CallArgs& args,
|
||||
unsigned messageArg, JSExnType exnType,
|
||||
HandleObject proto) {
|
||||
// Compute the error message, if any.
|
||||
RootedString message(cx, nullptr);
|
||||
if (args.hasDefined(messageArg)) {
|
||||
message = ToString<CanGC>(cx, args[messageArg]);
|
||||
if (!message) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the scripted caller, but only ones we're allowed to know about.
|
||||
NonBuiltinFrameIter iter(cx, cx->realm()->principals());
|
||||
|
||||
RootedString fileName(cx);
|
||||
uint32_t sourceId = 0;
|
||||
if (args.length() > messageArg + 1) {
|
||||
fileName = ToString<CanGC>(cx, args[messageArg + 1]);
|
||||
} else {
|
||||
fileName = cx->runtime()->emptyString;
|
||||
if (!iter.done()) {
|
||||
if (const char* cfilename = iter.filename()) {
|
||||
fileName = JS_NewStringCopyZ(cx, cfilename);
|
||||
}
|
||||
if (iter.hasScript()) {
|
||||
sourceId = iter.script()->scriptSource()->id();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!fileName) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t lineNumber, columnNumber = 0;
|
||||
if (args.length() > messageArg + 2) {
|
||||
if (!ToUint32(cx, args[messageArg + 2], &lineNumber)) {
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
lineNumber = iter.done() ? 0 : iter.computeLine(&columnNumber);
|
||||
columnNumber = FixupColumnForDisplay(columnNumber);
|
||||
}
|
||||
|
||||
RootedObject stack(cx);
|
||||
if (!CaptureStack(cx, &stack)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return ErrorObject::create(cx, exnType, stack, fileName, sourceId, 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
|
||||
// called as functions, without operator new. But as we do not give
|
||||
// each constructor a distinct JSClass, we must get the exception type
|
||||
// ourselves.
|
||||
JSExnType exnType =
|
||||
JSExnType(args.callee().as<JSFunction>().getExtendedSlot(0).toInt32());
|
||||
|
||||
MOZ_ASSERT(exnType != JSEXN_AGGREGATEERR,
|
||||
"AggregateError has its own constructor function");
|
||||
|
||||
JSProtoKey protoKey =
|
||||
JSCLASS_CACHED_PROTO_KEY(&ErrorObject::classes[exnType]);
|
||||
|
||||
// ES6 19.5.1.1 mandates the .prototype lookup happens before the toString
|
||||
RootedObject proto(cx);
|
||||
if (!GetPrototypeFromBuiltinConstructor(cx, args, protoKey, &proto)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto* obj = CreateErrorObject(cx, args, 0, exnType, proto);
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
args.rval().setObject(*obj);
|
||||
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));
|
||||
|
||||
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 (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_AggregateError,
|
||||
&proto)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 3 (Inlined IterableToList).
|
||||
|
||||
if (!args.requireAtLeast(cx, "AggregateError", 1)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedArrayObject errorsList(cx, IterableToArray(cx, args.get(0)));
|
||||
if (!errorsList) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 9.1.13 OrdinaryCreateFromConstructor, step 3.
|
||||
// Step 5.
|
||||
auto* obj = CreateErrorObject(cx, args, 1, JSEXN_AGGREGATEERR, proto);
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Step 4.
|
||||
obj->as<AggregateErrorObject>().setAggregateErrors(errorsList);
|
||||
|
||||
// Step 6.
|
||||
args.rval().setObject(*obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* static */
|
||||
JSObject* ErrorObject::createProto(JSContext* cx, JSProtoKey key) {
|
||||
JSExnType type = ExnTypeFromProtoKey(key);
|
||||
|
||||
if (type == JSEXN_ERR) {
|
||||
return GlobalObject::createBlankPrototype(
|
||||
cx, cx->global(), &ErrorObject::protoClasses[JSEXN_ERR]);
|
||||
}
|
||||
|
||||
RootedObject protoProto(
|
||||
cx, GlobalObject::getOrCreateErrorPrototype(cx, cx->global()));
|
||||
if (!protoProto) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return GlobalObject::createBlankPrototypeInheriting(
|
||||
cx, &ErrorObject::protoClasses[type], protoProto);
|
||||
}
|
||||
|
||||
/* static */
|
||||
JSObject* ErrorObject::createConstructor(JSContext* cx, JSProtoKey key) {
|
||||
JSExnType type = ExnTypeFromProtoKey(key);
|
||||
RootedObject ctor(cx);
|
||||
|
||||
if (type == JSEXN_ERR) {
|
||||
ctor = GenericCreateConstructor<Error, 1, gc::AllocKind::FUNCTION_EXTENDED>(
|
||||
cx, key);
|
||||
} else {
|
||||
RootedFunction proto(
|
||||
cx, GlobalObject::getOrCreateErrorConstructor(cx, cx->global()));
|
||||
if (!proto) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Native native;
|
||||
unsigned nargs;
|
||||
if (type == JSEXN_AGGREGATEERR) {
|
||||
native = AggregateError;
|
||||
nargs = 2;
|
||||
} else {
|
||||
native = Error;
|
||||
nargs = 1;
|
||||
}
|
||||
|
||||
ctor =
|
||||
NewFunctionWithProto(cx, native, nargs, FunctionFlags::NATIVE_CTOR,
|
||||
nullptr, ClassName(key, cx), proto,
|
||||
gc::AllocKind::FUNCTION_EXTENDED, SingletonObject);
|
||||
}
|
||||
|
||||
if (!ctor) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ctor->as<JSFunction>().setExtendedSlot(0, Int32Value(type));
|
||||
return ctor;
|
||||
}
|
||||
|
||||
/* static */
|
||||
Shape* js::ErrorObject::assignInitialShape(JSContext* cx,
|
||||
Handle<ErrorObject*> obj) {
|
||||
|
@ -698,154 +314,3 @@ bool js::ErrorObject::setStack_impl(JSContext* cx, const CallArgs& args) {
|
|||
|
||||
return DefineDataProperty(cx, thisObj, cx->names().stack, val);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return a string that may eval to something similar to the original object.
|
||||
*/
|
||||
static bool exn_toSource(JSContext* cx, unsigned argc, Value* vp) {
|
||||
if (!CheckRecursionLimit(cx)) {
|
||||
return false;
|
||||
}
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
RootedObject obj(cx, ToObject(cx, args.thisv()));
|
||||
if (!obj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedValue nameVal(cx);
|
||||
RootedString name(cx);
|
||||
if (!GetProperty(cx, obj, obj, cx->names().name, &nameVal) ||
|
||||
!(name = ToString<CanGC>(cx, nameVal))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedValue messageVal(cx);
|
||||
RootedString message(cx);
|
||||
if (!GetProperty(cx, obj, obj, cx->names().message, &messageVal) ||
|
||||
!(message = ValueToSource(cx, messageVal))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedValue filenameVal(cx);
|
||||
RootedString filename(cx);
|
||||
if (!GetProperty(cx, obj, obj, cx->names().fileName, &filenameVal) ||
|
||||
!(filename = ValueToSource(cx, filenameVal))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedValue linenoVal(cx);
|
||||
uint32_t lineno;
|
||||
if (!GetProperty(cx, obj, obj, cx->names().lineNumber, &linenoVal) ||
|
||||
!ToUint32(cx, linenoVal, &lineno)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSStringBuilder sb(cx);
|
||||
if (!sb.append("(new ") || !sb.append(name) || !sb.append("(")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!sb.append(message)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!filename->empty()) {
|
||||
if (!sb.append(", ") || !sb.append(filename)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (lineno != 0) {
|
||||
/* We have a line, but no filename, add empty string */
|
||||
if (filename->empty() && !sb.append(", \"\"")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSString* linenumber = ToString<CanGC>(cx, linenoVal);
|
||||
if (!linenumber) {
|
||||
return false;
|
||||
}
|
||||
if (!sb.append(", ") || !sb.append(linenumber)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!sb.append("))")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
JSString* str = sb.finishString();
|
||||
if (!str) {
|
||||
return false;
|
||||
}
|
||||
args.rval().setString(str);
|
||||
return true;
|
||||
}
|
||||
|
||||
ArrayObject* js::AggregateErrorObject::aggregateErrors() const {
|
||||
const Value& val = getReservedSlot(AGGREGATE_ERRORS_SLOT);
|
||||
if (val.isUndefined()) {
|
||||
return nullptr;
|
||||
}
|
||||
return &val.toObject().as<ArrayObject>();
|
||||
}
|
||||
|
||||
void js::AggregateErrorObject::setAggregateErrors(ArrayObject* errors) {
|
||||
MOZ_ASSERT(!aggregateErrors(),
|
||||
"aggregated errors mustn't be modified once set");
|
||||
setReservedSlot(AGGREGATE_ERRORS_SLOT, ObjectValue(*errors));
|
||||
}
|
||||
|
||||
static inline bool IsAggregateError(HandleValue v) {
|
||||
return v.isObject() && v.toObject().is<AggregateErrorObject>();
|
||||
}
|
||||
|
||||
// get AggregateError.prototype.errors
|
||||
bool js::AggregateErrorObject::getErrors(JSContext* cx, unsigned argc,
|
||||
Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
// Steps 1-4.
|
||||
return CallNonGenericMethod<IsAggregateError, getErrors_impl>(cx, args);
|
||||
}
|
||||
|
||||
// get AggregateError.prototype.errors
|
||||
bool js::AggregateErrorObject::getErrors_impl(JSContext* cx,
|
||||
const CallArgs& args) {
|
||||
MOZ_ASSERT(IsAggregateError(args.thisv()));
|
||||
|
||||
auto* obj = &args.thisv().toObject().as<AggregateErrorObject>();
|
||||
|
||||
// Step 5.
|
||||
// Create a copy of the [[AggregateErrors]] list.
|
||||
|
||||
RootedArrayObject errorsList(cx, obj->aggregateErrors());
|
||||
|
||||
// [[AggregateErrors]] may be absent when this error was created through
|
||||
// JS_ReportError.
|
||||
if (!errorsList) {
|
||||
ArrayObject* result = NewDenseEmptyArray(cx);
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
args.rval().setObject(*result);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t length = errorsList->length();
|
||||
|
||||
ArrayObject* result = NewDenseFullyAllocatedArray(cx, length);
|
||||
if (!result) {
|
||||
return false;
|
||||
}
|
||||
|
||||
result->setLength(cx, length);
|
||||
|
||||
if (length > 0) {
|
||||
result->initDenseElements(errorsList, 0, length);
|
||||
}
|
||||
|
||||
args.rval().setObject(*result);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -8,32 +8,27 @@
|
|||
#define vm_ErrorObject_h_
|
||||
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "jspubtd.h"
|
||||
#include "NamespaceImports.h"
|
||||
|
||||
#include "gc/Barrier.h"
|
||||
#include "js/Class.h"
|
||||
#include "js/ErrorReport.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "js/UniquePtr.h"
|
||||
#include "js/Value.h"
|
||||
#include "vm/JSObject.h"
|
||||
#include "vm/NativeObject.h"
|
||||
#include "vm/SavedStacks.h"
|
||||
#include "vm/Shape.h"
|
||||
|
||||
namespace js {
|
||||
class ArrayObject;
|
||||
|
||||
/*
|
||||
* Initialize the exception constructor/prototype hierarchy.
|
||||
*/
|
||||
extern JSObject* InitExceptionClasses(JSContext* cx, HandleObject obj);
|
||||
|
||||
class ErrorObject : public NativeObject {
|
||||
static JSObject* createProto(JSContext* cx, JSProtoKey key);
|
||||
|
||||
static JSObject* createConstructor(JSContext* cx, JSProtoKey key);
|
||||
|
||||
/* For access to createProto. */
|
||||
friend JSObject* js::InitExceptionClasses(JSContext* cx, HandleObject global);
|
||||
|
||||
static bool init(JSContext* cx, Handle<ErrorObject*> obj, JSExnType type,
|
||||
UniquePtr<JSErrorReport> errorReport, HandleString fileName,
|
||||
HandleObject stack, uint32_t sourceId, uint32_t lineNumber,
|
||||
|
@ -119,22 +114,6 @@ class ErrorObject : public NativeObject {
|
|||
static bool setStack_impl(JSContext* cx, const CallArgs& args);
|
||||
};
|
||||
|
||||
class AggregateErrorObject : public ErrorObject {
|
||||
friend class ErrorObject;
|
||||
|
||||
// [[AggregateErrors]] slot of AggregateErrorObjects.
|
||||
static const uint32_t AGGREGATE_ERRORS_SLOT = ErrorObject::RESERVED_SLOTS;
|
||||
static const uint32_t RESERVED_SLOTS = AGGREGATE_ERRORS_SLOT + 1;
|
||||
|
||||
public:
|
||||
ArrayObject* aggregateErrors() const;
|
||||
void setAggregateErrors(ArrayObject* errors);
|
||||
|
||||
// Getter for the AggregateError.prototype.errors accessor.
|
||||
static bool getErrors(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool getErrors_impl(JSContext* cx, const CallArgs& args);
|
||||
};
|
||||
|
||||
} // namespace js
|
||||
|
||||
template <>
|
||||
|
@ -142,9 +121,4 @@ inline bool JSObject::is<js::ErrorObject>() const {
|
|||
return js::ErrorObject::isErrorClass(getClass());
|
||||
}
|
||||
|
||||
template <>
|
||||
inline bool JSObject::is<js::AggregateErrorObject>() const {
|
||||
return hasClass(js::ErrorObject::classForType(JSEXN_AGGREGATEERR));
|
||||
}
|
||||
|
||||
#endif // vm_ErrorObject_h_
|
||||
|
|
|
@ -49,7 +49,6 @@
|
|||
#include "vm/AsyncIteration.h"
|
||||
#include "vm/DateObject.h"
|
||||
#include "vm/EnvironmentObject.h"
|
||||
#include "vm/ErrorObject.h"
|
||||
#include "vm/GeneratorObject.h"
|
||||
#include "vm/HelperThreads.h"
|
||||
#include "vm/JSContext.h"
|
||||
|
@ -141,11 +140,6 @@ bool GlobalObject::skipDeselectedConstructor(JSContext* cx, JSProtoKey key) {
|
|||
case JSProto_FinalizationGroup:
|
||||
return !cx->realm()->creationOptions().getWeakRefsEnabled();
|
||||
|
||||
#ifndef NIGHTLY_BUILD
|
||||
case JSProto_AggregateError:
|
||||
return true;
|
||||
#endif
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -7,52 +7,23 @@
|
|||
#ifndef vm_GlobalObject_h
|
||||
#define vm_GlobalObject_h
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <type_traits>
|
||||
|
||||
#include "jsapi.h"
|
||||
#include "jsexn.h"
|
||||
#include "jsfriendapi.h"
|
||||
#include "jspubtd.h"
|
||||
#include "jstypes.h"
|
||||
#include "NamespaceImports.h"
|
||||
#include "jsnum.h"
|
||||
|
||||
#include "gc/AllocKind.h"
|
||||
#include "gc/Rooting.h"
|
||||
#include "js/CallArgs.h"
|
||||
#include "js/Class.h"
|
||||
#include "js/ErrorReport.h"
|
||||
#include "js/PropertyDescriptor.h"
|
||||
#include "js/RootingAPI.h"
|
||||
#include "js/TypeDecls.h"
|
||||
#include "js/Value.h"
|
||||
#include "vm/JSContext.h"
|
||||
#include "builtin/Array.h"
|
||||
#include "builtin/Boolean.h"
|
||||
#include "js/Vector.h"
|
||||
#include "vm/ArrayBufferObject.h"
|
||||
#include "vm/ErrorObject.h"
|
||||
#include "vm/JSFunction.h"
|
||||
#include "vm/JSObject.h"
|
||||
#include "vm/NativeObject.h"
|
||||
#include "vm/Realm.h"
|
||||
#include "vm/Runtime.h"
|
||||
#include "vm/Shape.h"
|
||||
#include "vm/StringType.h"
|
||||
|
||||
struct JSFunctionSpec;
|
||||
struct JSPrincipals;
|
||||
struct JSPropertySpec;
|
||||
|
||||
namespace JS {
|
||||
class JS_PUBLIC_API RealmOptions;
|
||||
};
|
||||
|
||||
namespace js {
|
||||
|
||||
class GlobalScope;
|
||||
class TypedObjectModuleObject;
|
||||
class LexicalEnvironmentObject;
|
||||
class RegExpStatics;
|
||||
class TypeDescr;
|
||||
class TypedObjectModuleObject;
|
||||
|
||||
enum class ReferenceType;
|
||||
|
||||
|
@ -956,6 +927,9 @@ extern bool DefinePropertiesAndFunctions(JSContext* cx, HandleObject obj,
|
|||
const JSPropertySpec* ps,
|
||||
const JSFunctionSpec* fs);
|
||||
|
||||
typedef HashSet<GlobalObject*, DefaultHasher<GlobalObject*>, SystemAllocPolicy>
|
||||
GlobalObjectSet;
|
||||
|
||||
extern bool DefineToStringTag(JSContext* cx, HandleObject obj, JSAtom* tag);
|
||||
|
||||
/*
|
||||
|
|
|
@ -50,7 +50,6 @@
|
|||
#include "util/NativeStack.h"
|
||||
#include "util/Windows.h"
|
||||
#include "vm/BytecodeUtil.h"
|
||||
#include "vm/ErrorObject.h"
|
||||
#include "vm/ErrorReporting.h"
|
||||
#include "vm/HelperThreads.h"
|
||||
#include "vm/Iteration.h"
|
||||
|
@ -1403,9 +1402,13 @@ void JSContext::setPendingException(HandleValue v, HandleSavedFrame stack) {
|
|||
check(v);
|
||||
}
|
||||
|
||||
static const size_t MAX_REPORTED_STACK_DEPTH = 1u << 7;
|
||||
|
||||
void JSContext::setPendingExceptionAndCaptureStack(HandleValue value) {
|
||||
RootedObject stack(this);
|
||||
if (!CaptureStack(this, &stack)) {
|
||||
if (!CaptureCurrentStack(
|
||||
this, &stack,
|
||||
JS::StackCapture(JS::MaxFrames(MAX_REPORTED_STACK_DEPTH)))) {
|
||||
clearPendingException();
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#include "js/CharacterEncoding.h"
|
||||
#include "js/UniquePtr.h"
|
||||
#include "vm/ArrayObject.h"
|
||||
#include "vm/ErrorObject.h"
|
||||
#include "vm/GlobalObject.h"
|
||||
#include "vm/JSObject.h"
|
||||
#include "vm/RegExpObject.h"
|
||||
|
|
|
@ -391,15 +391,6 @@ static bool intrinsic_ThrowSyntaxError(JSContext* cx, unsigned argc,
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool intrinsic_ThrowAggregateError(JSContext* cx, unsigned argc,
|
||||
Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
MOZ_ASSERT(args.length() >= 1);
|
||||
|
||||
ThrowErrorWithType(cx, JSEXN_AGGREGATEERR, args);
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool intrinsic_ThrowInternalError(JSContext* cx, unsigned argc,
|
||||
Value* vp) {
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
@ -2178,7 +2169,6 @@ static const JSFunctionSpec intrinsic_functions[] = {
|
|||
JS_FN("ThrowRangeError", intrinsic_ThrowRangeError, 4, 0),
|
||||
JS_FN("ThrowTypeError", intrinsic_ThrowTypeError, 4, 0),
|
||||
JS_FN("ThrowSyntaxError", intrinsic_ThrowSyntaxError, 4, 0),
|
||||
JS_FN("ThrowAggregateError", intrinsic_ThrowAggregateError, 4, 0),
|
||||
JS_FN("ThrowInternalError", intrinsic_ThrowInternalError, 4, 0),
|
||||
JS_FN("GetErrorMessage", intrinsic_GetErrorMessage, 1, 0),
|
||||
JS_FN("CreateModuleSyntaxError", intrinsic_CreateModuleSyntaxError, 4, 0),
|
||||
|
|
|
@ -23,8 +23,6 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#include "jsnum.h"
|
||||
|
||||
#include "jit/ExecutableAllocator.h"
|
||||
#ifdef JS_ION_PERF
|
||||
# include "jit/PerfSpewer.h"
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include "js/PropertySpec.h" // JS_{PS,FN}{,_END}
|
||||
#include "util/StringBuffer.h"
|
||||
#include "util/Text.h"
|
||||
#include "vm/ErrorObject.h"
|
||||
#include "vm/Interpreter.h"
|
||||
#include "vm/StringType.h"
|
||||
#include "wasm/WasmBaselineCompile.h"
|
||||
|
|
|
@ -32,18 +32,11 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681
|
|||
}
|
||||
}
|
||||
|
||||
var {AppConstants} = SpecialPowers.Cu.import("resource://gre/modules/AppConstants.jsm", {});
|
||||
var isNightlyBuild = AppConstants.NIGHTLY_BUILD;
|
||||
var isReleaseOrBeta = AppConstants.RELEASE_OR_BETA;
|
||||
|
||||
typedArrayClasses = ['Uint8Array', 'Int8Array', 'Uint16Array', 'Int16Array',
|
||||
'Uint32Array', 'Int32Array', 'Float32Array', 'Float64Array',
|
||||
'Uint8ClampedArray'];
|
||||
errorObjectClasses = ['Error', 'InternalError', 'EvalError', 'RangeError', 'ReferenceError',
|
||||
'SyntaxError', 'TypeError', 'URIError'];
|
||||
if (isNightlyBuild) {
|
||||
errorObjectClasses.push('AggregateError');
|
||||
}
|
||||
|
||||
// A simpleConstructors entry can either be the name of a constructor as a
|
||||
// string, or an object containing the properties `name`, and `args`.
|
||||
|
@ -51,19 +44,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681
|
|||
// latter case, it is invoked with `args` as the arguments list.
|
||||
simpleConstructors = ['Object', 'Function', 'Array', 'Boolean', 'Date', 'Number',
|
||||
'String', 'RegExp', 'ArrayBuffer', 'WeakMap', 'WeakSet', 'Map', 'Set',
|
||||
{name: 'Promise', args: [function(){}]}];
|
||||
|
||||
// All TypedArray constructors can be called with zero arguments.
|
||||
simpleConstructors = simpleConstructors.concat(typedArrayClasses);
|
||||
|
||||
// All Error constructors except AggregateError can be called with zero arguments.
|
||||
simpleConstructors = simpleConstructors.concat(errorObjectClasses.map(name) => {
|
||||
if (name === 'AggregateError') {
|
||||
// AggregateError throws when called without an iterable object as its first argument.
|
||||
return {name: 'AggregateError', args: [[]]};
|
||||
}
|
||||
return name;
|
||||
});
|
||||
{name: 'Promise', args: [function(){}]}].concat(typedArrayClasses)
|
||||
.concat(errorObjectClasses);
|
||||
|
||||
function go() {
|
||||
window.iwin = document.getElementById('ifr').contentWindow;
|
||||
|
@ -185,6 +167,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681
|
|||
// Xray-safe.
|
||||
//
|
||||
// DO NOT CHANGE WTIHOUT REVIEW FROM AN XPCONNECT PEER.
|
||||
var {AppConstants} = SpecialPowers.Cu.import("resource://gre/modules/AppConstants.jsm", {});
|
||||
var isNightlyBuild = AppConstants.NIGHTLY_BUILD;
|
||||
var isReleaseOrBeta = AppConstants.RELEASE_OR_BETA;
|
||||
var gPrototypeProperties = {};
|
||||
var gConstructorProperties = {};
|
||||
function constructorProps(arr) {
|
||||
|
@ -239,9 +224,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681
|
|||
gPrototypeProperties[c] = ["constructor", "name", "message", "stack"];
|
||||
gConstructorProperties[c] = constructorProps([]);
|
||||
}
|
||||
if (gPrototypeProperties['AggregateError']) {
|
||||
gPrototypeProperties['AggregateError'].push("errors");
|
||||
}
|
||||
// toString and toSource only live on the parent proto (Error.prototype).
|
||||
gPrototypeProperties['Error'].push('toString');
|
||||
gPrototypeProperties['Error'].push('toSource');
|
||||
|
@ -265,9 +247,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681
|
|||
["constructor", "catch", "then", "finally", Symbol.toStringTag];
|
||||
gConstructorProperties['Promise'] =
|
||||
constructorProps(["resolve", "reject", "all", "allSettled", "race", Symbol.species]);
|
||||
if (isNightlyBuild) {
|
||||
gConstructorProperties['Promise'].push("any");
|
||||
}
|
||||
|
||||
gPrototypeProperties['ArrayBuffer'] =
|
||||
["constructor", "byteLength", "slice", Symbol.toStringTag];
|
||||
|
@ -837,12 +816,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681
|
|||
|
||||
// Make sure that the dependent classes have their prototypes set up correctly.
|
||||
for (let c of errorObjectClasses.filter(x => x != "Error")) {
|
||||
var args = ['some message'];
|
||||
if (c === 'AggregateError') {
|
||||
// AggregateError's first argument is the list of aggregated errors.
|
||||
args.unshift(['error 1', 'error 2']);
|
||||
}
|
||||
var e = new iwin[c](...args);
|
||||
var e = new iwin[c]('some message');
|
||||
is(Object.getPrototypeOf(e).name, c, "Prototype has correct name");
|
||||
is(Object.getPrototypeOf(Object.getPrototypeOf(e)), iwin.Error.prototype, "Dependent prototype set up correctly");
|
||||
is(e.name, c, "Exception name inherited correctly");
|
||||
|
@ -859,22 +833,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=933681
|
|||
testProperty('columnNumber', x => x == 1, 99, 99.5);
|
||||
testProperty('lineNumber', x => x == 0, 50, 'foo');
|
||||
|
||||
if (c === 'AggregateError') {
|
||||
let {errors} = e;
|
||||
is(errors.length, 2, "errors property has the correct length");
|
||||
is(errors[0], 'error 1', "errors[0] has the correct value");
|
||||
is(errors[1], 'error 2', "errors[1] has the correct value");
|
||||
|
||||
try {
|
||||
e.wrappedJSObject.errors = [];
|
||||
|
||||
throw new Error("Missing exception");
|
||||
} catch (exc) {
|
||||
is(exc.name, "TypeError", "setting the errors property throws a TypeError");
|
||||
}
|
||||
is(e.errors.length, 2, "errors property can't be set");
|
||||
}
|
||||
|
||||
// Note - an Exception newed via Xrays is going to have an empty stack given the
|
||||
// current semantics and implementation. This tests the current behavior, but that
|
||||
// may change in bug 1036527 or similar.
|
||||
|
|
|
@ -45,15 +45,15 @@ using namespace XrayUtils;
|
|||
|
||||
#define Between(x, a, b) (a <= x && x <= b)
|
||||
|
||||
static_assert(JSProto_URIError - JSProto_Error == 8,
|
||||
static_assert(JSProto_URIError - JSProto_Error == 7,
|
||||
"New prototype added in error object range");
|
||||
#define AssertErrorObjectKeyInBounds(key) \
|
||||
static_assert(Between(key, JSProto_Error, JSProto_URIError), \
|
||||
"We depend on js/ProtoKey.h ordering here");
|
||||
MOZ_FOR_EACH(AssertErrorObjectKeyInBounds, (),
|
||||
(JSProto_Error, JSProto_InternalError, JSProto_AggregateError,
|
||||
JSProto_EvalError, JSProto_RangeError, JSProto_ReferenceError,
|
||||
JSProto_SyntaxError, JSProto_TypeError, JSProto_URIError));
|
||||
(JSProto_Error, JSProto_InternalError, 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");
|
||||
|
|
Загрузка…
Ссылка в новой задаче