Implement ts_import for typemap
This introduces a ts_import path configuration for ts_typemap. When present, both the convert and webui code will import the necessary deps. Updated the nested test case to be a bit more interesting. Sample output: webui: gpaste/6232011783274496 converters: gpaste/4842181136482304 Bug: 40615900 Change-Id: I51eb269f4a76b8be629b7e2de159fd397f7d99fe Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5827800 Reviewed-by: Ken Rockot <rockot@google.com> Reviewed-by: Rebekah Potter <rbpotter@chromium.org> Reviewed-by: Charlie Reis <creis@chromium.org> Commit-Queue: Fred Shih <ffred@chromium.org> Cr-Commit-Position: refs/heads/main@{#1352268}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
6cd0f9325b
commit
8275fba70f
content/test
mojo/public/tools/bindings
@ -1183,10 +1183,8 @@ mojom("web_ui_ts_test_mojo_bindings") {
|
||||
},
|
||||
{
|
||||
mojom = "content.mojom.NestedMappedType"
|
||||
|
||||
# TODO(ffred): we should allow ts_import so we can typemap to user
|
||||
# defined types.
|
||||
ts = "Object"
|
||||
ts = "TestNode"
|
||||
ts_import = "./web_ui_mojo_ts_test_node.js"
|
||||
converter = "NestedTypeConverter"
|
||||
import = "web_ui_mojo_ts_test_converters.js"
|
||||
},
|
||||
@ -1200,6 +1198,7 @@ preprocess_if_expr("preprocess_mojo_webui_test") {
|
||||
out_folder = "$target_gen_dir/data"
|
||||
in_files = [
|
||||
"web_ui_mojo_ts_test.ts",
|
||||
"web_ui_mojo_ts_test_node.ts",
|
||||
"web_ui_mojo_ts_test_converters.ts",
|
||||
"web_ui_managed_interface_test.ts",
|
||||
]
|
||||
@ -1210,6 +1209,7 @@ webui_ts_library("web_ui_mojo_test_build_ts") {
|
||||
out_dir = "$target_gen_dir/data/tsc"
|
||||
in_files = [
|
||||
"web_ui_mojo_ts_test.ts",
|
||||
"web_ui_mojo_ts_test_node.ts",
|
||||
"web_ui_mojo_ts_test_converters.ts",
|
||||
"web_ui_ts_test.test-mojom-converters.ts",
|
||||
"web_ui_ts_test.test-mojom-webui.ts",
|
||||
|
@ -7956,6 +7956,7 @@ data/web_ui_mojo_test.js
|
||||
data/web_ui_mojo_ts_test.html
|
||||
data/web_ui_mojo_ts_test.ts
|
||||
data/web_ui_mojo_ts_test_converters.ts
|
||||
data/web_ui_mojo_ts_test_node.ts
|
||||
data/web_ui_shared_worker.js
|
||||
data/web_ui_test.test-mojom
|
||||
data/web_ui_test_types.test-mojom
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import {TestNode} from './web_ui_mojo_ts_test_node.js';
|
||||
import {OptionalNumericsStruct, TestEnum, WebUITsMojoTestCache} from './web_ui_ts_test.test-mojom-webui.js';
|
||||
|
||||
const TEST_DATA: Array<{url: string, contents: string}> = [
|
||||
@ -76,7 +77,7 @@ async function doTest(): Promise<boolean> {
|
||||
} =
|
||||
await cache.echo(
|
||||
true, null, TestEnum.kOne, testStruct, [], [], [], {}, {}, {}, '',
|
||||
{});
|
||||
new TestNode());
|
||||
if (optionalBool !== false) {
|
||||
return false;
|
||||
}
|
||||
@ -130,7 +131,8 @@ async function doTest(): Promise<boolean> {
|
||||
} =
|
||||
await cache.echo(
|
||||
null, 1, null, testStruct, inOptionalBools, inOptionalInts,
|
||||
inOptionalEnums, inBoolMap, inIntMap, inEnumMap, '', {});
|
||||
inOptionalEnums, inBoolMap, inIntMap, inEnumMap, '',
|
||||
new TestNode());
|
||||
if (optionalBool !== null) {
|
||||
return false;
|
||||
}
|
||||
@ -168,7 +170,7 @@ async function doTest(): Promise<boolean> {
|
||||
{
|
||||
const str = 'foobear';
|
||||
const result = await cache.echo(
|
||||
null, 1, null, testStruct, [], [], [], {}, {}, {}, str, {});
|
||||
null, 1, null, testStruct, [], [], [], {}, {}, {}, str, new TestNode());
|
||||
|
||||
if (result.simpleMappedType !== str) {
|
||||
return false;
|
||||
@ -178,32 +180,30 @@ async function doTest(): Promise<boolean> {
|
||||
// Tests an empty nested struct to test basic encoding/decoding.
|
||||
{
|
||||
const result = await cache.echo(
|
||||
null, 1, null, testStruct, [], [], [], {}, {}, {}, '', {});
|
||||
null, 1, null, testStruct, [], [], [], {}, {}, {}, '', new TestNode());
|
||||
|
||||
assertObjectEquals(
|
||||
{}, result.nestedMappedType,
|
||||
new TestNode(), result.nestedMappedType,
|
||||
'nested mappped type: got: ' + JSON.stringify(result.nestedMappedType) +
|
||||
', expected: {}');
|
||||
', expected: {next: null}');
|
||||
}
|
||||
|
||||
// Tests a nested type where a struct includes itself.
|
||||
{
|
||||
const depth = 10;
|
||||
const testNested: any = {};
|
||||
let cursor = testNested;
|
||||
const chain: TestNode = new TestNode();
|
||||
let cursor = chain;
|
||||
for (let i = 0; i < depth; ++i) {
|
||||
cursor.nested = {} as Object;
|
||||
cursor = cursor.nested;
|
||||
cursor = cursor!.next = new TestNode();
|
||||
}
|
||||
const result = await cache.echo(
|
||||
null, 1, null, testStruct, [], [], [], {}, {}, {}, '', testNested);
|
||||
null, 1, null, testStruct, [], [], [], {}, {}, {}, '', chain);
|
||||
|
||||
if (JSON.stringify(testNested) !==
|
||||
JSON.stringify(result.nestedMappedType)) {
|
||||
if (JSON.stringify(chain) !== JSON.stringify(result.nestedMappedType)) {
|
||||
throw new Error(
|
||||
'nested mappped type: got: ' +
|
||||
JSON.stringify(result.nestedMappedType) +
|
||||
', expected: ' + JSON.stringify(testNested));
|
||||
', expected: ' + JSON.stringify(chain));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import {TestNode} from './web_ui_mojo_ts_test_node.js';
|
||||
import {NestedMappedTypeDataView, NestedMappedTypeTypeMapper, SimpleMappedTypeDataView, SimpleMappedTypeTypeMapper,} from './web_ui_ts_test.test-mojom-converters.js';
|
||||
|
||||
export class SimpleTypeConverter implements SimpleMappedTypeTypeMapper<string> {
|
||||
@ -14,12 +15,13 @@ export class SimpleTypeConverter implements SimpleMappedTypeTypeMapper<string> {
|
||||
}
|
||||
}
|
||||
|
||||
export class NestedTypeConverter implements NestedMappedTypeTypeMapper<Object> {
|
||||
nested(mappedType: any): Object|null {
|
||||
return mappedType?.nested || null;
|
||||
export class NestedTypeConverter implements
|
||||
NestedMappedTypeTypeMapper<TestNode> {
|
||||
nested(mappedType: TestNode): TestNode|null {
|
||||
return mappedType.next;
|
||||
}
|
||||
|
||||
convert(dataView: NestedMappedTypeDataView): Object {
|
||||
return dataView.nested() ? {'nested': dataView.nested()} : {};
|
||||
convert(dataView: NestedMappedTypeDataView): TestNode {
|
||||
return new TestNode(dataView.nested());
|
||||
}
|
||||
}
|
||||
|
17
content/test/data/web_ui_mojo_ts_test_node.ts
Normal file
17
content/test/data/web_ui_mojo_ts_test_node.ts
Normal file
@ -0,0 +1,17 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// This is effectively the same structure as NestedMappedType mojom,
|
||||
// except it is implemented purely in ts and has a different field name
|
||||
// to exercise the conversion logic.
|
||||
//
|
||||
// Using a class instead of an interface in order to have a constructor to
|
||||
// instantiate objects of this type with "new"".
|
||||
export class TestNode {
|
||||
next: TestNode|null;
|
||||
|
||||
constructor(next?: TestNode|null) {
|
||||
this.next = next || null;
|
||||
}
|
||||
}
|
@ -32,6 +32,7 @@ This file specifies resources for content_browsertests.
|
||||
<include name="IDR_WEB_UI_TS_TEST_MOJOM_JS" file="${root_gen_dir}/content/test/data/tsc/web_ui_ts_test.test-mojom-webui.js" use_base_dir="false" type="BINDATA" resource_path="web_ui_ts_test.test-mojom-webui.js" />
|
||||
<include name="IDR_WEB_UI_TS_TEST_MOJOM_CONVERTER_JS" file="${root_gen_dir}/content/test/data/tsc/web_ui_ts_test.test-mojom-converters.js" use_base_dir="false" type="BINDATA" resource_path="web_ui_ts_test.test-mojom-converters.js" />
|
||||
<include name="IDR_WEB_UI_TS_TEST_CONVERTERS_JS" file="${root_gen_dir}/content/test/data/tsc/web_ui_mojo_ts_test_converters.js" use_base_dir="false" type="BINDATA" resource_path="web_ui_mojo_ts_test_converters.js" />
|
||||
<include name="IDR_WEB_UI_TS_TEST_NODE_JS" file="${root_gen_dir}/content/test/data/tsc/web_ui_mojo_ts_test_node.js" use_base_dir="false" type="BINDATA" resource_path="web_ui_mojo_ts_test_node.js" />
|
||||
<include name="IDR_WEB_UI_TS_TEST_TYPES_MOJOM_JS" file="${root_gen_dir}/content/test/data/tsc/web_ui_ts_test_types.test-mojom-webui.js" use_base_dir="false" type="BINDATA" resource_path="web_ui_ts_test_types.test-mojom-webui.js" />
|
||||
</includes>
|
||||
</release>
|
||||
|
@ -105,6 +105,7 @@ def LoadTsTypemapConfig(path):
|
||||
for entry in config['types']:
|
||||
configs[entry['mojom']] = {
|
||||
'typename': entry['ts'],
|
||||
'type_import': entry.get('ts_import', None),
|
||||
'converter_import': entry['import'],
|
||||
'converter': entry['converter'],
|
||||
}
|
||||
|
@ -245,6 +245,8 @@ class Generator(generator.Generator):
|
||||
"unions": self.module.unions,
|
||||
"generate_struct_deserializers": self.js_generate_struct_deserializers,
|
||||
"typemapped_structs": self._TypeMappedStructs(),
|
||||
"typemap_imports": self._TypeMapImports(),
|
||||
"converter_imports": self._ConverterImports(),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
@ -685,3 +687,41 @@ class Generator(generator.Generator):
|
||||
if struct.qualified_name in self.typemap:
|
||||
mapped_structs[struct] = self.typemap[struct.qualified_name]
|
||||
return mapped_structs
|
||||
|
||||
# Returns a list of imports in the format:
|
||||
# {
|
||||
# <import path>: [list of types],
|
||||
# ...
|
||||
# }
|
||||
def _TypeMapImports(self):
|
||||
imports = {}
|
||||
typemaps = self._TypeMappedStructs()
|
||||
|
||||
for typemap in typemaps.values():
|
||||
type_import = typemap['type_import']
|
||||
# The typemapping could just be a native type, in which case there would
|
||||
# not be any import.
|
||||
if not type_import:
|
||||
continue
|
||||
|
||||
imports.setdefault(type_import, []).append(typemap['typename'])
|
||||
|
||||
return imports
|
||||
|
||||
def _ConverterImports(self):
|
||||
imports = {}
|
||||
|
||||
# TODO(ffred): we also need to import types from other *-mojom-webui
|
||||
# dependencies.
|
||||
typemapped_structs = self._TypeMappedStructs()
|
||||
for struct in typemapped_structs:
|
||||
for field in struct.fields:
|
||||
if mojom.IsStructKind(field.kind):
|
||||
qualified = field.kind.qualified_name
|
||||
if qualified in self.typemap:
|
||||
typemap = self.typemap[qualified]
|
||||
typemap_import = typemap['type_import']
|
||||
if typemap_import:
|
||||
imports.setdefault(typemap_import, []).append(typemap['typename'])
|
||||
|
||||
return imports
|
||||
|
@ -8,6 +8,15 @@ import type {
|
||||
} from './{{module_filename}}';
|
||||
{%- endfor %}
|
||||
|
||||
{% for path, types in converter_imports.items()|sort -%}
|
||||
import type {
|
||||
{%- for type in types|sort %}
|
||||
{{type}}
|
||||
{%- if not loop.last -%},{% endif -%}
|
||||
{%- endfor %}
|
||||
} from '{{path}}';
|
||||
{% endfor %}
|
||||
|
||||
{%- for struct in typemapped_structs %}
|
||||
|
||||
export class {{struct.name}}DataView {
|
||||
|
@ -27,6 +27,15 @@ import {
|
||||
{%- endfor %}
|
||||
{%- endif %}
|
||||
|
||||
{% for path, types in typemap_imports.items()|sort -%}
|
||||
import type {
|
||||
{%- for type in types|sort %}
|
||||
{{type}}
|
||||
{%- if not loop.last -%},{% endif -%}
|
||||
{%- endfor %}
|
||||
} from '{{path}}';
|
||||
{% endfor %}
|
||||
|
||||
{% for typemap in typemapped_structs.values() -%}
|
||||
import { {{typemap.converter}} } from './{{typemap.converter_import}}';
|
||||
{% endfor -%}
|
||||
|
@ -11,7 +11,9 @@ mojom("test_mojom") {
|
||||
types = [
|
||||
{
|
||||
mojom = "bindings.tests.mojom.SimpleStruct"
|
||||
ts = "string"
|
||||
ts = "String16"
|
||||
ts_import =
|
||||
"//resources/mojo/mojo/public/mojom/base/string16.mojom-webui.js"
|
||||
converter = "SimpleStructConverter"
|
||||
import = "test_converter.js"
|
||||
},
|
||||
|
@ -3,18 +3,22 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
import { SimpleStructDataView, SimpleStructTypeMapper } from './test.test-mojom-converters.js';
|
||||
import type {
|
||||
String16
|
||||
} from 'chrome://resources/mojo/mojo/public/mojom/base/string16.mojom-webui.js';
|
||||
|
||||
export class SimpleStructConverter implements SimpleStructTypeMapper<string> {
|
||||
str(_: string): string {
|
||||
|
||||
export class SimpleStructConverter implements SimpleStructTypeMapper<String16> {
|
||||
str(_: String16): string {
|
||||
return '';
|
||||
}
|
||||
|
||||
number(_: string): number {
|
||||
number(_: String16): number {
|
||||
return 888;
|
||||
}
|
||||
|
||||
convert(_: SimpleStructDataView): string {
|
||||
return 'hihi';
|
||||
convert(_: SimpleStructDataView): String16 {
|
||||
return {data: []};
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ def CheckTsTypemapConfigs(target_name, config_filename, out_filename):
|
||||
])
|
||||
_SUPPORTED_TYPE_KEYS = set([
|
||||
'ts',
|
||||
'ts_import',
|
||||
'converter',
|
||||
'import',
|
||||
'mojom',
|
||||
|
Reference in New Issue
Block a user