mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1005978 - Add infrastructure to create main-thread WebIDL globals with XPConnect. r=bz.
--HG-- extra : rebase_source : 08c6f04e050bdd801a15883bb57d21ff93626024
This commit is contained in:
parent
3edcf39e96
commit
36aecd43e6
@ -2221,7 +2221,7 @@ CreateNativeGlobalForInner(JSContext* aCx,
|
|||||||
|
|
||||||
if (aNewInner->IsDOMBinding()) {
|
if (aNewInner->IsDOMBinding()) {
|
||||||
aGlobal.set(WindowBinding::Wrap(aCx, aNewInner, aNewInner, options,
|
aGlobal.set(WindowBinding::Wrap(aCx, aNewInner, aNewInner, options,
|
||||||
nsJSPrincipals::get(aPrincipal)));
|
nsJSPrincipals::get(aPrincipal), false));
|
||||||
if (!aGlobal || !xpc::InitGlobalObject(aCx, aGlobal, flags)) {
|
if (!aGlobal || !xpc::InitGlobalObject(aCx, aGlobal, flags)) {
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
|
@ -2197,12 +2197,15 @@ IsInCertifiedApp(JSContext* aCx, JSObject* aObj)
|
|||||||
Preferences::GetBool("dom.ignore_webidl_scope_checks", false);
|
Preferences::GetBool("dom.ignore_webidl_scope_checks", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
void
|
void
|
||||||
TraceGlobal(JSTracer* aTrc, JSObject* aObj)
|
VerifyTraceProtoAndIfaceCacheCalled(JSTracer *trc, void **thingp,
|
||||||
|
JSGCTraceKind kind)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(js::GetObjectClass(aObj)->flags & JSCLASS_DOM_GLOBAL);
|
// We don't do anything here, we only want to verify that
|
||||||
mozilla::dom::TraceProtoAndIfaceCache(aTrc, aObj);
|
// TraceProtoAndIfaceCache was called.
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
FinalizeGlobal(JSFreeOp* aFreeOp, JSObject* aObj)
|
FinalizeGlobal(JSFreeOp* aFreeOp, JSObject* aObj)
|
||||||
@ -2410,5 +2413,21 @@ ConvertExceptionToPromise(JSContext* cx,
|
|||||||
return WrapNewBindingObject(cx, promise, rval);
|
return WrapNewBindingObject(cx, promise, rval);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
void
|
||||||
|
CreateGlobalOptions<nsGlobalWindow>::TraceGlobal(JSTracer* aTrc, JSObject* aObj)
|
||||||
|
{
|
||||||
|
mozilla::dom::TraceProtoAndIfaceCache(aTrc, aObj);
|
||||||
|
xpc::GetCompartmentPrivate(aObj)->scope->TraceSelf(aTrc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */
|
||||||
|
bool
|
||||||
|
CreateGlobalOptions<nsGlobalWindow>::PostCreateGlobal(JSContext* aCx,
|
||||||
|
JS::Handle<JSObject*> aGlobal)
|
||||||
|
{
|
||||||
|
return XPCWrappedNativeScope::GetNewOrUsed(aCx, aGlobal);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace dom
|
} // namespace dom
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
@ -483,11 +483,35 @@ AllocateProtoAndIfaceCache(JSObject* obj, ProtoAndIfaceCache::Kind aKind)
|
|||||||
JS::PrivateValue(protoAndIfaceCache));
|
JS::PrivateValue(protoAndIfaceCache));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
void
|
||||||
|
VerifyTraceProtoAndIfaceCacheCalled(JSTracer *trc, void **thingp,
|
||||||
|
JSGCTraceKind kind);
|
||||||
|
|
||||||
|
struct VerifyTraceProtoAndIfaceCacheCalledTracer : public JSTracer
|
||||||
|
{
|
||||||
|
bool ok;
|
||||||
|
|
||||||
|
VerifyTraceProtoAndIfaceCacheCalledTracer(JSRuntime *rt)
|
||||||
|
: JSTracer(rt, VerifyTraceProtoAndIfaceCacheCalled), ok(false)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
inline void
|
inline void
|
||||||
TraceProtoAndIfaceCache(JSTracer* trc, JSObject* obj)
|
TraceProtoAndIfaceCache(JSTracer* trc, JSObject* obj)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL);
|
MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL);
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (trc->callback == VerifyTraceProtoAndIfaceCacheCalled) {
|
||||||
|
// We don't do anything here, we only want to verify that
|
||||||
|
// TraceProtoAndIfaceCache was called.
|
||||||
|
static_cast<VerifyTraceProtoAndIfaceCacheCalledTracer*>(trc)->ok = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!HasProtoAndIfaceCache(obj))
|
if (!HasProtoAndIfaceCache(obj))
|
||||||
return;
|
return;
|
||||||
ProtoAndIfaceCache* protoAndIfaceCache = GetProtoAndIfaceCache(obj);
|
ProtoAndIfaceCache* protoAndIfaceCache = GetProtoAndIfaceCache(obj);
|
||||||
@ -2562,9 +2586,6 @@ IsInPrivilegedApp(JSContext* aCx, JSObject* aObj);
|
|||||||
bool
|
bool
|
||||||
IsInCertifiedApp(JSContext* aCx, JSObject* aObj);
|
IsInCertifiedApp(JSContext* aCx, JSObject* aObj);
|
||||||
|
|
||||||
void
|
|
||||||
TraceGlobal(JSTracer* aTrc, JSObject* aObj);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FinalizeGlobal(JSFreeOp* aFop, JSObject* aObj);
|
FinalizeGlobal(JSFreeOp* aFop, JSObject* aObj);
|
||||||
|
|
||||||
@ -2575,55 +2596,86 @@ ResolveGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj,
|
|||||||
bool
|
bool
|
||||||
EnumerateGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj);
|
EnumerateGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj);
|
||||||
|
|
||||||
template <class T, JS::Handle<JSObject*> (*ProtoGetter)(JSContext*,
|
template <class T>
|
||||||
JS::Handle<JSObject*>)>
|
struct CreateGlobalOptions
|
||||||
JSObject*
|
|
||||||
CreateGlobal(JSContext* aCx, T* aObject, nsWrapperCache* aCache,
|
|
||||||
const JSClass* aClass, JS::CompartmentOptions& aOptions,
|
|
||||||
JSPrincipals* aPrincipal)
|
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(!NS_IsMainThread());
|
static MOZ_CONSTEXPR_VAR ProtoAndIfaceCache::Kind ProtoAndIfaceCacheKind =
|
||||||
|
ProtoAndIfaceCache::NonWindowLike;
|
||||||
|
// Intl API is broken and makes JS_InitStandardClasses fail intermittently,
|
||||||
|
// see bug 934889.
|
||||||
|
static MOZ_CONSTEXPR_VAR bool ForceInitStandardClassesToFalse = true;
|
||||||
|
static void TraceGlobal(JSTracer* aTrc, JSObject* aObj)
|
||||||
|
{
|
||||||
|
mozilla::dom::TraceProtoAndIfaceCache(aTrc, aObj);
|
||||||
|
}
|
||||||
|
static bool PostCreateGlobal(JSContext* aCx, JS::Handle<JSObject*> aGlobal)
|
||||||
|
{
|
||||||
|
MOZ_ALWAYS_TRUE(TryPreserveWrapper(aGlobal));
|
||||||
|
|
||||||
aOptions.setTrace(TraceGlobal);
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
JS::Rooted<JSObject*> global(aCx,
|
template <>
|
||||||
JS_NewGlobalObject(aCx, aClass, aPrincipal, JS::DontFireOnNewGlobalHook,
|
struct CreateGlobalOptions<nsGlobalWindow>
|
||||||
aOptions));
|
{
|
||||||
if (!global) {
|
static MOZ_CONSTEXPR_VAR ProtoAndIfaceCache::Kind ProtoAndIfaceCacheKind =
|
||||||
|
ProtoAndIfaceCache::WindowLike;
|
||||||
|
static MOZ_CONSTEXPR_VAR bool ForceInitStandardClassesToFalse = false;
|
||||||
|
static void TraceGlobal(JSTracer* aTrc, JSObject* aObj);
|
||||||
|
static bool PostCreateGlobal(JSContext* aCx, JS::Handle<JSObject*> aGlobal);
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T, ProtoGetter GetProto>
|
||||||
|
bool
|
||||||
|
CreateGlobal(JSContext* aCx, T* aNative, nsWrapperCache* aCache,
|
||||||
|
const JSClass* aClass, JS::CompartmentOptions& aOptions,
|
||||||
|
JSPrincipals* aPrincipal, bool aInitStandardClasses,
|
||||||
|
JS::MutableHandle<JSObject*> aGlobal)
|
||||||
|
{
|
||||||
|
aOptions.setTrace(CreateGlobalOptions<T>::TraceGlobal);
|
||||||
|
|
||||||
|
aGlobal.set(JS_NewGlobalObject(aCx, aClass, aPrincipal,
|
||||||
|
JS::DontFireOnNewGlobalHook, aOptions));
|
||||||
|
if (!aGlobal) {
|
||||||
NS_WARNING("Failed to create global");
|
NS_WARNING("Failed to create global");
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSAutoCompartment ac(aCx, global);
|
JSAutoCompartment ac(aCx, aGlobal);
|
||||||
|
|
||||||
dom::AllocateProtoAndIfaceCache(global, ProtoAndIfaceCache::WindowLike);
|
{
|
||||||
|
JS::AutoAssertNoGC nogc;
|
||||||
|
|
||||||
js::SetReservedSlot(global, DOM_OBJECT_SLOT, PRIVATE_TO_JSVAL(aObject));
|
// The setup of our global needs to be done before a GC happens.
|
||||||
NS_ADDREF(aObject);
|
js::SetReservedSlot(aGlobal, DOM_OBJECT_SLOT, PRIVATE_TO_JSVAL(aNative));
|
||||||
|
NS_ADDREF(aNative);
|
||||||
|
|
||||||
aCache->SetIsDOMBinding();
|
aCache->SetIsDOMBinding();
|
||||||
aCache->SetWrapper(global);
|
aCache->SetWrapper(aGlobal);
|
||||||
|
|
||||||
/* Intl API is broken and makes this fail intermittently, see bug 934889.
|
dom::AllocateProtoAndIfaceCache(aGlobal,
|
||||||
if (!JS_InitStandardClasses(aCx, global)) {
|
CreateGlobalOptions<T>::ProtoAndIfaceCacheKind);
|
||||||
|
|
||||||
|
if (!CreateGlobalOptions<T>::PostCreateGlobal(aCx, aGlobal)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aInitStandardClasses &&
|
||||||
|
!CreateGlobalOptions<T>::ForceInitStandardClassesToFalse &&
|
||||||
|
!JS_InitStandardClasses(aCx, aGlobal)) {
|
||||||
NS_WARNING("Failed to init standard classes");
|
NS_WARNING("Failed to init standard classes");
|
||||||
return nullptr;
|
return false;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
JS::Handle<JSObject*> proto = ProtoGetter(aCx, global);
|
JS::Handle<JSObject*> proto = GetProto(aCx, aGlobal);
|
||||||
NS_ENSURE_TRUE(proto, nullptr);
|
if (!proto || !JS_SplicePrototype(aCx, aGlobal, proto)) {
|
||||||
|
|
||||||
if (!JS_SetPrototype(aCx, global, proto)) {
|
|
||||||
NS_WARNING("Failed to set proto");
|
NS_WARNING("Failed to set proto");
|
||||||
return nullptr;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ALWAYS_TRUE(TryPreserveWrapper(global));
|
return true;
|
||||||
|
|
||||||
MOZ_ASSERT(UnwrapDOMObjectToISupports(global));
|
|
||||||
|
|
||||||
return global;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2961,7 +2961,8 @@ class CGWrapGlobalMethod(CGAbstractMethod):
|
|||||||
Argument(descriptor.nativeType + '*', 'aObject'),
|
Argument(descriptor.nativeType + '*', 'aObject'),
|
||||||
Argument('nsWrapperCache*', 'aCache'),
|
Argument('nsWrapperCache*', 'aCache'),
|
||||||
Argument('JS::CompartmentOptions&', 'aOptions'),
|
Argument('JS::CompartmentOptions&', 'aOptions'),
|
||||||
Argument('JSPrincipals*', 'aPrincipal')]
|
Argument('JSPrincipals*', 'aPrincipal'),
|
||||||
|
Argument('bool', 'aInitStandardClasses')]
|
||||||
CGAbstractMethod.__init__(self, descriptor, 'Wrap', 'JSObject*', args)
|
CGAbstractMethod.__init__(self, descriptor, 'Wrap', 'JSObject*', args)
|
||||||
self.descriptor = descriptor
|
self.descriptor = descriptor
|
||||||
self.properties = properties
|
self.properties = properties
|
||||||
@ -2976,6 +2977,13 @@ class CGWrapGlobalMethod(CGAbstractMethod):
|
|||||||
else:
|
else:
|
||||||
chromeProperties = "nullptr"
|
chromeProperties = "nullptr"
|
||||||
|
|
||||||
|
if self.descriptor.workers:
|
||||||
|
fireOnNewGlobal = """// XXXkhuey can't do this yet until workers can lazy resolve.
|
||||||
|
// JS_FireOnNewGlobalObject(aCx, obj);
|
||||||
|
"""
|
||||||
|
else:
|
||||||
|
fireOnNewGlobal = ""
|
||||||
|
|
||||||
return fill(
|
return fill(
|
||||||
"""
|
"""
|
||||||
${assertions}
|
${assertions}
|
||||||
@ -2983,12 +2991,17 @@ class CGWrapGlobalMethod(CGAbstractMethod):
|
|||||||
"nsISupports must be on our primary inheritance chain");
|
"nsISupports must be on our primary inheritance chain");
|
||||||
|
|
||||||
JS::Rooted<JSObject*> obj(aCx);
|
JS::Rooted<JSObject*> obj(aCx);
|
||||||
obj = CreateGlobal<${nativeType}, GetProtoObject>(aCx,
|
CreateGlobal<${nativeType}, GetProtoObject>(aCx,
|
||||||
aObject,
|
aObject,
|
||||||
aCache,
|
aCache,
|
||||||
Class.ToJSClass(),
|
Class.ToJSClass(),
|
||||||
aOptions,
|
aOptions,
|
||||||
aPrincipal);
|
aPrincipal,
|
||||||
|
aInitStandardClasses,
|
||||||
|
&obj);
|
||||||
|
if (!obj) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// obj is a new global, so has a new compartment. Enter it
|
// obj is a new global, so has a new compartment. Enter it
|
||||||
// before doing anything with it.
|
// before doing anything with it.
|
||||||
@ -3000,9 +3013,7 @@ class CGWrapGlobalMethod(CGAbstractMethod):
|
|||||||
$*{unforgeable}
|
$*{unforgeable}
|
||||||
|
|
||||||
$*{slots}
|
$*{slots}
|
||||||
|
$*{fireOnNewGlobal}
|
||||||
// XXXkhuey can't do this yet until workers can lazy resolve.
|
|
||||||
// JS_FireOnNewGlobalObject(aCx, obj);
|
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
""",
|
""",
|
||||||
@ -3011,7 +3022,8 @@ class CGWrapGlobalMethod(CGAbstractMethod):
|
|||||||
properties=properties,
|
properties=properties,
|
||||||
chromeProperties=chromeProperties,
|
chromeProperties=chromeProperties,
|
||||||
unforgeable=InitUnforgeableProperties(self.descriptor, self.properties),
|
unforgeable=InitUnforgeableProperties(self.descriptor, self.properties),
|
||||||
slots=InitMemberSlots(self.descriptor, True))
|
slots=InitMemberSlots(self.descriptor, True),
|
||||||
|
fireOnNewGlobal=fireOnNewGlobal)
|
||||||
|
|
||||||
|
|
||||||
class CGUpdateMemberSlotsMethod(CGAbstractStaticMethod):
|
class CGUpdateMemberSlotsMethod(CGAbstractStaticMethod):
|
||||||
|
@ -299,7 +299,8 @@ DedicatedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx)
|
|||||||
|
|
||||||
return DedicatedWorkerGlobalScopeBinding_workers::Wrap(aCx, this, this,
|
return DedicatedWorkerGlobalScopeBinding_workers::Wrap(aCx, this, this,
|
||||||
options,
|
options,
|
||||||
GetWorkerPrincipal());
|
GetWorkerPrincipal(),
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -336,7 +337,8 @@ SharedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx)
|
|||||||
mWorkerPrivate->CopyJSCompartmentOptions(options);
|
mWorkerPrivate->CopyJSCompartmentOptions(options);
|
||||||
|
|
||||||
return SharedWorkerGlobalScopeBinding_workers::Wrap(aCx, this, this, options,
|
return SharedWorkerGlobalScopeBinding_workers::Wrap(aCx, this, this, options,
|
||||||
GetWorkerPrincipal());
|
GetWorkerPrincipal(),
|
||||||
|
true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
@ -78,8 +78,10 @@ XPCWrappedNativeScope::XPCWrappedNativeScope(JSContext *cx,
|
|||||||
// add ourselves to the scopes list
|
// add ourselves to the scopes list
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(aGlobal);
|
MOZ_ASSERT(aGlobal);
|
||||||
MOZ_ASSERT(js::GetObjectClass(aGlobal)->flags & (JSCLASS_PRIVATE_IS_NSISUPPORTS |
|
DebugOnly<const js::Class*> clasp = js::GetObjectClass(aGlobal);
|
||||||
JSCLASS_HAS_PRIVATE));
|
MOZ_ASSERT(clasp->flags & (JSCLASS_PRIVATE_IS_NSISUPPORTS |
|
||||||
|
JSCLASS_HAS_PRIVATE) ||
|
||||||
|
IsDOMClass(clasp));
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext)
|
for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext)
|
||||||
MOZ_ASSERT(aGlobal != cur->GetGlobalJSObjectPreserveColor(), "dup object");
|
MOZ_ASSERT(aGlobal != cur->GetGlobalJSObjectPreserveColor(), "dup object");
|
||||||
|
@ -328,36 +328,9 @@ nsXPConnect::InitClasses(JSContext * aJSContext, JSObject * aGlobalJSObj)
|
|||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
static void
|
|
||||||
VerifyTraceXPCGlobalCalled(JSTracer *trc, void **thingp, JSGCTraceKind kind)
|
|
||||||
{
|
|
||||||
// We don't do anything here, we only want to verify that TraceXPCGlobal
|
|
||||||
// was called.
|
|
||||||
}
|
|
||||||
|
|
||||||
struct VerifyTraceXPCGlobalCalledTracer : public JSTracer
|
|
||||||
{
|
|
||||||
bool ok;
|
|
||||||
|
|
||||||
VerifyTraceXPCGlobalCalledTracer(JSRuntime *rt)
|
|
||||||
: JSTracer(rt, VerifyTraceXPCGlobalCalled), ok(false)
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
void
|
||||||
TraceXPCGlobal(JSTracer *trc, JSObject *obj)
|
TraceXPCGlobal(JSTracer *trc, JSObject *obj)
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
|
||||||
if (trc->callback == VerifyTraceXPCGlobalCalled) {
|
|
||||||
// We don't do anything here, we only want to verify that TraceXPCGlobal
|
|
||||||
// was called.
|
|
||||||
reinterpret_cast<VerifyTraceXPCGlobalCalledTracer*>(trc)->ok = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL)
|
if (js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL)
|
||||||
mozilla::dom::TraceProtoAndIfaceCache(trc, obj);
|
mozilla::dom::TraceProtoAndIfaceCache(trc, obj);
|
||||||
}
|
}
|
||||||
@ -388,7 +361,7 @@ CreateGlobalObject(JSContext *cx, const JSClass *clasp, nsIPrincipal *principal,
|
|||||||
// more complicated. Manual inspection shows that they do the right thing.
|
// more complicated. Manual inspection shows that they do the right thing.
|
||||||
if (!((const js::Class*)clasp)->ext.isWrappedNative)
|
if (!((const js::Class*)clasp)->ext.isWrappedNative)
|
||||||
{
|
{
|
||||||
VerifyTraceXPCGlobalCalledTracer trc(JS_GetRuntime(cx));
|
VerifyTraceProtoAndIfaceCacheCalledTracer trc(JS_GetRuntime(cx));
|
||||||
JS_TraceChildren(&trc, global, JSTRACE_OBJECT);
|
JS_TraceChildren(&trc, global, JSTRACE_OBJECT);
|
||||||
MOZ_ASSERT(trc.ok, "Trace hook on global needs to call TraceXPCGlobal for XPConnect compartments.");
|
MOZ_ASSERT(trc.ok, "Trace hook on global needs to call TraceXPCGlobal for XPConnect compartments.");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user