* Changes to observers and service manager APIs.
* Use nsIComponentManagerObsolete. * Fix weak reference leaks * Cache interface infos better for significant perf increase. * Better tests for leaks Not part of the build.
This commit is contained in:
@@ -26,7 +26,10 @@ from xpcom import _xpcom
|
||||
# of the real xpcom object. Presumably this "trace" object will delegate
|
||||
# to the real object, but presumably also taking some other action, such
|
||||
# as calling a profiler or debugger.
|
||||
tracer = None
|
||||
# tracer_unwrap is a function used to "unwrap" the tracer object.
|
||||
# If is expected that tracer_unwrap will be called with an object
|
||||
# previously returned by "tracer()".
|
||||
tracer = tracer_unwrap = None
|
||||
|
||||
# Wrap an instance in an interface (via a policy)
|
||||
def WrapObject(ob, iid, policy = None, bWrapClient = 1):
|
||||
@@ -42,7 +45,12 @@ def WrapObject(ob, iid, policy = None, bWrapClient = 1):
|
||||
|
||||
# Unwrap a Python object back into the Python object
|
||||
def UnwrapObject(ob):
|
||||
return _xpcom.UnwrapObject(ob)._obj_
|
||||
if ob is None:
|
||||
return None
|
||||
ret = _xpcom.UnwrapObject(ob)._obj_
|
||||
if tracer_unwrap is not None:
|
||||
ret = tracer_unwrap(ret)
|
||||
return ret
|
||||
|
||||
# Create the main module for the Python loader.
|
||||
# This is a once only init process, and the returned object
|
||||
@@ -54,3 +62,7 @@ def NS_GetModule( serviceManager, nsIFile ):
|
||||
import loader
|
||||
iid = _xpcom.IID_nsIModule
|
||||
return WrapObject(loader.MakePythonComponentLoaderModule(serviceManager, nsIFile), iid, bWrapClient = 0)
|
||||
|
||||
def _shutdown():
|
||||
from policy import _shutdown
|
||||
_shutdown()
|
||||
|
||||
@@ -68,15 +68,16 @@ def _GetNominatedInterfaces(obj):
|
||||
## We cache class infos by class
|
||||
class_info_cache = {}
|
||||
|
||||
def GetClassInfoForClass(klass):
|
||||
# Note we do not store the wrapped object in the class - this would
|
||||
# present us with shutdown problems (ie, needing to clear the
|
||||
# cache), and also messes with lifetime issues.
|
||||
def GetClassInfoForObject(ob):
|
||||
if xpcom.server.tracer_unwrap is not None:
|
||||
ob = xpcom.server.tracer_unwrap(ob)
|
||||
klass = ob.__class__
|
||||
ci = class_info_cache.get(klass)
|
||||
if ci is None:
|
||||
ci = DefaultClassInfo(klass)
|
||||
ci = xpcom.server.WrapObject(ci, _xpcom.IID_nsIClassInfo, bWrapClient = 0)
|
||||
class_info_cache[klass] = ci
|
||||
return xpcom.server.WrapObject(ci, _xpcom.IID_nsIClassInfo, bWrapClient = 0)
|
||||
return ci
|
||||
|
||||
class DefaultClassInfo:
|
||||
_com_interfaces_ = _xpcom.IID_nsIClassInfo
|
||||
@@ -88,7 +89,12 @@ class DefaultClassInfo:
|
||||
self.implementationLanguage = 3 # Python - avoid lookups just for this
|
||||
self.flags = 0 # what to do here??
|
||||
self.interfaces = None
|
||||
|
||||
|
||||
def get_classID(self):
|
||||
if self.classID is None:
|
||||
raise ServerException(nsError.NS_ERROR_NOT_IMPLEMENTED, "Class '%r' has no class ID" % (self.klass,))
|
||||
return self.classID
|
||||
|
||||
def getInterfaces(self):
|
||||
if self.interfaces is None:
|
||||
self.interfaces = _GetNominatedInterfaces(self.klass)
|
||||
@@ -133,7 +139,7 @@ class DefaultPolicy:
|
||||
|
||||
# Always support nsIClassInfo
|
||||
if iid == _xpcom.IID_nsIClassInfo:
|
||||
return GetClassInfoForClass(self._obj_.__class__)
|
||||
return GetClassInfoForObject(self._obj_)
|
||||
|
||||
# See if the instance has a QI
|
||||
# use lower-case "_query_interface_" as win32com does, and it doesnt really matter.
|
||||
@@ -276,3 +282,6 @@ class SupportsPrimitive:
|
||||
raise ServerException(nsError.NS_ERROR_NOT_IMPLEMENTED)
|
||||
def toString(self):
|
||||
return str(self.get_data())
|
||||
|
||||
def _shutdown():
|
||||
class_info_cache.clear()
|
||||
|
||||
Reference in New Issue
Block a user