Bug 1055472 - Part 5: Make the various Error constructors properly subclassable. (r=Waldo)

This commit is contained in:
Eric Faust 2015-11-13 18:22:21 -08:00
Родитель 008e427ef8
Коммит b1ed9776d1
8 изменённых файлов: 54 добавлений и 14 удалений

Просмотреть файл

@ -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