Bug 1477923. Make WebIDL callbacks store a global in addition to the object that's used as a callback. r=mccr8

We want to be able to enter the Realm we were in when the callback was created
before calling it, but if the callback stores a cross-compartment wrapper we
don't really have a good way to find that Realm.  So we store it explicitly by
storing a global when the callback is created.

The changes to the constructor signatures to use JSObject* instead of
JS::Handle<JSObject*> are so we can avoid having to root the global for these
calls.  These changes make two of the constructors ambiguous when nullptr is
being passed for the first arg; this patch adds casts to disambiguate.
This commit is contained in:
Boris Zbarsky 2018-08-03 17:11:39 -04:00
Родитель 757eed8c02
Коммит f771d7e529
13 изменённых файлов: 148 добавлений и 64 удалений

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

@ -727,11 +727,13 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
JS::RootingContext* rcx = RootingCx();
JS::Rooted<JSObject*> object(rcx);
JS::Rooted<JSObject*> nonCCWObject(rcx);
RefPtr<MessageListener> webIDLListener;
if (!weakListener) {
webIDLListener = listener.mStrongListener;
object = webIDLListener->CallbackOrNull();
nonCCWObject = webIDLListener->CallbackGlobalOrNull();
} else {
nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS = do_QueryInterface(weakListener);
if (!wrappedJS) {
@ -739,6 +741,9 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
}
object = wrappedJS->GetJSObject();
// This is not really guaranteed to not be a CCW yet, but hopefully bug
// 1478359 will help with that.
nonCCWObject = object;
}
if (!object) {
@ -749,10 +754,9 @@ nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
JSContext* cx = aes.cx();
// We passed the unwrapped object to AutoEntryScript so we now need to
// enter the (maybe wrapper) object's realm. We will have to revisit this
// later because CCWs are not associated with a single realm so this
// doesn't make much sense. See bug 1477923.
JSAutoRealmAllowCCW ar(cx, object);
// enter the realm of the non-ccw object that represents the realm of our
// callback.
JSAutoRealm ar(cx, nonCCWObject);
RootedDictionary<ReceiveMessageArgument> argument(cx);

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

@ -2360,7 +2360,10 @@ nsGlobalWindowInner::GetInstallTrigger()
rv.SuppressException();
return nullptr;
}
mInstallTrigger = new InstallTriggerImpl(jsImplObj, this);
MOZ_RELEASE_ASSERT(!js::IsWrapper(jsImplObj));
JS::Rooted<JSObject*> jsImplGlobal(RootingCx(),
JS::GetNonCCWObjectGlobal(jsImplObj));
mInstallTrigger = new InstallTriggerImpl(jsImplObj, jsImplGlobal, this);
}
return do_AddRef(mInstallTrigger);
@ -7451,7 +7454,10 @@ nsGlobalWindowInner::GetExternal(ErrorResult& aRv)
if (aRv.Failed()) {
return nullptr;
}
mExternal = new External(jsImplObj, this);
MOZ_RELEASE_ASSERT(!js::IsWrapper(jsImplObj));
JS::Rooted<JSObject*> jsImplGlobal(RootingCx(),
JS::GetNonCCWObjectGlobal(jsImplObj));
mExternal = new External(jsImplObj, jsImplGlobal, this);
}
RefPtr<External> external = static_cast<External*>(mExternal.get());

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

