From 4e0c34d1c3e2b5b80f6521d294e6b3d936a1757b Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Tue, 23 May 2017 16:35:31 -0500 Subject: [PATCH] Bug 1363200 - JSAPI for realms: JS::SetDestroyRealmCallback. r=sfink --HG-- extra : rebase_source : ad62e332bab6c31db2c98581163b1ca5fe8103f0 extra : intermediate-source : 0f72e0175f55a309ea4bc70240347e6659174af4 extra : source : ac9c7e04c174c8b2e4ca0e533a8a2838d293f700 --- js/public/Realm.h | 20 ++++++++++++++++++++ js/public/TypeDecls.h | 1 + js/src/jsapi.cpp | 6 ------ js/src/jsapi.h | 6 ------ js/src/jsgc.cpp | 2 ++ js/src/vm/Realm.cpp | 12 ++++++++++++ js/src/vm/Runtime.cpp | 1 + js/src/vm/Runtime.h | 5 ++++- js/xpconnect/src/XPCJSRuntime.cpp | 4 ++-- 9 files changed, 42 insertions(+), 15 deletions(-) diff --git a/js/public/Realm.h b/js/public/Realm.h index f9316b23a606..0585ea82c77c 100644 --- a/js/public/Realm.h +++ b/js/public/Realm.h @@ -69,6 +69,26 @@ GetRealmPrivate(Realm* realm); extern JS_PUBLIC_API(void) SetRealmPrivate(Realm* realm, void* data); +typedef void +(* DestroyRealmCallback)(JSFreeOp* fop, Realm* realm); + +// Set the callback SpiderMonkey calls just before garbage-collecting a realm. +// Embeddings can use this callback to free private data associated with the +// realm via SetRealmPrivate. +// +// By the time this is called, the global object for the realm has already been +// collected. +extern JS_PUBLIC_API(void) +SetDestroyRealmCallback(JSContext* cx, DestroyRealmCallback callback); + +typedef void +(* RealmNameCallback)(JSContext* cx, Handle realm, char* buf, size_t bufsize); + +// Set the callback SpiderMonkey calls to get the name of a realm, for +// diagnostic output. +extern JS_PUBLIC_API(void) +SetRealmNameCallback(JSContext* cx, RealmNameCallback callback); + extern JS_PUBLIC_API(JSObject*) GetRealmObjectPrototype(JSContext* cx); diff --git a/js/public/TypeDecls.h b/js/public/TypeDecls.h index 89c789598e04..cc8408da7198 100644 --- a/js/public/TypeDecls.h +++ b/js/public/TypeDecls.h @@ -28,6 +28,7 @@ class JSObject; class JSScript; class JSString; class JSAddonId; +struct JSFreeOp; struct jsid; diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index ea5a7d6df66a..0cb0533a77dd 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -683,12 +683,6 @@ JS_SetCompartmentNameCallback(JSContext* cx, JSCompartmentNameCallback callback) cx->runtime()->compartmentNameCallback = callback; } -JS_PUBLIC_API(void) -JS_SetRealmNameCallback(JSContext* cx, JSRealmNameCallback callback) -{ - cx->runtime()->realmNameCallback = callback; -} - JS_PUBLIC_API(void) JS_SetWrapObjectCallbacks(JSContext* cx, const JSWrapObjectCallbacks* callbacks) { diff --git a/js/src/jsapi.h b/js/src/jsapi.h index 92754a3ae796..22285b388688 100644 --- a/js/src/jsapi.h +++ b/js/src/jsapi.h @@ -716,9 +716,6 @@ typedef void (* JSCompartmentNameCallback)(JSContext* cx, JSCompartment* compartment, char* buf, size_t bufsize); -typedef void -(* JSRealmNameCallback)(JSContext* cx, JS::Handle realm, char* buf, size_t bufsize); - /** * Callback used by memory reporting to ask the embedder how much memory an * external string is keeping alive. The embedder is expected to return a value @@ -1371,9 +1368,6 @@ JS_SetSizeOfIncludingThisCompartmentCallback(JSContext* cx, extern JS_PUBLIC_API(void) JS_SetCompartmentNameCallback(JSContext* cx, JSCompartmentNameCallback callback); -extern JS_PUBLIC_API(void) -JS_SetRealmNameCallback(JSContext* cx, JSRealmNameCallback callback); - extern JS_PUBLIC_API(void) JS_SetWrapObjectCallbacks(JSContext* cx, const JSWrapObjectCallbacks* callbacks); diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 0f0e8ce5ee26..75d6e1a03a2d 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -3444,6 +3444,8 @@ void JSCompartment::destroy(FreeOp* fop) { JSRuntime* rt = fop->runtime(); + if (auto callback = rt->destroyRealmCallback) + callback(fop, JS::GetRealmForCompartment(this)); if (auto callback = rt->destroyCompartmentCallback) callback(fop, this); if (principals()) diff --git a/js/src/vm/Realm.cpp b/js/src/vm/Realm.cpp index dc5f78a7b4db..04b51868c968 100644 --- a/js/src/vm/Realm.cpp +++ b/js/src/vm/Realm.cpp @@ -46,6 +46,18 @@ JS::SetRealmPrivate(JS::Realm* realm, void* data) GetCompartmentForRealm(realm)->realmData = data; } +JS_PUBLIC_API(void) +JS::SetDestroyRealmCallback(JSContext* cx, JS::DestroyRealmCallback callback) +{ + cx->runtime()->destroyRealmCallback = callback; +} + +JS_PUBLIC_API(void) +JS::SetRealmNameCallback(JSContext* cx, JS::RealmNameCallback callback) +{ + cx->runtime()->realmNameCallback = callback; +} + JS_PUBLIC_API(JSObject*) JS::GetRealmObjectPrototype(JSContext* cx) { diff --git a/js/src/vm/Runtime.cpp b/js/src/vm/Runtime.cpp index df986bac5982..f95de16225db 100644 --- a/js/src/vm/Runtime.cpp +++ b/js/src/vm/Runtime.cpp @@ -119,6 +119,7 @@ JSRuntime::JSRuntime(JSRuntime* parentRuntime) destroyCompartmentCallback(nullptr), sizeOfIncludingThisCompartmentCallback(nullptr), compartmentNameCallback(nullptr), + destroyRealmCallback(nullptr), realmNameCallback(nullptr), externalStringSizeofCallback(nullptr), securityCallbacks(&NullSecurityCallbacks), diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h index 4056712ae48d..a0189b801451 100644 --- a/js/src/vm/Runtime.h +++ b/js/src/vm/Runtime.h @@ -501,8 +501,11 @@ struct JSRuntime : public js::MallocProvider /* Call this to get the name of a compartment. */ js::ActiveThreadData compartmentNameCallback; + /* Realm destroy callback. */ + js::ActiveThreadData destroyRealmCallback; + /* Call this to get the name of a realm. */ - js::ActiveThreadData realmNameCallback; + js::ActiveThreadData realmNameCallback; /* Callback for doing memory reporting on external strings. */ js::ActiveThreadData externalStringSizeofCallback; diff --git a/js/xpconnect/src/XPCJSRuntime.cpp b/js/xpconnect/src/XPCJSRuntime.cpp index c48c7d48b29a..afa0a3e23e13 100644 --- a/js/xpconnect/src/XPCJSRuntime.cpp +++ b/js/xpconnect/src/XPCJSRuntime.cpp @@ -2664,7 +2664,7 @@ CompartmentNameCallback(JSContext* cx, JSCompartment* comp, } static void -RealmNameCallback(JSContext* cx, JS::Handle realm, char* buf, size_t bufsize) +GetRealmName(JSContext* cx, JS::Handle realm, char* buf, size_t bufsize) { JSCompartment* comp = JS::GetCompartmentForRealm(realm); CompartmentNameCallback(cx, comp, buf, bufsize); @@ -2841,7 +2841,7 @@ XPCJSRuntime::Initialize(JSContext* cx) JS_SetDestroyCompartmentCallback(cx, CompartmentDestroyedCallback); JS_SetSizeOfIncludingThisCompartmentCallback(cx, CompartmentSizeOfIncludingThisCallback); JS_SetCompartmentNameCallback(cx, CompartmentNameCallback); - JS_SetRealmNameCallback(cx, RealmNameCallback); + JS::SetRealmNameCallback(cx, GetRealmName); mPrevGCSliceCallback = JS::SetGCSliceCallback(cx, GCSliceCallback); mPrevDoCycleCollectionCallback = JS::SetDoCycleCollectionCallback(cx, DoCycleCollectionCallback);