Bug 1125423 part 2 - Rename stopAtOuter argument to *Unwrap functions to stopAtWindowProxy. r=bz

This commit is contained in:
Jan de Mooij 2015-11-06 19:03:52 +01:00
parent a84c33ecb0
commit fffc37012e
24 changed files with 54 additions and 53 deletions

View File

@ -2253,7 +2253,7 @@ Navigator::DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
JS::Rooted<JSObject*> naviObj(aCx,
js::CheckedUnwrap(aObject,
/* stopAtOuter = */ false));
/* stopAtWindowProxy = */ false));
if (!naviObj) {
return Throw(aCx, NS_ERROR_DOM_SECURITY_ERR);
}

View File

@ -1513,7 +1513,7 @@ nsDOMConstructor::HasInstance(nsIXPConnectWrappedNative *wrapper,
NS_ASSERTION(dom_obj, "nsDOMConstructor::HasInstance couldn't get object");
// This might not be the right object, if there are wrappers. Unwrap if we can.
JSObject *wrapped_obj = js::CheckedUnwrap(dom_obj, /* stopAtOuter = */ false);
JSObject *wrapped_obj = js::CheckedUnwrap(dom_obj, /* stopAtWindowProxy = */ false);
if (wrapped_obj)
dom_obj = wrapped_obj;
@ -2042,7 +2042,7 @@ nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx,
// way the callee can decide whether to allow access based on the caller
// or the window being touched.
JS::Rooted<JSObject*> global(cx,
js::CheckedUnwrap(obj, /* stopAtOuter = */ false));
js::CheckedUnwrap(obj, /* stopAtWindowProxy = */ false));
if (!global) {
return NS_ERROR_DOM_SECURITY_ERR;
}

View File

