зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1055472 - Part 5: Make the various Error constructors properly subclassable. (r=Waldo)
This commit is contained in:
Родитель
008e427ef8
Коммит
b1ed9776d1
|
@ -338,6 +338,11 @@ Error(JSContext* cx, unsigned argc, Value* vp)
|
|||
{
|
||||
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)) {
|
||||
|
@ -389,7 +394,7 @@ 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));
|
||||
lineNumber, columnNumber, nullptr, message, proto));
|
||||
if (!obj)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -1863,14 +1863,7 @@ FunctionConstructor(JSContext* cx, unsigned argc, Value* vp, GeneratorKind gener
|
|||
if (!proto)
|
||||
return false;
|
||||
} else {
|
||||
RootedObject toTest(cx);
|
||||
// If we are invoked without |new|, then just use Function.prototype
|
||||
if (args.isConstructing())
|
||||
toTest = &args.newTarget().toObject();
|
||||
else
|
||||
toTest = &args.callee();
|
||||
|
||||
if (!GetPrototypeFromConstructor(cx, toTest, &proto))
|
||||
if (!GetPrototypeFromCallableConstructor(cx, args, &proto))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -997,6 +997,17 @@ js::GetPrototypeFromConstructor(JSContext* cx, HandleObject newTarget, MutableHa
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
js::GetPrototypeFromCallableConstructor(JSContext* cx, const CallArgs& args, MutableHandleObject proto)
|
||||
{
|
||||
RootedObject newTarget(cx);
|
||||
if (args.isConstructing())
|
||||
newTarget = &args.newTarget().toObject();
|
||||
else
|
||||
newTarget = &args.callee();
|
||||
return GetPrototypeFromConstructor(cx, newTarget, proto);
|
||||
}
|
||||
|
||||
JSObject*
|
||||
js::CreateThisForFunction(JSContext* cx, HandleObject callee, HandleObject newTarget,
|
||||
NewObjectKind newKind)
|
||||
|
|
|
@ -1093,6 +1093,9 @@ GetInitialHeap(NewObjectKind newKind, const Class* clasp)
|
|||
extern bool
|
||||
GetPrototypeFromConstructor(JSContext* cx, js::HandleObject newTarget, js::MutableHandleObject proto);
|
||||
|
||||
extern bool
|
||||
GetPrototypeFromCallableConstructor(JSContext* cx, const CallArgs& args, js::MutableHandleObject proto);
|
||||
|
||||
// Specialized call for constructing |this| with a known function callee,
|
||||
// and a known prototype.
|
||||
extern JSObject*
|
||||
|
|
|
@ -18,6 +18,13 @@ function testBuiltin(builtin) {
|
|||
testBuiltin(Function);
|
||||
testBuiltin(Object);
|
||||
testBuiltin(Boolean);
|
||||
testBuiltin(Error);
|
||||
testBuiltin(EvalError);
|
||||
testBuiltin(RangeError);
|
||||
testBuiltin(ReferenceError);
|
||||
testBuiltin(SyntaxError);
|
||||
testBuiltin(TypeError);
|
||||
testBuiltin(URIError);
|
||||
|
||||
`;
|
||||
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
var order = 0;
|
||||
function assertOrdering(ordering) {
|
||||
assertEq(order, ordering);
|
||||
order++;
|
||||
}
|
||||
|
||||
// Spec mandates that the prototype is looked up /before/ we toString the
|
||||
// argument.
|
||||
var handler = { get() { assertOrdering(0); return Error.prototype } };
|
||||
var errorProxy = new Proxy(Error, handler);
|
||||
|
||||
var toStringable = { toString() { assertOrdering(1); return "Argument"; } };
|
||||
|
||||
new errorProxy(toStringable);
|
||||
|
||||
if (typeof reportCompare === 'function')
|
||||
reportCompare(0,0,"OK");
|
|
@ -84,13 +84,17 @@ js::ErrorObject::init(JSContext* cx, Handle<ErrorObject*> obj, JSExnType type,
|
|||
/* static */ ErrorObject*
|
||||
js::ErrorObject::create(JSContext* cx, JSExnType errorType, HandleObject stack,
|
||||
HandleString fileName, uint32_t lineNumber, uint32_t columnNumber,
|
||||
ScopedJSFreePtr<JSErrorReport>* report, HandleString message)
|
||||
ScopedJSFreePtr<JSErrorReport>* report, HandleString message,
|
||||
HandleObject protoArg /* = nullptr */)
|
||||
{
|
||||
AssertObjectIsSavedFrameOrWrapper(cx, stack);
|
||||
|
||||
Rooted<JSObject*> proto(cx, GlobalObject::getOrCreateCustomErrorPrototype(cx, cx->global(), errorType));
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
RootedObject proto(cx, protoArg);
|
||||
if (!proto) {
|
||||
proto = GlobalObject::getOrCreateCustomErrorPrototype(cx, cx->global(), errorType);
|
||||
if (!proto)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Rooted<ErrorObject*> errObject(cx);
|
||||
{
|
||||
|
|
|
@ -72,7 +72,7 @@ class ErrorObject : public NativeObject
|
|||
static ErrorObject*
|
||||
create(JSContext* cx, JSExnType type, HandleObject stack, HandleString fileName,
|
||||
uint32_t lineNumber, uint32_t columnNumber, ScopedJSFreePtr<JSErrorReport>* report,
|
||||
HandleString message);
|
||||
HandleString message, HandleObject proto = nullptr);
|
||||
|
||||
/*
|
||||
* Assign the initial error shape to the empty object. (This shape does
|
||||
|
|
Загрузка…
Ссылка в новой задаче