vendor/tracemonkey/xpconnect/src/qsgen.py in johnson-2.0.0.pre0 vs vendor/tracemonkey/xpconnect/src/qsgen.py in johnson-2.0.0.pre1
- old
+ new
@@ -99,20 +99,10 @@
# that use GetCurrentNativeCallContext and are called indirectly from
# quick-stubbed methods, because only the current top XPCCallContext is
# exposed--nsAXPCNativeCallContext does not expose
# XPCCallContext::GetPrevCallContext.)
#
-# - There are a few differences in how the "this" JSObject is unwrapped.
-# Ordinarily, XPConnect searches the prototype chain of the "this" JSObject
-# for an XPCOM object of the desired "proto". For details, see the parts of
-# XPCWrappedNative::GetWrappedNativeOfJSObject that use "proto". Some quick
-# stubs (methods, not getters or setters, that have XPCCallContexts) do this,
-# but most instead look for an XPCOM object that supports the desired
-# *interface*. This is more lenient. The difference is observable in some
-# cases where a getter/setter/method is taken from one object and applied to
-# another object.
-#
# - Quick stubs never suspend the JS request. So they are only suitable for
# main-thread-only interfaces.
#
# - Quick stubs don't call XPCContext::SetLastResult. This is visible on the
# Components object.
@@ -130,11 +120,10 @@
import xpidl
import header
import os, re
import sys
-import sets
# === Preliminaries
# --makedepend-output support.
make_dependencies = []
@@ -328,11 +317,10 @@
# === Generating the header file
def writeHeaderFile(filename, name):
print "Creating header file", filename
- make_targets.append(filename)
headerMacro = '__gen_%s__' % filename.replace('.', '_')
f = open(filename, 'w')
try:
f.write("/* THIS FILE IS AUTOGENERATED - DO NOT EDIT */\n"
@@ -394,12 +382,11 @@
" if (!JS_ValueToNumber(cx, ${argVal}, &${name}))\n"
" return JS_FALSE;\n",
'boolean':
" PRBool ${name};\n"
- " if (!JS_ValueToBoolean(cx, ${argVal}, &${name}))\n"
- " return JS_FALSE;\n",
+ " JS_ValueToBoolean(cx, ${argVal}, &${name});\n",
'[astring]':
" xpc_qsAString ${name}(cx, ${argPtr});\n"
" if (!${name}.IsValid())\n"
" return JS_FALSE;\n",
@@ -484,14 +471,15 @@
# Should have special atomizing behavior. Fall through.
pass
else:
if not rvdeclared:
f.write(" nsresult rv;\n");
- f.write(" nsCOMPtr<%s> %s;\n" % (type.name, name))
+ f.write(" %s *%s;\n" % (type.name, name))
+ f.write(" xpc_qsSelfRef %sref;\n" % name)
f.write(" rv = xpc_qsUnwrapArg<%s>("
- "cx, %s, getter_AddRefs(%s));\n"
- % (type.name, argVal, name))
+ "cx, %s, &%s, &%sref.ptr, %s);\n"
+ % (type.name, argVal, name, name, argPtr))
f.write(" if (NS_FAILED(rv)) {\n")
if isSetter:
f.write(" xpc_qsThrowBadSetterValue("
"cx, rv, JSVAL_TO_OBJECT(*tvr.addr()), id);\n")
elif haveCcx:
@@ -591,11 +579,11 @@
}
def isVariantType(t):
return isSpecificInterfaceType(t, 'nsIVariant')
-def writeResultConv(f, type, paramNum, jsvalPtr, jsvalRef):
+def writeResultConv(f, type, jsvalPtr, jsvalRef):
""" Emit code to convert the C++ variable `result` to a jsval.
The emitted code contains a return statement; it returns JS_TRUE on
success, JS_FALSE on error.
"""
@@ -609,19 +597,18 @@
f.write(substitute(template, values))
return
# else fall through; this type isn't supported yet
elif isInterfaceType(type):
if isVariantType(type):
- f.write(" return xpc_qsVariantToJsval(ccx, result, %d, %s);\n"
- % (paramNum, jsvalPtr))
+ f.write(" return xpc_qsVariantToJsval(lccx, result, %s);\n"
+ % jsvalPtr)
return
else:
- f.write(" AutoMarkingNativeInterfacePtr resultiface(ccx, "
- "%s_Interface(ccx));\n" % type.name)
- f.write(" return xpc_qsXPCOMObjectToJsval(ccx, result, "
- "xpc_qsGetWrapperCache(result), resultiface, %s);\n"
- % jsvalPtr)
+ f.write(" return xpc_qsXPCOMObjectToJsval(lccx, result, "
+ "xpc_qsGetWrapperCache(result), &NS_GET_IID(%s), "
+ "&interfaces[k_%s], %s);\n"
+ % (type.name, type.name, jsvalPtr))
return
warn("Unable to convert result of type %s" % type.name)
f.write(" !; // TODO - Convert `result` to jsval, store in `%s`.\n"
% jsvalRef)
@@ -678,46 +665,53 @@
f.write(" JSObject *obj = JS_THIS_OBJECT(cx, vp);\n"
" if (!obj)\n"
" return JS_FALSE;\n")
# Create ccx if needed.
- haveCcx = isMethod and (isInterfaceType(member.realtype)
- or anyParamRequiresCcx(member))
+ haveCcx = isMethod and anyParamRequiresCcx(member)
if haveCcx:
- f.write(" XPCCallContext ccx(JS_CALLER, cx, obj, "
- "JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));\n")
- else:
- # In some cases we emit a ccx, but it does not count as
- # "haveCcx" because it's not complete.
- if isAttr and isInterfaceType(member.realtype):
- f.write(" XPCCallContext ccx(JS_CALLER, cx, obj);\n")
+ f.write(" XPCCallContext ccx(JS_CALLER, cx, obj, "
+ "JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));\n")
+ if isInterfaceType(member.realtype):
+ f.write(" XPCLazyCallContext lccx(ccx);\n")
+ elif isInterfaceType(member.realtype):
+ if isMethod:
+ f.write(" JSObject *callee = "
+ "JSVAL_TO_OBJECT(JS_CALLEE(cx, vp));\n")
+ elif isGetter:
+ f.write(" JSObject *callee = nsnull;\n")
# Get the 'self' pointer.
if customMethodCall is None or not 'thisType' in customMethodCall:
f.write(" %s *self;\n" % member.iface.name)
else:
f.write(" %s *self;\n" % customMethodCall['thisType'])
f.write(" xpc_qsSelfRef selfref;\n")
# Don't use FromCcx for getters or setters; the way we construct the ccx in
# a getter/setter causes it to find the wrong wrapper in some cases.
- if isMethod and haveCcx:
+ if haveCcx:
# Undocumented, but the interpreter puts 'this' at argv[-1],
# which is vp[1]; and it's ok to overwrite it.
f.write(" if (!xpc_qsUnwrapThisFromCcx(ccx, &self, &selfref.ptr, "
"&vp[1]))\n")
f.write(" return JS_FALSE;\n")
else:
if isGetter:
pthisval = 'vp'
elif isSetter:
- f.write(" xpc_qsTempRoot tvr(cx);\n")
+ f.write(" JSAutoTempValueRooter tvr(cx);\n")
pthisval = 'tvr.addr()'
else:
pthisval = '&vp[1]' # as above, ok to overwrite vp[1]
- f.write(" if (!xpc_qsUnwrapThis(cx, obj, &self, &selfref.ptr, "
- "%s))\n" % pthisval)
+ if not isSetter and isInterfaceType(member.realtype):
+ f.write(" XPCLazyCallContext lccx(JS_CALLER, cx, obj);\n")
+ f.write(" if (!xpc_qsUnwrapThis(cx, obj, callee, &self, "
+ "&selfref.ptr, %s, &lccx))\n" % pthisval)
+ else:
+ f.write(" if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, "
+ "&selfref.ptr, %s, nsnull))\n" % pthisval)
f.write(" return JS_FALSE;\n")
if isMethod:
# If there are any required arguments, check argc.
requiredArgs = len(member.params)
@@ -807,14 +801,12 @@
" \"Got the wrong answer from the custom "
"method call!\");\n")
f.write("#endif\n")
# Convert the return value.
- if isMethod:
- writeResultConv(f, member.realtype, len(member.params) + 1, 'vp', '*vp')
- elif isGetter:
- writeResultConv(f, member.realtype, None, 'vp', '*vp')
+ if isMethod or isGetter:
+ writeResultConv(f, member.realtype, 'vp', '*vp')
else:
f.write(" return JS_TRUE;\n")
# Epilog.
f.write("}\n\n")
@@ -913,12 +905,11 @@
" const PRUnichar *${name} = JS_GetStringChars({argVal});\n",
}
def writeTraceableArgumentConversion(f, member, i, name, type, haveCcx,
rvdeclared):
- argVal = "arg%d" % i
- argPtr = "&" + argVal
+ argVal = "_arg%d" % i
params = {
'name': name,
'argVal': argVal
}
@@ -945,14 +936,15 @@
# Should have special atomizing behavior. Fall through.
pass
else:
if not rvdeclared:
f.write(" nsresult rv;\n");
- f.write(" nsCOMPtr<%s> %s;\n" % (type.name, name))
+ f.write(" %s *%s;\n" % (type.name, name))
+ f.write(" xpc_qsSelfRef %sref;\n" % name)
f.write(" rv = xpc_qsUnwrapArg<%s>("
- "cx, %s, getter_AddRefs(%s));\n"
- % (type.name, argVal, name))
+ "cx, %s, &%s, &%sref.ptr, &vp.array[%d]);\n"
+ % (type.name, argVal, name, name, 1 + i))
f.write(" if (NS_FAILED(rv)) {\n")
if haveCcx:
f.write(" xpc_qsThrowBadArgWithCcx(ccx, rv, %d);\n" % i)
else:
# XXX Fix this to return a real error!
@@ -990,11 +982,11 @@
" if (!xpc_qsStringToJsval(cx, result, &rval)) {\n"
" JS_ReportOutOfMemory(cx);\n${errorStr}"
" return rval;\n",
}
-def writeTraceableResultConv(f, type, paramNum):
+def writeTraceableResultConv(f, type):
typeName = getBuiltinOrNativeTypeName(type)
if typeName is not None:
template = traceableResultConvTemplates.get(typeName)
if template is not None:
values = { 'errorStr': getFailureString(
@@ -1002,21 +994,20 @@
f.write(substitute(template, values))
return
# else fall through; this type isn't supported yet
elif isInterfaceType(type):
if isVariantType(type):
- f.write(" JSBool ok = xpc_qsVariantToJsval(ccx, result, %d, "
- "tvr.addr());\n" % paramNum)
+ f.write(" JSBool ok = xpc_qsVariantToJsval(lccx, result, "
+ "&vp.array[0]);\n")
else:
- f.write(" AutoMarkingNativeInterfacePtr resultiface(ccx, "
- "%s_Interface(ccx));\n" % type.name)
- f.write(" JSBool ok = xpc_qsXPCOMObjectToJsval(ccx, result, "
- "xpc_qsGetWrapperCache(result), resultiface, tvr.addr());"
- "\n")
+ f.write(" JSBool ok = xpc_qsXPCOMObjectToJsval(lccx, result, "
+ "xpc_qsGetWrapperCache(result), &NS_GET_IID(%s), "
+ "&interfaces[k_%s], &vp.array[0]);"
+ "\n" % (type.name, type.name))
f.write(" if (!ok) {\n");
writeFailure(f, getTraceInfoDefaultReturn(type), 2)
- f.write(" return *tvr.addr();\n")
+ f.write(" return vp.array[0];\n")
return
warn("Unable to convert result of type %s" % typeName)
f.write(" !; // TODO - Convert `result` to jsval, store in rval.\n")
f.write(" return xpc_qsThrow(cx, NS_ERROR_UNEXPECTED); // FIXME\n")
@@ -1027,54 +1018,60 @@
traceInfo = {
'type': getTraceInfoType(member.type) + "_FAIL",
'params': ["CONTEXT", "THIS"]
}
- haveCcx = isInterfaceType(member.realtype) or anyParamRequiresCcx(member)
+ haveCcx = (member.kind == 'method') and anyParamRequiresCcx(member)
customMethodCall = customMethodCalls.get(stubName, None)
# Write the function
f.write("static %sFASTCALL\n" % getTraceType(member.type))
f.write("%s(JSContext *cx, JSObject *obj" % (stubName + "_tn"))
- if haveCcx:
+ if haveCcx or isInterfaceType(member.realtype):
f.write(", JSObject *callee")
traceInfo["params"].append("CALLEE")
for i, param in enumerate(member.params):
type = getBuiltinOrNativeTypeName(param.realtype)
- f.write(", %sarg%d" % (getTraceType(type), i))
+ f.write(", %s_arg%d" % (getTraceType(type), i))
traceInfo["params"].append(getTraceInfoType(type))
f.write(")\n{\n");
f.write(" XPC_QS_ASSERT_CONTEXT_OK(cx);\n")
# Create ccx if needed.
if haveCcx:
f.write(" XPCCallContext ccx(JS_CALLER, cx, obj, callee);\n")
+ if isInterfaceType(member.realtype):
+ f.write(" XPCLazyCallContext lccx(ccx);\n")
# Get the 'self' pointer.
if customMethodCall is None or not 'thisType' in customMethodCall:
f.write(" %s *self;\n" % member.iface.name)
else:
f.write(" %s *self;\n" % customMethodCall['thisType'])
f.write(" xpc_qsSelfRef selfref;\n")
- f.write(" xpc_qsTempRoot tvr(cx);\n")
+ f.write(" xpc_qsArgValArray<%d> vp(cx);\n" % (1 + len(member.params)))
if haveCcx:
f.write(" if (!xpc_qsUnwrapThisFromCcx(ccx, &self, &selfref.ptr, "
- "tvr.addr())) {\n")
+ "&vp.array[0])) {\n")
+ elif (member.kind == 'method') and isInterfaceType(member.realtype):
+ f.write(" XPCLazyCallContext lccx(JS_CALLER, cx, obj);\n")
+ f.write(" if (!xpc_qsUnwrapThis(cx, obj, callee, &self, &selfref.ptr, "
+ "&vp.array[0], &lccx)) {\n")
else:
- f.write(" if (!xpc_qsUnwrapThis(cx, obj, &self, &selfref.ptr, "
- "tvr.addr())) {\n")
+ f.write(" if (!xpc_qsUnwrapThis(cx, obj, nsnull, &self, &selfref.ptr, "
+ "&vp.array[0], nsnull)) {\n")
writeFailure(f, getTraceInfoDefaultReturn(member.type), 2)
argNames = []
# Convert in-parameters.
rvdeclared = False
for i, param in enumerate(member.params):
validateParam(member, param)
type = unaliasType(param.realtype)
- argName = "_arg%d" % i
+ argName = "arg%d" % i
rvdeclared = writeTraceableArgumentConversion(f, member, i, argName,
param.realtype,
haveCcx, rvdeclared)
argNames.append(argName)
@@ -1122,11 +1119,11 @@
" \"Got the wrong answer from the custom "
"method call!\");\n")
f.write("#endif\n")
# Convert the return value.
- writeTraceableResultConv(f, member.realtype, len(member.params) + 1)
+ writeTraceableResultConv(f, member.realtype)
# Epilog.
f.write("}\n\n")
# Write the JS_DEFINE_TRCINFO block
@@ -1138,11 +1135,11 @@
def writeAttrStubs(f, customMethodCalls, attr):
getterName = (attr.iface.name + '_'
+ header.attributeNativeName(attr, True))
writeQuickStub(f, customMethodCalls, attr, getterName)
if attr.readonly:
- setterName = 'xpc_qsReadOnlySetter'
+ setterName = 'js_GetterOnlyPropertyStub'
else:
setterName = (attr.iface.name + '_'
+ header.attributeNativeName(attr, False))
writeQuickStub(f, customMethodCalls, attr, setterName, isSetter=True)
@@ -1160,11 +1157,11 @@
def writeTraceableStub(f, customMethodCalls, method):
""" Write a method stub to `f`. Return an xpc_qsTraceableSpec initializer. """
stubName = method.iface.name + '_' + header.methodNativeName(method)
writeTraceableQuickStub(f, customMethodCalls, method, stubName)
fs = '{"%s", %s, %d}' % (method.name,
- "JS_DATA_TO_FUNC_PTR(JSNative, %s_trcinfo)" % stubName,
+ "JS_DATA_TO_FUNC_PTR(JSNative, &%s_trcinfo)" % stubName,
len(method.params))
return fs
def writeStubsForInterface(f, customMethodCalls, iface):
f.write("// === interface %s\n\n" % iface.name)
@@ -1228,12 +1225,11 @@
f.write(" memset(interfaces, 0, %d * "
"sizeof(XPCNativeInterface*));\n" % count)
f.write("}\n\n")
i = 0
for type in resulttypes:
- f.write("XPC_QS_DEFINE_XPCNATIVEINTERFACE_GETTER(%s, interfaces[%d])\n"
- % (type, i))
+ f.write("static const PRUint32 k_%s = %d;\n" % (type, i))
i += 1
if count > 0:
f.write("\n\n")
def writeDefiner(f, conf, interfaces):
@@ -1355,11 +1351,11 @@
def writeStubFile(filename, headerFilename, conf, interfaces):
print "Creating stub file", filename
make_targets.append(filename)
f = open(filename, 'w')
- filesIncluded = sets.Set()
+ filesIncluded = set()
def includeType(type):
type = unaliasType(type)
if type.kind in ('builtin', 'native'):
return None
@@ -1396,10 +1392,10 @@
f.write('#include "%s"\n' % customInclude)
resulttypes = []
for iface in interfaces:
resulttypes.extend(writeIncludesForInterface(iface))
f.write("\n\n")
- writeResultXPCInterfacesArray(f, conf, sets.ImmutableSet(resulttypes))
+ writeResultXPCInterfacesArray(f, conf, frozenset(resulttypes))
for iface in interfaces:
writeStubsForInterface(f, conf.customMethodCalls, iface)
writeDefiner(f, conf, interfaces)
finally:
f.close()