diff --git a/js/src/xpconnect/src/dom_quickstubs.qsconf b/js/src/xpconnect/src/dom_quickstubs.qsconf index 4e3f15ae7f2..16e4d99e5ee 100644 --- a/js/src/xpconnect/src/dom_quickstubs.qsconf +++ b/js/src/xpconnect/src/dom_quickstubs.qsconf @@ -554,11 +554,11 @@ CUSTOM_QS_TN = { customMethodCalls = { 'nsIDOMNode_GetNextSibling': { 'thisType': 'nsINode', - 'code': ' nsINode* result = self->GetSibling(1);' + 'code': ' nsINode *result = self->GetSibling(1);' }, 'nsIDOMNode_GetFirstChild': { 'thisType': 'nsINode', - 'code': ' nsINode* result = self->GetChildAt(0);' + 'code': ' nsINode *result = self->GetChildAt(0);' }, 'nsIDOMNode_GetChildNodes': { 'thisType': 'nsINode', @@ -567,23 +567,56 @@ customMethodCalls = { }, 'nsIDOMNode_GetPreviousSibling': { 'thisType': 'nsINode', - 'code': ' nsINode* result = self->GetSibling(-1);' + 'code': ' nsINode *result = self->GetSibling(-1);' }, 'nsIDOMNode_GetLastChild': { 'thisType': 'nsINode', - 'code': ' nsINode* result = self->GetLastChild();' + 'code': ' nsINode *result = self->GetLastChild();' }, 'nsIDOMNode_GetOwnerDocument': { 'thisType': 'nsINode', - 'code': ' nsIDocument* result = self->GetOwnerDocument();' + 'code': ' nsIDocument *result = self->GetOwnerDocument();' }, 'nsIDOMNode_GetParentNode': { 'thisType': 'nsINode', - 'code': ' nsINode* result = self->GetNodeParent();' + 'code': ' nsINode *result = self->GetNodeParent();' + }, + 'nsIDOMNode_InsertBefore': { + 'thisType': 'nsINode', + 'arg0Type': 'nsINode', + 'arg1Type': 'nsINode', + 'code': ' nsINode *result = self->InsertBefore(arg0, arg1, &rv);\n' + ' if(NS_FAILED(rv))\n' + ' result = nsnull;', + 'canFail': True + }, + 'nsIDOMNode_ReplaceChild': { + 'thisType': 'nsINode', + 'arg0Type': 'nsINode', + 'arg1Type': 'nsINode', + 'code': ' nsINode *result = self->ReplaceChild(arg0, arg1, &rv);\n' + ' if(NS_FAILED(rv))\n' + ' result = nsnull;', + 'canFail': True + }, + 'nsIDOMNode_RemoveChild': { + 'thisType': 'nsINode', + 'arg0Type': 'nsINode', + 'code': ' rv = self->RemoveChild(arg0);\n' + ' nsINode *result = NS_SUCCEEDED(rv) ? arg0 : nsnull;', + 'canFail': True + }, + 'nsIDOMNode_AppendChild': { + 'thisType': 'nsINode', + 'arg0Type': 'nsINode', + 'code': ' nsINode *result = self->AppendChild(arg0, &rv);\n' + ' if(NS_FAILED(rv))\n' + ' result = nsnull;', + 'canFail': True }, 'nsIDOMNodeList_Item': { 'thisType': 'nsINodeList', - 'code': ' nsINode* result = self->GetNodeAt(arg0);' + 'code': ' nsINode *result = self->GetNodeAt(arg0);' }, 'nsIDOMHTMLDocument_Write': { 'code': nsIDOMHTMLDocument_Write_customMethodCallCode % 'Write', diff --git a/js/src/xpconnect/src/qsgen.py b/js/src/xpconnect/src/qsgen.py index e00b191394f..e87a63e2d15 100644 --- a/js/src/xpconnect/src/qsgen.py +++ b/js/src/xpconnect/src/qsgen.py @@ -865,10 +865,17 @@ def writeQuickStub(f, customMethodCalls, member, stubName, isSetter=False): if len(member.params) > 0: f.write(" jsval *argv = JS_ARGV(cx, vp);\n") for i, param in enumerate(member.params): - validateParam(member, param) + argName = 'arg%d' % i + argTypeKey = argName + 'Type' + if customMethodCall is None or not argTypeKey in customMethodCall: + validateParam(member, param) + realtype = param.realtype + else: + realtype = xpidl.Forward(name=customMethodCall[argTypeKey], + location='', doccomments='') # Emit code to convert this argument from jsval. rvdeclared = writeArgumentUnboxing( - f, i, 'arg%d' % i, param.realtype, + f, i, argName, realtype, haveCcx=haveCcx, optional=param.optional, rvdeclared=rvdeclared, @@ -1255,12 +1262,17 @@ def writeTraceableQuickStub(f, customMethodCalls, member, stubName): # Convert in-parameters. rvdeclared = False for i, param in enumerate(member.params): - validateParam(member, param) - type = unaliasType(param.realtype) argName = "arg%d" % i + argTypeKey = argName + 'Type' + if customMethodCall is None or not argTypeKey in customMethodCall: + validateParam(member, param) + realtype = unaliasType(param.realtype) + else: + realtype = xpidl.Forward(name=customMethodCall[argTypeKey], + location='', doccomments='') rvdeclared = writeTraceableArgumentConversion(f, member, i, argName, - param.realtype, - haveCcx, rvdeclared) + realtype, haveCcx, + rvdeclared) argNames.append(argName) if customMethodCall is not None: diff --git a/js/src/xpconnect/src/xpcquickstubs.cpp b/js/src/xpconnect/src/xpcquickstubs.cpp index 92ea4a741ef..4ca90abae9c 100644 --- a/js/src/xpconnect/src/xpcquickstubs.cpp +++ b/js/src/xpconnect/src/xpcquickstubs.cpp @@ -797,7 +797,7 @@ getNative(nsISupports *idobj, return rv; } -static nsresult +inline nsresult getNativeFromWrapper(XPCWrappedNative *wrapper, const nsIID &iid, void **ppThis, @@ -809,40 +809,50 @@ getNativeFromWrapper(XPCWrappedNative *wrapper, } -JSBool -xpc_qsUnwrapThisImpl(JSContext *cx, - JSObject *obj, - JSObject *callee, - const nsIID &iid, - void **ppThis, - nsISupports **pThisRef, - jsval *vp, - XPCLazyCallContext *lccx) +nsresult +getWrapper(JSContext *cx, + JSObject *obj, + JSObject *callee, + XPCWrappedNative **wrapper, + JSObject **cur, + XPCWrappedNativeTearOff **tearoff) { - if(XPCWrapper::IsSecurityWrapper(obj)) + if(XPCWrapper::IsSecurityWrapper(obj) && + !(obj = XPCWrapper::Unwrap(cx, obj))) { - obj = XPCWrapper::Unwrap(cx, obj); - if(!obj) - return xpc_qsThrow(cx, NS_ERROR_XPC_SECURITY_MANAGER_VETO); + return NS_ERROR_XPC_SECURITY_MANAGER_VETO; } - JSObject *cur = obj; - XPCWrappedNativeTearOff *tearoff = nsnull; - XPCWrappedNative *wrapper = - XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj, callee, &cur, - &tearoff); + *cur = obj; + *tearoff = nsnull; + + *wrapper = + XPCWrappedNative::GetWrappedNativeOfJSObject(cx, obj, callee, cur, + tearoff); + + return NS_OK; +} + +nsresult +castNative(JSContext *cx, + XPCWrappedNative *wrapper, + JSObject *cur, + XPCWrappedNativeTearOff *tearoff, + const nsIID &iid, + void **ppThis, + nsISupports **pThisRef, + jsval *vp, + XPCLazyCallContext *lccx) +{ if(wrapper) { nsresult rv = getNativeFromWrapper(wrapper, iid, ppThis, pThisRef, vp); - if(NS_SUCCEEDED(rv)) - { - if(lccx) - lccx->SetWrapper(wrapper, tearoff); - - return JS_TRUE; - } + + if(lccx && NS_SUCCEEDED(rv)) + lccx->SetWrapper(wrapper, tearoff); + if(rv != NS_ERROR_NO_INTERFACE) - return xpc_qsThrow(cx, rv); + return rv; } else if(cur) { @@ -853,12 +863,12 @@ xpc_qsUnwrapThisImpl(JSContext *cx, if(lccx) lccx->SetWrapper(cur); - return JS_TRUE; + return NS_OK; } } *pThisRef = nsnull; - return xpc_qsThrow(cx, NS_ERROR_XPC_BAD_OP_ON_WN_PROTO); + return NS_ERROR_XPC_BAD_OP_ON_WN_PROTO; } JSBool @@ -880,6 +890,29 @@ xpc_qsUnwrapThisFromCcxImpl(XPCCallContext &ccx, return JS_TRUE; } +JSObject* +xpc_qsUnwrapObj(jsval v, nsISupports **ppArgRef, nsresult *rv) +{ + if(JSVAL_IS_VOID(v) || JSVAL_IS_NULL(v)) + { + *ppArgRef = nsnull; + *rv = NS_OK; + return nsnull; + } + + if(!JSVAL_IS_OBJECT(v)) + { + *ppArgRef = nsnull; + *rv = ((JSVAL_IS_INT(v) && JSVAL_TO_INT(v) == 0) + ? NS_ERROR_XPC_BAD_CONVERT_JS_ZERO_ISNOT_NULL + : NS_ERROR_XPC_BAD_CONVERT_JS); + return nsnull; + } + + *rv = NS_OK; + return JSVAL_TO_OBJECT(v); +} + nsresult xpc_qsUnwrapArgImpl(JSContext *cx, jsval v, @@ -888,50 +921,25 @@ xpc_qsUnwrapArgImpl(JSContext *cx, nsISupports **ppArgRef, jsval *vp) { - // From XPCConvert::JSData2Native - if(JSVAL_IS_VOID(v) || JSVAL_IS_NULL(v)) + nsresult rv; + JSObject *src = xpc_qsUnwrapObj(v, ppArgRef, &rv); + if(!src) { *ppArg = nsnull; - *ppArgRef = nsnull; - return NS_OK; + + return rv; } - if(!JSVAL_IS_OBJECT(v)) - { - *ppArgRef = nsnull; - return ((JSVAL_IS_INT(v) && JSVAL_TO_INT(v) == 0) - ? NS_ERROR_XPC_BAD_CONVERT_JS_ZERO_ISNOT_NULL - : NS_ERROR_XPC_BAD_CONVERT_JS); - } - JSObject *src = JSVAL_TO_OBJECT(v); + XPCWrappedNative *wrapper; + XPCWrappedNativeTearOff *tearoff; + JSObject *obj2; + rv = getWrapper(cx, src, nsnull, &wrapper, &obj2, &tearoff); + NS_ENSURE_SUCCESS(rv, rv); - JSObject *inner = nsnull; - if(XPCWrapper::IsSecurityWrapper(src)) + if(wrapper || obj2) { - inner = XPCWrapper::Unwrap(cx, src); - if(!inner) - return NS_ERROR_XPC_SECURITY_MANAGER_VETO; - } - - // From XPCConvert::JSObject2NativeInterface - JSObject* obj2; - XPCWrappedNative* wrappedNative = - XPCWrappedNative::GetWrappedNativeOfJSObject(cx, inner ? inner : src, - nsnull, &obj2); - nsISupports *iface; - if(wrappedNative) - { - iface = wrappedNative->GetIdentityObject(); - if(NS_FAILED(getNativeFromWrapper(wrappedNative, iid, ppArg, ppArgRef, - vp))) - return NS_ERROR_XPC_BAD_CONVERT_JS; - return NS_OK; - } - if(obj2) - { - iface = static_cast(xpc_GetJSPrivate(obj2)); - if(NS_FAILED(getNative(iface, GetOffsetsFromSlimWrapper(obj2), - obj2, iid, ppArg, ppArgRef, vp))) + if(NS_FAILED(castNative(cx, wrapper, obj2, tearoff, iid, ppArg, + ppArgRef, vp, nsnull))) return NS_ERROR_XPC_BAD_CONVERT_JS; return NS_OK; } @@ -948,6 +956,7 @@ xpc_qsUnwrapArgImpl(JSContext *cx, } // Try to unwrap a slim wrapper. + nsISupports *iface; if(XPCConvert::GetISupportsFromJSObject(src, &iface)) { if(!iface || NS_FAILED(iface->QueryInterface(iid, ppArg))) @@ -968,10 +977,10 @@ xpc_qsUnwrapArgImpl(JSContext *cx, return NS_ERROR_XPC_BAD_CONVERT_JS; } - nsXPCWrappedJS *wrapper; - nsresult rv = - nsXPCWrappedJS::GetNewOrUsed(ccx, src, iid, nsnull, &wrapper); - if(NS_FAILED(rv) || !wrapper) + nsRefPtr wrappedJS; + rv = nsXPCWrappedJS::GetNewOrUsed(ccx, src, iid, nsnull, + getter_AddRefs(wrappedJS)); + if(NS_FAILED(rv) || !wrappedJS) { *ppArgRef = nsnull; return rv; @@ -981,13 +990,12 @@ xpc_qsUnwrapArgImpl(JSContext *cx, // the right thing for the various 'special' interfaces; e.g. // nsIPropertyBag. We must use AggregatedQueryInterface in cases where // there is an outer to avoid nasty recursion. - rv = wrapper->QueryInterface(iid, ppArg); + rv = wrappedJS->QueryInterface(iid, ppArg); if(NS_SUCCEEDED(rv)) { *ppArgRef = static_cast(*ppArg); - *vp = OBJECT_TO_JSVAL(wrapper->GetJSObject()); + *vp = OBJECT_TO_JSVAL(wrappedJS->GetJSObject()); } - NS_RELEASE(wrapper); return rv; } diff --git a/js/src/xpconnect/src/xpcquickstubs.h b/js/src/xpconnect/src/xpcquickstubs.h index 0943aab68a1..57aa3727343 100644 --- a/js/src/xpconnect/src/xpcquickstubs.h +++ b/js/src/xpconnect/src/xpcquickstubs.h @@ -348,15 +348,24 @@ xpc_qsJsvalToWcharStr(JSContext *cx, jsval v, jsval *pval, PRUnichar **pstr); JSBool xpc_qsStringToJsval(JSContext *cx, const nsAString &str, jsval *rval); -JSBool -xpc_qsUnwrapThisImpl(JSContext *cx, - JSObject *obj, - JSObject *callee, - const nsIID &iid, - void **ppThis, - nsISupports **ppThisRef, - jsval *vp, - XPCLazyCallContext *lccx); +nsresult +getWrapper(JSContext *cx, + JSObject *obj, + JSObject *callee, + XPCWrappedNative **wrapper, + JSObject **cur, + XPCWrappedNativeTearOff **tearoff); + +nsresult +castNative(JSContext *cx, + XPCWrappedNative *wrapper, + JSObject *cur, + XPCWrappedNativeTearOff *tearoff, + const nsIID &iid, + void **ppThis, + nsISupports **ppThisRef, + jsval *vp, + XPCLazyCallContext *lccx); /** * Search @a obj and its prototype chain for an XPCOM object that implements @@ -384,14 +393,15 @@ xpc_qsUnwrapThis(JSContext *cx, jsval *pThisVal, XPCLazyCallContext *lccx) { - return xpc_qsUnwrapThisImpl(cx, - obj, - callee, - NS_GET_TEMPLATE_IID(T), - reinterpret_cast(ppThis), - pThisRef, - pThisVal, - lccx); + XPCWrappedNative *wrapper; + XPCWrappedNativeTearOff *tearoff; + nsresult rv = getWrapper(cx, obj, callee, &wrapper, &obj, &tearoff); + if(NS_SUCCEEDED(rv)) + rv = castNative(cx, wrapper, obj, tearoff, NS_GET_TEMPLATE_IID(T), + reinterpret_cast(ppThis), pThisRef, pThisVal, + lccx); + + return NS_SUCCEEDED(rv) || xpc_qsThrow(cx, rv); } JSBool