mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
Bug 1254968 - Add support for running JS builtins' constructors over Xray wrappers without unwrapping the newTarget. r=bholley,f=bz
This commit is contained in:
parent
f8c3aa8993
commit
dc24ad50e8
@ -665,7 +665,19 @@ struct JSClass {
|
||||
// SetNewObjectMetadata itself
|
||||
#define JSCLASS_PRIVATE_IS_NSISUPPORTS (1<<3) // private is (nsISupports*)
|
||||
#define JSCLASS_IS_DOMJSCLASS (1<<4) // objects are DOM
|
||||
// Bit 5 is unused.
|
||||
#define JSCLASS_HAS_XRAYED_CONSTRUCTOR (1<<5) // if wrapped by an xray
|
||||
// wrapper, the builtin
|
||||
// class's constructor won't
|
||||
// be unwrapped and invoked.
|
||||
// Instead, the constructor is
|
||||
// resolved in the caller's
|
||||
// compartment and invoked
|
||||
// with a wrapped newTarget.
|
||||
// The constructor has to
|
||||
// detect and handle this
|
||||
// situation.
|
||||
// See PromiseConstructor for
|
||||
// details.
|
||||
#define JSCLASS_EMULATES_UNDEFINED (1<<6) // objects of this class act
|
||||
// like the value undefined,
|
||||
// in some contexts
|
||||
|
@ -911,6 +911,48 @@ JSXrayTraits::enumerateNames(JSContext* cx, HandleObject wrapper, unsigned flags
|
||||
clasp->spec.prototypeProperties(), flags, props);
|
||||
}
|
||||
|
||||
bool
|
||||
JSXrayTraits::construct(JSContext* cx, HandleObject wrapper,
|
||||
const JS::CallArgs& args, const js::Wrapper& baseInstance)
|
||||
{
|
||||
JSXrayTraits& self = JSXrayTraits::singleton;
|
||||
JS::RootedObject holder(cx, self.ensureHolder(cx, wrapper));
|
||||
if (self.getProtoKey(holder) == JSProto_Function) {
|
||||
JSProtoKey standardConstructor = constructorFor(holder);
|
||||
if (standardConstructor == JSProto_Null)
|
||||
return baseInstance.construct(cx, wrapper, args);
|
||||
|
||||
const js::Class* clasp = js::ProtoKeyToClass(standardConstructor);
|
||||
MOZ_ASSERT(clasp);
|
||||
if (!(clasp->flags & JSCLASS_HAS_XRAYED_CONSTRUCTOR))
|
||||
return baseInstance.construct(cx, wrapper, args);
|
||||
|
||||
// If the JSCLASS_HAS_XRAYED_CONSTRUCTOR flag is set on the Class,
|
||||
// we don't use the constructor at hand. Instead, we retrieve the
|
||||
// equivalent standard constructor in the xray compartment and run
|
||||
// it in that compartment. The newTarget isn't unwrapped, and the
|
||||
// constructor has to be able to detect and handle this situation.
|
||||
// See the comments in js/public/Class.h and PromiseConstructor for
|
||||
// details and an example.
|
||||
RootedObject ctor(cx);
|
||||
if (!JS_GetClassObject(cx, standardConstructor, &ctor))
|
||||
return false;
|
||||
|
||||
RootedValue ctorVal(cx, ObjectValue(*ctor));
|
||||
HandleValueArray vals(args);
|
||||
RootedObject result(cx);
|
||||
if (!JS::Construct(cx, ctorVal, wrapper, vals, &result))
|
||||
return false;
|
||||
AssertSameCompartment(cx, result);
|
||||
args.rval().setObject(*result);
|
||||
return true;
|
||||
}
|
||||
|
||||
JS::RootedValue v(cx, JS::ObjectValue(*wrapper));
|
||||
js::ReportIsNotFunction(cx, v);
|
||||
return false;
|
||||
}
|
||||
|
||||
JSObject*
|
||||
JSXrayTraits::createHolder(JSContext* cx, JSObject* wrapper)
|
||||
{
|
||||
|
@ -251,17 +251,7 @@ public:
|
||||
}
|
||||
|
||||
static bool construct(JSContext* cx, JS::HandleObject wrapper,
|
||||
const JS::CallArgs& args, const js::Wrapper& baseInstance)
|
||||
{
|
||||
JSXrayTraits& self = JSXrayTraits::singleton;
|
||||
JS::RootedObject holder(cx, self.ensureHolder(cx, wrapper));
|
||||
if (self.getProtoKey(holder) == JSProto_Function)
|
||||
return baseInstance.construct(cx, wrapper, args);
|
||||
|
||||
JS::RootedValue v(cx, JS::ObjectValue(*wrapper));
|
||||
js::ReportIsNotFunction(cx, v);
|
||||
return false;
|
||||
}
|
||||
const JS::CallArgs& args, const js::Wrapper& baseInstance);
|
||||
|
||||
bool getPrototype(JSContext* cx, JS::HandleObject wrapper,
|
||||
JS::HandleObject target,
|
||||
|
Loading…
Reference in New Issue
Block a user