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
e66849dff6
commit
8119bfc066
@ -2221,7 +2221,7 @@ CreateNativeGlobalForInner(JSContext* aCx,
|
||||
|
||||
if (aNewInner->IsDOMBinding()) {
|
||||
aGlobal.set(WindowBinding::Wrap(aCx, aNewInner, aNewInner, options,
|
||||
nsJSPrincipals::get(aPrincipal)));
|
||||
nsJSPrincipals::get(aPrincipal), false));
|
||||
if (!aGlobal || !xpc::InitGlobalObject(aCx, aGlobal, flags)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
@ -2197,12 +2197,15 @@ IsInCertifiedApp(JSContext* aCx, JSObject* aObj)
|
||||
Preferences::GetBool("dom.ignore_webidl_scope_checks", false);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
void
|
||||
TraceGlobal(JSTracer* aTrc, JSObject* aObj)
|
||||
VerifyTraceProtoAndIfaceCacheCalled(JSTracer *trc, void **thingp,
|
||||
JSGCTraceKind kind)
|
||||
{
|
||||
MOZ_ASSERT(js::GetObjectClass(aObj)->flags & JSCLASS_DOM_GLOBAL);
|
||||
mozilla::dom::TraceProtoAndIfaceCache(aTrc, aObj);
|
||||
// We don't do anything here, we only want to verify that
|
||||
// TraceProtoAndIfaceCache was called.
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
FinalizeGlobal(JSFreeOp* aFreeOp, JSObject* aObj)
|
||||
@ -2410,5 +2413,21 @@ ConvertExceptionToPromise(JSContext* cx,
|
||||
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 mozilla
|
||||
|
@ -483,11 +483,35 @@ AllocateProtoAndIfaceCache(JSObject* obj, ProtoAndIfaceCache::Kind aKind)
|
||||
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
|
||||
TraceProtoAndIfaceCache(JSTracer* trc, JSObject* obj)
|
||||
{
|
||||
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))
|
||||
return;
|
||||
ProtoAndIfaceCache* protoAndIfaceCache = GetProtoAndIfaceCache(obj);
|
||||
@ -2562,9 +2586,6 @@ IsInPrivilegedApp(JSContext* aCx, JSObject* aObj);
|
||||
bool
|
||||
IsInCertifiedApp(JSContext* aCx, JSObject* aObj);
|
||||
|
||||
void
|
||||
TraceGlobal(JSTracer* aTrc, JSObject* aObj);
|
||||
|
||||
void
|
||||
FinalizeGlobal(JSFreeOp* aFop, JSObject* aObj);
|
||||
|
||||
@ -2575,55 +2596,86 @@ ResolveGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj,
|
||||
bool
|
||||
EnumerateGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj);
|
||||
|
||||
template <class T, JS::Handle<JSObject*> (*ProtoGetter)(JSContext*,
|
||||
JS::Handle<JSObject*>)>
|
||||
JSObject*
|
||||
CreateGlobal(JSContext* aCx, T* aObject, nsWrapperCache* aCache,
|
||||
const JSClass* aClass, JS::CompartmentOptions& aOptions,
|
||||
JSPrincipals* aPrincipal)
|
||||
template <class T>
|
||||
struct CreateGlobalOptions
|
||||
{
|
||||
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,
|
||||
JS_NewGlobalObject(aCx, aClass, aPrincipal, JS::DontFireOnNewGlobalHook,
|
||||
aOptions));
|
||||
if (!global) {
|
||||
template <>
|
||||
struct CreateGlobalOptions<nsGlobalWindow>
|
||||
{
|
||||
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");
|
||||
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));
|
||||
NS_ADDREF(aObject);
|
||||
// The setup of our global needs to be done before a GC happens.
|
||||
js::SetReservedSlot(aGlobal, DOM_OBJECT_SLOT, PRIVATE_TO_JSVAL(aNative));
|
||||
NS_ADDREF(aNative);
|
||||
|
||||
aCache->SetIsDOMBinding();
|
||||
aCache->SetWrapper(global);
|
||||
aCache->SetIsDOMBinding();
|
||||
aCache->SetWrapper(aGlobal);
|
||||
|
||||
/* Intl API is broken and makes this fail intermittently, see bug 934889.
|
||||
if (!JS_InitStandardClasses(aCx, global)) {
|
||||
dom::AllocateProtoAndIfaceCache(aGlobal,
|
||||
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");
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
JS::Handle<JSObject*> proto = ProtoGetter(aCx, global);
|
||||
NS_ENSURE_TRUE(proto, nullptr);
|
||||
|
||||
if (!JS_SetPrototype(aCx, global, proto)) {
|
||||
JS::Handle<JSObject*> proto = GetProto(aCx, aGlobal);
|
||||
if (!proto || !JS_SplicePrototype(aCx, aGlobal, proto)) {
|
||||
NS_WARNING("Failed to set proto");
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_TRUE(TryPreserveWrapper(global));
|
||||
|
||||
MOZ_ASSERT(UnwrapDOMObjectToISupports(global));
|
||||
|
||||
return global;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2961,7 +2961,8 @@ class CGWrapGlobalMethod(CGAbstractMethod):
|
||||
Argument(descriptor.nativeType + '*', 'aObject'),
|
||||
Argument('nsWrapperCache*', 'aCache'),
|
||||
Argument('JS::CompartmentOptions&', 'aOptions'),
|
||||
Argument('JSPrincipals*', 'aPrincipal')]
|
||||
Argument('JSPrincipals*', 'aPrincipal'),
|
||||
Argument('bool', 'aInitStandardClasses')]
|
||||
CGAbstractMethod.__init__(self, descriptor, 'Wrap', 'JSObject*', args)
|
||||
self.descriptor = descriptor
|
||||
self.properties = properties
|
||||
@ -2976,6 +2977,13 @@ class CGWrapGlobalMethod(CGAbstractMethod):
|
||||
else:
|
||||
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(
|
||||
"""
|
||||
${assertions}
|
||||
@ -2983,12 +2991,17 @@ class CGWrapGlobalMethod(CGAbstractMethod):
|
||||
"nsISupports must be on our primary inheritance chain");
|
||||
|
||||
JS::Rooted<JSObject*> obj(aCx);
|
||||
obj = CreateGlobal<${nativeType}, GetProtoObject>(aCx,
|
||||
aObject,
|
||||
aCache,
|
||||
Class.ToJSClass(),
|
||||
aOptions,
|
||||
aPrincipal);
|
||||
CreateGlobal<${nativeType}, GetProtoObject>(aCx,
|
||||
aObject,
|
||||
aCache,
|
||||
Class.ToJSClass(),
|
||||
aOptions,
|
||||
aPrincipal,
|
||||
aInitStandardClasses,
|
||||
&obj);
|
||||
if (!obj) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// obj is a new global, so has a new compartment. Enter it
|
||||
// before doing anything with it.
|
||||
@ -3000,9 +3013,7 @@ class CGWrapGlobalMethod(CGAbstractMethod):
|
||||
$*{unforgeable}
|
||||
|
||||
$*{slots}
|
||||
|
||||
// XXXkhuey can't do this yet until workers can lazy resolve.
|
||||
// JS_FireOnNewGlobalObject(aCx, obj);
|
||||
$*{fireOnNewGlobal}
|
||||
|
||||
return obj;
|
||||
""",
|
||||
@ -3011,7 +3022,8 @@ class CGWrapGlobalMethod(CGAbstractMethod):
|
||||
properties=properties,
|
||||
chromeProperties=chromeProperties,
|
||||
unforgeable=InitUnforgeableProperties(self.descriptor, self.properties),
|
||||
slots=InitMemberSlots(self.descriptor, True))
|
||||
slots=InitMemberSlots(self.descriptor, True),
|
||||
fireOnNewGlobal=fireOnNewGlobal)
|
||||
|
||||
|
||||
class CGUpdateMemberSlotsMethod(CGAbstractStaticMethod):
|
||||
|
@ -299,7 +299,8 @@ DedicatedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx)
|
||||
|
||||
return DedicatedWorkerGlobalScopeBinding_workers::Wrap(aCx, this, this,
|
||||
options,
|
||||
GetWorkerPrincipal());
|
||||
GetWorkerPrincipal(),
|
||||
true);
|
||||
}
|
||||
|
||||
void
|
||||
@ -336,7 +337,8 @@ SharedWorkerGlobalScope::WrapGlobalObject(JSContext* aCx)
|
||||
mWorkerPrivate->CopyJSCompartmentOptions(options);
|
||||
|
||||
return SharedWorkerGlobalScopeBinding_workers::Wrap(aCx, this, this, options,
|
||||
GetWorkerPrincipal());
|
||||
GetWorkerPrincipal(),
|
||||
true);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -78,8 +78,10 @@ XPCWrappedNativeScope::XPCWrappedNativeScope(JSContext *cx,
|
||||
// add ourselves to the scopes list
|
||||
{
|
||||
MOZ_ASSERT(aGlobal);
|
||||
MOZ_ASSERT(js::GetObjectClass(aGlobal)->flags & (JSCLASS_PRIVATE_IS_NSISUPPORTS |
|
||||
JSCLASS_HAS_PRIVATE));
|
||||
DebugOnly<const js::Class*> clasp = js::GetObjectClass(aGlobal);
|
||||
MOZ_ASSERT(clasp->flags & (JSCLASS_PRIVATE_IS_NSISUPPORTS |
|
||||
JSCLASS_HAS_PRIVATE) ||
|
||||
IsDOMClass(clasp));
|
||||
#ifdef DEBUG
|
||||
for (XPCWrappedNativeScope* cur = gScopes; cur; cur = cur->mNext)
|
||||
MOZ_ASSERT(aGlobal != cur->GetGlobalJSObjectPreserveColor(), "dup object");
|
||||
|
@ -328,36 +328,9 @@ nsXPConnect::InitClasses(JSContext * aJSContext, JSObject * aGlobalJSObj)
|
||||
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
|
||||
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)
|
||||
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.
|
||||
if (!((const js::Class*)clasp)->ext.isWrappedNative)
|
||||
{
|
||||
VerifyTraceXPCGlobalCalledTracer trc(JS_GetRuntime(cx));
|
||||
VerifyTraceProtoAndIfaceCacheCalledTracer trc(JS_GetRuntime(cx));
|
||||
JS_TraceChildren(&trc, global, JSTRACE_OBJECT);
|
||||
MOZ_ASSERT(trc.ok, "Trace hook on global needs to call TraceXPCGlobal for XPConnect compartments.");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user