зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1683281 - Part 6-1: Create CGHelperFunctionGenerator and refactor into more generic base class; r=peterv
So we could reuse it to generate helper function for observable array type Depends on D112280 Differential Revision: https://phabricator.services.mozilla.com/D113728
This commit is contained in:
Родитель
ebd37b74c8
Коммит
d70b01fd77
|
@ -21501,7 +21501,7 @@ class CGMaplikeOrSetlikeMethodGenerator(CGThing):
|
|||
|
||||
def appendBoolResult(self):
|
||||
if self.helperImpl:
|
||||
return ([CGGeneric()], ["&aRetVal"], [])
|
||||
return ([CGGeneric("bool retVal;\n")], ["&retVal"], [])
|
||||
return ([CGGeneric("bool result;\n")], ["&result"], [])
|
||||
|
||||
def forEach(self):
|
||||
|
@ -21578,7 +21578,7 @@ class CGMaplikeOrSetlikeMethodGenerator(CGThing):
|
|||
code = []
|
||||
# We don't need to create the result variable because it'll be created elsewhere
|
||||
# for JSObject Get method
|
||||
if not self.helperImpl or not self.helperImpl.handleJSObjectGetHelper():
|
||||
if not self.helperImpl or not self.helperImpl.needsScopeBody():
|
||||
code = [
|
||||
CGGeneric(
|
||||
dedent(
|
||||
|
@ -21647,19 +21647,20 @@ class CGMaplikeOrSetlikeMethodGenerator(CGThing):
|
|||
return self.cgRoot.define()
|
||||
|
||||
|
||||
class CGMaplikeOrSetlikeHelperFunctionGenerator(CallbackMember):
|
||||
class CGHelperFunctionGenerator(CallbackMember):
|
||||
"""
|
||||
Generates code to allow C++ to perform operations on backing objects. Gets
|
||||
a context from the binding wrapper, turns arguments into JS::Values (via
|
||||
Generates code to allow C++ to perform operations. Gets a context from the
|
||||
binding wrapper, turns arguments into JS::Values (via
|
||||
CallbackMember/CGNativeMember argument conversion), then uses
|
||||
CGMaplikeOrSetlikeMethodGenerator to generate the body.
|
||||
|
||||
getCall to generate the body for getting result, and maybe convert the
|
||||
result into return type (via CallbackMember/CGNativeMember result
|
||||
conversion)
|
||||
"""
|
||||
|
||||
class HelperFunction(CGAbstractMethod):
|
||||
"""
|
||||
Generates context retrieval code and rooted JSObject for interface for
|
||||
CGMaplikeOrSetlikeMethodGenerator to use
|
||||
method generator to use
|
||||
"""
|
||||
|
||||
def __init__(self, descriptor, name, args, code, returnType):
|
||||
|
@ -21672,31 +21673,14 @@ class CGMaplikeOrSetlikeHelperFunctionGenerator(CallbackMember):
|
|||
def __init__(
|
||||
self,
|
||||
descriptor,
|
||||
maplikeOrSetlike,
|
||||
name,
|
||||
needsKeyArg=False,
|
||||
needsValueArg=False,
|
||||
needsValueTypeReturn=False,
|
||||
needsBoolReturn=False,
|
||||
args,
|
||||
returnType=BuiltinTypes[IDLBuiltinType.Types.void],
|
||||
needsResultConversion=True,
|
||||
):
|
||||
assert not (needsValueTypeReturn and needsBoolReturn)
|
||||
args = []
|
||||
self.maplikeOrSetlike = maplikeOrSetlike
|
||||
self.needsBoolReturn = needsBoolReturn
|
||||
self.needsValueTypeReturn = needsValueTypeReturn
|
||||
assert returnType.isType()
|
||||
self.needsResultConversion = needsResultConversion
|
||||
|
||||
returnType = (
|
||||
BuiltinTypes[IDLBuiltinType.Types.void]
|
||||
if not self.needsValueTypeReturn
|
||||
else maplikeOrSetlike.valueType
|
||||
)
|
||||
|
||||
if needsKeyArg:
|
||||
args.append(FakeArgument(maplikeOrSetlike.keyType, "aKey"))
|
||||
if needsValueArg:
|
||||
assert needsKeyArg
|
||||
assert not needsValueTypeReturn
|
||||
args.append(FakeArgument(maplikeOrSetlike.valueType, "aValue"))
|
||||
# Run CallbackMember init function to generate argument conversion code.
|
||||
# wrapScope is set to 'obj' when generating maplike or setlike helper
|
||||
# functions, as we don't have access to the CallbackPreserveColor
|
||||
|
@ -21708,26 +21692,21 @@ class CGMaplikeOrSetlikeHelperFunctionGenerator(CallbackMember):
|
|||
descriptor,
|
||||
False,
|
||||
wrapScope="obj",
|
||||
passJSBitsAsNeeded=self.handleJSObjectGetHelper(),
|
||||
passJSBitsAsNeeded=typeNeedsCx(returnType),
|
||||
)
|
||||
|
||||
if self.needsValueTypeReturn:
|
||||
finalReturnType = self.returnType
|
||||
elif needsBoolReturn:
|
||||
finalReturnType = "bool"
|
||||
else:
|
||||
finalReturnType = "void"
|
||||
# Wrap CallbackMember body code into a CGAbstractMethod to make
|
||||
# generation easier.
|
||||
self.implMethod = CGMaplikeOrSetlikeHelperFunctionGenerator.HelperFunction(
|
||||
descriptor, name, self.args, self.body, finalReturnType
|
||||
self.implMethod = CGHelperFunctionGenerator.HelperFunction(
|
||||
descriptor, name, self.args, self.body, self.returnType
|
||||
)
|
||||
|
||||
def getCallSetup(self):
|
||||
# If handleJSObjectGetHelper is true, it means the caller will provide a JSContext,
|
||||
# so we don't need to create JSContext and enter UnprivilegedJunkScopeOrWorkerGlobal here.
|
||||
# If passJSBitsAsNeeded is true, it means the caller will provide a
|
||||
# JSContext, so we don't need to create JSContext and enter
|
||||
# UnprivilegedJunkScopeOrWorkerGlobal here.
|
||||
code = "MOZ_ASSERT(self);\n"
|
||||
if not self.handleJSObjectGetHelper():
|
||||
if not self.passJSBitsAsNeeded:
|
||||
code += dedent(
|
||||
"""
|
||||
AutoJSAPI jsapi;
|
||||
|
@ -21761,21 +21740,12 @@ class CGMaplikeOrSetlikeHelperFunctionGenerator(CallbackMember):
|
|||
% self.getDefaultRetval()
|
||||
)
|
||||
|
||||
# For the JSObject Get method, we'd like wrap the inner code in a scope such that
|
||||
# the code can use the same realm. So here we are creating the result variable
|
||||
# outside of the scope.
|
||||
if self.handleJSObjectGetHelper():
|
||||
code += dedent(
|
||||
"""
|
||||
JS::Rooted<JS::Value> result(cx);
|
||||
"""
|
||||
)
|
||||
else:
|
||||
code += dedent(
|
||||
"""
|
||||
JSAutoRealm reflectorRealm(cx, obj);
|
||||
"""
|
||||
)
|
||||
# We'd like wrap the inner code in a scope such that the code can use the
|
||||
# same realm. So here we are creating the result variable outside of the
|
||||
# scope.
|
||||
if self.needsScopeBody():
|
||||
code += "JS::Rooted<JS::Value> result(cx);\n"
|
||||
|
||||
return code
|
||||
|
||||
def getArgs(self, returnType, argList):
|
||||
|
@ -21785,20 +21755,15 @@ class CGMaplikeOrSetlikeHelperFunctionGenerator(CallbackMember):
|
|||
return [Argument(self.descriptorProvider.nativeType + "*", "self")] + args
|
||||
|
||||
def needsScopeBody(self):
|
||||
return self.handleJSObjectGetHelper()
|
||||
return self.passJSBitsAsNeeded
|
||||
|
||||
def getArgvDeclFailureCode(self):
|
||||
return "aRv.Throw(NS_ERROR_UNEXPECTED);\n"
|
||||
|
||||
def handleJSObjectGetHelper(self):
|
||||
return self.needsValueTypeReturn and self.maplikeOrSetlike.valueType.isObject()
|
||||
|
||||
def getResultConversion(self):
|
||||
if self.needsBoolReturn:
|
||||
return "return aRetVal;\n"
|
||||
elif self.needsValueTypeReturn:
|
||||
if self.needsResultConversion:
|
||||
code = ""
|
||||
if self.handleJSObjectGetHelper():
|
||||
if self.needsScopeBody():
|
||||
code = dedent(
|
||||
"""
|
||||
if (!JS_WrapValue(cx, &result)) {
|
||||
|
@ -21811,7 +21776,7 @@ class CGMaplikeOrSetlikeHelperFunctionGenerator(CallbackMember):
|
|||
failureCode = dedent("aRv.Throw(NS_ERROR_UNEXPECTED);\nreturn nullptr;\n")
|
||||
|
||||
exceptionCode = None
|
||||
if self.maplikeOrSetlike.valueType.isPrimitive():
|
||||
if self.retvalType.isPrimitive():
|
||||
exceptionCode = dedent(
|
||||
"aRv.NoteJSContextException(cx);\nreturn%s;\n"
|
||||
% self.getDefaultRetval()
|
||||
|
@ -21824,34 +21789,26 @@ class CGMaplikeOrSetlikeHelperFunctionGenerator(CallbackMember):
|
|||
isDefinitelyObject=True,
|
||||
exceptionCode=exceptionCode,
|
||||
)
|
||||
return "return;\n"
|
||||
|
||||
assignRetval = string.Template(
|
||||
self.getRetvalInfo(self.retvalType, False)[2]
|
||||
).substitute(
|
||||
{
|
||||
"declName": "retVal",
|
||||
}
|
||||
)
|
||||
return assignRetval
|
||||
|
||||
def getRvalDecl(self):
|
||||
if self.needsBoolReturn:
|
||||
return "bool aRetVal;\n"
|
||||
elif self.handleJSObjectGetHelper():
|
||||
return "JSAutoRealm reflectorRealm(cx, obj);\n"
|
||||
return ""
|
||||
# hack to make sure we put JSAutoRealm inside the body scope
|
||||
return "JSAutoRealm reflectorRealm(cx, obj);\n"
|
||||
|
||||
def getArgcDecl(self):
|
||||
# Don't need argc for anything.
|
||||
return None
|
||||
|
||||
def getDefaultRetval(self):
|
||||
if self.needsBoolReturn:
|
||||
return " false"
|
||||
elif self.needsValueTypeReturn:
|
||||
return CallbackMember.getDefaultRetval(self)
|
||||
return ""
|
||||
|
||||
def getCall(self):
|
||||
return CGMaplikeOrSetlikeMethodGenerator(
|
||||
self.descriptorProvider,
|
||||
self.maplikeOrSetlike,
|
||||
self.name.lower(),
|
||||
self.needsValueTypeReturn,
|
||||
helperImpl=self,
|
||||
).define()
|
||||
assert False # Override me!
|
||||
|
||||
def getPrettyName(self):
|
||||
return self.name
|
||||
|
@ -21863,6 +21820,61 @@ class CGMaplikeOrSetlikeHelperFunctionGenerator(CallbackMember):
|
|||
return self.implMethod.define()
|
||||
|
||||
|
||||
class CGMaplikeOrSetlikeHelperFunctionGenerator(CGHelperFunctionGenerator):
|
||||
"""
|
||||
Generates code to allow C++ to perform operations on backing objects. Gets
|
||||
a context from the binding wrapper, turns arguments into JS::Values (via
|
||||
CallbackMember/CGNativeMember argument conversion), then uses
|
||||
CGMaplikeOrSetlikeMethodGenerator to generate the body.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
descriptor,
|
||||
maplikeOrSetlike,
|
||||
name,
|
||||
needsKeyArg=False,
|
||||
needsValueArg=False,
|
||||
needsValueTypeReturn=False,
|
||||
needsBoolReturn=False,
|
||||
needsResultConversion=True,
|
||||
):
|
||||
self.maplikeOrSetlike = maplikeOrSetlike
|
||||
self.needsValueTypeReturn = needsValueTypeReturn
|
||||
|
||||
args = []
|
||||
if needsKeyArg:
|
||||
args.append(FakeArgument(maplikeOrSetlike.keyType, "aKey"))
|
||||
if needsValueArg:
|
||||
assert needsKeyArg
|
||||
assert not needsValueTypeReturn
|
||||
args.append(FakeArgument(maplikeOrSetlike.valueType, "aValue"))
|
||||
|
||||
returnType = BuiltinTypes[IDLBuiltinType.Types.void]
|
||||
if needsBoolReturn:
|
||||
returnType = BuiltinTypes[IDLBuiltinType.Types.boolean]
|
||||
elif needsValueTypeReturn:
|
||||
returnType = maplikeOrSetlike.valueType
|
||||
|
||||
CGHelperFunctionGenerator.__init__(
|
||||
self,
|
||||
descriptor,
|
||||
name,
|
||||
args,
|
||||
returnType,
|
||||
needsResultConversion,
|
||||
)
|
||||
|
||||
def getCall(self):
|
||||
return CGMaplikeOrSetlikeMethodGenerator(
|
||||
self.descriptorProvider,
|
||||
self.maplikeOrSetlike,
|
||||
self.name.lower(),
|
||||
self.needsValueTypeReturn,
|
||||
helperImpl=self,
|
||||
).define()
|
||||
|
||||
|
||||
class CGMaplikeOrSetlikeHelperGenerator(CGNamespace):
|
||||
"""
|
||||
Declares and defines convenience methods for accessing backing objects on
|
||||
|
@ -21889,6 +21901,7 @@ class CGMaplikeOrSetlikeHelperGenerator(CGNamespace):
|
|||
"Delete",
|
||||
needsKeyArg=True,
|
||||
needsBoolReturn=True,
|
||||
needsResultConversion=False,
|
||||
),
|
||||
CGMaplikeOrSetlikeHelperFunctionGenerator(
|
||||
descriptor,
|
||||
|
@ -21896,6 +21909,7 @@ class CGMaplikeOrSetlikeHelperGenerator(CGNamespace):
|
|||
"Has",
|
||||
needsKeyArg=True,
|
||||
needsBoolReturn=True,
|
||||
needsResultConversion=False,
|
||||
),
|
||||
]
|
||||
if self.maplikeOrSetlike.isMaplike():
|
||||
|
|
Загрузка…
Ссылка в новой задаче