Commit 9e2d6ecc authored by Giovanni Ortuño Urquidi's avatar Giovanni Ortuño Urquidi Committed by Commit Bot

mojo-ts: Add necessary things for minimum TS/JS bindings generation

Adds:

1. "enable_typescript_bindings" gn arg, which must be set to true
   to test Typescript bindings.
2. "use_typescript_sources" gn variable that can be set to opt-in a
   target into generating Typescript bindings.
3. Test interfaces folder where interfaces will be added as features
   are implemented.
4. A mojom gn target that includes the tests interfaces. This target is
   included as part of mojo_unittests
5. Basic template and generator implementation.
6. Script to compile generated Typescript bindings into JS bindings.

Bug: 1002798
Change-Id: Id8424d707ad4b2ec9a773b291fd4a41332623274
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1817860Reviewed-by: default avatarDan Beam <dbeam@chromium.org>
Reviewed-by: default avatarKen Rockot <rockot@google.com>
Commit-Queue: Giovanni Ortuño Urquidi <ortuno@chromium.org>
Cr-Commit-Position: refs/heads/master@{#699993}
parent bbc3d86b
......@@ -41,6 +41,7 @@ test("mojo_unittests") {
"//mojo/public/cpp/bindings/tests",
"//mojo/public/cpp/platform/tests",
"//mojo/public/cpp/system/tests",
"//mojo/public/js/ts/bindings/tests",
]
}
......
# Mojo Typescript/JavaScript Bindings
Generated Mojo Typescript bindings are compiled to plain JavaScript bindings for
plain JavaScript clients and to Closure-annotated JavaScript for Closure
clients.
**These bindings are work in progress and are not ready for general use.**
## Getting started
To use the Typescript bindings to generate JS bindings, set
`use_typescript_sources` to true in your mojom target:
```
mojom("interfaces") {
sources = [
"echo.mojom",
]
use_typescript_sources = true
}
```
and add `enable_typescript_bindings = true` to your `args.gn`.
## Tests
There are two sets of tests: compilation and runtime.
* Compilation tests are done by including the
`//mojo/public/js/ts/bindings/tests` gn target, which triggers the Typescript
bindings generation and their compilation. This target is included as part of
`mojo_unittests`.
* Runtime tests are done as part of Blink's Web Tests. They are in
`//third_party/blink/web_tests/mojo/bindings-lite-*.html`.
# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import("//mojo/public/tools/bindings/mojom.gni")
# Partial copy of //mojo/public/interfaces/bindings/tests:test_interfaces. Used
# to incrementally develop Typescript bindings.
mojom("test_interfaces") {
testonly = true
sources = [
"module.test-mojom",
]
use_typescript_sources = true
}
source_set("tests") {
testonly = true
deps = [
":test_interfaces_js",
]
}
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Empty Mojo module. Used to incrementally develop Typescript Bindings.
module mojo.tstest;
......@@ -79,6 +79,8 @@ action("precompile_templates") {
"$mojom_generator_root/generators/js_templates/struct_definition.tmpl",
"$mojom_generator_root/generators/js_templates/union_definition.tmpl",
"$mojom_generator_root/generators/js_templates/validation_macros.tmpl",
"$mojom_generator_root/generators/ts_templates/module_definition.tmpl",
"$mojom_generator_root/generators/ts_templates/mojom.tmpl",
]
script = mojom_generator_script
......@@ -87,6 +89,7 @@ action("precompile_templates") {
"$target_gen_dir/cpp_templates.zip",
"$target_gen_dir/java_templates.zip",
"$target_gen_dir/js_templates.zip",
"$target_gen_dir/ts_templates.zip",
]
args = [
"--use_bundled_pylibs",
......
# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import os
import sys
import argparse
_HERE_PATH = os.path.dirname(__file__)
_SRC_PATH = os.path.normpath(os.path.join(_HERE_PATH, '..', '..', '..', '..'))
sys.path.append(os.path.join(_SRC_PATH, 'third_party', 'node'))
import node
import node_modules
def main(argv):
parser = argparse.ArgumentParser()
parser.add_argument('--filelist', required=True)
args = parser.parse_args(argv)
files = []
with open(args.filelist) as filelist_file:
for line in filelist_file:
for f in line.split():
files.append(os.path.join(os.getcwd(), f))
file_paths = ' '.join(files)
result = node.RunNode(
[node_modules.PathToTypescript()] +
[
"--target 'es6'",
"--module 'es6'",
"--lib 'es6'",
"--strict",
file_paths
])
if len(result) != 0:
raise RuntimeError('Failed to compile Typescript: \n%s' % result)
if __name__ == '__main__':
main(sys.argv[1:])
# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Generates Typescript source files from a mojom.Module."""
import mojom.generate.generator as generator
from mojom.generate.template_expander import UseJinja
class TypescriptStylizer(generator.Stylizer):
def StylizeModule(self, mojom_namespace):
return '.'.join(generator.ToCamel(word, lower_initial=True)
for word in mojom_namespace.split('.'))
class Generator(generator.Generator):
def _GetParameters(self, use_es_modules=False):
return {
"module": self.module,
"use_es_modules": use_es_modules,
}
@staticmethod
def GetTemplatePrefix():
return "ts_templates"
def GetFilters(self):
ts_filters = {}
return ts_filters
@UseJinja("mojom.tmpl")
def _GenerateBindings(self):
return self._GetParameters()
@UseJinja("mojom.tmpl")
def _GenerateESModulesBindings(self):
return self._GetParameters(use_es_modules=True)
def GenerateFiles(self, args):
if self.variant:
raise Exception("Variants not supported in JavaScript bindings.")
self.module.Stylize(TypescriptStylizer())
self.Write(self._GenerateBindings(), "%s-lite.ts" % self.module.path)
self.Write(self._GenerateESModulesBindings(),
"%s-lite.m.ts" % self.module.path)
{%- if not use_es_modules %}
namespace {{module.namespace}} {
{% endif %}
{%- if not use_es_modules %}
} // namespace {{module.namespace}}
{% endif %}
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
{% include "module_definition.tmpl" %}
......@@ -43,6 +43,9 @@ declare_args() {
# Enable adding annotations to generated C++ headers that are used for
# cross-references in CodeSearch.
enable_kythe_annotations = false
# Enables generating Typescript bindings and compiling them to JS bindings.
enable_typescript_bindings = false
}
# NOTE: We would like to avoid scrambling message IDs where it doesn't add
......@@ -64,6 +67,7 @@ enable_scrambled_message_ids =
((enable_nacl || is_nacl || is_nacl_nonsfi) && target_os != "chromeos"))
mojom_generator_root = "//mojo/public/tools/bindings"
compile_typescript_script = "$mojom_generator_root/compile_typescript.py"
mojom_generator_script = "$mojom_generator_root/mojom_bindings_generator.py"
mojom_generator_sources = [
"$mojom_generator_root/generators/mojom_cpp_generator.py",
......@@ -286,6 +290,9 @@ if (enable_mojom_typemapping) {
# Use old names i.e. FooProxy, Foo, getProxy(), etc. instead of the new
# names i.e. FooRemote, FooReceiver, getRemote(), etc.
#
# use_typescript_sources (optional)
# Uses the Typescript generator to generate JavaScript bindings.
#
# The following parameters are used to support the component build. They are
# needed so that bindings which are linked with a component can use the same
# export settings for classes. The first three are for the chromium variant, and
......@@ -1221,7 +1228,16 @@ template("mojom") {
}
}
if (generate_fuzzing || !defined(invoker.cpp_only) || !invoker.cpp_only) {
use_typescript_for_target =
enable_typescript_bindings && defined(invoker.use_typescript_sources) &&
invoker.use_typescript_sources
if (!use_typescript_for_target && defined(invoker.use_typescript_sources)) {
not_needed(invoker, [ "use_typescript_sources" ])
}
if ((generate_fuzzing || !defined(invoker.cpp_only) || !invoker.cpp_only) &&
!use_typescript_for_target) {
if (defined(invoker.sources)) {
generator_js_target_name = "${target_name}_js__generator"
generator_js_lite_outputs =
......@@ -1355,6 +1371,79 @@ template("mojom") {
}
}
}
if ((generate_fuzzing || !defined(invoker.cpp_only) || !invoker.cpp_only) &&
use_typescript_for_target) {
generator_ts_target_name = "${target_name}_ts__generator"
source_filelist = []
ts_filelist = []
ts_outputs = []
js_outputs = []
foreach(source, invoker.sources) {
source_filelist += [ rebase_path("$source", root_build_dir) ]
ts_outputs += [
"$target_gen_dir/$source-lite.ts",
"$target_gen_dir/$source-lite.m.ts",
]
ts_filelist += [
rebase_path("$target_gen_dir/$source-lite.ts", root_build_dir),
rebase_path("$target_gen_dir/$source-lite.m.ts", root_build_dir),
]
js_outputs += [
"$target_gen_dir/$source-lite.js",
"$target_gen_dir/$source-lite.m.js",
]
}
generator_ts_target_name = "${target_name}_ts__generator"
action(generator_ts_target_name) {
script = mojom_generator_script
inputs = mojom_generator_sources + jinja2_sources
sources = invoker.sources
deps = [
":$parsed_target_name",
"//mojo/public/tools/bindings:precompile_templates",
] + verify_deps_target_names
outputs = ts_outputs
args = common_generator_args
response_file_contents = source_filelist
args += [
"--filelist={{response_file_name}}",
"-g",
"typescript",
]
# TODO(crbug.com/1007587): Support scramble_message_ids.
# TODO(crbug.com/1007591): Support generate_fuzzing.
}
generator_js_target_name = "${target_name}_js__generator"
action(generator_js_target_name) {
script = compile_typescript_script
sources = ts_outputs
outputs = js_outputs
public_deps = [
":$generator_ts_target_name",
]
response_file_contents = ts_filelist
args = [ "--filelist={{response_file_name}}" ]
}
js_target_name = target_name + "_js"
group(js_target_name) {
public_deps = []
if (defined(invoker.sources)) {
public_deps += [ ":$generator_js_target_name" ]
}
foreach(d, all_deps) {
full_name = get_label_info(d, "label_no_toolchain")
public_deps += [ "${full_name}_js" ]
}
}
}
}
# A helper for the mojom() template above when component libraries are desired
......
......@@ -61,6 +61,7 @@ _BUILTIN_GENERATORS = {
"c++": "mojom_cpp_generator",
"javascript": "mojom_js_generator",
"java": "mojom_java_generator",
"typescript": "mojom_ts_generator",
}
......
......@@ -36,3 +36,8 @@ def PathToSvgo():
def PathToUglify():
return _path_in_node_modules('uglify-es', 'bin', 'uglifyjs')
# Typescript is not approved for general use in Chromium. Email chromium-dev
# if you want to use it.
def PathToTypescript():
return _path_in_node_modules('typescript', 'bin', 'tsc')
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment