Skip to content

Commit

Permalink
Merge pull request #110 from cloudflare/bcoll/types
Browse files Browse the repository at this point in the history
Automatic TypeScript definition generation from JSG RTTI
  • Loading branch information
mrbbot authored Oct 17, 2022
2 parents 571b161 + f297730 commit 2fd13d8
Show file tree
Hide file tree
Showing 31 changed files with 3,982 additions and 63 deletions.
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")

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;
-
/**
* Create a new pointer to a struct.
*
Loading

0 comments on commit 2fd13d8

Please sign in to comment.