diff --git a/js/xpconnect/wrappers/WrapperFactory.cpp b/js/xpconnect/wrappers/WrapperFactory.cpp index 1c85a07ce541..5813be28156b 100644 --- a/js/xpconnect/wrappers/WrapperFactory.cpp +++ b/js/xpconnect/wrappers/WrapperFactory.cpp @@ -120,6 +120,21 @@ WrapperFactory::DoubleWrap(JSContext *cx, HandleObject obj, unsigned flags) return obj; } +// In general, we're trying to deprecate COWs incrementally as we introduce +// Xrays to the corresponding object types. But switching off COWs for Object +// instances would be too tumultuous at present, so we punt on that for later. +static bool +ForceCOWBehavior(JSObject *obj) +{ + if (IdentifyStandardInstanceOrPrototype(obj) == JSProto_Object) { + MOZ_ASSERT(GetXrayType(obj) == XrayForJSObject, + "We should use XrayWrappers for standard ES Object instances " + "modulo this hack"); + return true; + } + return false; +} + JSObject * WrapperFactory::PrepareForWrapping(JSContext *cx, HandleObject scope, HandleObject objArg, unsigned flags) @@ -169,7 +184,7 @@ WrapperFactory::PrepareForWrapping(JSContext *cx, HandleObject scope, bool subsumes = AccessCheck::subsumes(js::GetContextCompartment(cx), js::GetObjectCompartment(obj)); XrayType xrayType = GetXrayType(obj); - if (!subsumes && xrayType == NotXray) { + if (!subsumes && (xrayType == NotXray || ForceCOWBehavior(obj))) { JSProtoKey key = JSProto_Null; { JSAutoCompartment ac(cx, obj); @@ -418,7 +433,12 @@ WrapperFactory::Rewrap(JSContext *cx, HandleObject existing, HandleObject obj, // If this is a chrome object being exposed to content without Xrays, use // a COW. - else if (originIsChrome && !targetIsChrome && xrayType == NotXray) { + // + // We make an exception for Object instances, because we still rely on COWs + // for those in a lot of places in the tree. + else if (originIsChrome && !targetIsChrome && + (xrayType == NotXray || ForceCOWBehavior(obj))) + { wrapper = &ChromeObjectWrapper::singleton; }