@ -27,16 +27,18 @@ class CallbackFunction : public CallbackObject
public:
// See CallbackObject for an explanation of the arguments.
explicit CallbackFunction(JSContext* aCx, JS::Handle<JSObject*> aCallable,
JS::Handle<JSObject*> aCallableGlobal,
nsIGlobalObject* aIncumbentGlobal)
: CallbackObject(aCx, aCallable, aIncumbentGlobal)
: CallbackObject(aCx, aCallable, aCallableGlobal, aIncumbentGlobal)
{
}
// See CallbackObject for an explanation of the arguments.
explicit CallbackFunction(JS::Handle<JSObject*> aCallable,
JS::Handle<JSObject*> aAsyncStack,
explicit CallbackFunction(JSObject* aCallable,
JSObject* aCallableGlobal,
JSObject* aAsyncStack,
nsIGlobalObject* aIncumbentGlobal)
: CallbackObject(aCallable, aAsyncStack, aIncumbentGlobal)
: CallbackObject(aCallable, aCallableGlobal, aAsyncStack, aIncumbentGlobal)
{
}
@ -63,9 +65,10 @@ protected:
}
// See CallbackObject for an explanation of the arguments.
CallbackFunction(JS::Handle<JSObject*> aCallable,
CallbackFunction(JSObject* aCallable,
JSObject* aCallableGlobal,
const FastCallbackConstructor&)
: CallbackObject(aCallable, FastCallbackConstructor())
: CallbackObject(aCallable, aCallableGlobal, FastCallbackConstructor())
{
}
};

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

@ -26,16 +26,18 @@ class CallbackInterface : public CallbackObject
public:
// See CallbackObject for an explanation of the arguments.
explicit CallbackInterface(JSContext* aCx, JS::Handle<JSObject*> aCallback,
JS::Handle<JSObject*> aCallbackGlobal,
nsIGlobalObject* aIncumbentGlobal)
: CallbackObject(aCx, aCallback, aIncumbentGlobal)
: CallbackObject(aCx, aCallback, aCallbackGlobal, aIncumbentGlobal)
{
}
// See CallbackObject for an explanation of the arguments.
explicit CallbackInterface(JS::Handle<JSObject*> aCallback,
JS::Handle<JSObject*> aAsyncStack,
explicit CallbackInterface(JSObject* aCallback,
JSObject* aCallbackGlobal,
JSObject* aAsyncStack,
nsIGlobalObject* aIncumbentGlobal)
: CallbackObject(aCallback, aAsyncStack, aIncumbentGlobal)
: CallbackObject(aCallback, aCallbackGlobal, aAsyncStack, aIncumbentGlobal)
{
}
@ -44,9 +46,10 @@ protected:
JS::MutableHandle<JS::Value> aCallable);
// See CallbackObject for an explanation of the arguments.
CallbackInterface(JS::Handle<JSObject*> aCallable,
CallbackInterface(JSObject* aCallback,
JSObject* aCallbackGlobal,
const FastCallbackConstructor&)
: CallbackObject(aCallable, FastCallbackConstructor())
: CallbackObject(aCallback, aCallbackGlobal, FastCallbackConstructor())
{
}
};

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