@ -4512,7 +4512,7 @@ nsGlobalWindow::SetOpener(JSContext* aCx, JS::Handle<JS::Value> aOpener,
nsPIDOMWindow* win = nullptr;
if (aOpener.isObject()) {
JSObject* unwrapped = js::CheckedUnwrap(&aOpener.toObject(),
/* stopAtOuter = */ false);
/* stopAtWindowProxy = */ false);
if (!unwrapped) {
aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
@ -7824,7 +7824,7 @@ nsGlobalWindow::CallerInnerWindow()
bool ok = JS_GetPrototype(cx, scope, &scopeProto);
NS_ENSURE_TRUE(ok, nullptr);
if (scopeProto && xpc::IsSandboxPrototypeProxy(scopeProto) &&
(scopeProto = js::CheckedUnwrap(scopeProto, /* stopAtOuter = */ false)))
(scopeProto = js::CheckedUnwrap(scopeProto, /* stopAtWindowProxy = */ false)))
{
global = xpc::NativeGlobal(scopeProto);
NS_ENSURE_TRUE(global, nullptr);

View File

@ -997,7 +997,7 @@ QueryInterface(JSContext* cx, unsigned argc, JS::Value* vp)
// unwrap.
JS::Rooted<JSObject*> origObj(cx, &thisv.toObject());
JS::Rooted<JSObject*> obj(cx, js::CheckedUnwrap(origObj,
/* stopAtOuter = */ false));
/* stopAtWindowProxy = */ false));
if (!obj) {
JS_ReportError(cx, "Permission denied to access object");
return false;
@ -2007,7 +2007,7 @@ GlobalObject::GlobalObject(JSContext* aCx, JSObject* aObject)
MOZ_ASSERT(mCx);
JS::Rooted<JSObject*> obj(aCx, aObject);
if (js::IsWrapper(obj)) {
obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
obj = js::CheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
if (!obj) {
// We should never end up here on a worker thread, since there shouldn't
// be any security wrappers to worry about.
@ -2078,7 +2078,8 @@ InterfaceHasInstance(JSContext* cx, JS::Handle<JSObject*> obj,
const DOMIfaceAndProtoJSClass* clasp =
DOMIfaceAndProtoJSClass::FromJSClass(js::GetObjectClass(obj));
const DOMJSClass* domClass = GetDOMClass(js::UncheckedUnwrap(instance, /* stopAtOuter = */ false));
const DOMJSClass* domClass =
GetDOMClass(js::UncheckedUnwrap(instance, /* stopAtWindowProxy = */ false));
MOZ_ASSERT(!domClass || clasp->mPrototypeID != prototypes::id::_ID_Count,
"Why do we have a hasInstance hook if we don't have a prototype "
@ -2909,7 +2910,7 @@ GetMaplikeSetlikeBackingObject(JSContext* aCx, JS::Handle<JSObject*> aObj,
{
JS::Rooted<JSObject*> reflector(aCx);
reflector = IsDOMObject(aObj) ? aObj : js::UncheckedUnwrap(aObj,
/* stopAtOuter = */ false);
/* stopAtWindowProxy = */ false);
// Retrieve the backing object from the reserved slot on the maplike/setlike
// object. If it doesn't exist yet, create it.

View File

@ -222,7 +222,7 @@ UnwrapObject(JSObject* obj, U& value, prototypes::ID protoID,
return NS_ERROR_XPC_BAD_CONVERT_JS;
}
obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
obj = js::CheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
if (!obj) {
return NS_ERROR_XPC_SECURITY_MANAGER_VETO;
}
@ -1089,7 +1089,7 @@ WrapNewBindingNonWrapperCachedObject(JSContext* cx,
JS::Rooted<JSObject*> scope(cx, scopeArg);
JS::Rooted<JSObject*> proto(cx, givenProto);
if (js::IsWrapper(scope)) {
scope = js::CheckedUnwrap(scope, /* stopAtOuter = */ false);
scope = js::CheckedUnwrap(scope, /* stopAtWindowProxy = */ false);
if (!scope)
return false;
ac.emplace(cx, scope);
@ -1140,7 +1140,7 @@ WrapNewBindingNonWrapperCachedObject(JSContext* cx,
JS::Rooted<JSObject*> scope(cx, scopeArg);
JS::Rooted<JSObject*> proto(cx, givenProto);
if (js::IsWrapper(scope)) {
scope = js::CheckedUnwrap(scope, /* stopAtOuter = */ false);
scope = js::CheckedUnwrap(scope, /* stopAtWindowProxy = */ false);
if (!scope)
return false;
ac.emplace(cx, scope);

View File

@ -237,7 +237,7 @@ CallbackObject::CallSetup::ShouldRethrowException(JS::Handle<JS::Value> aExcepti
}
JS::Rooted<JSObject*> obj(mCx, &aException.toObject());
obj = js::UncheckedUnwrap(obj, /* stopAtOuter = */ false);
obj = js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
return js::GetObjectCompartment(obj) == mCompartment;
}

View File

@ -1861,7 +1861,7 @@ class CGClassHasInstanceHook(CGAbstractStaticMethod):
// FIXME Limit this to chrome by checking xpc::AccessCheck::isChrome(obj).
nsISupports* native =
nsContentUtils::XPConnect()->GetNativeOfWrapper(cx,
js::UncheckedUnwrap(instance, /* stopAtOuter = */ false));
js::UncheckedUnwrap(instance, /* stopAtWindowProxy = */ false));
nsCOMPtr<nsIDOM${name}> qiResult = do_QueryInterface(native);
*bp = !!qiResult;
return true;
@ -1871,7 +1871,7 @@ class CGClassHasInstanceHook(CGAbstractStaticMethod):
hasInstanceCode = dedent("""
const DOMJSClass* domClass = GetDOMClass(js::UncheckedUnwrap(instance, /* stopAtOuter = */ false));
const DOMJSClass* domClass = GetDOMClass(js::UncheckedUnwrap(instance, /* stopAtWindowProxy = */ false));
*bp = false;
if (!domClass) {
// Not a DOM object, so certainly not an instance of this interface
@ -1879,7 +1879,7 @@ class CGClassHasInstanceHook(CGAbstractStaticMethod):
}
""")
if self.descriptor.interface.identifier.name == "ChromeWindow":
setBp = "*bp = UnwrapDOMObject<nsGlobalWindow>(js::UncheckedUnwrap(instance, /* stopAtOuter = */ false))->IsChromeWindow()"
setBp = "*bp = UnwrapDOMObject<nsGlobalWindow>(js::UncheckedUnwrap(instance, /* stopAtWindowProxy = */ false))->IsChromeWindow()"
else:
setBp = "*bp = true"
# Sort interaces implementing self by name so we get stable output.
@ -8384,7 +8384,7 @@ class CGSpecializedGetter(CGAbstractStaticMethod):
// Safe to do an unchecked unwrap, since we've gotten this far.
// Also make sure to unwrap outer windows, since we want the
// real DOM object.
reflector = IsDOMObject(obj) ? obj : js::UncheckedUnwrap(obj, /* stopAtOuter = */ false);
reflector = IsDOMObject(obj) ? obj : js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
{
// Scope for cachedVal
JS::Value cachedVal = js::GetReservedSlot(reflector, ${slot});
@ -15395,7 +15395,7 @@ class CGMaplikeOrSetlikeHelperFunctionGenerator(CallbackMember):
// This is a reflector, but due to trying to name things
// similarly across method generators, it's called obj here.
JS::Rooted<JSObject*> obj(cx);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtOuter = */ false);
obj = js::UncheckedUnwrap(&v.toObject(), /* stopAtWindowProxy = */ false);
JSAutoCompartment reflectorCompartment(cx, obj);
""" % self.getDefaultRetval())

View File

@ -45,7 +45,7 @@ JSDebugger::AddClass(JS::Handle<JS::Value> global, JSContext* cx)
}
JS::RootedObject obj(cx, &global.toObject());
obj = js::UncheckedUnwrap(obj, /* stopAtOuter = */ false);
obj = js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
if (!obj) {
return NS_ERROR_FAILURE;
}

View File

@ -416,7 +416,7 @@ JSCompartment::wrap(JSContext* cx, MutableHandleObject obj, HandleObject existin
// Unwrap the object, but don't unwrap outer windows.
RootedObject objectPassedToWrap(cx, obj);
obj.set(UncheckedUnwrap(obj, /* stopAtOuter = */ true));
obj.set(UncheckedUnwrap(obj, /* stopAtWindowProxy = */ true));
if (obj->compartment() == this) {
MOZ_ASSERT(!IsWindow(obj));

View File

@ -276,23 +276,23 @@ IsWrapper(JSObject* obj)
}
// Given a JSObject, returns that object stripped of wrappers. If
// stopAtOuter is true, then this returns the outer window if it was
// stopAtWindowProxy is true, then this returns the WindowProxy if it was
// previously wrapped. Otherwise, this returns the first object for
// which JSObject::isWrapper returns false.
JS_FRIEND_API(JSObject*)
UncheckedUnwrap(JSObject* obj, bool stopAtOuter = true, unsigned* flagsp = nullptr);
UncheckedUnwrap(JSObject* obj, bool stopAtWindowProxy = true, unsigned* flagsp = nullptr);
// Given a JSObject, returns that object stripped of wrappers. At each stage,
// the security wrapper has the opportunity to veto the unwrap. Since checked
// code should never be unwrapping outer window wrappers, we always stop at
// outer windows.
// the security wrapper has the opportunity to veto the unwrap. If
// stopAtWindowProxy is true, then this returns the WindowProxy if it was
// previously wrapped.
JS_FRIEND_API(JSObject*)
CheckedUnwrap(JSObject* obj, bool stopAtOuter = true);
CheckedUnwrap(JSObject* obj, bool stopAtWindowProxy = true);
// Unwrap only the outermost security wrapper, with the same semantics as
// above. This is the checked version of Wrapper::wrappedObject.
JS_FRIEND_API(JSObject*)
UnwrapOneChecked(JSObject* obj, bool stopAtOuter = true);
UnwrapOneChecked(JSObject* obj, bool stopAtWindowProxy = true);
JS_FRIEND_API(bool)
IsCrossCompartmentWrapper(JSObject* obj);

View File

@ -55,12 +55,12 @@ Wrapper::isConstructor(JSObject* obj) const
}
JS_FRIEND_API(JSObject*)
js::UncheckedUnwrap(JSObject* wrapped, bool stopAtOuter, unsigned* flagsp)
js::UncheckedUnwrap(JSObject* wrapped, bool stopAtWindowProxy, unsigned* flagsp)
{
unsigned flags = 0;
while (true) {
if (!wrapped->is<WrapperObject>() ||
MOZ_UNLIKELY(stopAtOuter && wrapped->getClass()->ext.innerObject))
MOZ_UNLIKELY(stopAtWindowProxy && wrapped->getClass()->ext.innerObject))
{
break;
}
@ -78,21 +78,21 @@ js::UncheckedUnwrap(JSObject* wrapped, bool stopAtOuter, unsigned* flagsp)
}
JS_FRIEND_API(JSObject*)
js::CheckedUnwrap(JSObject* obj, bool stopAtOuter)
js::CheckedUnwrap(JSObject* obj, bool stopAtWindowProxy)
{
while (true) {
JSObject* wrapper = obj;
obj = UnwrapOneChecked(obj, stopAtOuter);
obj = UnwrapOneChecked(obj, stopAtWindowProxy);
if (!obj || obj == wrapper)
return obj;
}
}
JS_FRIEND_API(JSObject*)
js::UnwrapOneChecked(JSObject* obj, bool stopAtOuter)
js::UnwrapOneChecked(JSObject* obj, bool stopAtWindowProxy)
{
if (!obj->is<WrapperObject>() ||
MOZ_UNLIKELY(!!obj->getClass()->ext.innerObject && stopAtOuter))
MOZ_UNLIKELY(!!obj->getClass()->ext.innerObject && stopAtWindowProxy))
{
return obj;
}

View File

@ -31,7 +31,7 @@ namespace xpc {
bool
IsReflector(JSObject* obj)
{
obj = CheckedUnwrap(obj, /* stopAtOuter = */ false);
obj = CheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
if (!obj)
return false;
return IS_WN_REFLECTOR(obj) || dom::IsDOMObject(obj);

View File

@ -510,7 +510,7 @@ sandbox_addProperty(JSContext* cx, HandleObject obj, HandleId id, HandleValue v)
return false;
// After bug 1015790 is fixed, we should be able to remove this unwrapping.
RootedObject unwrappedProto(cx, js::UncheckedUnwrap(proto, /* stopAtOuter = */ false));
RootedObject unwrappedProto(cx, js::UncheckedUnwrap(proto, /* stopAtWindowProxy = */ false));
Rooted<JSPropertyDescriptor> pd(cx);
if (!JS_GetPropertyDescriptorById(cx, proto, id, &pd))

View File

@ -57,7 +57,7 @@ XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage,
mTearOff = nullptr;
JSObject* unwrapped = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
JSObject* unwrapped = js::CheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
if (!unwrapped) {
JS_ReportError(mJSContext, "Permission denied to call method on |this|");
mState = INIT_FAILED;

View File

@ -2767,7 +2767,7 @@ nsXPCComponents_Utils::IsProxy(HandleValue vobj, JSContext* cx, bool* rval)
}
RootedObject obj(cx, &vobj.toObject());
obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
obj = js::CheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
NS_ENSURE_TRUE(obj, NS_ERROR_FAILURE);
*rval = js::IsScriptedProxy(obj);
@ -3045,7 +3045,7 @@ nsXPCComponents_Utils::BlockScriptForGlobal(HandleValue globalArg,
{
NS_ENSURE_TRUE(globalArg.isObject(), NS_ERROR_INVALID_ARG);
RootedObject global(cx, UncheckedUnwrap(&globalArg.toObject(),
/* stopAtOuter = */ false));
/* stopAtWindowProxy = */ false));
NS_ENSURE_TRUE(JS_IsGlobalObject(global), NS_ERROR_INVALID_ARG);
if (nsContentUtils::IsSystemPrincipal(xpc::GetObjectPrincipal(global))) {
JS_ReportError(cx, "Script may not be disabled for system globals");
@ -3061,7 +3061,7 @@ nsXPCComponents_Utils::UnblockScriptForGlobal(HandleValue globalArg,
{
NS_ENSURE_TRUE(globalArg.isObject(), NS_ERROR_INVALID_ARG);
RootedObject global(cx, UncheckedUnwrap(&globalArg.toObject(),
/* stopAtOuter = */ false));
/* stopAtWindowProxy = */ false));
NS_ENSURE_TRUE(JS_IsGlobalObject(global), NS_ERROR_INVALID_ARG);
if (nsContentUtils::IsSystemPrincipal(xpc::GetObjectPrincipal(global))) {
JS_ReportError(cx, "Script may not be disabled for system globals");
@ -3111,7 +3111,7 @@ nsXPCComponents_Utils::GetClassName(HandleValue aObj, bool aUnwrap, JSContext* a
return NS_ERROR_INVALID_ARG;
RootedObject obj(aCx, &aObj.toObject());
if (aUnwrap)
obj = js::UncheckedUnwrap(obj, /* stopAtOuter = */ false);
obj = js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
*aRv = NS_strdup(js::GetObjectClass(obj)->name);
NS_ENSURE_TRUE(*aRv, NS_ERROR_OUT_OF_MEMORY);
return NS_OK;

View File

@ -904,7 +904,7 @@ XPCConvert::JSObject2NativeInterface(void** dest, HandleObject src,
// because the caller may explicitly want to create the XPCWrappedJS
// around a security wrapper. XBL does this with Xrays from the XBL
// scope - see nsBindingManager::GetBindingImplementation.
JSObject* inner = js::CheckedUnwrap(src, /* stopAtOuter = */ false);
JSObject* inner = js::CheckedUnwrap(src, /* stopAtWindowProxy = */ false);
if (!inner) {
if (pErr)
*pErr = NS_ERROR_XPC_SECURITY_MANAGER_VETO;
@ -1037,7 +1037,7 @@ XPCConvert::JSValToXPCException(MutableHandleValue s,
}
// is this really a native xpcom object with a wrapper?
JSObject* unwrapped = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
JSObject* unwrapped = js::CheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
if (!unwrapped)
return NS_ERROR_XPC_SECURITY_MANAGER_VETO;
XPCWrappedNative* wrapper = IS_WN_REFLECTOR(unwrapped) ? XPCWrappedNative::Get(unwrapped)

View File

@ -463,7 +463,7 @@ FindObjectForHasInstance(JSContext* cx, HandleObject objArg)
!IsDOMObject(obj) && !mozilla::jsipc::IsCPOW(obj))
{
if (js::IsWrapper(obj)) {
obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
obj = js::CheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
continue;
}
if (!js::GetObjectProto(cx, obj, &proto))

View File

@ -550,7 +550,7 @@ AddonWindowOrNull(JSObject* aObj)
// about it and get them to change their code.
MOZ_RELEASE_ASSERT(js::IsCrossCompartmentWrapper(proto) ||
xpc::IsSandboxPrototypeProxy(proto));
JSObject* mainGlobal = js::UncheckedUnwrap(proto, /* stopAtOuter = */ false);
JSObject* mainGlobal = js::UncheckedUnwrap(proto, /* stopAtWindowProxy = */ false);
MOZ_RELEASE_ASSERT(JS_IsGlobalObject(mainGlobal));
return WindowOrNull(mainGlobal);
@ -1433,7 +1433,7 @@ XPCJSRuntime::InterruptCallback(JSContext* cx)
if (!JS_GetPrototype(cx, global, &proto))
return false;
if (proto && IsSandboxPrototypeProxy(proto) &&
(proto = js::CheckedUnwrap(proto, /* stopAtOuter = */ false)))
(proto = js::CheckedUnwrap(proto, /* stopAtWindowProxy = */ false)))
{
win = WindowGlobalOrNull(proto);
}

View File

@ -45,7 +45,7 @@ XPCVariant::XPCVariant(JSContext* cx, Value aJSVal)
JSObject* obj = js::ToWindowIfWindowProxy(&mJSVal.toObject());
mJSVal = JS::ObjectValue(*obj);
JSObject* unwrapped = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
JSObject* unwrapped = js::CheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
mReturnRawObject = !(unwrapped && IS_WN_REFLECTOR(unwrapped));
} else
mReturnRawObject = false;

View File

@ -623,7 +623,7 @@ nsXPConnect::GetWrappedNativeOfJSObject(JSContext * aJSContext,
MOZ_ASSERT(_retval, "bad param");
RootedObject aJSObj(aJSContext, aJSObjArg);
aJSObj = js::CheckedUnwrap(aJSObj, /* stopAtOuter = */ false);
aJSObj = js::CheckedUnwrap(aJSObj, /* stopAtWindowProxy = */ false);
if (!aJSObj || !IS_WN_REFLECTOR(aJSObj)) {
*_retval = nullptr;
return NS_ERROR_FAILURE;
@ -638,7 +638,7 @@ nsISupports*
xpc::UnwrapReflectorToISupports(JSObject* reflector)
{
// Unwrap security wrappers, if allowed.
reflector = js::CheckedUnwrap(reflector, /* stopAtOuter = */ false);
reflector = js::CheckedUnwrap(reflector, /* stopAtWindowProxy = */ false);
if (!reflector)
return nullptr;

View File

@ -142,7 +142,7 @@ IsFrameId(JSContext* cx, JSObject* obj, jsid idArg)
CrossOriginObjectType
IdentifyCrossOriginObject(JSObject* obj)
{
obj = js::UncheckedUnwrap(obj, /* stopAtOuter = */ false);
obj = js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
const js::Class* clasp = js::GetObjectClass(obj);
MOZ_ASSERT(!XrayUtils::IsXPCWNHolderClass(Jsvalify(clasp)), "shouldn't have a holder here");
@ -171,7 +171,7 @@ AccessCheck::isCrossOriginAccessPermitted(JSContext* cx, HandleObject wrapper, H
isCrossOriginAccessPermitted(cx, wrapper, id, Wrapper::SET);
}
RootedObject obj(cx, js::UncheckedUnwrap(wrapper, /* stopAtOuter = */ false));
RootedObject obj(cx, js::UncheckedUnwrap(wrapper, /* stopAtWindowProxy = */ false));
CrossOriginObjectType type = IdentifyCrossOriginObject(obj);
if (JSID_IS_STRING(id)) {
if (IsPermitted(type, JSID_TO_FLAT_STRING(id), act == Wrapper::SET))

View File

@ -124,7 +124,7 @@ inline bool
ShouldWaiveXray(JSContext* cx, JSObject* originalObj)
{
unsigned flags;
(void) js::UncheckedUnwrap(originalObj, /* stopAtOuter = */ true, &flags);
(void) js::UncheckedUnwrap(originalObj, /* stopAtWindowProxy = */ true, &flags);
// If the original object did not point through an Xray waiver, we're done.
if (!(flags & WrapperFactory::WAIVE_XRAY_WRAPPER_FLAG))

View File

@ -94,7 +94,7 @@ IsJSXraySupported(JSProtoKey key)
XrayType
GetXrayType(JSObject* obj)
{
obj = js::UncheckedUnwrap(obj, /* stopAtOuter = */ false);
obj = js::UncheckedUnwrap(obj, /* stopAtWindowProxy = */ false);
if (mozilla::dom::UseDOMXray(obj))
return XrayForDOMObject;

View File

@ -64,7 +64,7 @@ public:
XrayTraits() {}
static JSObject* getTargetObject(JSObject* wrapper) {
return js::UncheckedUnwrap(wrapper, /* stopAtOuter = */ false);
return js::UncheckedUnwrap(wrapper, /* stopAtWindowProxy = */ false);
}
virtual bool resolveNativeProperty(JSContext* cx, JS::HandleObject wrapper,