0

Specify the layout of mojo result response

In general, mojo expects responses to be structs, so we do not want to
change this. Instead, result responses are effectively structs with a
single field "result," which is a union comprised of a "success" field
and a "failure" field.

Bug: 40841428
Change-Id: I634aa28573fac3fccf432583a0bf0fe0227910ae
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6302338
Commit-Queue: Fred Shih <ffred@chromium.org>
Reviewed-by: Alex Gough <ajgo@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1430529}
This commit is contained in:
Fred Shih
2025-03-10 15:27:52 -07:00
committed by Chromium LUCI CQ
parent 53739ec95d
commit 67ec7b3da6
5 changed files with 111 additions and 15 deletions
mojo

@ -157,6 +157,12 @@ export const ResultTestErrorSpec: { $: mojo.internal.MojomType } =
export const ResultInterface_Method_ParamsSpec: { $: mojo.internal.MojomType } =
{ $: {} as unknown as mojo.internal.MojomType };
export const ResultInterface_Method_ResponseParamsSpec: { $: mojo.internal.MojomType } =
{ $: {} as unknown as mojo.internal.MojomType };
export const ResultInterface_Method_ResponseParams_ResultSpec: { $: mojo.internal.MojomType } =
{ $: {} as unknown as mojo.internal.MojomType };
@ -201,3 +207,47 @@ mojo.internal.Struct<ResultInterface_Method_ParamsMojoType>(
export interface ResultInterface_Method_ResponseParamsMojoType {
result: ResultInterface_Method_ResponseParams_Result;
}
export type ResultInterface_Method_ResponseParams = ResultInterface_Method_ResponseParamsMojoType;
mojo.internal.Struct<ResultInterface_Method_ResponseParamsMojoType>(
ResultInterface_Method_ResponseParamsSpec.$,
'ResultInterface_Method_ResponseParams',
[
mojo.internal.StructField<ResultInterface_Method_ResponseParamsMojoType, ResultInterface_Method_ResponseParams_Result>(
'result', 0,
0,
ResultInterface_Method_ResponseParams_ResultSpec.$,
null,
false /* nullable */,
0,
undefined,
undefined,
),
],
[[0, 24],]);
mojo.internal.Union(
ResultInterface_Method_ResponseParams_ResultSpec.$, 'ResultInterface_Method_ResponseParams_Result',
{
'success': {
'ordinal': 0,
'type': mojo.internal.Bool,
},
'failure': {
'ordinal': 1,
'type': ResultTestErrorSpec.$,
},
});
export interface ResultInterface_Method_ResponseParams_Result {
success?: boolean,
failure?: ResultTestError,
}

@ -188,7 +188,8 @@ def AddComputedData(module):
interface.version = max(interface.version,
method.param_struct.versions[-1].version)
if method.response_parameters is not None:
if method.response_parameters is not None or \
method.result_response is not None:
method.response_param_struct = _GetResponseStructFromMethod(method)
if interface.stable:
method.response_param_struct.attributes[mojom.ATTRIBUTE_STABLE] = True
@ -218,6 +219,13 @@ def AddComputedData(module):
"""Converts a method's response_parameters into the fields of a struct."""
params_class = "%s_%s_ResponseParams" % (method.interface.mojom_name,
method.mojom_name)
if method.response_parameters is not None:
return _GetResponseStructForParamList(method, params_class)
if method.result_response is not None:
return _GetResponseStructForResultResponse(method, params_class)
raise Exception('method should only be called for methods with response')
def _GetResponseStructForParamList(method, params_class):
struct = mojom.Struct(params_class,
module=method.interface.module,
attributes={})
@ -230,6 +238,30 @@ def AddComputedData(module):
_AddStructComputedData(False, struct)
return struct
def _GetResponseStructForResultResponse(method, params_class):
struct = mojom.Struct(params_class,
module=method.interface.module,
attributes={})
result = method.interface.module.AddUnion(f"{params_class}_Result")
result.AddField(
'success',
method.result_response.success_kind,
0,
)
result.AddField(
'failure',
method.result_response.failure_kind,
1,
)
struct.AddField(
'result',
result,
0,
)
_AddStructComputedData(False, struct)
return struct
for struct in module.structs:
_AddStructComputedData(True, struct)
for interface in module.interfaces:

@ -955,14 +955,14 @@ class Parameter:
class Result:
def __init__(self, success_type, failure_type):
self.success_type = success_type
self.failure_type = failure_type
def __init__(self, success_kind, failure_kind):
self.success_kind = success_kind
self.failure_kind = failure_kind
def Repr(self):
return GenericRepr(self, {
'success_type': self.success_type,
'failure_type': self.failure_type,
'success_kind': self.success_kind,
'failure_kind': self.failure_kind,
})

@ -808,8 +808,13 @@ def _Method(module, parsed_method, interface):
parsed_method.response_parameter_list))
if parsed_method.result_response is not None:
result_type = parsed_method.result_response
method.result = mojom.Result(_MapKind(result_type.success_type),
_MapKind(result_type.failure_type))
success_kind = _Kind(module, module.kinds,
_MapKind(result_type.success_type),
(module.mojom_namespace, interface.mojom_name))
failure_kind = _Kind(module, module.kinds,
_MapKind(result_type.failure_type),
(module.mojom_namespace, interface.mojom_name))
method.result_response = mojom.Result(success_kind, failure_kind)
method.attributes = _AttributeListToDict(module, method,
parsed_method.attribute_list)

@ -20,10 +20,12 @@ class ResultTest(MojomParserTestCase):
a = self.LoadModule(a_mojom)
self.assertEqual(1, len(a.interfaces))
self.assertEqual(1, len(a.interfaces[0].methods))
self.assertEqual('b', a.interfaces[0].methods[0].result.success_type)
self.assertEqual('s', a.interfaces[0].methods[0].result.failure_type)
self.assertEqual(mojom.BOOL,
a.interfaces[0].methods[0].result_response.success_kind)
self.assertEqual(mojom.STRING,
a.interfaces[0].methods[0].result_response.failure_kind)
def testResultResponse(self):
def testResultResponseStructs(self):
a_mojom = 'a.mojom'
self.WriteFile(
a_mojom, """
@ -38,7 +40,14 @@ class ResultTest(MojomParserTestCase):
a = self.LoadModule(a_mojom)
self.assertEqual(1, len(a.interfaces))
self.assertEqual(1, len(a.interfaces[0].methods))
self.assertEqual('x:Success',
a.interfaces[0].methods[0].result.success_type)
self.assertEqual('x:Failure',
a.interfaces[0].methods[0].result.failure_type)
result_response = a.interfaces[0].methods[0].result_response
self.assertIsNotNone(result_response.success_kind)
self.assertIsNotNone(result_response.failure_kind)
name_to_kind = {}
for kind in a.structs:
name_to_kind[kind.mojom_name] = kind
self.assertEqual(name_to_kind['Success'], result_response.success_kind)
self.assertEqual(name_to_kind['Failure'], result_response.failure_kind)