@ -81,6 +81,7 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(CallbackObject)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(CallbackObject)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCallback)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCallbackGlobal)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mCreationStack)
NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mIncumbentJSGlobal)
NS_IMPL_CYCLE_COLLECTION_TRACE_END
@ -89,6 +90,7 @@ void
CallbackObject::Trace(JSTracer* aTracer)
{
JS::TraceEdge(aTracer, &mCallback, "CallbackObject.mCallback");
JS::TraceEdge(aTracer, &mCallbackGlobal, "CallbackObject.mCallbackGlobal");
JS::TraceEdge(aTracer, &mCreationStack, "CallbackObject.mCreationStack");
JS::TraceEdge(aTracer, &mIncumbentJSGlobal,
"CallbackObject.mIncumbentJSGlobal");
@ -239,6 +241,7 @@ CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
// with the cx from mAutoEntryScript, avoiding the cost of finding another
// JSContext. (Rooted<> does not care about requests or compartments.)
mRootedCallable.emplace(cx, aCallback->CallbackOrNull());
mRootedCallableGlobal.emplace(cx, aCallback->CallbackGlobalOrNull());
mAsyncStack.emplace(cx, aCallback->GetCreationStack());
if (*mAsyncStack) {
@ -250,7 +253,7 @@ CallbackObject::CallSetup::CallSetup(CallbackObject* aCallback,
// Note that if the callback is a wrapper, this will not be the same
// realm that we ended up in with mAutoEntryScript above, because the
// entry point is based off of the unwrapped callback (realCallback).
mAr.emplace(cx, *mRootedCallable);
mAr.emplace(cx, *mRootedCallableGlobal);
// And now we're ready to go.
mCx = cx;

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

@ -56,6 +56,7 @@ public:
// is invoked. aCx can be nullptr, in which case no stack is
// captured.
explicit CallbackObject(JSContext* aCx, JS::Handle<JSObject*> aCallback,
JS::Handle<JSObject*> aCallbackGlobal,
nsIGlobalObject* aIncumbentGlobal)
{
if (aCx && JS::ContextOptionsRef(aCx).asyncStack()) {
@ -63,20 +64,21 @@ public:
if (!JS::CaptureCurrentStack(aCx, &stack)) {
JS_ClearPendingException(aCx);
}
Init(aCallback, stack, aIncumbentGlobal);
Init(aCallback, aCallbackGlobal, stack, aIncumbentGlobal);
} else {
Init(aCallback, nullptr, aIncumbentGlobal);
Init(aCallback, aCallbackGlobal, nullptr, aIncumbentGlobal);
}
}
// Instead of capturing the current stack to use as an async parent when the
// callback is invoked, the caller can use this overload to pass in a stack
// for that purpose.
explicit CallbackObject(JS::Handle<JSObject*> aCallback,
JS::Handle<JSObject*> aAsyncStack,
explicit CallbackObject(JSObject* aCallback,
JSObject* aCallbackGlobal,
JSObject* aAsyncStack,
nsIGlobalObject* aIncumbentGlobal)
{
Init(aCallback, aAsyncStack, aIncumbentGlobal);
Init(aCallback, aCallbackGlobal, aAsyncStack, aIncumbentGlobal);
}
// This is guaranteed to be non-null from the time the CallbackObject is
@ -93,6 +95,12 @@ public:
return CallbackPreserveColor();
}
JSObject* CallbackGlobalOrNull() const
{
mCallbackGlobal.exposeToActiveJS();
return mCallbackGlobal;
}
// Like CallbackOrNull(), but will return a new dead proxy object in the
// caller's realm if the callback is null.
JSObject* Callback(JSContext* aCx);
@ -105,6 +113,7 @@ public:
void MarkForCC()
{
mCallback.exposeToActiveJS();
mCallbackGlobal.exposeToActiveJS();
mCreationStack.exposeToActiveJS();
}
@ -165,7 +174,8 @@ protected:
explicit CallbackObject(CallbackObject* aCallbackObject)
{
Init(aCallbackObject->mCallback, aCallbackObject->mCreationStack,
Init(aCallbackObject->mCallback, aCallbackObject->mCallbackGlobal,
aCallbackObject->mCreationStack,
aCallbackObject->mIncumbentGlobal);
}
@ -199,13 +209,17 @@ protected:
};
private:
inline void InitNoHold(JSObject* aCallback, JSObject* aCreationStack,
inline void InitNoHold(JSObject* aCallback, JSObject* aCallbackGlobal,
JSObject* aCreationStack,
nsIGlobalObject* aIncumbentGlobal)
{
MOZ_ASSERT(aCallback && !mCallback);
// Set script objects before we hold, on the off chance that a GC could
// somehow happen in there... (which would be pretty odd, granted).
MOZ_ASSERT(aCallbackGlobal);
MOZ_DIAGNOSTIC_ASSERT(js::GetObjectCompartment(aCallback) ==
js::GetObjectCompartment(aCallbackGlobal));
MOZ_ASSERT(JS_IsGlobalObject(aCallbackGlobal));
mCallback = aCallback;
mCallbackGlobal = aCallbackGlobal;
mCreationStack = aCreationStack;
if (aIncumbentGlobal) {
mIncumbentGlobal = aIncumbentGlobal;
@ -213,16 +227,20 @@ private:
}
}
inline void Init(JSObject* aCallback, JSObject* aCreationStack,
inline void Init(JSObject* aCallback, JSObject* aCallbackGlobal,
JSObject* aCreationStack,
nsIGlobalObject* aIncumbentGlobal)
{
InitNoHold(aCallback, aCreationStack, aIncumbentGlobal);
// Set script objects before we hold, on the off chance that a GC could
// somehow happen in there... (which would be pretty odd, granted).
InitNoHold(aCallback, aCallbackGlobal, aCreationStack, aIncumbentGlobal);
mozilla::HoldJSObjects(this);
}
inline void ClearJSReferences()
{
mCallback = nullptr;
mCallbackGlobal = nullptr;
mCreationStack = nullptr;
mIncumbentJSGlobal = nullptr;
}
@ -262,10 +280,11 @@ protected:
// assumption that we will do that last whenever we decide to actually
// HoldJSObjects; see FinishSlowJSInitIfMoreThanOneOwner). If you use this,
// you MUST ensure that the object is traced until the HoldJSObjects happens!
CallbackObject(JS::Handle<JSObject*> aCallback,
CallbackObject(JSObject* aCallback,
JSObject* aCallbackGlobal,
const FastCallbackConstructor&)
{
InitNoHold(aCallback, nullptr, nullptr);
InitNoHold(aCallback, aCallbackGlobal, nullptr, nullptr);
}
// mCallback is not unwrapped, so it can be a cross-compartment-wrapper.
@ -273,6 +292,11 @@ protected:
// its members, directly itself, this code won't call f(), or get its members,
// on the code's behalf.
JS::Heap<JSObject*> mCallback;
// mCallbackGlobal is the global that we were in when we created the
// callback. In particular, it is guaranteed to be same-compartment with
// aCallback. We store it separately, because we have no way to recover the
// global if mCallback is a cross-compartment wrapper.
JS::Heap<JSObject*> mCallbackGlobal;
JS::Heap<JSObject*> mCreationStack;
// Ideally, we'd just hold a reference to the nsIGlobalObject, since that's
// what we need to pass to AutoIncumbentScript. Unfortunately, that doesn't
@ -330,7 +354,9 @@ protected:
Maybe<AutoEntryScript> mAutoEntryScript;
Maybe<AutoIncumbentScript> mAutoIncumbentScript;
Maybe<JS::Rooted<JSObject*> > mRootedCallable;
Maybe<JS::Rooted<JSObject*>> mRootedCallable;
// The global of mRootedCallable.
Maybe<JS::Rooted<JSObject*>> mRootedCallableGlobal;
// Members which are used to set the async stack.
Maybe<JS::Rooted<JSObject*>> mAsyncStack;

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

@ -4240,7 +4240,10 @@ class CastableObjectUnwrapper():
$*{exceptionCode}
}
JS::Rooted<JSObject*> jsImplSourceObj(cx, &${source}.toObject());
${target} = new ${type}(jsImplSourceObj, contentGlobal);
MOZ_RELEASE_ASSERT(!js::IsWrapper(jsImplSourceObj),
"Don't return JS implementations from other compartments");
JS::Rooted<JSObject*> jsImplSourceGlobal(cx, JS::GetNonCCWObjectGlobal(jsImplSourceObj));
${target} = new ${type}(jsImplSourceObj, jsImplSourceGlobal, contentGlobal);
} else {
$*{codeOnFailure}
}
@ -4297,11 +4300,15 @@ def getCallbackConversionInfo(type, idlObject, isMember, isCallbackReturnValue,
not isOptional)
if useFastCallback:
name = "binding_detail::Fast%s" % name
argsPre = ""
argsPost = ""
rootArgs = ""
args = "&${val}.toObject(), JS::CurrentGlobalOrNull(cx)"
else:
argsPre = "cx, "
argsPost = ", GetIncumbentGlobal()"
rootArgs = dedent(
"""
JS::Rooted<JSObject*> tempRoot(cx, &${val}.toObject());
JS::Rooted<JSObject*> tempGlobalRoot(cx, JS::CurrentGlobalOrNull(cx));
""")
args = "cx, tempRoot, tempGlobalRoot, GetIncumbentGlobal()"
if type.nullable() or isCallbackReturnValue:
declType = CGGeneric("RefPtr<%s>" % name)
@ -4316,14 +4323,14 @@ def getCallbackConversionInfo(type, idlObject, isMember, isCallbackReturnValue,
conversion = fill(
"""
{ // scope for tempRoot
JS::Rooted<JSObject*> tempRoot(cx, &$${val}.toObject());
$${declName} = new ${name}(${argsPre}tempRoot${argsPost});
{ // scope for tempRoot and tempGlobalRoot if needed
$*{rootArgs}
$${declName} = new ${name}(${args});
}
""",
rootArgs=rootArgs,
name=name,
argsPre=argsPre,
argsPost=argsPost)
args=args)
return (declType, declArgs, conversion)
@ -15066,8 +15073,11 @@ def genConstructorBody(descriptor, initCall=""):
if (aRv.Failed()) {
return nullptr;
}
// We should be getting the implementation object for the relevant
// contract here, which should never be a cross-compartment wrapper.
JS::Rooted<JSObject*> jsImplGlobal(cx, JS::GetNonCCWObjectGlobal(jsImplObj));
// Build the C++ implementation.
RefPtr<${implClass}> impl = new ${implClass}(jsImplObj, globalHolder);
RefPtr<${implClass}> impl = new ${implClass}(jsImplObj, jsImplGlobal, globalHolder);
$*{initCall}
return impl.forget();
""",
@ -15219,14 +15229,14 @@ class CGJSImplClass(CGBindingImplClass):
destructor = ClassDestructor(virtual=False, visibility="private")
baseConstructors = [
("mImpl(new %s(nullptr, aJSImplObject, /* aIncumbentGlobal = */ nullptr))" %
("mImpl(new %s(nullptr, aJSImplObject, aJSImplGlobal, /* aIncumbentGlobal = */ nullptr))" %
jsImplName(descriptor.name)),
"mParent(aParent)"]
parentInterface = descriptor.interface.parent
while parentInterface:
if parentInterface.isJSImplemented():
baseConstructors.insert(
0, "%s(aJSImplObject, aParent)" % parentClass)
0, "%s(aJSImplObject, aJSImplGlobal, aParent)" % parentClass)
break
parentInterface = parentInterface.parent
if not parentInterface and descriptor.interface.parent:
@ -15236,6 +15246,7 @@ class CGJSImplClass(CGBindingImplClass):
constructor = ClassConstructor(
[Argument("JS::Handle<JSObject*>", "aJSImplObject"),
Argument("JS::Handle<JSObject*>", "aJSImplGlobal"),
Argument("nsIGlobalObject*", "aParent")],
visibility="public",
baseConstructors=baseConstructors)
@ -15331,7 +15342,8 @@ class CGJSImplClass(CGBindingImplClass):
nsCOMPtr<nsIGlobalObject> globalHolder = do_QueryInterface(global.GetAsSupports());
MOZ_ASSERT(globalHolder);
JS::Rooted<JSObject*> arg(cx, &args[1].toObject());
RefPtr<${implName}> impl = new ${implName}(arg, globalHolder);
JS::Rooted<JSObject*> argGlobal(cx, JS::CurrentGlobalOrNull(cx));
RefPtr<${implName}> impl = new ${implName}(arg, argGlobal, globalHolder);
MOZ_ASSERT(js::IsObjectInContextCompartment(arg, cx));
return GetOrCreateDOMReflector(cx, impl, args.rval());
""",
@ -15404,33 +15416,39 @@ class CGCallback(CGClass):
ClassConstructor(
[Argument("JSContext*", "aCx"),
Argument("JS::Handle<JSObject*>", "aCallback"),
Argument("JS::Handle<JSObject*>", "aCallbackGlobal"),
Argument("nsIGlobalObject*", "aIncumbentGlobal")],
bodyInHeader=True,
visibility="public",
explicit=True,
baseConstructors=[
"%s(aCx, aCallback, aIncumbentGlobal)" % self.baseName,
"%s(aCx, aCallback, aCallbackGlobal, aIncumbentGlobal)" %
self.baseName,
],
body=body),
ClassConstructor(
[Argument("JS::Handle<JSObject*>", "aCallback"),
[Argument("JSObject*", "aCallback"),
Argument("JSObject*", "aCallbackGlobal"),
Argument("const FastCallbackConstructor&", "")],
bodyInHeader=True,
visibility="public",
explicit=True,
baseConstructors=[
"%s(aCallback, FastCallbackConstructor())" % self.baseName,
"%s(aCallback, aCallbackGlobal, FastCallbackConstructor())" %
self.baseName,
],
body=body),
ClassConstructor(
[Argument("JS::Handle<JSObject*>", "aCallback"),
Argument("JS::Handle<JSObject*>", "aAsyncStack"),
[Argument("JSObject*", "aCallback"),
Argument("JSObject*", "aCallbackGlobal"),
Argument("JSObject*", "aAsyncStack"),
Argument("nsIGlobalObject*", "aIncumbentGlobal")],
bodyInHeader=True,
visibility="public",
explicit=True,
baseConstructors=[
"%s(aCallback, aAsyncStack, aIncumbentGlobal)" % self.baseName,
"%s(aCallback, aCallbackGlobal, aAsyncStack, aIncumbentGlobal)" %
self.baseName,
],
body=body)]
@ -15591,12 +15609,13 @@ class CGFastCallback(CGClass):
self._deps = idlObject.getDeps()
baseName = idlObject.identifier.name
constructor = ClassConstructor(
[Argument("JS::Handle<JSObject*>", "aCallback")],
[Argument("JSObject*", "aCallback"),
Argument("JSObject*", "aCallbackGlobal")],
bodyInHeader=True,
visibility="public",
explicit=True,
baseConstructors=[
"%s(aCallback, FastCallbackConstructor())" %
"%s(aCallback, aCallbackGlobal, FastCallbackConstructor())" %
baseName,
],
body="")

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

@ -17,8 +17,9 @@ class TestCImplementedInterface : public TestJSImplInterface
{
public:
TestCImplementedInterface(JS::Handle<JSObject*> aJSImpl,
JS::Handle<JSObject*> aJSImplGlobal,
nsIGlobalObject* aParent)
: TestJSImplInterface(aJSImpl, aParent)
: TestJSImplInterface(aJSImpl, aJSImplGlobal, aParent)
{}
};

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

@ -1054,17 +1054,27 @@ EventListenerManager::CompileEventHandlerInternal(Listener* aListener,
NS_ENSURE_SUCCESS(result, result);
NS_ENSURE_TRUE(handler, NS_ERROR_FAILURE);
MOZ_ASSERT(js::IsObjectInContextCompartment(handler, cx));
JS::Rooted<JSObject*> handlerGlobal(cx, JS::CurrentGlobalOrNull(cx));
if (jsEventHandler->EventName() == nsGkAtoms::onerror && win) {
RefPtr<OnErrorEventHandlerNonNull> handlerCallback =
new OnErrorEventHandlerNonNull(nullptr, handler, /* aIncumbentGlobal = */ nullptr);
new OnErrorEventHandlerNonNull(static_cast<JSContext*>(nullptr), handler,
handlerGlobal,
/* aIncumbentGlobal = */ nullptr);
jsEventHandler->SetHandler(handlerCallback);
} else if (jsEventHandler->EventName() == nsGkAtoms::onbeforeunload && win) {
RefPtr<OnBeforeUnloadEventHandlerNonNull> handlerCallback =
new OnBeforeUnloadEventHandlerNonNull(nullptr, handler, /* aIncumbentGlobal = */ nullptr);
new OnBeforeUnloadEventHandlerNonNull(static_cast<JSContext*>(nullptr),
handler,
handlerGlobal,
/* aIncumbentGlobal = */ nullptr);
jsEventHandler->SetHandler(handlerCallback);
} else {
RefPtr<EventHandlerNonNull> handlerCallback =
new EventHandlerNonNull(nullptr, handler, /* aIncumbentGlobal = */ nullptr);
new EventHandlerNonNull(static_cast<JSContext*>(nullptr), handler,
handlerGlobal,
/* aIncumbentGlobal = */ nullptr);
jsEventHandler->SetHandler(handlerCallback);
}

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

@ -291,8 +291,9 @@ ToEventListener(JSContext* aCx, JS::Handle<JS::Value> aValue)
}
JS::Rooted<JSObject*> obj(aCx, &aValue.toObject());
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
RefPtr<EventListener> listener =
new EventListener(aCx, obj, GetIncumbentGlobal());
new EventListener(aCx, obj, global, GetIncumbentGlobal());
return listener.forget();
}

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

@ -377,7 +377,9 @@ nsXBLPrototypeHandler::ExecuteHandler(EventTarget* aTarget,
NS_ENSURE_TRUE(bound, NS_ERROR_FAILURE);
RefPtr<EventHandlerNonNull> handlerCallback =
new EventHandlerNonNull(nullptr, bound, /* aIncumbentGlobal = */ nullptr);
new EventHandlerNonNull(static_cast<JSContext*>(nullptr), bound,
scopeObject,
/* aIncumbentGlobal = */ nullptr);
TypedEventHandler typedHandler(handlerCallback);

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

@ -131,8 +131,9 @@ nsSessionStoreUtils::AddDynamicFrameFilteredListener(EventTarget* aTarget,
NS_ENSURE_TRUE(aTarget, NS_ERROR_NO_INTERFACE);
JS::Rooted<JSObject*> obj(aCx, &aListener.toObject());
JS::Rooted<JSObject*> global(aCx, JS::CurrentGlobalOrNull(aCx));
RefPtr<EventListener> listener =
new EventListener(aCx, obj, GetIncumbentGlobal());
new EventListener(aCx, obj, global, GetIncumbentGlobal());
nsCOMPtr<nsIDOMEventListener> filter(new DynamicFrameEventFilter(listener));

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

@ -205,10 +205,12 @@ class PromiseJobRunnable final : public MicroTaskRunnable
{
public:
PromiseJobRunnable(JS::HandleObject aCallback,
JS::HandleObject aCallbackGlobal,
JS::HandleObject aAllocationSite,
nsIGlobalObject* aIncumbentGlobal)
:mCallback(
new PromiseJobCallback(aCallback, aAllocationSite, aIncumbentGlobal))
new PromiseJobCallback(aCallback, aCallbackGlobal, aAllocationSite,
aIncumbentGlobal))
{
MOZ_ASSERT(js::IsFunctionObject(aCallback));
}
@ -266,7 +268,10 @@ CycleCollectedJSContext::EnqueuePromiseJobCallback(JSContext* aCx,
if (aIncumbentGlobal) {
global = xpc::NativeGlobal(aIncumbentGlobal);
}
RefPtr<MicroTaskRunnable> runnable = new PromiseJobRunnable(aJob, aAllocationSite, global);
JS::RootedObject jobGlobal(aCx, JS::CurrentGlobalOrNull(aCx));
RefPtr<MicroTaskRunnable> runnable = new PromiseJobRunnable(aJob, jobGlobal,
aAllocationSite,
global);
self->DispatchToMicroTask(runnable.forget());
return true;
}