mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-06 07:48:38 +09:00
Handle the now ordinary error prototype object in stack
This commit is contained in:
parent
105cbadae7
commit
4fad420bb8
3 changed files with 48 additions and 31 deletions
|
|
@ -85,10 +85,17 @@ ExnTypeFromProtoKey(JSProtoKey key)
|
|||
{
|
||||
JSExnType type = static_cast<JSExnType>(key - JSProto_Error);
|
||||
MOZ_ASSERT(type >= JSEXN_ERR);
|
||||
MOZ_ASSERT(type < JSEXN_WARN);
|
||||
MOZ_ASSERT(type < JSEXN_ERROR_LIMIT);
|
||||
return type;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
IsErrorProtoKey(JSProtoKey key)
|
||||
{
|
||||
JSExnType type = static_cast<JSExnType>(key - JSProto_Error);
|
||||
return type >= JSEXN_ERR && type < JSEXN_ERROR_LIMIT;
|
||||
}
|
||||
|
||||
class AutoClearPendingException
|
||||
{
|
||||
JSContext* cx;
|
||||
|
|
|
|||
|
|
@ -164,29 +164,25 @@ js::ErrorObject::getOrCreateErrorReport(JSContext* cx)
|
|||
}
|
||||
|
||||
static bool
|
||||
ErrorObject_checkAndUnwrapThis(JSContext* cx, CallArgs& args, const char* fnName,
|
||||
MutableHandle<ErrorObject*> error)
|
||||
FindErrorInstanceOrPrototype(JSContext* cx, HandleObject obj, MutableHandleObject result)
|
||||
{
|
||||
const Value& thisValue = args.thisv();
|
||||
// Walk up the prototype chain until we find an error object instance or
|
||||
// prototype object. This allows code like:
|
||||
// Object.create(Error.prototype).stack
|
||||
// or
|
||||
// function NYI() { }
|
||||
// NYI.prototype = new Error;
|
||||
// (new NYI).stack
|
||||
// to continue returning stacks that are useless, but at least don't throw.
|
||||
|
||||
if (!thisValue.isObject()) {
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_NOT_NONNULL_OBJECT,
|
||||
InformalValueTypeName(thisValue));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Walk up the prototype chain until we find the first ErrorObject that has
|
||||
// the slots we need. This allows us to support the poor-man's subclassing
|
||||
// of error: Object.create(Error.prototype).
|
||||
|
||||
RootedObject target(cx, CheckedUnwrap(&thisValue.toObject()));
|
||||
RootedObject target(cx, CheckedUnwrap(obj));
|
||||
if (!target) {
|
||||
JS_ReportErrorASCII(cx, "Permission denied to access object");
|
||||
return false;
|
||||
}
|
||||
|
||||
RootedObject proto(cx);
|
||||
while (!target->is<ErrorObject>()) {
|
||||
while (!IsErrorProtoKey(StandardProtoKeyOrNull(target))) {
|
||||
if (!GetPrototype(cx, target, &proto))
|
||||
return false;
|
||||
|
||||
|
|
@ -194,7 +190,7 @@ ErrorObject_checkAndUnwrapThis(JSContext* cx, CallArgs& args, const char* fnName
|
|||
// We walked the whole prototype chain and did not find an Error
|
||||
// object.
|
||||
JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_INCOMPATIBLE_PROTO,
|
||||
js_Error_str, fnName, thisValue.toObject().getClass()->name);
|
||||
js_Error_str, "(get stack)", obj->getClass()->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -205,19 +201,40 @@ ErrorObject_checkAndUnwrapThis(JSContext* cx, CallArgs& args, const char* fnName
|
|||
}
|
||||
}
|
||||
|
||||
error.set(&target->as<ErrorObject>());
|
||||
result.set(target);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
IsObject(HandleValue v)
|
||||
{
|
||||
return v.isObject();
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
js::ErrorObject::getStack(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
Rooted<ErrorObject*> error(cx);
|
||||
if (!ErrorObject_checkAndUnwrapThis(cx, args, "(get stack)", &error))
|
||||
// We accept any object here, because of poor-man's subclassing of Error.
|
||||
return CallNonGenericMethod<IsObject, getStack_impl>(cx, args);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
js::ErrorObject::getStack_impl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
RootedObject thisObj(cx, &args.thisv().toObject());
|
||||
|
||||
RootedObject obj(cx);
|
||||
if (!FindErrorInstanceOrPrototype(cx, thisObj, &obj))
|
||||
return false;
|
||||
|
||||
RootedObject savedFrameObj(cx, error->stack());
|
||||
if (!obj->is<ErrorObject>()) {
|
||||
args.rval().setString(cx->runtime()->emptyString);
|
||||
return true;
|
||||
}
|
||||
|
||||
RootedObject savedFrameObj(cx, obj->as<ErrorObject>().stack());
|
||||
RootedString stackString(cx);
|
||||
if (!BuildStackString(cx, savedFrameObj, &stackString))
|
||||
return false;
|
||||
|
|
@ -245,12 +262,6 @@ js::ErrorObject::getStack(JSContext* cx, unsigned argc, Value* vp)
|
|||
return true;
|
||||
}
|
||||
|
||||
static MOZ_ALWAYS_INLINE bool
|
||||
IsObject(HandleValue v)
|
||||
{
|
||||
return v.isObject();
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
js::ErrorObject::setStack(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
|
|
@ -262,9 +273,7 @@ js::ErrorObject::setStack(JSContext* cx, unsigned argc, Value* vp)
|
|||
/* static */ bool
|
||||
js::ErrorObject::setStack_impl(JSContext* cx, const CallArgs& args)
|
||||
{
|
||||
const Value& thisValue = args.thisv();
|
||||
MOZ_ASSERT(thisValue.isObject());
|
||||
RootedObject thisObj(cx, &thisValue.toObject());
|
||||
RootedObject thisObj(cx, &args.thisv().toObject());
|
||||
|
||||
if (!args.requireAtLeast(cx, "(set stack)", 1))
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -106,6 +106,7 @@ class ErrorObject : public NativeObject
|
|||
|
||||
// Getter and setter for the Error.prototype.stack accessor.
|
||||
static bool getStack(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool getStack_impl(JSContext* cx, const CallArgs& args);
|
||||
static bool setStack(JSContext* cx, unsigned argc, Value* vp);
|
||||
static bool setStack_impl(JSContext* cx, const CallArgs& args);
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue