From 50d2799bf86184a9837f4636880ef521f1cf1792 Mon Sep 17 00:00:00 2001 From: "mhammond%skippinet.com.au" Date: Mon, 29 Apr 2002 05:32:45 +0000 Subject: [PATCH] Add support for nsIVariant, and fix a number of other bugs. Replace nsAllocator with nsMemory. Not part of the build; using global "a=" for this part of the tree. git-svn-id: svn://10.0.0.236/branches/MOZILLA_1_0_BRANCH@120173 18797224-902f-48f8-a5cc-f745e15eee43 --- .../python/xpcom/client/__init__.py | 6 +- mozilla/extensions/python/xpcom/components.py | 6 +- mozilla/extensions/python/xpcom/file.py | 34 +- .../extensions/python/xpcom/server/policy.py | 52 +- .../extensions/python/xpcom/src/Makefile.in | 1 + .../extensions/python/xpcom/src/PyGBase.cpp | 8 +- .../extensions/python/xpcom/src/PyGModule.cpp | 25 +- .../extensions/python/xpcom/src/PyGStub.cpp | 4 +- .../python/xpcom/src/PyIClassInfo.cpp | 8 +- .../python/xpcom/src/PyIComponentManager.cpp | 6 +- mozilla/extensions/python/xpcom/src/PyIID.cpp | 10 +- .../python/xpcom/src/PyIInputStream.cpp | 6 +- .../python/xpcom/src/PyIInterfaceInfo.cpp | 6 +- .../xpcom/src/PyIInterfaceInfoManager.cpp | 6 +- .../python/xpcom/src/PyISupports.cpp | 146 ++-- mozilla/extensions/python/xpcom/src/PyXPCOM.h | 28 +- .../extensions/python/xpcom/src/PyXPCOM_std.h | 3 +- .../python/xpcom/src/TypeObject.cpp | 6 +- .../python/xpcom/src/VariantUtils.cpp | 742 ++++++++++++++---- .../extensions/python/xpcom/src/dllmain.cpp | 6 +- .../extensions/python/xpcom/src/makefile.win | 3 +- mozilla/extensions/python/xpcom/src/xpcom.cpp | 4 +- .../xpcom/test/test_component/makefile.win | 5 +- .../test/test_component/py_test_component.idl | 9 + .../test/test_component/py_test_component.py | 27 +- .../python/xpcom/test/test_test_component.py | 31 +- .../extensions/python/xpcom/xpcom_consts.py | 38 +- mozilla/extensions/python/xpcom/xpt.py | 15 +- 28 files changed, 968 insertions(+), 273 deletions(-) diff --git a/mozilla/extensions/python/xpcom/client/__init__.py b/mozilla/extensions/python/xpcom/client/__init__.py index 34820ae4fec..648d575ad1d 100644 --- a/mozilla/extensions/python/xpcom/client/__init__.py +++ b/mozilla/extensions/python/xpcom/client/__init__.py @@ -12,7 +12,7 @@ # Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 # ActiveState Tool Corp. All Rights Reserved. # -# Contributor(s): Mark Hammond (original author) +# Contributor(s): Mark Hammond (original author) # import os @@ -75,11 +75,14 @@ interface_method_cache = {} # Keyed by clsid from nsIClassInfo - everything ever queried for the CID. contractid_info_cache = {} +have_shutdown = 0 def _shutdown(): interface_cache.clear() interface_method_cache.clear() contractid_info_cache.clear() + global have_shutdown + have_shutdown = 1 # Fully process the named method, generating method code etc. def BuildMethod(method_info, iid): @@ -112,6 +115,7 @@ FLAGS_TO_IGNORE = XPT_MD_NOTXPCOM | XPT_MD_CTOR | XPT_MD_HIDDEN # Pre-process the interface - generate a list of methods, constants etc, # but don't actually generate the method code. def BuildInterfaceInfo(iid): + assert not have_shutdown, "Can't build interface info after a shutdown" ret = interface_cache.get(iid, None) if ret is None: # Build the data for the cache. diff --git a/mozilla/extensions/python/xpcom/components.py b/mozilla/extensions/python/xpcom/components.py index 7766dc00ffd..e16d024040f 100644 --- a/mozilla/extensions/python/xpcom/components.py +++ b/mozilla/extensions/python/xpcom/components.py @@ -12,7 +12,7 @@ # Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 # ActiveState Tool Corp. All Rights Reserved. # -# Contributor(s): Mark Hammond (original author) +# Contributor(s): Mark Hammond (original author) # # This module provides the JavaScript "components" interface @@ -201,8 +201,8 @@ ID = _xpcom.IID class _ShutdownObserver: _com_interfaces_ = interfaces.nsIObserver def observe(self, service, topic, extra): - global manager, interfaceInfoManager, _shutdownObserver, serviceManager, _constants_by_iid_map - manager = interfaceInfoManager = _shutdownObserver = serviceManager = _constants_by_iid_map = None + global manager, classes, interfaces, interfaceInfoManager, _shutdownObserver, serviceManager, _constants_by_iid_map + manager = classes = interfaces = interfaceInfoManager = _shutdownObserver = serviceManager = _constants_by_iid_map = None xpcom.client._shutdown() xpcom.server._shutdown() diff --git a/mozilla/extensions/python/xpcom/file.py b/mozilla/extensions/python/xpcom/file.py index 6cb624f996d..61e4aa70a28 100644 --- a/mozilla/extensions/python/xpcom/file.py +++ b/mozilla/extensions/python/xpcom/file.py @@ -12,7 +12,7 @@ # Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 # ActiveState Tool Corp. All Rights Reserved. # -# Contributor(s): Mark Hammond (original author) +# Contributor(s): Mark Hammond (original author) # """Implementation of Python file objects for Mozilla/xpcom. @@ -54,18 +54,6 @@ NS_TRUNCATE = components.interfaces.nsIFileChannel.NS_TRUNCATE NS_SYNC = components.interfaces.nsIFileChannel.NS_SYNC NS_EXCL = components.interfaces.nsIFileChannel.NS_EXCL -# A helper function - you pass a progID, an interface, plus optionally the -# name of the "constructor" and its args. -def _construct(progid, interface, ctor = None, *args): - assert (ctor is None and not args) or (ctor is not None and args), \ - "no point having a ctor with no args, or if you provide args, there must be a ctor!" - instance = components.classes[progid] \ - .createInstance(interface) - if ctor is not None: - ctor = getattr(instance, ctor) - apply(ctor, args) - return instance - # A helper function that may come in useful def LocalFileToURL(localFileName): "Convert a filename to an XPCOM nsIFileURL object." @@ -167,11 +155,16 @@ class URIFile(_File): # You open this file using a local file name (as a string) so it really is pointless - # you may as well be using a standard Python file object! class LocalFile(_File): + def __init__(self, *args): + self.fileIO = None + _File.__init__(self, *args) + def init(self, name, mode = "r"): name = os.path.abspath(name) # Moz libraries under Linux fail with relative paths. self.close() - file = _construct('@mozilla.org/file/local;1', "nsILocalFile", "initWithPath", name) - self.fileIO = _construct('@mozilla.org/network/file-io;1', "nsIFileIO", "init", file, -1, -1) + file = components.classes['@mozilla.org/file/local;1'].createInstance("nsILocalFile") + file.initWithPath(name) + self.fileIO = components.classes['@mozilla.org/network/file-io;1'].createInstance("nsIFileIO") if mode in ["w","a"]: if mode== "w": if file.exists(): @@ -181,17 +174,24 @@ class LocalFile(_File): moz_mode = NS_APPEND else: assert 0, "Can't happen!" + self.fileIO.init(file, moz_mode, -1) self.outputStream = self.fileIO.outputStream elif mode == "r": - self.contentType, self.contentLength = self.fileIO.open() + self.fileIO.init(file, NS_RDONLY, -1) self.inputStream = self.fileIO.inputStream else: raise ValueError, "Unknown mode" + def close(self): + if self.fileIO is not None: + self.fileIO.close(0) + self.fileIO = None + _File.close(self) + def read(self, n = -1): if n == -1: - n = self.contentLength + n = self.fileIO.contentLength return _File.read(self, n) diff --git a/mozilla/extensions/python/xpcom/server/policy.py b/mozilla/extensions/python/xpcom/server/policy.py index 1ab0f7aa204..15892984c15 100644 --- a/mozilla/extensions/python/xpcom/server/policy.py +++ b/mozilla/extensions/python/xpcom/server/policy.py @@ -12,7 +12,7 @@ # Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 # ActiveState Tool Corp. All Rights Reserved. # -# Contributor(s): Mark Hammond (original author) +# Contributor(s): Mark Hammond (original author) # from xpcom import xpcom_consts, _xpcom, client, nsError, ServerException, COMException @@ -23,9 +23,19 @@ import operator import types IID_nsISupports = _xpcom.IID_nsISupports +IID_nsIVariant = _xpcom.IID_nsIVariant XPT_MD_IS_GETTER = xpcom_consts.XPT_MD_IS_GETTER XPT_MD_IS_SETTER = xpcom_consts.XPT_MD_IS_SETTER +VARIANT_INT_TYPES = xpcom_consts.VTYPE_INT8, xpcom_consts.VTYPE_INT16, xpcom_consts.VTYPE_INT32, \ + xpcom_consts.VTYPE_UINT8, xpcom_consts.VTYPE_UINT16, xpcom_consts.VTYPE_INT32 +VARIANT_LONG_TYPES = xpcom_consts.VTYPE_INT64, xpcom_consts.VTYPE_UINT64 +VARIANT_FLOAT_TYPES = xpcom_consts.VTYPE_FLOAT, xpcom_consts.VTYPE_DOUBLE +VARIANT_STRING_TYPES = xpcom_consts.VTYPE_CHAR, xpcom_consts.VTYPE_CHAR_STR, xpcom_consts.VTYPE_STRING_SIZE_IS, \ + xpcom_consts.VTYPE_CSTRING +VARIANT_UNICODE_TYPES = xpcom_consts.VTYPE_WCHAR, xpcom_consts.VTYPE_DOMSTRING, xpcom_consts.VTYPE_WSTRING_SIZE_IS, \ + xpcom_consts.VTYPE_ASTRING + _supports_primitives_map_ = {} # Filled on first use. _interface_sequence_types_ = types.TupleType, types.ListType @@ -175,11 +185,47 @@ class DefaultPolicy: if iid is None: iid = self._interface_info_.GetIIDForParam(method_index, param_index) self._interface_iid_map_[(method_index, param_index)] = iid -# iid = _xpcom.IID_nsISupports + # handle nsIVariant + if iid == IID_nsIVariant: + interface = interface.QueryInterface(iid) + dt = interface.dataType + if dt in VARIANT_INT_TYPES: + return interface.getAsInt32() + if dt in VARIANT_LONG_TYPES: + return interface.getAsInt64() + if dt in VARIANT_FLOAT_TYPES: + return interface.getAsFloat() + if dt in VARIANT_STRING_TYPES: + return interface.getAsStringWithSize() + if dt in VARIANT_UNICODE_TYPES: + return interface.getAsWStringWithSize() + if dt == xpcom_consts.VTYPE_BOOL: + return interface.getAsBool() + if dt == xpcom_consts.VTYPE_INTERFACE: + return interface.getAsISupports() + if dt == xpcom_consts.VTYPE_INTERFACE_IS: + return interface.getAsInterface() + if dt == xpcom_consts.VTYPE_EMPTY or dt == xpcom_consts.VTYPE_VOID: + return None + if dt == xpcom_consts.VTYPE_ARRAY: + return interface.getAsArray() + if dt == xpcom_consts.VTYPE_EMPTY_ARRAY: + return [] + if dt == xpcom_consts.VTYPE_ID: + return interface.getAsID() + # all else fails... + print "Warning: nsIVariant type %d not supported - returning a string" % (dt,) + try: + return interface.getAsString() + except COMException: + print "Error: failed to get Variant as a string - returning variant object" + traceback.print_exc() + return interface + return client.Component(interface, iid) def _CallMethod_(self, com_object, index, info, params): -# print "_CallMethod_", index, info, params + #print "_CallMethod_", index, info, params flags, name, param_descs, ret = info assert ret[1][0] == xpcom_consts.TD_UINT32, "Expected an nsresult (%s)" % (ret,) if XPT_MD_IS_GETTER(flags): diff --git a/mozilla/extensions/python/xpcom/src/Makefile.in b/mozilla/extensions/python/xpcom/src/Makefile.in index 1cfeafc6556..fe97ab9ca0b 100644 --- a/mozilla/extensions/python/xpcom/src/Makefile.in +++ b/mozilla/extensions/python/xpcom/src/Makefile.in @@ -82,6 +82,7 @@ CPPSRCS= \ PyIInterfaceInfoManager.cpp \ PyISimpleEnumerator.cpp \ PyISupports.cpp \ + PyIVariant.cpp \ Pyxpt_info.cpp \ TypeObject.cpp \ VariantUtils.cpp \ diff --git a/mozilla/extensions/python/xpcom/src/PyGBase.cpp b/mozilla/extensions/python/xpcom/src/PyGBase.cpp index 0bf35f3ce8e..cbafa255135 100644 --- a/mozilla/extensions/python/xpcom/src/PyGBase.cpp +++ b/mozilla/extensions/python/xpcom/src/PyGBase.cpp @@ -13,7 +13,7 @@ * Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 * ActiveState Tool Corp. All Rights Reserved. * - * Contributor(s): Mark Hammond (original author) + * Contributor(s): Mark Hammond (original author) * */ @@ -115,7 +115,7 @@ PyG_Base::PyG_Base(PyObject *instance, const nsIID &iid) PyObject *real_repr = PyObject_Repr(real_instance); PYXPCOM_LOG_DEBUG("PyG_Base created at %p\n instance_repr=%s\n IID=%s\n", this, PyString_AsString(real_repr), iid_repr); - nsAllocator::Free(iid_repr); + nsMemory::Free(iid_repr); Py_XDECREF(real_instance); Py_XDECREF(real_repr); } @@ -281,9 +281,11 @@ done: } Py_XDECREF(obIID); Py_XDECREF(obParamDesc); - if (result==NULL) // we had an error. + if (result==NULL) { // we had an error. + PyErr_Clear(); // but are not reporting it back to Python itself! // return our obISupports. If NULL, we are really hosed and nothing we can do. return obISupports; + } // Dont need to return this - we have a better result. Py_XDECREF(obISupports); return result; diff --git a/mozilla/extensions/python/xpcom/src/PyGModule.cpp b/mozilla/extensions/python/xpcom/src/PyGModule.cpp index 0ff13c16ce4..9d91514d232 100644 --- a/mozilla/extensions/python/xpcom/src/PyGModule.cpp +++ b/mozilla/extensions/python/xpcom/src/PyGModule.cpp @@ -13,7 +13,7 @@ * Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 * ActiveState Tool Corp. All Rights Reserved. * - * Contributor(s): Mark Hammond (original author) + * Contributor(s): Mark Hammond (original author) * */ @@ -65,7 +65,7 @@ PyG_nsIModule::GetClassObject(nsIComponentManager *aCompMgr, NS_PRECONDITION(r_classObj, "null pointer"); *r_classObj = nsnull; CEnterLeavePython _celp; - PyObject *cm = MakeInterfaceParam(aCompMgr, &NS_GET_IID(nsIComponentManagerObsolete)); + PyObject *cm = Py_nsISupports::PyObjectFromInterface(aCompMgr, NS_GET_IID(nsIComponentManagerObsolete), PR_TRUE); PyObject *iid = Py_nsIID::PyObjectFromIID(aIID); PyObject *clsid = Py_nsIID::PyObjectFromIID(aClass); const char *methodName = "getClassObject"; @@ -95,8 +95,8 @@ PyG_nsIModule::RegisterSelf(nsIComponentManager *aCompMgr, NS_PRECONDITION(aCompMgr, "null pointer"); NS_PRECONDITION(aPath, "null pointer"); CEnterLeavePython _celp; - PyObject *cm = MakeInterfaceParam(aCompMgr, &NS_GET_IID(nsIComponentManagerObsolete)); - PyObject *path = MakeInterfaceParam(aPath, &NS_GET_IID(nsIFile)); + PyObject *cm = Py_nsISupports::PyObjectFromInterface(aCompMgr, NS_GET_IID(nsIComponentManagerObsolete), PR_TRUE); + PyObject *path = Py_nsISupports::PyObjectFromInterface(aPath, NS_GET_IID(nsIFile), PR_TRUE); const char *methodName = "registerSelf"; nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "OOzz", cm, path, registryLocation, componentType); Py_XDECREF(cm); @@ -112,8 +112,8 @@ PyG_nsIModule::UnregisterSelf(nsIComponentManager* aCompMgr, NS_PRECONDITION(aCompMgr, "null pointer"); NS_PRECONDITION(aPath, "null pointer"); CEnterLeavePython _celp; - PyObject *cm = MakeInterfaceParam(aCompMgr, &NS_GET_IID(nsIComponentManagerObsolete)); - PyObject *path = MakeInterfaceParam(aPath, &NS_GET_IID(nsIFile)); + PyObject *cm = Py_nsISupports::PyObjectFromInterface(aCompMgr, NS_GET_IID(nsIComponentManagerObsolete), PR_TRUE); + PyObject *path = Py_nsISupports::PyObjectFromInterface(aPath, NS_GET_IID(nsIFile), PR_TRUE); const char *methodName = "unregisterSelf"; nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "OOz", cm, path, registryLocation); Py_XDECREF(cm); @@ -127,7 +127,8 @@ PyG_nsIModule::CanUnload(nsIComponentManager *aCompMgr, PRBool *okToUnload) NS_PRECONDITION(aCompMgr, "null pointer"); NS_PRECONDITION(okToUnload, "null pointer"); CEnterLeavePython _celp; - PyObject *cm = MakeInterfaceParam(aCompMgr, &NS_GET_IID(nsIComponentManagerObsolete)); + // we are shutting down - don't ask for a nice wrapped object. + PyObject *cm = Py_nsISupports::PyObjectFromInterface(aCompMgr, NS_GET_IID(nsIComponentManagerObsolete), PR_TRUE, PR_FALSE); const char *methodName = "canUnload"; PyObject *ret = NULL; nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "O", cm); @@ -183,8 +184,8 @@ NS_IMETHODIMP PyG_nsIComponentLoader::Init(nsIComponentManager *aCompMgr, nsISup { CEnterLeavePython _celp; const char *methodName = "init"; - PyObject *c = MakeInterfaceParam(aCompMgr, &NS_GET_IID(nsIComponentManagerObsolete)); - PyObject *r = MakeInterfaceParam(aRegistry, &NS_GET_IID(nsISupports)); + PyObject *c = Py_nsISupports::PyObjectFromInterface(aCompMgr, NS_GET_IID(nsIComponentManagerObsolete), PR_TRUE); + PyObject *r = Py_nsISupports::PyObjectFromInterface(aRegistry, NS_GET_IID(nsISupports), PR_TRUE); nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "OO", c, r); Py_XDECREF(c); Py_XDECREF(r); @@ -214,7 +215,7 @@ NS_IMETHODIMP PyG_nsIComponentLoader::AutoRegisterComponents(PRInt32 aWhen, nsIF { CEnterLeavePython _celp; const char *methodName = "autoRegisterComponents"; - PyObject *c = MakeInterfaceParam(aDirectory, &NS_GET_IID(nsIFile)); + PyObject *c = Py_nsISupports::PyObjectFromInterface(aDirectory, NS_GET_IID(nsIFile), PR_TRUE); nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "iO", aWhen, c); Py_XDECREF(c); return nr; @@ -226,7 +227,7 @@ NS_IMETHODIMP PyG_nsIComponentLoader::AutoRegisterComponent(PRInt32 aWhen, nsIFi CEnterLeavePython _celp; const char *methodName = "autoRegisterComponent"; PyObject *ret = NULL; - PyObject *c = MakeInterfaceParam(aComponent, &NS_GET_IID(nsIFile)); + PyObject *c = Py_nsISupports::PyObjectFromInterface(aComponent, NS_GET_IID(nsIFile), PR_TRUE); nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "iO", aWhen, c); Py_XDECREF(c); if (NS_SUCCEEDED(nr)) { @@ -244,7 +245,7 @@ NS_IMETHODIMP PyG_nsIComponentLoader::AutoUnregisterComponent(PRInt32 aWhen, nsI CEnterLeavePython _celp; const char *methodName = "autoUnregisterComponent"; PyObject *ret = NULL; - PyObject *c = MakeInterfaceParam(aComponent, &NS_GET_IID(nsIFile)); + PyObject *c = Py_nsISupports::PyObjectFromInterface(aComponent, NS_GET_IID(nsIFile), PR_TRUE); nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "iO", aWhen, c); Py_XDECREF(c); if (NS_SUCCEEDED(nr)) { diff --git a/mozilla/extensions/python/xpcom/src/PyGStub.cpp b/mozilla/extensions/python/xpcom/src/PyGStub.cpp index b04d6dd34d5..e4a37eff520 100644 --- a/mozilla/extensions/python/xpcom/src/PyGStub.cpp +++ b/mozilla/extensions/python/xpcom/src/PyGStub.cpp @@ -13,7 +13,7 @@ * Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 * ActiveState Tool Corp. All Rights Reserved. * - * Contributor(s): Mark Hammond (original author) + * Contributor(s): Mark Hammond (original author) * */ @@ -99,7 +99,7 @@ done: // good error reporting is critical for users to know WTF // is going on - especially with TypeErrors etc in their // return values (ie, after the Python code has successfully - // existed, but we encountered errors unpacking their + // exited, but we encountered errors unpacking the // result values for the COM caller - there is literally no // way to catch these exceptions from Python code, as their // is no Python function on the call-stack) diff --git a/mozilla/extensions/python/xpcom/src/PyIClassInfo.cpp b/mozilla/extensions/python/xpcom/src/PyIClassInfo.cpp index 58be94ec982..0c73b72ea6c 100644 --- a/mozilla/extensions/python/xpcom/src/PyIClassInfo.cpp +++ b/mozilla/extensions/python/xpcom/src/PyIClassInfo.cpp @@ -13,7 +13,7 @@ * Portions created by ActiveState Tool Corp. are Copyright (C) 2001 * ActiveState Tool Corp. All Rights Reserved. * - * Contributor(s): Mark Hammond (original author) + * Contributor(s): Mark Hammond (original author) * */ @@ -111,7 +111,7 @@ Py_nsIClassInfo::getattr(const char *name) Py_END_ALLOW_THREADS; GETATTR_CHECK_RESULT(nr); ret = MakeStringOrNone(str_ret); - nsAllocator::Free(str_ret); + nsMemory::Free(str_ret); } else if (strcmp(name, "classDescription")==0) { char *str_ret; Py_BEGIN_ALLOW_THREADS; @@ -119,7 +119,7 @@ Py_nsIClassInfo::getattr(const char *name) Py_END_ALLOW_THREADS; GETATTR_CHECK_RESULT(nr); ret = MakeStringOrNone(str_ret); - nsAllocator::Free(str_ret); + nsMemory::Free(str_ret); } else if (strcmp(name, "classID")==0) { nsIID *iid; Py_BEGIN_ALLOW_THREADS; @@ -127,7 +127,7 @@ Py_nsIClassInfo::getattr(const char *name) Py_END_ALLOW_THREADS; GETATTR_CHECK_RESULT(nr); ret = Py_nsIID::PyObjectFromIID(*iid); - nsAllocator::Free(iid); + nsMemory::Free(iid); } else if (strcmp(name, "implementationLanguage")==0) { PRUint32 i; Py_BEGIN_ALLOW_THREADS; diff --git a/mozilla/extensions/python/xpcom/src/PyIComponentManager.cpp b/mozilla/extensions/python/xpcom/src/PyIComponentManager.cpp index 6fdde120598..012f57b3995 100644 --- a/mozilla/extensions/python/xpcom/src/PyIComponentManager.cpp +++ b/mozilla/extensions/python/xpcom/src/PyIComponentManager.cpp @@ -13,7 +13,7 @@ * Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 * ActiveState Tool Corp. All Rights Reserved. * - * Contributor(s): Mark Hammond (original author) + * Contributor(s): Mark Hammond (original author) * */ @@ -118,8 +118,8 @@ static PyObject *PyCLSIDToContractID(PyObject *self, PyObject *args) PyObject *ob_pid = PyString_FromString(ret_pid); PyObject *ob_class = PyString_FromString(ret_class); PyObject *ret = Py_BuildValue("OO", ob_pid, ob_class); - nsAllocator::Free(ret_pid); - nsAllocator::Free(ret_class); + nsMemory::Free(ret_pid); + nsMemory::Free(ret_class); Py_XDECREF(ob_pid); Py_XDECREF(ob_class); return ret; diff --git a/mozilla/extensions/python/xpcom/src/PyIID.cpp b/mozilla/extensions/python/xpcom/src/PyIID.cpp index 8ef8a85df64..16b25a2d9c6 100644 --- a/mozilla/extensions/python/xpcom/src/PyIID.cpp +++ b/mozilla/extensions/python/xpcom/src/PyIID.cpp @@ -13,7 +13,7 @@ * Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 * ActiveState Tool Corp. All Rights Reserved. * - * Contributor(s): Mark Hammond (original author) + * Contributor(s): Mark Hammond (original author) * */ @@ -81,7 +81,7 @@ Py_nsIID::IIDFromPyObject(PyObject *ob, nsIID *pRet) { PRBool ok = PR_TRUE; nsIID iid; if (ob==NULL) { - PyErr_SetString(PyExc_RuntimeError, "The object is invalid!"); + PyErr_SetString(PyExc_RuntimeError, "The IID object is invalid!"); return PR_FALSE; } if (PyString_Check(ob)) { @@ -161,7 +161,7 @@ Py_nsIID::PyTypeMethod_getattr(PyObject *self, char *name) PyObject *ret; if (iid_repr != nsnull) { ret = PyString_FromString(iid_repr); - nsAllocator::Free(iid_repr); + nsMemory::Free(iid_repr); } else ret = PyString_FromString(""); return ret; @@ -184,7 +184,7 @@ Py_nsIID::PyTypeMethod_repr(PyObject *self) char buf[256]; char *sziid = s_iid->m_iid.ToString(); sprintf(buf, "_xpcom.IID('%s')", sziid); - nsAllocator::Free(sziid); + nsMemory::Free(sziid); return PyString_FromString(buf); } @@ -194,7 +194,7 @@ Py_nsIID::PyTypeMethod_str(PyObject *self) Py_nsIID *s_iid = (Py_nsIID *)self; char *sziid = s_iid->m_iid.ToString(); PyObject *ret = PyString_FromString(sziid); - nsAllocator::Free(sziid); + nsMemory::Free(sziid); return ret; } diff --git a/mozilla/extensions/python/xpcom/src/PyIInputStream.cpp b/mozilla/extensions/python/xpcom/src/PyIInputStream.cpp index bbc9024c453..cf9f22a03af 100644 --- a/mozilla/extensions/python/xpcom/src/PyIInputStream.cpp +++ b/mozilla/extensions/python/xpcom/src/PyIInputStream.cpp @@ -13,7 +13,7 @@ * Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 * ActiveState Tool Corp. All Rights Reserved. * - * Contributor(s): Mark Hammond (original author) + * Contributor(s): Mark Hammond (original author) * */ @@ -80,7 +80,7 @@ static PyObject *DoPyRead_Size(nsIInputStream *pI, PRUint32 n) if (NS_FAILED(r)) return PyXPCOM_BuildPyException(r); } - char *buf = (char *)nsAllocator::Alloc(n); + char *buf = (char *)nsMemory::Alloc(n); if (buf==NULL) { PyErr_NoMemory(); return NULL; @@ -108,7 +108,7 @@ static PyObject *DoPyRead_Size(nsIInputStream *pI, PRUint32 n) } } else PyXPCOM_BuildPyException(r); - nsAllocator::Free(buf); + nsMemory::Free(buf); return rc; } diff --git a/mozilla/extensions/python/xpcom/src/PyIInterfaceInfo.cpp b/mozilla/extensions/python/xpcom/src/PyIInterfaceInfo.cpp index d3ec2e78b2c..f4e17fb5e6b 100644 --- a/mozilla/extensions/python/xpcom/src/PyIInterfaceInfo.cpp +++ b/mozilla/extensions/python/xpcom/src/PyIInterfaceInfo.cpp @@ -13,7 +13,7 @@ * Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 * ActiveState Tool Corp. All Rights Reserved. * - * Contributor(s): Mark Hammond (original author) + * Contributor(s): Mark Hammond (original author) * */ @@ -57,7 +57,7 @@ static PyObject *PyGetName(PyObject *self, PyObject *args) if ( NS_FAILED(r) ) return PyXPCOM_BuildPyException(r); PyObject *ret = PyString_FromString(name); - nsAllocator::Free(name); + nsMemory::Free(name); return ret; } @@ -78,7 +78,7 @@ static PyObject *PyGetIID(PyObject *self, PyObject *args) if ( NS_FAILED(r) ) return PyXPCOM_BuildPyException(r); PyObject *ret = Py_nsIID::PyObjectFromIID(*iid_ret); - nsAllocator::Free(iid_ret); + nsMemory::Free(iid_ret); return ret; } diff --git a/mozilla/extensions/python/xpcom/src/PyIInterfaceInfoManager.cpp b/mozilla/extensions/python/xpcom/src/PyIInterfaceInfoManager.cpp index f9c462c3f0d..1a1952d6c6c 100644 --- a/mozilla/extensions/python/xpcom/src/PyIInterfaceInfoManager.cpp +++ b/mozilla/extensions/python/xpcom/src/PyIInterfaceInfoManager.cpp @@ -13,7 +13,7 @@ * Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 * ActiveState Tool Corp. All Rights Reserved. * - * Contributor(s): Mark Hammond (original author) + * Contributor(s): Mark Hammond (original author) * */ @@ -117,7 +117,7 @@ static PyObject *PyGetNameForIID(PyObject *self, PyObject *args) return PyXPCOM_BuildPyException(r); PyObject *ret = PyString_FromString(ret_name); - nsAllocator::Free(ret_name); + nsMemory::Free(ret_name); return ret; } @@ -140,7 +140,7 @@ static PyObject *PyGetIIDForName(PyObject *self, PyObject *args) return PyXPCOM_BuildPyException(r); PyObject *ret = Py_nsIID::PyObjectFromIID(*iid_ret); - nsAllocator::Free(iid_ret); + nsMemory::Free(iid_ret); return ret; } diff --git a/mozilla/extensions/python/xpcom/src/PyISupports.cpp b/mozilla/extensions/python/xpcom/src/PyISupports.cpp index f227d582d57..ea792aaccd0 100644 --- a/mozilla/extensions/python/xpcom/src/PyISupports.cpp +++ b/mozilla/extensions/python/xpcom/src/PyISupports.cpp @@ -13,7 +13,7 @@ * Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 * ActiveState Tool Corp. All Rights Reserved. * - * Contributor(s): Mark Hammond (original author) + * Contributor(s): Mark Hammond (original author) * */ @@ -120,51 +120,11 @@ Py_nsISupports::Constructor(nsISupports *pInitObj, const nsIID &iid) type); } -/*static*/PRBool -Py_nsISupports::InterfaceFromPyObject(PyObject *ob, - const nsIID &iid, - nsISupports **ppv, - PRBool bNoneOK, - PRBool bTryAutoWrap /* = PR_TRUE */) +PRBool +Py_nsISupports::InterfaceFromPyISupports(PyObject *ob, + const nsIID &iid, + nsISupports **ppv) { - if ( ob == NULL ) - { - // don't overwrite an error message - if ( !PyErr_Occurred() ) - PyErr_SetString(PyExc_TypeError, "The Python object is invalid"); - return PR_FALSE; - } - if ( ob == Py_None ) - { - if ( bNoneOK ) - { - *ppv = NULL; - return PR_TRUE; - } - else - { - PyErr_SetString(PyExc_TypeError, "None is not a invalid interface object in this context"); - return PR_FALSE; - } - } - - if (PyInstance_Check(ob)) { - // Get the _comobj_ attribute - PyObject *use_ob = PyObject_GetAttrString(ob, "_comobj_"); - if (use_ob==NULL) { - PyErr_Clear(); - if (bTryAutoWrap) - // Try and auto-wrap it - errors will leave Py exception set, - return PyXPCOM_XPTStub::AutoWrapPythonInstance(ob, iid, ppv); - PyErr_SetString(PyExc_TypeError, "The Python instance can not be converted to an XP COM object"); - return PR_FALSE; - } else - ob = use_ob; - - } else { - Py_XINCREF(ob); - } - nsISupports *pis; PRBool rc = PR_FALSE; if ( !Check(ob) ) @@ -204,13 +164,82 @@ Py_nsISupports::InterfaceFromPyObject(PyObject *ob, /* note: the QI added a ref for the return value */ } } - rc = PR_TRUE; done: - Py_XDECREF(ob); return rc; } +PRBool +Py_nsISupports::InterfaceFromPyObject(PyObject *ob, + const nsIID &iid, + nsISupports **ppv, + PRBool bNoneOK, + PRBool bTryAutoWrap /* = PR_TRUE */) +{ + if ( ob == NULL ) + { + // don't overwrite an error message + if ( !PyErr_Occurred() ) + PyErr_SetString(PyExc_TypeError, "The Python object is invalid"); + return PR_FALSE; + } + if ( ob == Py_None ) + { + if ( bNoneOK ) + { + *ppv = NULL; + return PR_TRUE; + } + else + { + PyErr_SetString(PyExc_TypeError, "None is not a invalid interface object in this context"); + return PR_FALSE; + } + } + + // support nsIVariant + if (iid.Equals(NS_GET_IID(nsIVariant)) || iid.Equals(NS_GET_IID(nsIWritableVariant))) { + // Check it is not already nsIVariant + if (PyInstance_Check(ob)) { + PyObject *sub_ob = PyObject_GetAttrString(ob, "_comobj_"); + if (sub_ob==NULL) { + PyErr_Clear(); + } else { + if (InterfaceFromPyISupports(sub_ob, iid, ppv)) { + Py_DECREF(sub_ob); + return PR_TRUE; + } + PyErr_Clear(); + Py_DECREF(sub_ob); + } + } + *ppv = PyObject_AsVariant(ob); + return *ppv != NULL; + } + // end of variant support. + + if (PyInstance_Check(ob)) { + // Get the _comobj_ attribute + PyObject *use_ob = PyObject_GetAttrString(ob, "_comobj_"); + if (use_ob==NULL) { + PyErr_Clear(); + if (bTryAutoWrap) + // Try and auto-wrap it - errors will leave Py exception set, + return PyXPCOM_XPTStub::AutoWrapPythonInstance(ob, iid, ppv); + PyErr_SetString(PyExc_TypeError, "The Python instance can not be converted to an XPCOM object"); + return PR_FALSE; + } else + ob = use_ob; + + } else { + Py_INCREF(ob); + } + PRBool rc = InterfaceFromPyISupports(ob, iid, ppv); + Py_DECREF(ob); + return rc; +} + + // Interface conversions /*static*/void Py_nsISupports::RegisterInterface( const nsIID &iid, PyTypeObject *t) @@ -226,6 +255,28 @@ Py_nsISupports::RegisterInterface( const nsIID &iid, PyTypeObject *t) } } +/*static */PyObject * +Py_nsISupports::PyObjectFromInterfaceOrVariant(nsISupports *pis, + const nsIID &riid, + PRBool bAddRef, + PRBool bMakeNicePyObject /* = PR_TRUE */) +{ + // Quick exit. + if (pis==NULL) { + Py_INCREF(Py_None); + return Py_None; + } + if (riid.Equals(NS_GET_IID(nsIVariant))) { + PyObject *ret = PyObject_FromVariant((nsIVariant *)pis); + // If we were asked not to add a reference, then there + // will be a spare reference on pis() - remove it. + if (!bAddRef) + pis->Release(); + return ret; + } + return PyObjectFromInterface(pis, riid, bAddRef, bMakeNicePyObject); +} + /*static */PyObject * Py_nsISupports::PyObjectFromInterface(nsISupports *pis, const nsIID &riid, @@ -241,7 +292,6 @@ Py_nsISupports::PyObjectFromInterface(nsISupports *pis, // If the IID is for nsISupports, dont bother with // a map lookup as we know the type! if (!riid.Equals(NS_GET_IID(nsISupports))) { - // Look up the map PyObject *obiid = Py_nsIID::PyObjectFromIID(riid); if (!obiid) return NULL; diff --git a/mozilla/extensions/python/xpcom/src/PyXPCOM.h b/mozilla/extensions/python/xpcom/src/PyXPCOM.h index 3bc6aa7e7ab..32e4003a176 100644 --- a/mozilla/extensions/python/xpcom/src/PyXPCOM.h +++ b/mozilla/extensions/python/xpcom/src/PyXPCOM.h @@ -13,7 +13,7 @@ * Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 * ActiveState Tool Corp. All Rights Reserved. * - * Contributor(s): Mark Hammond (original author) + * Contributor(s): Mark Hammond (original author) * */ @@ -176,9 +176,14 @@ public: // see the correct xpcom.client.Interface object even when calling // xpcom function directly. static PyObject *PyObjectFromInterface(nsISupports *ps, - const nsIID &iid, - PRBool bAddRef, - PRBool bMakeNicePyObject = PR_TRUE); + const nsIID &iid, + PRBool bAddRef, + PRBool bMakeNicePyObject = PR_TRUE); + + static PyObject *PyObjectFromInterfaceOrVariant(nsISupports *ps, + const nsIID &iid, + PRBool bAddRef, + PRBool bMakeNicePyObject = PR_TRUE); // Given a Python object that is a registered COM type, return a given // interface pointer on its underlying object, with a NEW REFERENCE ADDED. @@ -187,6 +192,8 @@ public: // provided to stop accidental recursion should the object returned by // the wrap process itself be in instance (where it should already be // a COM object. + // If |iid|==nsIVariant, then arbitary Python objects will be wrapped + // in an nsIVariant. static PRBool InterfaceFromPyObject( PyObject *ob, const nsIID &iid, @@ -194,6 +201,13 @@ public: PRBool bNoneOK, PRBool bTryAutoWrap = PR_TRUE); + // Given a Py_nsISupports, return an interface. + // Object *must* be Py_nsISupports - there is no + // "autowrap", no "None" support, etc + static PRBool InterfaceFromPyISupports(PyObject *ob, + const nsIID &iid, + nsISupports **ppv); + static Py_nsISupports *Constructor(nsISupports *pInitObj, const nsIID &iid); // The Python methods static PyObject *QueryInterface(PyObject *self, PyObject *args); @@ -459,6 +473,7 @@ private: PRUint32 GetSizeIs( int var_index, PRBool is_arg1); PRBool SetSizeIs( int var_index, PRBool is_arg1, PRUint32 new_size); PRBool CanSetSizeIs( int var_index, PRBool is_arg1 ); + nsIInterfaceInfo *GetInterfaceInfo(); // NOTE: no ref count on result. nsXPTCMiniVariant* m_params; @@ -466,7 +481,7 @@ private: int m_method_index; PythonTypeDescriptor *m_python_type_desc_array; int m_num_type_descs; - + nsCOMPtr m_interface_info; }; // Misc converters. @@ -478,6 +493,8 @@ PyObject *PyObject_FromXPTParamDescriptor( const XPTParamDescriptor *d); PyObject *PyObject_FromXPTMethodDescriptor( const XPTMethodDescriptor *d); PyObject *PyObject_FromXPTConstant( const XPTConstDescriptor *d); +nsIVariant *PyObject_AsVariant( PyObject *ob); +PyObject *PyObject_FromVariant( nsIVariant *v); // DLL reference counting functions. // Although we maintain the count, we never actually @@ -669,5 +686,6 @@ PyXPCOM_INTERFACE_DECLARE(Py_nsIInterfaceInfo, nsIInterfaceInfo, PyMethods_IInte PyXPCOM_INTERFACE_DECLARE(Py_nsIServiceManager, nsIServiceManager, PyMethods_IServiceManager) PyXPCOM_INTERFACE_DECLARE(Py_nsIInputStream, nsIInputStream, PyMethods_IInputStream) PyXPCOM_ATTR_INTERFACE_DECLARE(Py_nsIClassInfo, nsIClassInfo, PyMethods_IClassInfo) +PyXPCOM_ATTR_INTERFACE_DECLARE(Py_nsIVariant, nsIVariant, PyMethods_IVariant) #endif // __PYXPCOM_H__ diff --git a/mozilla/extensions/python/xpcom/src/PyXPCOM_std.h b/mozilla/extensions/python/xpcom/src/PyXPCOM_std.h index 27afdea01fa..0b691a70175 100644 --- a/mozilla/extensions/python/xpcom/src/PyXPCOM_std.h +++ b/mozilla/extensions/python/xpcom/src/PyXPCOM_std.h @@ -13,7 +13,7 @@ * Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 * ActiveState Tool Corp. All Rights Reserved. * - * Contributor(s): Mark Hammond (original author) + * Contributor(s): Mark Hammond (original author) * */ @@ -38,6 +38,7 @@ #include "nsIComponentManager.h" #include "nsIServiceManager.h" #include "nsIInputStream.h" +#include "nsIVariant.h" #include "nsXPIDLString.h" diff --git a/mozilla/extensions/python/xpcom/src/TypeObject.cpp b/mozilla/extensions/python/xpcom/src/TypeObject.cpp index 9a29d98685c..53016e88123 100644 --- a/mozilla/extensions/python/xpcom/src/TypeObject.cpp +++ b/mozilla/extensions/python/xpcom/src/TypeObject.cpp @@ -13,7 +13,7 @@ * Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 * ActiveState Tool Corp. All Rights Reserved. * - * Contributor(s): Mark Hammond (original author) + * Contributor(s): Mark Hammond (original author) * */ @@ -131,7 +131,7 @@ PyXPCOM_TypeObject::Py_repr(PyObject *self) // XXX - need some sort of buffer overflow. char buf[512]; sprintf(buf, "", iid_repr, self, pis->m_obj); - nsAllocator::Free(iid_repr); + nsMemory::Free(iid_repr); return PyString_FromString(buf); } @@ -153,7 +153,7 @@ PyXPCOM_TypeObject::Py_str(PyObject *self) ret = Py_repr(self); else ret = PyString_FromString(val); - if (val) nsAllocator::Free(val); + if (val) nsMemory::Free(val); return ret; } diff --git a/mozilla/extensions/python/xpcom/src/VariantUtils.cpp b/mozilla/extensions/python/xpcom/src/VariantUtils.cpp index 7a980df828a..f7b574d6899 100644 --- a/mozilla/extensions/python/xpcom/src/VariantUtils.cpp +++ b/mozilla/extensions/python/xpcom/src/VariantUtils.cpp @@ -13,7 +13,7 @@ * Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 * ActiveState Tool Corp. All Rights Reserved. * - * Contributor(s): Mark Hammond (original author) + * Contributor(s): Mark Hammond (original author) * */ @@ -33,6 +33,9 @@ #include #include +// ------------------------------------------------------------------------ +// nsString utilities +// ------------------------------------------------------------------------ // one day we may know what they look like. inline PRBool @@ -43,80 +46,47 @@ IsNullDOMString( const nsAString& aString ) inline PRBool -IsNULLDOMString( const nsACString& aString ) +IsNullDOMString( const nsACString& aString ) { return PR_FALSE; } -class PythonTypeDescriptor { -public: - PythonTypeDescriptor() { - param_flags = type_flags = argnum = argnum2 = 0; - extra = NULL; - is_auto_out = PR_FALSE; - is_auto_in = PR_FALSE; - have_set_auto = PR_FALSE; - } - ~PythonTypeDescriptor() { - Py_XDECREF(extra); - } - PRUint8 param_flags; - PRUint8 type_flags; - PRUint8 argnum; /* used for iid_is and size_is */ - PRUint8 argnum2; /* used for length_is */ - PyObject *extra; // The IID object, or the type of the array. - // Extra items to help our processing. - // Is this auto-filled by some other "in" param? - PRBool is_auto_in; - // Is this auto-filled by some other "out" param? - PRBool is_auto_out; - // If is_auto_out, have I already filled it? Used when multiple - // params share a size_is fields - first time sets it, subsequent - // time check it. - PRBool have_set_auto; -}; - -static int ProcessPythonTypeDescriptors(PythonTypeDescriptor *pdescs, int num) +PyObject *PyObject_FromNSString( const nsACString &s, PRBool bAssumeUTF8 = PR_FALSE ) { - // Loop over the array, checking all the params marked as having an arg. - // If these args nominate another arg as the size_is param, then - // we reset the size_is param to _not_ requiring an arg. - int i; - for (i=0;ipis = ps; + pdata->iid = NS_GET_IID(nsISupports); + } else + ps->Release(); + return nsIDataType::VTYPE_INTERFACE_IS; + } else + PyErr_Clear(); + if (Py_nsIID::IIDFromPyObject(ob, &iid)) { + if (pdata) + pdata->iid = iid; + return nsIDataType::VTYPE_ID; + } else + PyErr_Clear(); + if (PySequence_Check(ob)) + return PySequence_Length(ob) ? nsIDataType::VTYPE_ARRAY : nsIDataType::VTYPE_EMPTY_ARRAY; + return (PRUint16)-1; +} + +nsIVariant *PyObject_AsVariant( PyObject *ob) +{ + nsresult nr = NS_ERROR_UNEXPECTED; + nsCOMPtr v = do_CreateInstance("@mozilla.org/variant;1", &nr); + if (NS_FAILED(nr)) { + PyXPCOM_BuildPyException(nr); + return NULL; + } + // *sigh* - I tried the abstract API (PyNumber_Check, etc) + // but our COM instances too often qualify. + BVFTResult cvt_result; + PRUint16 dt = BestVariantTypeForPyObject(ob, &cvt_result); + switch (dt) { + case nsIDataType::VTYPE_BOOL: + nr = v->SetAsBool(ob==Py_True); + break; + case nsIDataType::VTYPE_INT32: + nr = v->SetAsInt32(PyInt_AsLong(ob)); + break; + case nsIDataType::VTYPE_INT64: + nr = v->SetAsInt64(PyLong_AsLongLong(ob)); + break; + case nsIDataType::VTYPE_DOUBLE: + nr = v->SetAsDouble(PyFloat_AsDouble(ob)); + break; + case nsIDataType::VTYPE_STRING_SIZE_IS: + nr = v->SetAsStringWithSize(PyString_Size(ob), PyString_AsString(ob)); + break; + case nsIDataType::VTYPE_WSTRING_SIZE_IS: + nr = v->SetAsWStringWithSize(PyUnicode_GetSize(ob), PyUnicode_AsUnicode(ob)); + break; + case nsIDataType::VTYPE_INTERFACE_IS: + { + nsISupports *ps = cvt_result.pis; + nr = v->SetAsInterface(cvt_result.iid, ps); + if (ps) { + Py_BEGIN_ALLOW_THREADS; // MUST release thread-lock, incase a Python COM object that re-acquires. + ps->Release(); + Py_END_ALLOW_THREADS; + } + break; + } + case nsIDataType::VTYPE_ID: + nr = v->SetAsID(cvt_result.iid); + break; + case nsIDataType::VTYPE_ARRAY: + { + int seq_length = PySequence_Length(ob); + NS_ABORT_IF_FALSE(seq_length!=0, "VTYPE_ARRAY assumes at least one element!"); + PyObject *first = PySequence_GetItem(ob, 0); + if (!first) break; + int array_type = BestVariantTypeForPyObject(first); + Py_DECREF(first); + // Arrays can't handle all types. This means we lost embedded NULLs. + // This should really be fixed in XPCOM. + if (array_type == nsIDataType::VTYPE_STRING_SIZE_IS) array_type = nsIDataType::VTYPE_CHAR_STR; + if (array_type == nsIDataType::VTYPE_WSTRING_SIZE_IS) array_type = nsIDataType::VTYPE_WCHAR_STR; + PRUint32 element_size = GetArrayElementSize(array_type); + int cb_buffer_pointer = seq_length * element_size; + void *buffer_pointer; + if ((buffer_pointer = (void *)nsMemory::Alloc(cb_buffer_pointer)) == nsnull) { + PyErr_NoMemory(); + nr = NS_ERROR_UNEXPECTED; + break; + } + memset(buffer_pointer, 0, cb_buffer_pointer); + if (FillSingleArray(buffer_pointer, ob, seq_length, element_size, array_type)) { + nr = v->SetAsArray(array_type, &NS_GET_IID(nsISupports), seq_length, buffer_pointer); + FreeSingleArray(buffer_pointer, seq_length, array_type); + } else + nr = NS_ERROR_UNEXPECTED; + nsMemory::Free(buffer_pointer); + break; + } + case nsIDataType::VTYPE_EMPTY: + v->SetAsEmpty(); + break; + case nsIDataType::VTYPE_EMPTY_ARRAY: + v->SetAsEmptyArray(); + break; + case (PRUint16)-1: + PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be converted to an nsIVariant", ob->ob_type->tp_name); + return NULL; + default: + NS_ABORT_IF_FALSE(0, "BestVariantTypeForPyObject() returned a variant type not handled here!"); + PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be converted to an nsIVariant", ob->ob_type->tp_name); + return NULL; + } + nsIVariant *ret; + v->QueryInterface(NS_GET_IID(nsIVariant), (void **)&ret); + return ret; +} + +static PyObject *MyBool_FromBool(PRBool v) +{ + PyObject *ret = v ? Py_True : Py_False; + Py_INCREF(ret); + return ret; +} +static PyObject *MyObject_FromInterface(nsISupports *p) +{ + return Py_nsISupports::PyObjectFromInterface(p, NS_GET_IID(nsISupports), PR_FALSE); +} + +#define GET_FROM_V(Type, FuncGet, FuncConvert) { \ + Type t; \ + if (NS_FAILED(nr = FuncGet( &t ))) goto done;\ + ret = FuncConvert(t);\ + break; \ +} + +PyObject *PyObject_FromVariantArray( nsIVariant *v) +{ + nsresult nr; + NS_PRECONDITION(v, "NULL variant!"); + if (!v) + return PyXPCOM_BuildPyException(NS_ERROR_INVALID_POINTER); +#ifdef NS_DEBUG + PRUint16 dt; + nr = v->GetDataType(&dt); + NS_ABORT_IF_FALSE(dt == nsIDataType::VTYPE_ARRAY, "expected an array variant"); +#endif + nsIID iid; + void *p; + PRUint16 type; + PRUint32 count; + nr = v->GetAsArray(&type, &iid, &count, &p); + if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr); + PyObject *ret = UnpackSingleArray(p, count, (PRUint8)type, &iid); + FreeSingleArray(p, count, (PRUint8)type); + nsMemory::Free(p); + return ret; +} + +PyObject *PyObject_FromVariant( nsIVariant *v) +{ + if (!v) { + Py_INCREF(Py_None); + return Py_None; + } + PRUint16 dt; + nsresult nr; + PyObject *ret = NULL; + nr = v->GetDataType(&dt); + if (NS_FAILED(nr)) goto done; + switch (dt) { + case nsIDataType::VTYPE_VOID: + case nsIDataType::VTYPE_EMPTY: + case nsIDataType::VTYPE_EMPTY_ARRAY: + ret = Py_None; + Py_INCREF(Py_None); + break; + case nsIDataType::VTYPE_ARRAY: + ret = PyObject_FromVariantArray(v); + break; + case nsIDataType::VTYPE_INT8: + case nsIDataType::VTYPE_INT16: + case nsIDataType::VTYPE_INT32: + GET_FROM_V(PRInt32, v->GetAsInt32, PyInt_FromLong); + case nsIDataType::VTYPE_UINT8: + case nsIDataType::VTYPE_UINT16: + case nsIDataType::VTYPE_UINT32: + GET_FROM_V(PRUint32, v->GetAsUint32, PyLong_FromUnsignedLong); + case nsIDataType::VTYPE_INT64: + GET_FROM_V(PRInt64, v->GetAsInt64, PyLong_FromLongLong); + case nsIDataType::VTYPE_UINT64: + GET_FROM_V(PRUint64, v->GetAsUint64, PyLong_FromUnsignedLongLong); + case nsIDataType::VTYPE_FLOAT: + case nsIDataType::VTYPE_DOUBLE: + GET_FROM_V(double, v->GetAsDouble, PyFloat_FromDouble); + case nsIDataType::VTYPE_BOOL: + GET_FROM_V(PRBool, v->GetAsBool, MyBool_FromBool); + default: + PyXPCOM_LogWarning("Converting variant to Python object - variant type '%d' unknown - using string.\n", dt); + // Fall through to the string case + case nsIDataType::VTYPE_CHAR: + case nsIDataType::VTYPE_CHAR_STR: + case nsIDataType::VTYPE_STRING_SIZE_IS: + case nsIDataType::VTYPE_CSTRING: { + nsCAutoString s; + if (NS_FAILED(nr=v->GetAsACString(s))) goto done; + ret = PyObject_FromNSString(s); + break; + } + case nsIDataType::VTYPE_WCHAR: + case nsIDataType::VTYPE_DOMSTRING: + case nsIDataType::VTYPE_WSTRING_SIZE_IS: + case nsIDataType::VTYPE_ASTRING: { + nsAutoString s; + if (NS_FAILED(nr=v->GetAsAString(s))) goto done; + ret = PyObject_FromNSString(s); + break; + } + case nsIDataType::VTYPE_ID: + GET_FROM_V(nsIID, v->GetAsID, Py_nsIID::PyObjectFromIID); + case nsIDataType::VTYPE_INTERFACE: + GET_FROM_V(nsISupports *, v->GetAsISupports, MyObject_FromInterface); + case nsIDataType::VTYPE_INTERFACE_IS: { + nsISupports *p; + nsIID *iid; + if (NS_FAILED(nr=v->GetAsInterface(&iid, (void **)&p))) goto done; + ret = Py_nsISupports::PyObjectFromInterface(p, *iid, PR_FALSE); + break; + } + } +done: + if (NS_FAILED(nr)) { + NS_ABORT_IF_FALSE(ret==NULL, "Have an error, but also a return val!"); + PyXPCOM_BuildPyException(nr); + } + return ret; +} + +// ------------------------------------------------------------------------ +// TypeDescriptor helper class +// ------------------------------------------------------------------------ +class PythonTypeDescriptor { +public: + PythonTypeDescriptor() { + param_flags = type_flags = argnum = argnum2 = 0; + extra = NULL; + is_auto_out = PR_FALSE; + is_auto_in = PR_FALSE; + have_set_auto = PR_FALSE; + } + ~PythonTypeDescriptor() { + Py_XDECREF(extra); + } + PRUint8 param_flags; + PRUint8 type_flags; + PRUint8 argnum; /* used for iid_is and size_is */ + PRUint8 argnum2; /* used for length_is */ + PyObject *extra; // The IID object, or the type of the array. + // Extra items to help our processing. + // Is this auto-filled by some other "in" param? + PRBool is_auto_in; + // Is this auto-filled by some other "out" param? + PRBool is_auto_out; + // If is_auto_out, have I already filled it? Used when multiple + // params share a size_is fields - first time sets it, subsequent + // time check it. + PRBool have_set_auto; +}; + +static int ProcessPythonTypeDescriptors(PythonTypeDescriptor *pdescs, int num) +{ + // Loop over the array, checking all the params marked as having an arg. + // If these args nominate another arg as the size_is param, then + // we reset the size_is param to _not_ requiring an arg. + int i; + for (i=0;iLength() ); - CopyUnicodeTo(*rs, 0, PyUnicode_AsUnicode(ret), rs->Length()); - } + ret = PyObject_FromNSString(*rs); break; } + case nsXPTType::T_UTF8STRING: + case nsXPTType::T_CSTRING: { + nsCString *rs = (nsCString *)ns_v.ptr; + ret = PyObject_FromNSString(*rs, XPT_TDP_TAG(ns_v.type)==nsXPTType::T_UTF8STRING); + break; + } + case nsXPTType::T_CHAR_STR: if (*((char **)ns_v.ptr) == NULL) { ret = Py_None; @@ -1165,7 +1571,7 @@ PyObject *PyXPCOM_InterfaceVariantHelper::MakeSinglePythonResult(int index) nsISupports *iret = *((nsISupports **)ns_v.ptr); // We _do_ add a reference here, as our cleanup code will // remove this reference should we own it. - ret = Py_nsISupports::PyObjectFromInterface(iret, iid, PR_TRUE); + ret = Py_nsISupports::PyObjectFromInterfaceOrVariant(iret, iid, PR_TRUE); break; } case nsXPTType::T_INTERFACE_IS: { @@ -1187,7 +1593,7 @@ PyObject *PyXPCOM_InterfaceVariantHelper::MakeSinglePythonResult(int index) nsISupports *iret = *((nsISupports **)ns_v.ptr); // We _do_ add a reference here, as our cleanup code will // remove this reference should we own it. - ret = Py_nsISupports::PyObjectFromInterface(iret, iid, PR_TRUE); + ret = Py_nsISupports::PyObjectFromInterfaceOrVariant(iret, iid, PR_TRUE); break; } case nsXPTType::T_ARRAY: { @@ -1200,9 +1606,8 @@ PyObject *PyXPCOM_InterfaceVariantHelper::MakeSinglePythonResult(int index) break; } PRUint8 array_type = (PRUint8)PyInt_AsLong(td.extra); - PRUint32 element_size = GetArrayElementSize(array_type); PRUint32 seq_size = GetSizeIs(index, PR_FALSE); - ret = UnpackSingleArray(* ((void **)ns_v.ptr), seq_size, element_size, array_type); + ret = UnpackSingleArray(* ((void **)ns_v.ptr), seq_size, array_type&XPT_TDP_TAGMASK, NULL); break; } @@ -1481,16 +1886,18 @@ PyObject *PyXPCOM_GatewayVariantHelper::MakeSingleParam(int index, PythonTypeDes ret = Py_nsIID::PyObjectFromIID( * DEREF_IN_OR_OUT(ns_v.val.p, const nsIID *) ); break; } + case nsXPTType::T_ASTRING: case nsXPTType::T_DOMSTRING: { NS_ABORT_IF_FALSE(is_out || !XPT_PD_IS_DIPPER(td.param_flags), "DOMStrings can't be inout"); const nsAString *rs = (const nsAString *)ns_v.val.p; - if (rs==NULL || IsNullDOMString(*rs)) { - ret = Py_None; - Py_INCREF(Py_None); - } else { - ret = PyUnicode_FromUnicode( NULL, rs->Length() ); - CopyUnicodeTo(*rs, 0, PyUnicode_AsUnicode(ret), rs->Length()); + ret = PyObject_FromNSString(*rs); + break; } + case nsXPTType::T_CSTRING: + case nsXPTType::T_UTF8STRING: { + NS_ABORT_IF_FALSE(is_out || !XPT_PD_IS_DIPPER(td.param_flags), "DOMStrings can't be inout"); + const nsCString *rs = (const nsCString *)ns_v.val.p; + ret = PyObject_FromNSString(*rs, (td.type_flags & XPT_TDP_TAGMASK)==nsXPTType::T_UTF8STRING); break; } case nsXPTType::T_CHAR_STR: { @@ -1546,9 +1953,8 @@ PyObject *PyXPCOM_GatewayVariantHelper::MakeSingleParam(int index, PythonTypeDes PyXPCOM_BuildPyException(ns); break; } - PRUint32 element_size = GetArrayElementSize(array_type); PRUint32 seq_size = GetSizeIs(index, PR_FALSE); - ret = UnpackSingleArray(t, seq_size, element_size, array_type); + ret = UnpackSingleArray(t, seq_size, array_type&XPT_TDP_TAGMASK, NULL); } break; } @@ -1638,6 +2044,17 @@ PRBool PyXPCOM_GatewayVariantHelper::GetIIDForINTERFACE_ID(int index, const nsII return PR_TRUE; } +nsIInterfaceInfo *PyXPCOM_GatewayVariantHelper::GetInterfaceInfo() +{ + if (!m_interface_info) { + nsCOMPtr iim = + dont_AddRef(XPTI_GetInterfaceInfoManager()); + if (iim) + iim->GetInfoForIID(&m_gateway->m_iid, getter_AddRefs(m_interface_info)); + } + return m_interface_info; +} + #undef FILL_SIMPLE_POINTER #define FILL_SIMPLE_POINTER( type, ob ) *((type *)ns_v.val.p) = (type)(ob); @@ -1654,7 +2071,6 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index NS_ABORT_IF_FALSE(pi->IsDipper() || ns_v.val.p, "No space for result!"); if (!pi->IsDipper() && !ns_v.val.p) return NS_ERROR_INVALID_POINTER; - NS_ABORT_IF_FALSE(((pi->IsDipper()==0) ^ (XPT_TDP_TAG(typ)==nsXPTType::T_DOMSTRING==0)) == 0, "Only handle DOMString dippers!"); PRBool rc = PR_TRUE; switch (XPT_TDP_TAG(typ)) { @@ -1733,8 +2149,8 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index nsIID **pp = (nsIID **)ns_v.val.p; // If there is an existing [in] IID, free it. if (*pp && pi->IsIn()) - nsAllocator::Free(*pp); - *pp = (nsIID *)nsAllocator::Alloc(sizeof(nsIID)); + nsMemory::Free(*pp); + *pp = (nsIID *)nsMemory::Alloc(sizeof(nsIID)); if (*pp==NULL) { PyErr_NoMemory(); BREAK_FALSE; @@ -1743,6 +2159,7 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index break; } + case nsXPTType::T_ASTRING: case nsXPTType::T_DOMSTRING: { nsAString *ws = (nsAString *)ns_v.val.p; NS_ABORT_IF_FALSE(ws->Length() == 0, "Why does this writable string already have chars??"); @@ -1760,12 +2177,50 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index } break; } + case nsXPTType::T_CSTRING: { + nsCString *ws = (nsCString *)ns_v.val.p; + NS_ABORT_IF_FALSE(ws->Length() == 0, "Why does this writable string already have chars??"); + if (val == Py_None) { + NS_ABORT_IF_FALSE(0, "dont handle None here yet"); + } else { + if (!PyString_Check(val) && !PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object"); + BREAK_FALSE; + } + val_use = PyObject_Str(val); + NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!"); + const char *sz = PyString_AS_STRING(val_use); + ws->Assign(sz); + } + break; + } + case nsXPTType::T_UTF8STRING: { + nsCString *ws = (nsCString *)ns_v.val.p; + NS_ABORT_IF_FALSE(ws->Length() == 0, "Why does this writable string already have chars??"); + if (val == Py_None) { + NS_ABORT_IF_FALSE(0, "dont handle None here yet"); + } else { + if (PyString_Check(val)) { + val_use = val; + Py_INCREF(val); + } else if (PyUnicode_Check(val)) { + val_use = PyUnicode_AsUTF8String(val); + } else { + PyErr_SetString(PyExc_TypeError, "UTF8 parameters must be string or Unicode objects"); + BREAK_FALSE; + } + NS_ABORT_IF_FALSE(PyString_Check(val_use), "must have a string object!"); + const char *sz = PyString_AS_STRING(val_use); + ws->Assign(sz); + } + break; + } case nsXPTType::T_CHAR_STR: { // If it is an existing string, free it. char **pp = (char **)ns_v.val.p; if (*pp && pi->IsIn()) - nsAllocator::Free(*pp); + nsMemory::Free(*pp); *pp = nsnull; if (val == Py_None) @@ -1782,7 +2237,7 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index const char *sz = PyString_AS_STRING(val_use); int nch = PyString_GET_SIZE(val_use); - *pp = (char *)nsAllocator::Alloc(nch+1); + *pp = (char *)nsMemory::Alloc(nch+1); if (*pp==NULL) { PyErr_NoMemory(); BREAK_FALSE; @@ -1794,7 +2249,7 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index // If it is an existing string, free it. PRUnichar **pp = (PRUnichar **)ns_v.val.p; if (*pp && pi->IsIn()) - nsAllocator::Free(*pp); + nsMemory::Free(*pp); *pp = nsnull; if (val == Py_None) break; // Remains NULL. @@ -1807,7 +2262,7 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index const PRUnichar *sz = PyUnicode_AS_UNICODE(val_use); int nch = PyUnicode_GET_SIZE(val_use); - *pp = (PRUnichar *)nsAllocator::Alloc(sizeof(PRUnichar) * (nch+1)); + *pp = (PRUnichar *)nsMemory::Alloc(sizeof(PRUnichar) * (nch+1)); if (*pp==NULL) { PyErr_NoMemory(); BREAK_FALSE; @@ -1817,10 +2272,17 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index } case nsXPTType::T_INTERFACE: { nsISupports *pnew = nsnull; + // Find out what IID we are declared to use. + nsIID *iid; + nsIInterfaceInfo *ii = GetInterfaceInfo(); + if (ii) + ii->GetIIDForParam(m_method_index, pi, &iid); + // Get it the "standard" way. // We do allow NULL here, even tho doing so will no-doubt crash some objects. // (but there will certainly be objects out there that will allow NULL :-( - if (!Py_nsISupports::InterfaceFromPyObject(val, NS_GET_IID(nsISupports), &pnew, PR_TRUE)) + nsIID iid_use = iid ? *iid : NS_GET_IID(nsISupports); + if (!Py_nsISupports::InterfaceFromPyObject(val, iid_use, &pnew, PR_TRUE)) BREAK_FALSE; nsISupports **pp = (nsISupports **)ns_v.val.p; if (*pp && pi->IsIn()) { @@ -1892,11 +2354,11 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index // If we have an existing string, free it! char **pp = (char **)ns_v.val.p; if (*pp && pi->IsIn()) - nsAllocator::Free(*pp); + nsMemory::Free(*pp); *pp = nsnull; if (sz==nsnull) // None specified. break; // Remains NULL. - *pp = (char *)nsAllocator::Alloc(nch); + *pp = (char *)nsMemory::Alloc(nch); if (*pp==NULL) { PyErr_NoMemory(); BREAK_FALSE; @@ -1948,12 +2410,12 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index // If it is an existing string, free it. PRUnichar **pp = (PRUnichar **)ns_v.val.p; if (*pp && pi->IsIn()) - nsAllocator::Free(*pp); + nsMemory::Free(*pp); *pp = nsnull; if (val == Py_None) break; // Remains NULL. - *pp = (PRUnichar *)nsAllocator::Alloc(nbytes); + *pp = (PRUnichar *)nsMemory::Alloc(nbytes); if (*pp==NULL) { PyErr_NoMemory(); BREAK_FALSE; @@ -1998,21 +2460,21 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index bBackFill = pi->IsIn(); } if (bBackFill) - rc = FillSingleArray(*(void **)ns_v.val.p, val, sequence_size, element_size, array_type); + rc = FillSingleArray(*(void **)ns_v.val.p, val, sequence_size, element_size, array_type&XPT_TDP_TAGMASK); else { // If it is an existing array, free it. void **pp = (void **)ns_v.val.p; if (*pp && pi->IsIn()) { FreeSingleArray(*pp, existing_size, array_type); - nsAllocator::Free(*pp); + nsMemory::Free(*pp); } *pp = nsnull; if (val == Py_None) break; // Remains NULL. size_t nbytes = sequence_size * element_size; - *pp = (void *)nsAllocator::Alloc(nbytes); + *pp = (void *)nsMemory::Alloc(nbytes); memset(*pp, 0, nbytes); - rc = FillSingleArray(*pp, val, sequence_size, element_size, array_type); + rc = FillSingleArray(*pp, val, sequence_size, element_size, array_type&XPT_TDP_TAGMASK); if (!rc) break; if (bCanSetSizeIs) rc = SetSizeIs(index, PR_FALSE, sequence_size); diff --git a/mozilla/extensions/python/xpcom/src/dllmain.cpp b/mozilla/extensions/python/xpcom/src/dllmain.cpp index 23179c1f074..397cdb9a497 100644 --- a/mozilla/extensions/python/xpcom/src/dllmain.cpp +++ b/mozilla/extensions/python/xpcom/src/dllmain.cpp @@ -13,7 +13,7 @@ * Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 * ActiveState Tool Corp. All Rights Reserved. * - * Contributor(s): Mark Hammond (original author) + * Contributor(s): Mark Hammond (original author) * */ @@ -86,7 +86,7 @@ PRBool PyXPCOM_ThreadState_Ensure() if (PyXPCOM_InterpreterState==NULL) { Py_FatalError("Can not setup thread state, as have no interpreter state"); } - pData = (ThreadData *)nsAllocator::Alloc(sizeof(ThreadData)); + pData = (ThreadData *)nsMemory::Alloc(sizeof(ThreadData)); if (!pData) Py_FatalError("Out of memory allocating thread state."); memset(pData, 0, sizeof(*pData)); @@ -128,7 +128,7 @@ void PyXPCOM_ThreadState_Free() PyThreadState *thisThreadState = pData->ts; PyThreadState_Delete(thisThreadState); PR_SetThreadPrivate(tlsIndex, NULL); - nsAllocator::Free(pData); + nsMemory::Free(pData); } void PyXPCOM_ThreadState_Clear() diff --git a/mozilla/extensions/python/xpcom/src/makefile.win b/mozilla/extensions/python/xpcom/src/makefile.win index c43eeb66775..cddb0b2c735 100755 --- a/mozilla/extensions/python/xpcom/src/makefile.win +++ b/mozilla/extensions/python/xpcom/src/makefile.win @@ -15,7 +15,7 @@ # Portions created by ActiveState are Copyright (C) 2000 ActiveState. # All Rights Reserved. # -# Contributor(s): Mark Hammond +# Contributor(s): Mark Hammond # DIRS = \ @@ -52,6 +52,7 @@ CPP_OBJS= \ .\$(OBJDIR)\PyIInterfaceInfoManager.obj \ .\$(OBJDIR)\PyISimpleEnumerator.obj \ .\$(OBJDIR)\PyISupports.obj \ + .\$(OBJDIR)\PyIVariant.obj \ .\$(OBJDIR)\Pyxpt_info.obj \ .\$(OBJDIR)\TypeObject.obj \ .\$(OBJDIR)\VariantUtils.obj \ diff --git a/mozilla/extensions/python/xpcom/src/xpcom.cpp b/mozilla/extensions/python/xpcom/src/xpcom.cpp index af349d2fc64..c78867287d3 100644 --- a/mozilla/extensions/python/xpcom/src/xpcom.cpp +++ b/mozilla/extensions/python/xpcom/src/xpcom.cpp @@ -13,7 +13,7 @@ * Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 * ActiveState Tool Corp. All Rights Reserved. * - * Contributor(s): Mark Hammond (original author) + * Contributor(s): Mark Hammond (original author) * */ @@ -63,6 +63,7 @@ PyXPCOM_INTERFACE_DEFINE(Py_nsISimpleEnumerator, nsISimpleEnumerator, PyMethods_ PyXPCOM_INTERFACE_DEFINE(Py_nsIInterfaceInfo, nsIInterfaceInfo, PyMethods_IInterfaceInfo) PyXPCOM_INTERFACE_DEFINE(Py_nsIInputStream, nsIInputStream, PyMethods_IInputStream) PyXPCOM_INTERFACE_DEFINE(Py_nsIClassInfo, nsIClassInfo, PyMethods_IClassInfo) +PyXPCOM_INTERFACE_DEFINE(Py_nsIVariant, nsIVariant, PyMethods_IVariant) //////////////////////////////////////////////////////////// // This is the main entry point called by the Python component @@ -594,6 +595,7 @@ init_xpcom() { Py_nsIInterfaceInfo::InitType(dict); Py_nsIInputStream::InitType(dict); Py_nsIClassInfo::InitType(dict); + Py_nsIVariant::InitType(dict); // yet another { // temp scope nsIComponentManagerObsolete hack :( diff --git a/mozilla/extensions/python/xpcom/test/test_component/makefile.win b/mozilla/extensions/python/xpcom/test/test_component/makefile.win index abb9b37a195..e0ab5e23a7c 100644 --- a/mozilla/extensions/python/xpcom/test/test_component/makefile.win +++ b/mozilla/extensions/python/xpcom/test/test_component/makefile.win @@ -17,8 +17,11 @@ # DEPTH =..\..\..\..\.. +MODULE=pyxpcom +REQUIRES = xpcom \ + $(NULL) - +PUBLIC=foo ################################################################################ ## exports diff --git a/mozilla/extensions/python/xpcom/test/test_component/py_test_component.idl b/mozilla/extensions/python/xpcom/test/test_component/py_test_component.idl index 7db3ac7cc37..07800b73267 100644 --- a/mozilla/extensions/python/xpcom/test/test_component/py_test_component.idl +++ b/mozilla/extensions/python/xpcom/test/test_component/py_test_component.idl @@ -21,6 +21,7 @@ // We try to get as many data-types etc exposed, meaning this // doesnt really make a good demo of a "simple component" #include "nsISupports.idl" +#include "nsIVariant.idl" [scriptable, uuid(1ECAED4F-E4D5-4ee7-ABF0-7D72AE1441D7)] interface nsIPythonTestInterface : nsISupports @@ -121,6 +122,8 @@ interface nsIPythonTestInterfaceExtra : nsIPythonTestInterface void UpString2(in PRUint32 count, [size_is(count)] in string in_str, [size_is(count)]out string out_str); + void CopyUTF8String(in AUTF8String in_str, out AUTF8String out_str); + void CopyUTF8String2(in AUTF8String in_str, out AUTF8String out_str); // Test we can get an "out" array with an "in" size (and the size is not used anywhere as a size for an in!) void GetFixedString(in PRUint32 count, [size_is(count)]out string out_str); @@ -154,6 +157,10 @@ interface nsIPythonTestInterfaceExtra : nsIPythonTestInterface void CheckInterfaceArray(in PRUint32 count, [array, size_is(count)] in nsISupports data, [retval] out PRBool all_non_null); + void CopyInterfaceArray(in PRUint32 count, + [array, size_is(count)] in nsISupports data, + [array, size_is(out_count)] out nsISupports out_data, + out PRUint32 out_count); void GetInterfaceArray(out PRUint32 count, [array, size_is(count)] out nsISupports data); void ExtendInterfaceArray(inout PRUint32 count, @@ -181,6 +188,8 @@ interface nsIPythonTestInterfaceExtra : nsIPythonTestInterface void CopyAndDoubleArray(inout PRUint32 count, [array, size_is(count)]in PRInt32 array1, [array, size_is(count)]out PRInt32 array2); // Test our "in-out" count param can be shared as one "in", plus one "in-out" param. void AppendArray(inout PRUint32 count, [array, size_is(count)]in PRInt32 array1, [array, size_is(count)]inout PRInt32 array2); + void AppendVariant(in nsIVariant variant, inout nsIVariant result); + nsIVariant CopyVariant(in nsIVariant variant); }; // DOM String support is a "recent" (01/2001) addition to XPCOM. These test diff --git a/mozilla/extensions/python/xpcom/test/test_component/py_test_component.py b/mozilla/extensions/python/xpcom/test/test_component/py_test_component.py index 7dc495f058d..596036b1a71 100644 --- a/mozilla/extensions/python/xpcom/test/test_component/py_test_component.py +++ b/mozilla/extensions/python/xpcom/test/test_component/py_test_component.py @@ -217,7 +217,10 @@ class PythonTestComponent: def UpWideString(self, val): return val.upper() UpWideString2 = UpWideString - + def CopyUTF8String(self, v): + return v + def CopyUTF8String2(self, v): + return v.encode("utf8") # Test we can get an "out" array with an "in" size (and the size is not used anywhere as a size for an in!) def GetFixedWideString(self, count): # void GetFixedWideString(in PRUint32 count, [size_is(count)out string out_str); @@ -251,6 +254,8 @@ class PythonTestComponent: ret = 0 break return ret + def CopyInterfaceArray(self, a): + return a def GetInterfaceArray(self): # void GetInterfaceArray(out PRUint32 count, # [array, size_is(count)] out nsISupports data); @@ -316,6 +321,26 @@ class PythonTestComponent: if array2 is not None: rc.extend(array2) return rc + # Test nsIVariant support + def AppendVariant(self, invar, inresult): + if type(invar)==type([]): + invar_use = invar[0] + for v in invar[1:]: + invar_use += v + else: + invar_use = invar + if type(inresult)==type([]): + inresult_use = inresult[0] + for v in inresult[1:]: + inresult_use += v + else: + inresult_use = inresult + if inresult_use is None and invar_use is None: + return None + return inresult_use + invar_use + + def CopyVariant(self, invar): + return invar # Some tests for the "new" (Feb-2001) DOMString type. def GetDOMStringResult( self, length ): diff --git a/mozilla/extensions/python/xpcom/test/test_test_component.py b/mozilla/extensions/python/xpcom/test/test_test_component.py index eb08b6e66ef..47093abedaa 100644 --- a/mozilla/extensions/python/xpcom/test/test_test_component.py +++ b/mozilla/extensions/python/xpcom/test/test_test_component.py @@ -79,7 +79,7 @@ def test_method(method, args, expected_results): print "Testing %s%s" % (method.__name__, `args`) ret = method(*args) if ret != expected_results: - print_error("calling method %s - expected %s, but got %s" % (method.__name__, expected_results, ret)) + print_error("calling method %s - expected %r, but got %r" % (method.__name__, expected_results, ret)) def test_int_method(meth): test_method(meth, (0,0), (0,0,0)) @@ -292,6 +292,15 @@ def test_derived_interface(c, test_flat = 0): test_method(c.UpWideString, (val,), val.upper()) test_method(c.UpWideString2, (val,), val.upper()) test_method(c.GetFixedWideString, (20,), u"A"*20) + val = u"The Euro Symbol is '\u20ac'" + test_method(c.CopyUTF8String, ("foo",), "foo") + test_method(c.CopyUTF8String, (u"foo",), "foo") + test_method(c.CopyUTF8String, (val,), val) + test_method(c.CopyUTF8String, (val.encode("utf8"),), val) + test_method(c.CopyUTF8String2, ("foo",), "foo") + test_method(c.CopyUTF8String2, (u"foo",), "foo") + test_method(c.CopyUTF8String2, (val,), val) + test_method(c.CopyUTF8String2, (val.encode("utf8"),), val) items = [1,2,3,4,5] test_method(c.MultiplyEachItemInIntegerArray, (3, items,), map(lambda i:i*3, items)) @@ -322,6 +331,7 @@ def test_derived_interface(c, test_flat = 0): test_method(c.CheckInterfaceArray, ((c, c),), 1) test_method(c.CheckInterfaceArray, ((c, None),), 0) test_method(c.CheckInterfaceArray, ((),), 1) + test_method(c.CopyInterfaceArray, ((c, c),), [c,c]) test_method(c.GetInterfaceArray, (), [c,c,c, None]) test_method(c.ExtendInterfaceArray, ((c,c,c, None),), [c,c,c,None,c,c,c,None] ) @@ -339,6 +349,25 @@ def test_derived_interface(c, test_flat = 0): test_method(c.AppendArray, ([1,2,3],), [1,2,3]) test_method(c.AppendArray, ([1,2,3],[4,5,6]), [1,2,3,4,5,6]) + test_method(c.CopyVariant, (None,), None) + test_method(c.CopyVariant, (1,), 1) + test_method(c.CopyVariant, (1.0,), 1.0) + test_method(c.CopyVariant, (-1,), -1) + test_method(c.CopyVariant, (sys.maxint+1,), sys.maxint+1) + test_method(c.CopyVariant, ("foo",), "foo") + test_method(c.CopyVariant, (u"foo",), u"foo") + test_method(c.CopyVariant, (c,), c) + test_method(c.CopyVariant, (component_iid,), component_iid) + test_method(c.CopyVariant, ((1,2),), [1,2]) + test_method(c.CopyVariant, ((1.2,2.1),), [1.2,2.1]) + test_method(c.CopyVariant, (("foo","bar"),), ["foo", "bar"]) + test_method(c.CopyVariant, ((component_iid,component_iid),), [component_iid,component_iid]) + test_method(c.CopyVariant, ((c,c),), [c,c]) + test_method(c.AppendVariant, (1,2), 3) + test_method(c.AppendVariant, ((1,2),(3,4)), 10) + test_method(c.AppendVariant, ("bar", "foo"), "foobar") + test_method(c.AppendVariant, (None, None), None) + if not test_flat: c = c.queryInterface(xpcom.components.interfaces.nsIPythonTestInterfaceDOMStrings) # NULL DOM strings don't work yet. diff --git a/mozilla/extensions/python/xpcom/xpcom_consts.py b/mozilla/extensions/python/xpcom/xpcom_consts.py index c45534aadad..110a36b9408 100644 --- a/mozilla/extensions/python/xpcom/xpcom_consts.py +++ b/mozilla/extensions/python/xpcom/xpcom_consts.py @@ -12,7 +12,7 @@ # Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 # ActiveState Tool Corp. All Rights Reserved. # -# Contributor(s): Mark Hammond (original author) +# Contributor(s): Mark Hammond (original author) # # Could maybe later have a process that extracted these enums should they change. @@ -143,6 +143,9 @@ TD_INTERFACE_IS_TYPE = 19 TD_ARRAY = 20 TD_PSTRING_SIZE_IS = 21 TD_PWSTRING_SIZE_IS = 22 +TD_UTF8STRING = 23 +TD_CSTRING = 24 +TD_ASTRING = 25 # From xpt_struct.h XPT_TDP_POINTER = 0x80 @@ -214,3 +217,36 @@ T_INTERFACE_IS = TD_INTERFACE_IS_TYPE T_ARRAY = TD_ARRAY T_PSTRING_SIZE_IS = TD_PSTRING_SIZE_IS T_PWSTRING_SIZE_IS = TD_PWSTRING_SIZE_IS +T_UTF8STRING = TD_UTF8STRING +T_CSTRING = TD_CSTRING +T_ASTRING = TD_ASTRING + +# from nsIVariant +VTYPE_INT8 = 0 +VTYPE_INT16 = 1 +VTYPE_INT32 = 2 +VTYPE_INT64 = 3 +VTYPE_UINT8 = 4 +VTYPE_UINT16 = 5 +VTYPE_UINT32 = 6 +VTYPE_UINT64 = 7 +VTYPE_FLOAT = 8 +VTYPE_DOUBLE = 9 +VTYPE_BOOL = 10 +VTYPE_CHAR = 11 +VTYPE_WCHAR = 12 +VTYPE_VOID = 13 +VTYPE_ID = 14 +VTYPE_DOMSTRING = 15 +VTYPE_CHAR_STR = 16 +VTYPE_WCHAR_STR = 17 +VTYPE_INTERFACE = 18 +VTYPE_INTERFACE_IS = 19 +VTYPE_ARRAY = 20 +VTYPE_STRING_SIZE_IS = 21 +VTYPE_WSTRING_SIZE_IS = 22 +VTYPE_UTF8STRING = 23 +VTYPE_CSTRING = 24 +VTYPE_ASTRING = 25 +VTYPE_EMPTY_ARRAY = 254 +VTYPE_EMPTY = 255 diff --git a/mozilla/extensions/python/xpcom/xpt.py b/mozilla/extensions/python/xpcom/xpt.py index 4aeacce7601..c03d152a707 100644 --- a/mozilla/extensions/python/xpcom/xpt.py +++ b/mozilla/extensions/python/xpcom/xpt.py @@ -13,7 +13,7 @@ # ActiveState Tool Corp. All Rights Reserved. # # Contributor(s): David Ascher (original author) -# Mark Hammond +# Mark Hammond # """ @@ -56,10 +56,15 @@ from xpcom_consts import * class Interface: def __init__(self, iid): iim = xpcom._xpcom.XPTI_GetInterfaceInfoManager() - if hasattr(iid, "upper"): # Is it a stringy thing. - item = iim.GetInfoForName(iid) - else: - item = iim.GetInfoForIID(iid) + try: + if hasattr(iid, "upper"): # Is it a stringy thing. + item = iim.GetInfoForName(iid) + else: + item = iim.GetInfoForIID(iid) + except xpcom.COMException: + name = getattr(iid, "name", str(iid)) + print "Failed to get info for IID '%s'" % (name,) + raise self.interface_info = item self.namespace = "" # where does this come from? self.methods = Methods(item)