Bug 1155946 part 2. Add mayResolve methods to DOM classes with resolve hooks. r=peterv

This commit is contained in:
Boris Zbarsky 2015-04-28 12:25:55 -04:00
Родитель 4e8def4afd
Коммит 864f723c0c
12 изменённых файлов: 146 добавлений и 9 удалений

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

@ -2087,6 +2087,7 @@ Navigator::DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
JS::Handle<jsid> aId,
JS::MutableHandle<JSPropertyDescriptor> aDesc)
{
// Note: Keep this in sync with MayResolve.
if (!JSID_IS_STRING(aId)) {
return true;
}
@ -2238,6 +2239,28 @@ Navigator::DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
return true;
}
/* static */
bool
Navigator::MayResolve(jsid aId)
{
// Note: This function does not fail and may not have any side-effects.
// Note: Keep this in sync with DoResolve.
if (!JSID_IS_STRING(aId)) {
return false;
}
nsScriptNameSpaceManager *nameSpaceManager = PeekNameSpaceManager();
if (!nameSpaceManager) {
// Really shouldn't happen here. Fail safe.
return true;
}
nsAutoString name;
AssignJSFlatString(name, JSID_TO_FLAT_STRING(aId));
return nameSpaceManager->LookupNavigatorName(name);
}
struct NavigatorNameEnumeratorClosure
{
NavigatorNameEnumeratorClosure(JSContext* aCx, JSObject* aWrapper,

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

@ -281,6 +281,9 @@ public:
bool DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
JS::Handle<jsid> aId,
JS::MutableHandle<JSPropertyDescriptor> aDesc);
// The return value is whether DoResolve might end up resolving the given id.
// If in doubt, return true.
static bool MayResolve(jsid aId);
void GetOwnPropertyNames(JSContext* aCx, nsTArray<nsString>& aNames,
ErrorResult& aRv);
void GetLanguages(nsTArray<nsString>& aLanguages);

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

@ -4266,6 +4266,8 @@ nsGlobalWindow::DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObj,
{
MOZ_ASSERT(IsInnerWindow());
// Note: Keep this in sync with MayResolve.
// Note: The infallibleInit call in GlobalResolve depends on this check.
if (!JSID_IS_STRING(aId)) {
return true;
@ -4279,6 +4281,44 @@ nsGlobalWindow::DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObj,
return true;
}
/* static */
bool
nsGlobalWindow::MayResolve(jsid aId)
{
// Note: This function does not fail and may not have any side-effects.
// Note: Keep this in sync with DoResolve.
if (!JSID_IS_STRING(aId)) {
return false;
}
if (aId == XPCJSRuntime::Get()->GetStringID(XPCJSRuntime::IDX_COMPONENTS)) {
return true;
}
if (aId == XPCJSRuntime::Get()->GetStringID(XPCJSRuntime::IDX_CONTROLLERS)) {
// We only resolve .controllers in release builds and on non-chrome windows,
// but let's not worry about any of that stuff.
return true;
}
nsScriptNameSpaceManager *nameSpaceManager = PeekNameSpaceManager();
if (!nameSpaceManager) {
// Really shouldn't happen. Fail safe.
return true;
}
nsAutoString name;
AssignJSFlatString(name, JSID_TO_FLAT_STRING(aId));
const nsGlobalNameStruct *name_struct =
nameSpaceManager->LookupName(name);
// LookupName only returns structs for the global.
MOZ_ASSERT_IF(name_struct,
name_struct->mType != nsGlobalNameStruct::eTypeNavigatorProperty);
return name_struct;
}
struct GlobalNameEnumeratorClosure
{
GlobalNameEnumeratorClosure(JSContext* aCx, nsGlobalWindow* aWindow,

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

@ -502,6 +502,9 @@ public:
bool DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObj,
JS::Handle<jsid> aId,
JS::MutableHandle<JSPropertyDescriptor> aDesc);
// The return value is whether DoResolve might end up resolving the given id.
// If in doubt, return true.
static bool MayResolve(jsid aId);
void GetOwnPropertyNames(JSContext* aCx, nsTArray<nsString>& aNames,
mozilla::ErrorResult& aRv);

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

@ -2826,6 +2826,12 @@ mozilla::dom::GetNameSpaceManager()
return gNameSpaceManager;
}
nsScriptNameSpaceManager*
mozilla::dom::PeekNameSpaceManager()
{
return gNameSpaceManager;
}
void
mozilla::dom::ShutdownJSEnvironment()
{

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

@ -182,6 +182,9 @@ void ShutdownJSEnvironment();
// Get the NameSpaceManager, creating if necessary
nsScriptNameSpaceManager* GetNameSpaceManager();
// Peek the NameSpaceManager, without creating it.
nsScriptNameSpaceManager* PeekNameSpaceManager();
// Runnable that's used to do async error reporting
class AsyncErrorReporter : public nsRunnable
{

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

@ -3667,6 +3667,14 @@ nsObjectLoadingContent::DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
return true;
}
/* static */
bool
nsObjectLoadingContent::MayResolve(jsid aId)
{
// We can resolve anything, really.
return true;
}
void
nsObjectLoadingContent::GetOwnPropertyNames(JSContext* aCx,
nsTArray<nsString>& /* unused */,

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

@ -171,6 +171,10 @@ class nsObjectLoadingContent : public nsImageLoadingContent
bool DoResolve(JSContext* aCx, JS::Handle<JSObject*> aObject,
JS::Handle<jsid> aId,
JS::MutableHandle<JSPropertyDescriptor> aDesc);
// The return value is whether DoResolve might end up resolving the given
// id. If in doubt, return true.
static bool MayResolve(jsid aId);
// Helper for WebIDL enumeration
void GetOwnPropertyNames(JSContext* aCx, nsTArray<nsString>& /* unused */,
mozilla::ErrorResult& aRv);

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

@ -2436,6 +2436,12 @@ ResolveGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj,
return JS_ResolveStandardClass(aCx, aObj, aId, aResolvedp);
}
bool
MayResolveGlobal(const JSAtomState& aNames, jsid aId, JSObject* aMaybeObj)
{
return JS_MayResolveStandardClass(aNames, aId, aMaybeObj);
}
bool
EnumerateGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj)
{

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

@ -2968,6 +2968,9 @@ bool
ResolveGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj,
JS::Handle<jsid> aId, bool* aResolvedp);
bool
MayResolveGlobal(const JSAtomState& aNames, jsid aId, JSObject* aMaybeObj);
bool
EnumerateGlobal(JSContext* aCx, JS::Handle<JSObject*> aObj);

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

@ -23,6 +23,7 @@ CONSTRUCT_HOOK_NAME = '_constructor'
LEGACYCALLER_HOOK_NAME = '_legacycaller'
HASINSTANCE_HOOK_NAME = '_hasInstance'
RESOLVE_HOOK_NAME = '_resolve'
MAY_RESOLVE_HOOK_NAME = '_mayResolve'
ENUMERATE_HOOK_NAME = '_enumerate'
ENUM_ENTRY_VARIABLE_NAME = 'strings'
INSTANCE_RESERVED_SLOTS = 1
@ -457,12 +458,15 @@ class CGDOMJSClass(CGThing):
reservedSlots = slotCount
if self.descriptor.interface.getExtendedAttribute("NeedResolve"):
resolveHook = RESOLVE_HOOK_NAME
mayResolveHook = MAY_RESOLVE_HOOK_NAME
enumerateHook = ENUMERATE_HOOK_NAME
elif self.descriptor.isGlobal():
resolveHook = "mozilla::dom::ResolveGlobal"
mayResolveHook = "mozilla::dom::MayResolveGlobal"
enumerateHook = "mozilla::dom::EnumerateGlobal"
else:
resolveHook = "nullptr"
mayResolveHook = "nullptr"
enumerateHook = "nullptr"
return fill(
@ -476,7 +480,7 @@ class CGDOMJSClass(CGThing):
nullptr, /* setProperty */
${enumerate}, /* enumerate */
${resolve}, /* resolve */
nullptr, /* mayResolve */
${mayResolve}, /* mayResolve */
nullptr, /* convert */
${finalize}, /* finalize */
${call}, /* call */
@ -498,6 +502,7 @@ class CGDOMJSClass(CGThing):
addProperty=ADDPROPERTY_HOOK_NAME if wantsAddProperty(self.descriptor) else 'nullptr',
enumerate=enumerateHook,
resolve=resolveHook,
mayResolve=mayResolveHook,
finalize=FINALIZE_HOOK_NAME,
call=callHook,
trace=traceHook,
@ -7769,7 +7774,7 @@ class CGLegacyCallHook(CGAbstractBindingMethod):
self._legacycaller)
class CGResolveHook(CGAbstractBindingMethod):
class CGResolveHook(CGAbstractClassHook):
"""
Resolve hook for objects that have the NeedResolve extended attribute.
"""
@ -7780,13 +7785,11 @@ class CGResolveHook(CGAbstractBindingMethod):
Argument('JS::Handle<JSObject*>', 'obj'),
Argument('JS::Handle<jsid>', 'id'),
Argument('bool*', 'resolvedp')]
# Our "self" is actually the "obj" argument in this case, not the thisval.
CGAbstractBindingMethod.__init__(
self, descriptor, RESOLVE_HOOK_NAME,
args, getThisObj="", callArgs="")
CGAbstractClassHook.__init__(self, descriptor, RESOLVE_HOOK_NAME,
"bool", args)
def generate_code(self):
return CGGeneric(dedent("""
return dedent("""
JS::Rooted<JSPropertyDescriptor> desc(cx);
if (!self->DoResolve(cx, obj, id, &desc)) {
return false;
@ -7803,7 +7806,7 @@ class CGResolveHook(CGAbstractBindingMethod):
}
*resolvedp = true;
return true;
"""))
""")
def definition_body(self):
if self.descriptor.isGlobal():
@ -7819,7 +7822,35 @@ class CGResolveHook(CGAbstractBindingMethod):
""")
else:
prefix = ""
return prefix + CGAbstractBindingMethod.definition_body(self)
return prefix + CGAbstractClassHook.definition_body(self)
class CGMayResolveHook(CGAbstractStaticMethod):
"""
Resolve hook for objects that have the NeedResolve extended attribute.
"""
def __init__(self, descriptor):
assert descriptor.interface.getExtendedAttribute("NeedResolve")
args = [Argument('const JSAtomState&', 'names'),
Argument('jsid', 'id'),
Argument('JSObject*', 'maybeObj')]
CGAbstractStaticMethod.__init__(self, descriptor, MAY_RESOLVE_HOOK_NAME,
"bool", args)
def definition_body(self):
if self.descriptor.isGlobal():
# Check whether this would resolve as a standard class.
prefix = dedent("""
if (MayResolveGlobal(names, id, maybeObj)) {
return true;
}
""")
else:
prefix = ""
return (prefix +
"return %s::MayResolve(id);\n" % self.descriptor.nativeType)
class CGEnumerateHook(CGAbstractBindingMethod):
@ -11348,6 +11379,7 @@ class CGDescriptor(CGThing):
cgThings.append(CGLegacyCallHook(descriptor))
if descriptor.interface.getExtendedAttribute("NeedResolve"):
cgThings.append(CGResolveHook(descriptor))
cgThings.append(CGMayResolveHook(descriptor))
cgThings.append(CGEnumerateHook(descriptor))
if descriptor.hasNamedPropertiesObject:

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

@ -174,6 +174,12 @@ var ignoreFunctions = {
// And these are workarounds to avoid even more analysis work,
// which would sadly still be needed even with bug 898815.
"void js::AutoCompartment::AutoCompartment(js::ExclusiveContext*, JSCompartment*)": true,
// The nsScriptNameSpaceManager functions can't actually GC. They
// just use a pldhash which has function pointers, which makes the
// analysis think maybe they can.
"nsGlobalNameStruct* nsScriptNameSpaceManager::LookupNavigatorName(nsAString_internal*)": true,
"nsGlobalNameStruct* nsScriptNameSpaceManager::LookupName(nsAString_internal*, uint16**)": true,
};
function ignoreGCFunction(mangled)