Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatic TypeScript definition generation from JSG RTTI #110

Merged
merged 5 commits into from
Oct 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
.idea
.DS_Store

/rust-deps/target
/rust-deps/Cargo.toml

Expand Down
16 changes: 16 additions & 0 deletions BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
load("@capnp-cpp//src/capnp:cc_capnp_library.bzl", "cc_capnp_library")
load("@hedron_compile_commands//:refresh_compile_commands.bzl", "refresh_compile_commands")
load("@aspect_rules_js//npm:defs.bzl", "npm_link_package", "npm_package")
load("@npm//:defs.bzl", "npm_link_all_packages")
load("@npm//:capnpc-ts/package_json.bzl", capnpc_ts_bin = "bin")

cc_capnp_library(
name = "icudata-embed",
Expand All @@ -13,3 +16,16 @@ cc_capnp_library(
refresh_compile_commands(
name = "refresh_compile_commands",
)

npm_link_all_packages(name = "node_modules")

npm_link_package(
name = "node_modules/@workerd/jsg",
src = "//src/workerd/jsg:jsg_js",
package = "@workerd/jsg",
)

capnpc_ts_bin.capnpc_ts_binary(
name = "capnpc_ts",
visibility = ["//visibility:public"],
)
52 changes: 52 additions & 0 deletions WORKSPACE
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,58 @@ load("//rust-deps/cxxbridge_crates:crates.bzl", cxxbridge_repositories = "crate_

cxxbridge_repositories()

# ========================================================================================
# Node.js bootstrap
#
# workerd uses Node.js scripts for generating TypeScript types.

http_archive(
name = "aspect_rules_js",
sha256 = "b9fde0f20de6324ad443500ae738bda00facbd73900a12b417ce794856e01407",
strip_prefix = "rules_js-1.5.0",
url = "https://github.com/aspect-build/rules_js/archive/refs/tags/v1.5.0.tar.gz",
)

http_archive(
name = "aspect_rules_ts",
sha256 = "743f0e988e4e3f1e25e52c79f9dc3da1ddd77507ae88787ae95b4e70c537872b",
strip_prefix = "rules_ts-1.0.0-rc4",
url = "https://github.com/aspect-build/rules_ts/archive/refs/tags/v1.0.0-rc4.tar.gz",
)

load("@aspect_rules_js//js:repositories.bzl", "rules_js_dependencies")

rules_js_dependencies()

load("@rules_nodejs//nodejs:repositories.bzl", "nodejs_register_toolchains")

nodejs_register_toolchains(
name = "nodejs",
node_version = "18.10.0",
)

load("@aspect_rules_ts//ts:repositories.bzl", TS_LATEST_VERSION = "LATEST_VERSION", "rules_ts_dependencies")
mrbbot marked this conversation as resolved.
Show resolved Hide resolved

rules_ts_dependencies(ts_version = TS_LATEST_VERSION)

load("@aspect_rules_js//npm:npm_import.bzl", "npm_translate_lock")

npm_translate_lock(
name = "npm",
pnpm_lock = "//:pnpm-lock.yaml",
# Patches required for `capnp-ts` to type-check
patches = {
"[email protected]": ["//:patches/[email protected]"],
},
patch_args = {
"[email protected]": ["-p1"],
},
)

load("@npm//:repositories.bzl", "npm_repositories")

npm_repositories()

# ========================================================================================
# V8 and its dependencies
#
Expand Down
124 changes: 124 additions & 0 deletions build/js_capnp_library.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
"""
Bazel rule to compile .capnp files into JavaScript using capnp-ts.
Based on https://github.com/capnproto/capnproto/blob/3b2e368cecc4b1419b40c5970d74a7a342224fac/c++/src/capnp/cc_capnp_library.bzl.
"""

load("@aspect_rules_js//js:defs.bzl", "js_library")

capnp_provider = provider("Capnproto Provider", fields = {
"includes": "includes for this target (transitive)",
"inputs": "src + data for the target",
"src_prefix": "src_prefix of the target",
})

def _workspace_path(label, path):
if label.workspace_root == "":
return path
return label.workspace_root + "/" + path

def _capnp_gen_impl(ctx):
label = ctx.label
src_prefix = _workspace_path(label, ctx.attr.src_prefix)
includes = []

inputs = ctx.files.srcs + ctx.files.data
for dep_target in ctx.attr.deps:
includes += dep_target[capnp_provider].includes
inputs += dep_target[capnp_provider].inputs

if src_prefix != "":
includes.append(src_prefix)

system_include = ctx.files._capnp_system[0].dirname.removesuffix("/capnp")

out_dir = ctx.var["GENDIR"]
if src_prefix != "":
out_dir = out_dir + "/" + src_prefix

js_out = "-o%s:%s" % (ctx.executable._capnpc_ts.path, out_dir)
args = ctx.actions.args()
args.add_all(["compile", "--verbose", js_out])
args.add_all(["-I" + inc for inc in includes])
args.add_all(["-I", system_include])
if src_prefix != "":
args.add_all(["--src-prefix", src_prefix])

args.add_all([s for s in ctx.files.srcs])

ctx.actions.run(
inputs = inputs + ctx.files._capnpc_ts + ctx.files._capnpc_capnp + ctx.files._capnp_system,
tools = [ctx.executable._capnpc_ts], # Include required js_binary runfiles
outputs = ctx.outputs.outs,
executable = ctx.executable._capnpc,
arguments = [args],
mnemonic = "GenCapnp",
)

return [
capnp_provider(
includes = includes,
inputs = inputs,
src_prefix = src_prefix,
),
]

_capnp_gen = rule(
attrs = {
"srcs": attr.label_list(allow_files = True),
"deps": attr.label_list(providers = [capnp_provider]),
"data": attr.label_list(allow_files = True),
"outs": attr.output_list(),
"src_prefix": attr.string(),
"_capnpc": attr.label(executable = True, allow_single_file = True, cfg = "exec", default = "@capnp-cpp//src/capnp:capnp_tool"),
"_capnpc_ts": attr.label(executable = True, allow_single_file = True, cfg = "exec", default = "//:capnpc_ts"),
"_capnpc_capnp": attr.label(executable = True, allow_single_file = True, cfg = "exec", default = "@capnp-cpp//src/capnp:capnpc-capnp"),
"_capnp_system": attr.label(default = "@capnp-cpp//src/capnp:capnp_system_library"),
},
output_to_genfiles = True,
implementation = _capnp_gen_impl,
)

def js_capnp_library(
name,
srcs = [],
data = [],
deps = [],
src_prefix = "",
visibility = None,
target_compatible_with = None,
**kwargs):
"""Bazel rule to create a JavaScript capnproto library from capnp source files

Args:
name: library name
srcs: list of files to compile
data: additional files to provide to the compiler - data files and includes that need not to
be compiled
deps: other js_capnp_library rules to depend on
src_prefix: src_prefix for capnp compiler to the source root
visibility: rule visibility
target_compatible_with: target compatibility
**kwargs: rest of the arguments to js_library rule
"""

js_files = [s + ".js" for s in srcs]
d_ts_files = [s + ".d.ts" for s in srcs]

_capnp_gen(
name = name + "_gen",
srcs = srcs,
deps = [s + "_gen" for s in deps],
data = data,
outs = js_files + d_ts_files,
src_prefix = src_prefix,
visibility = visibility,
target_compatible_with = target_compatible_with,
)
js_library(
name = name,
srcs = js_files + d_ts_files,
deps = deps + ["//:node_modules/capnp-ts"],
visibility = visibility,
target_compatible_with = target_compatible_with,
**kwargs
)
25 changes: 25 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"name": "@cloudflare/workerd-root",
"private": true,
"scripts": {
"lint": "eslint types/src"
},
"dependencies": {
"capnp-ts": "^0.7.0",
"prettier": "^2.7.1",
"typescript": "~4.7.4"
},
"devDependencies": {
"@types/debug": "^4.1.7",
"@types/node": "^18.7.18",
"@types/prettier": "^2.7.1",
"@typescript-eslint/eslint-plugin": "^5.37.0",
"@typescript-eslint/parser": "^5.37.0",
"capnpc-ts": "^0.7.0",
"esbuild": "^0.15.7",
"eslint": "^8.22.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-prettier": "^4.2.1"
}
}
11 changes: 11 additions & 0 deletions patches/[email protected]
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
--- a/src/serialization/pointers/struct.ts
+++ b/src/serialization/pointers/struct.ts
@@ -107,8 +107,6 @@ export class Struct extends Pointer {
static readonly setText = setText;
static readonly testWhich = testWhich;

- readonly _capnp!: _Struct;
mrbbot marked this conversation as resolved.
Show resolved Hide resolved
-
/**
* Create a new pointer to a struct.
*
Loading