tswasm 0.1.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +55 -0
- package/NOTICE +436 -0
- package/README.md +326 -0
- package/THIRD_PARTY_NOTICES.md +80 -0
- package/dist/index.d.ts +46 -0
- package/dist/index.js +114 -0
- package/dist/tswasm.wasm +0 -0
- package/dist/wasm_exec.js +589 -0
- package/package.json +80 -0
- package/tswasm.wasm.d.ts +3 -0
package/README.md
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
# tswasm
|
|
2
|
+
|
|
3
|
+
Alpha package for running the TypeScript Go compiler from JavaScript runtimes
|
|
4
|
+
through WebAssembly.
|
|
5
|
+
|
|
6
|
+
This repository keeps `microsoft/typescript-go` as a git subtree, then builds a
|
|
7
|
+
small wasm command from inside that subtree. Building from inside the upstream Go
|
|
8
|
+
module lets the command legally import `typescript-go/internal/...` without
|
|
9
|
+
patching upstream compiler packages.
|
|
10
|
+
|
|
11
|
+
The current API compiles one in-memory TypeScript file, `/input.ts` by default,
|
|
12
|
+
with modern ECMAScript lib definitions and returns diagnostics plus emitted
|
|
13
|
+
JavaScript.
|
|
14
|
+
|
|
15
|
+
`tswasm` is published as an alpha. The package is useful for experiments,
|
|
16
|
+
browser-side tools, Cloudflare Worker prototypes, and performance comparisons,
|
|
17
|
+
but the API is intentionally narrow while `typescript-go` is still moving.
|
|
18
|
+
|
|
19
|
+
## Install
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm install tswasm
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
When the JavaScript file and `tswasm.wasm` asset are served from the same
|
|
28
|
+
package location, `createCompiler()` loads the packaged wasm automatically:
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { createCompiler } from 'tswasm'
|
|
32
|
+
|
|
33
|
+
const ts = await createCompiler()
|
|
34
|
+
const result = ts.compile('const x: number = 123')
|
|
35
|
+
|
|
36
|
+
console.log(result.success) // true
|
|
37
|
+
|
|
38
|
+
ts.compile('const s: string = 42') // { success: false, diagnostics: [{..., message: "Type 'number' is not assignable to type 'string'.", ...}] }
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
For bundlers and worker runtimes, pass the wasm module or URL explicitly:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { createCompiler } from 'tswasm'
|
|
45
|
+
import wasm from 'tswasm/tswasm.wasm'
|
|
46
|
+
|
|
47
|
+
let tsPromise: ReturnType<typeof createCompiler>
|
|
48
|
+
|
|
49
|
+
function getCompiler() {
|
|
50
|
+
tsPromise ||= createCompiler({ wasm })
|
|
51
|
+
return tsPromise
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export default {
|
|
55
|
+
async fetch(request: Request) {
|
|
56
|
+
const code = new URL(request.url).searchParams.get('code') || 'const x = 1'
|
|
57
|
+
const ts = await getCompiler()
|
|
58
|
+
return Response.json(ts.compile(code))
|
|
59
|
+
},
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
If the runtime serves wasm as a normal static file, compile it yourself and pass
|
|
64
|
+
the `WebAssembly.Module`:
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
import { createCompiler } from 'tswasm'
|
|
68
|
+
|
|
69
|
+
const bytes = await fetch('/tswasm.wasm').then(response => response.arrayBuffer())
|
|
70
|
+
const wasm = await WebAssembly.compile(bytes)
|
|
71
|
+
const ts = await createCompiler({ wasm })
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Current Limits
|
|
75
|
+
|
|
76
|
+
- Compiles one in-memory input file per call. Pass `fileName` when diagnostics
|
|
77
|
+
should use a path other than `/input.ts`.
|
|
78
|
+
- Uses bundled `lib.es2024.d.ts` files, `strict: true`, `target: ES2024`, and
|
|
79
|
+
`module: ESNext`.
|
|
80
|
+
- Does not load a `tsconfig.json`, file graph, package dependencies, or custom
|
|
81
|
+
declaration files yet.
|
|
82
|
+
- Has no disposal API. Reusing one `createCompiler()` result is cheaper than
|
|
83
|
+
repeatedly creating new runtimes.
|
|
84
|
+
- Ships a large wasm payload: about 29 MiB raw and about 6.8 MiB compressed in
|
|
85
|
+
the current package.
|
|
86
|
+
|
|
87
|
+
## Why
|
|
88
|
+
|
|
89
|
+
If a compiler needs to run in a browser, Cloudflare Worker, or another
|
|
90
|
+
JavaScript runtime where native subprocesses are not available, the practical
|
|
91
|
+
implementation choices are JavaScript or WebAssembly. Native `tsgo` is the
|
|
92
|
+
obvious choice when native code is allowed, but it does not cover those
|
|
93
|
+
environments.
|
|
94
|
+
|
|
95
|
+
That matters because TypeScript is moving toward the native compiler and
|
|
96
|
+
language service for TypeScript 7.0. The TypeScript team describes the native
|
|
97
|
+
port as a way to improve raw performance, memory use, and parallelism:
|
|
98
|
+
<https://devblogs.microsoft.com/typescript/progress-on-typescript-7-december-2025/>.
|
|
99
|
+
TypeScript 6.0 is also explicitly a transition release for TypeScript 7.0:
|
|
100
|
+
<https://www.typescriptlang.org/docs/handbook/release-notes/typescript-6-0.html>.
|
|
101
|
+
Microsoft says the existing JavaScript/TypeScript implementation will be
|
|
102
|
+
maintained for the foreseeable future, but that the eventual intent is to
|
|
103
|
+
develop only the native codebase:
|
|
104
|
+
<https://github.com/microsoft/typescript-go/discussions/454>.
|
|
105
|
+
|
|
106
|
+
`tswasm` explores the practical middle ground: keep the supported native
|
|
107
|
+
compiler path available in wasm-capable environments, and measure whether that
|
|
108
|
+
path is also faster than the JavaScript compiler APIs those environments can
|
|
109
|
+
use today.
|
|
110
|
+
|
|
111
|
+
## Size
|
|
112
|
+
|
|
113
|
+
This repo includes a size report for the current package contents:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
pnpm size
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The script builds `tswasm`, runs `npm pack --dry-run --json`, rejects
|
|
120
|
+
benchmark-only native binaries if they would be packed, and prints raw,
|
|
121
|
+
gzip, and brotli sizes for the runtime assets. The local JS compiler reference
|
|
122
|
+
rows are direct local package/file sizes, not full browser bundle graphs.
|
|
123
|
+
|
|
124
|
+
Representative local run on 2026-06-19:
|
|
125
|
+
|
|
126
|
+
### Packed Package
|
|
127
|
+
|
|
128
|
+
| Package | packed tarball | unpacked install | files |
|
|
129
|
+
|---|---:|---:|---:|
|
|
130
|
+
| tswasm@0.1.0-alpha.0 | 6.84 MiB | 29.05 MiB | 10 |
|
|
131
|
+
|
|
132
|
+
### Runtime Assets
|
|
133
|
+
|
|
134
|
+
| Asset | raw | gzip | brotli |
|
|
135
|
+
|---|---:|---:|---:|
|
|
136
|
+
| API JS | 4.17 KiB | 1.45 KiB | 1.25 KiB |
|
|
137
|
+
| Types | 1.19 KiB | 490 B | 397 B |
|
|
138
|
+
| Go wasm runtime JS | 16.93 KiB | 4.40 KiB | 3.79 KiB |
|
|
139
|
+
| TypeScript Go wasm | 28.96 MiB | 6.81 MiB | 5.15 MiB |
|
|
140
|
+
| Runtime payload total | 28.98 MiB | 6.82 MiB | 5.16 MiB |
|
|
141
|
+
|
|
142
|
+
### Local JS Compiler References
|
|
143
|
+
|
|
144
|
+
| Reference | raw/install | gzip | brotli |
|
|
145
|
+
|---|---:|---:|---:|
|
|
146
|
+
| TypeScript JS compiler file | 8.69 MiB | 1.56 MiB | 1.10 MiB |
|
|
147
|
+
| TypeScript JS package | 22.53 MiB | - | - |
|
|
148
|
+
| ts-morph bundled JS | 932.10 KiB | 127.57 KiB | 97.12 KiB |
|
|
149
|
+
| ts-morph package | 1.41 MiB | - | - |
|
|
150
|
+
|
|
151
|
+
## Performance
|
|
152
|
+
|
|
153
|
+
This repo includes a local benchmark runner for the current one-file compiler
|
|
154
|
+
API:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
pnpm bench
|
|
158
|
+
pnpm bench:quick
|
|
159
|
+
pnpm bench:profile
|
|
160
|
+
pnpm exec tsx bench/compile.bench.ts --filter=warm
|
|
161
|
+
pnpm exec tsx bench/compile.bench.ts --skip-native --json=tasks/bench-results.ignoreme.json
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
`pnpm bench` builds `tswasm`, builds a local native `tsgo` CLI from
|
|
165
|
+
`typescript-go/`, and then prints Markdown tables. `bench:quick` uses shorter
|
|
166
|
+
sample windows for iteration while changing benchmark code. `bench:profile`
|
|
167
|
+
adds internal diagnostic rows for the wasm path and a spawn-only `tsgo` row.
|
|
168
|
+
|
|
169
|
+
The benchmark has two source cases:
|
|
170
|
+
|
|
171
|
+
- `simple snippet`: the existing compile-test async function using `Map`,
|
|
172
|
+
`Array.from`, and `Promise.all`.
|
|
173
|
+
- `type-heavy snippet`: a compact source using recursive conditional types,
|
|
174
|
+
mapped type key remapping, template literal types, and generic call-site
|
|
175
|
+
inference.
|
|
176
|
+
|
|
177
|
+
The rows are grouped by comparison category. The first category is the main one:
|
|
178
|
+
portable full compile, where every row typechecks and emits and can run in the
|
|
179
|
+
same wasm-capable environments as `tswasm`.
|
|
180
|
+
|
|
181
|
+
- `tswasm warm compile`: one shared `createCompiler()` result for the whole
|
|
182
|
+
process; timed work is only `ts.compile(code)`.
|
|
183
|
+
- `tswasm cold createCompiler+compile`: timed work includes `createCompiler()`
|
|
184
|
+
and one compile. Repeated samples currently accumulate Go wasm runtimes
|
|
185
|
+
because the public API has no disposal hook.
|
|
186
|
+
- `TypeScript JS full program (in-memory)`: recreates an in-memory
|
|
187
|
+
`ts.createProgram`, collects pre-emit diagnostics, and emits.
|
|
188
|
+
- `ts-morph full program (in-memory)`: creates an in-memory ts-morph project,
|
|
189
|
+
collects pre-emit diagnostics, and emits to memory.
|
|
190
|
+
- `TypeScript JS transpileModule (emit only)`: intentionally favorable baseline
|
|
191
|
+
for the classic JS compiler. It does not typecheck.
|
|
192
|
+
- `tsgo native CLI (process+files)`: runs the local native TypeScript CLI in a
|
|
193
|
+
subprocess against a temp project. This includes process startup and file
|
|
194
|
+
reads/writes, so it is a native-Go curiosity rather than a portable
|
|
195
|
+
wasm-environment comparison.
|
|
196
|
+
|
|
197
|
+
The comparison framing follows:
|
|
198
|
+
|
|
199
|
+
- Microsoft's native TypeScript announcement measured project-level `tsc` runs
|
|
200
|
+
and reported roughly order-of-magnitude speedups for native TypeScript:
|
|
201
|
+
<https://devblogs.microsoft.com/typescript/typescript-native-port/>
|
|
202
|
+
- The TypeScript Compiler API docs distinguish full `createProgram` compilation
|
|
203
|
+
from `transpileModule` emit-only transforms:
|
|
204
|
+
<https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API>
|
|
205
|
+
- ts-morph's performance docs call out the wrapper costs around program resets,
|
|
206
|
+
node tracking, and batching:
|
|
207
|
+
<https://ts-morph.com/manipulation/performance>
|
|
208
|
+
|
|
209
|
+
Representative local run on 2026-06-18:
|
|
210
|
+
|
|
211
|
+
- Runtime: node v26.0.0 darwin/arm64
|
|
212
|
+
- CPU: Apple M4 Max
|
|
213
|
+
- TypeScript JS: 5.9.3
|
|
214
|
+
- ts-morph: 28.0.0
|
|
215
|
+
- tsgo native: Version 7.0.0-dev
|
|
216
|
+
|
|
217
|
+
Lower latency is better. Tinybench rows use a time-driven loop; startup-heavy
|
|
218
|
+
rows use fixed samples.
|
|
219
|
+
|
|
220
|
+
### Simple Snippet: Portable Full Compile
|
|
221
|
+
|
|
222
|
+
These rows typecheck and emit, and can run in the same wasm-capable environments
|
|
223
|
+
as `tswasm`.
|
|
224
|
+
|
|
225
|
+
| Benchmark | mean ms | median ms | samples | vs fastest | notes |
|
|
226
|
+
|---|---:|---:|---:|---:|---|
|
|
227
|
+
| tswasm warm compile | 28.90 | 28.11 | 18 | fastest | rme 4.63% |
|
|
228
|
+
| tswasm cold createCompiler+compile | 60.51 | 60.86 | 5 | 2.09x slower | fixed samples |
|
|
229
|
+
| ts-morph full program (in-memory) | 75.53 | 74.58 | 10 | 2.61x slower | rme 3.99% |
|
|
230
|
+
| TypeScript JS full program (in-memory) | 163.2 | 162.2 | 10 | 5.65x slower | rme 3.26% |
|
|
231
|
+
|
|
232
|
+
### Simple Snippet: Emit-Only Baseline
|
|
233
|
+
|
|
234
|
+
This classic TypeScript JS row emits without typechecking. It is useful, but not
|
|
235
|
+
apples-to-apples. `tswasm` warm compile and TypeScript JS full program are
|
|
236
|
+
repeated here as reference points.
|
|
237
|
+
|
|
238
|
+
| Benchmark | mean ms | median ms | samples | vs fastest | notes |
|
|
239
|
+
|---|---:|---:|---:|---:|---|
|
|
240
|
+
| TypeScript JS transpileModule (emit only) | 0.2819 | 0.1908 | 1774 | fastest | rme 7.55% |
|
|
241
|
+
| tswasm warm compile | 28.90 | 28.11 | 18 | 102.52x slower | rme 4.63% |
|
|
242
|
+
| TypeScript JS full program (in-memory) | 163.2 | 162.2 | 10 | 579.0x slower | rme 3.26% |
|
|
243
|
+
|
|
244
|
+
### Simple Snippet: Native Go Curiosity
|
|
245
|
+
|
|
246
|
+
These rows require native Go or a native helper process. If native Go is
|
|
247
|
+
available, use it; these are not portable wasm-environment comparisons. The
|
|
248
|
+
`tswasm` rows are repeated here as reference points.
|
|
249
|
+
|
|
250
|
+
| Benchmark | mean ms | median ms | samples | vs fastest | notes |
|
|
251
|
+
|---|---:|---:|---:|---:|---|
|
|
252
|
+
| tsgo native CLI (process+files) | 27.73 | 26.91 | 5 | fastest | fixed samples |
|
|
253
|
+
| tswasm warm compile | 28.90 | 28.11 | 18 | 1.04x slower | rme 4.63% |
|
|
254
|
+
| tswasm cold createCompiler+compile | 60.51 | 60.86 | 5 | 2.18x slower | fixed samples |
|
|
255
|
+
|
|
256
|
+
### Type-Heavy Snippet: Portable Full Compile
|
|
257
|
+
|
|
258
|
+
These rows typecheck and emit, and can run in the same wasm-capable environments
|
|
259
|
+
as `tswasm`.
|
|
260
|
+
|
|
261
|
+
| Benchmark | mean ms | median ms | samples | vs fastest | notes |
|
|
262
|
+
|---|---:|---:|---:|---:|---|
|
|
263
|
+
| tswasm warm compile | 24.21 | 23.53 | 21 | fastest | rme 6.99% |
|
|
264
|
+
| tswasm cold createCompiler+compile | 56.63 | 56.72 | 5 | 2.34x slower | fixed samples |
|
|
265
|
+
| ts-morph full program (in-memory) | 68.35 | 66.82 | 10 | 2.82x slower | rme 3.97% |
|
|
266
|
+
| TypeScript JS full program (in-memory) | 161.9 | 157.8 | 10 | 6.69x slower | rme 4.59% |
|
|
267
|
+
|
|
268
|
+
### Type-Heavy Snippet: Emit-Only Baseline
|
|
269
|
+
|
|
270
|
+
This classic TypeScript JS row emits without typechecking. It is useful, but not
|
|
271
|
+
apples-to-apples. `tswasm` warm compile and TypeScript JS full program are
|
|
272
|
+
repeated here as reference points.
|
|
273
|
+
|
|
274
|
+
| Benchmark | mean ms | median ms | samples | vs fastest | notes |
|
|
275
|
+
|---|---:|---:|---:|---:|---|
|
|
276
|
+
| TypeScript JS transpileModule (emit only) | 0.4030 | 0.3025 | 1241 | fastest | rme 5.93% |
|
|
277
|
+
| tswasm warm compile | 24.21 | 23.53 | 21 | 60.07x slower | rme 6.99% |
|
|
278
|
+
| TypeScript JS full program (in-memory) | 161.9 | 157.8 | 10 | 401.7x slower | rme 4.59% |
|
|
279
|
+
|
|
280
|
+
### Type-Heavy Snippet: Native Go Curiosity
|
|
281
|
+
|
|
282
|
+
These rows require native Go or a native helper process. If native Go is
|
|
283
|
+
available, use it; these are not portable wasm-environment comparisons. The
|
|
284
|
+
`tswasm` rows are repeated here as reference points.
|
|
285
|
+
|
|
286
|
+
| Benchmark | mean ms | median ms | samples | vs fastest | notes |
|
|
287
|
+
|---|---:|---:|---:|---:|---|
|
|
288
|
+
| tswasm warm compile | 24.21 | 23.53 | 21 | fastest | rme 6.99% |
|
|
289
|
+
| tsgo native CLI (process+files) | 28.64 | 27.41 | 5 | 1.18x slower | fixed samples |
|
|
290
|
+
| tswasm cold createCompiler+compile | 56.63 | 56.72 | 5 | 2.34x slower | fixed samples |
|
|
291
|
+
|
|
292
|
+
## Upstream Layout
|
|
293
|
+
|
|
294
|
+
- `typescript-go/` is a git subtree of `microsoft/typescript-go`.
|
|
295
|
+
- `go/tswasm-wasm/` is this package's wasm command source.
|
|
296
|
+
- `scripts/build-wasm.ts` overlays the command into
|
|
297
|
+
`typescript-go/cmd/tswasm-wasm`, copies the needed lib definition files, and
|
|
298
|
+
builds `dist/tswasm.wasm`.
|
|
299
|
+
|
|
300
|
+
That keeps the public package separate from upstream while still allowing the Go
|
|
301
|
+
entrypoint to reach tsgo's current internal compiler APIs.
|
|
302
|
+
|
|
303
|
+
## Development
|
|
304
|
+
|
|
305
|
+
```bash
|
|
306
|
+
pnpm install
|
|
307
|
+
pnpm run build
|
|
308
|
+
pnpm test
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## Release Checks
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
pnpm run release:check
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
The release check builds the wasm and JavaScript output, runs the default Vitest
|
|
318
|
+
suite, prints the package size report, and runs `npm pack --dry-run --json`.
|
|
319
|
+
That default suite includes the Node and Miniflare Worker tests. Run these
|
|
320
|
+
additional environment checks before claiming browser or Expo web support for a
|
|
321
|
+
release:
|
|
322
|
+
|
|
323
|
+
```bash
|
|
324
|
+
pnpm test:browser
|
|
325
|
+
pnpm test:expo
|
|
326
|
+
```
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
This package redistributes generated runtime artifacts from the projects listed
|
|
4
|
+
below. The package source is licensed under Apache-2.0; these notices describe
|
|
5
|
+
the redistributed third-party material.
|
|
6
|
+
|
|
7
|
+
## TypeScript Go
|
|
8
|
+
|
|
9
|
+
`dist/tswasm.wasm` is built from `microsoft/typescript-go`, plus the local
|
|
10
|
+
`go/tswasm-wasm` command in this repository.
|
|
11
|
+
|
|
12
|
+
- Source: <https://github.com/microsoft/typescript-go>
|
|
13
|
+
- License: Apache-2.0
|
|
14
|
+
- Notice file: see `NOTICE`
|
|
15
|
+
|
|
16
|
+
## Go wasm runtime
|
|
17
|
+
|
|
18
|
+
`dist/wasm_exec.js` is copied from the Go toolchain and patched at build time so
|
|
19
|
+
the runtime can use Web Crypto, Node Web Crypto, or a deterministic fallback in
|
|
20
|
+
restricted worker-like runtimes.
|
|
21
|
+
|
|
22
|
+
- Source: <https://go.dev/>
|
|
23
|
+
- License: BSD-style license below
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
Copyright 2009 The Go Authors.
|
|
27
|
+
|
|
28
|
+
Redistribution and use in source and binary forms, with or without
|
|
29
|
+
modification, are permitted provided that the following conditions are
|
|
30
|
+
met:
|
|
31
|
+
|
|
32
|
+
* Redistributions of source code must retain the above copyright
|
|
33
|
+
notice, this list of conditions and the following disclaimer.
|
|
34
|
+
* Redistributions in binary form must reproduce the above
|
|
35
|
+
copyright notice, this list of conditions and the following disclaimer
|
|
36
|
+
in the documentation and/or other materials provided with the
|
|
37
|
+
distribution.
|
|
38
|
+
* Neither the name of Google LLC nor the names of its
|
|
39
|
+
contributors may be used to endorse or promote products derived from
|
|
40
|
+
this software without specific prior written permission.
|
|
41
|
+
|
|
42
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
43
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
44
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
45
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
46
|
+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
47
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
48
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
49
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
50
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
51
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
52
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The installed Go toolchain also includes this patent grant:
|
|
56
|
+
|
|
57
|
+
```text
|
|
58
|
+
Additional IP Rights Grant (Patents)
|
|
59
|
+
|
|
60
|
+
"This implementation" means the copyrightable works distributed by
|
|
61
|
+
Google as part of the Go project.
|
|
62
|
+
|
|
63
|
+
Google hereby grants to You a perpetual, worldwide, non-exclusive,
|
|
64
|
+
no-charge, royalty-free, irrevocable (except as stated in this section)
|
|
65
|
+
patent license to make, have made, use, offer to sell, sell, import,
|
|
66
|
+
transfer and otherwise run, modify and propagate the contents of this
|
|
67
|
+
implementation of Go, where such license applies only to those patent
|
|
68
|
+
claims, both currently owned or controlled by Google and acquired in
|
|
69
|
+
the future, licensable by Google that are necessarily infringed by this
|
|
70
|
+
implementation of Go. This grant does not include claims that would be
|
|
71
|
+
infringed only as a consequence of further modification of this
|
|
72
|
+
implementation. If you or your agent or exclusive licensee institute or
|
|
73
|
+
order or agree to the institution of patent litigation against any
|
|
74
|
+
entity (including a cross-claim or counterclaim in a lawsuit) alleging
|
|
75
|
+
that this implementation of Go or any code incorporated within this
|
|
76
|
+
implementation of Go constitutes direct or contributory patent
|
|
77
|
+
infringement, or inducement of patent infringement, then any patent
|
|
78
|
+
rights granted to you under this License for this implementation of Go
|
|
79
|
+
shall terminate as of the date such litigation is filed.
|
|
80
|
+
```
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import "./wasm_exec.js";
|
|
2
|
+
export interface CompileRequest {
|
|
3
|
+
code: string;
|
|
4
|
+
fileName?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface CompileResult {
|
|
7
|
+
js: string;
|
|
8
|
+
diagnostics: Diagnostic[];
|
|
9
|
+
success: boolean;
|
|
10
|
+
compiler: CompilerInfo;
|
|
11
|
+
}
|
|
12
|
+
export interface Diagnostic {
|
|
13
|
+
message: string;
|
|
14
|
+
code: number;
|
|
15
|
+
category: "error" | "warning" | "suggestion" | "message";
|
|
16
|
+
line?: number;
|
|
17
|
+
column?: number;
|
|
18
|
+
}
|
|
19
|
+
export interface CompilerInfo {
|
|
20
|
+
name: string;
|
|
21
|
+
runtime: string;
|
|
22
|
+
mode: string;
|
|
23
|
+
lib: string;
|
|
24
|
+
}
|
|
25
|
+
export interface Compiler {
|
|
26
|
+
compile(code: string): CompileResult;
|
|
27
|
+
compile(request: CompileRequest): CompileResult;
|
|
28
|
+
}
|
|
29
|
+
export interface CreateCompilerOptions {
|
|
30
|
+
wasm?: WebAssembly.Module | URL | string;
|
|
31
|
+
}
|
|
32
|
+
export declare const compilerInfo: CompilerInfo;
|
|
33
|
+
type NativeCompile = (requestJson: string) => string;
|
|
34
|
+
interface GoRuntime {
|
|
35
|
+
importObject: WebAssembly.Imports;
|
|
36
|
+
run(instance: WebAssembly.Instance): Promise<void>;
|
|
37
|
+
}
|
|
38
|
+
interface GoConstructor {
|
|
39
|
+
new (): GoRuntime;
|
|
40
|
+
}
|
|
41
|
+
declare global {
|
|
42
|
+
var Go: GoConstructor | undefined;
|
|
43
|
+
var __tswasmCompile: NativeCompile | undefined;
|
|
44
|
+
}
|
|
45
|
+
export declare function createCompiler(options?: CreateCompilerOptions): Promise<Compiler>;
|
|
46
|
+
export {};
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// @ts-ignore Generated into dist by scripts/build-wasm.ts.
|
|
2
|
+
import "./wasm_exec.js";
|
|
3
|
+
export const compilerInfo = {
|
|
4
|
+
name: "typescript-go (tsgo)",
|
|
5
|
+
runtime: "Go wasm",
|
|
6
|
+
mode: "single in-memory /input.ts",
|
|
7
|
+
lib: "bundled TypeScript lib.es2024.d.ts",
|
|
8
|
+
};
|
|
9
|
+
export async function createCompiler(options = {}) {
|
|
10
|
+
const wasm = options.wasm || defaultWasmUrl();
|
|
11
|
+
const nativeCompile = await createNativeCompile(wasm);
|
|
12
|
+
return {
|
|
13
|
+
compile(input) {
|
|
14
|
+
const request = typeof input === "string" ? { code: input } : input;
|
|
15
|
+
const nativeResult = JSON.parse(nativeCompile(JSON.stringify(request)));
|
|
16
|
+
return {
|
|
17
|
+
...nativeResult,
|
|
18
|
+
compiler: compilerInfo,
|
|
19
|
+
};
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function defaultWasmUrl() {
|
|
24
|
+
// Keep module-url syntax out of this module so Metro-style classic script
|
|
25
|
+
// bundles can parse the package when callers provide options.wasm.
|
|
26
|
+
const stack = new Error().stack || "";
|
|
27
|
+
const urlMatch = stack.match(/(?:file|https?):\/\/[^\s)]+\/index\.js(?::\d+:\d+)?/u);
|
|
28
|
+
if (urlMatch) {
|
|
29
|
+
return new URL("./tswasm.wasm", urlMatch[0].replace(/:\d+:\d+$/u, ""));
|
|
30
|
+
}
|
|
31
|
+
const pathMatch = stack.match(/(?:\/|[A-Za-z]:\\)[^\s)]+[/\\]index\.js(?::\d+:\d+)?/u);
|
|
32
|
+
const nodeUrl = nodeBuiltin("url");
|
|
33
|
+
if (pathMatch && nodeUrl?.pathToFileURL) {
|
|
34
|
+
return new URL("./tswasm.wasm", nodeUrl.pathToFileURL(pathMatch[0].replace(/:\d+:\d+$/u, "")));
|
|
35
|
+
}
|
|
36
|
+
const nodeProcess = globalThis.process;
|
|
37
|
+
const nodeFs = nodeBuiltin("fs");
|
|
38
|
+
const nodePath = nodeBuiltin("path");
|
|
39
|
+
if (nodeProcess?.cwd && nodeUrl?.pathToFileURL && nodeFs?.existsSync && nodePath?.join) {
|
|
40
|
+
const repoLocalWasm = nodePath.join(nodeProcess.cwd(), "dist", "tswasm.wasm");
|
|
41
|
+
if (nodeFs.existsSync(repoLocalWasm)) {
|
|
42
|
+
return nodeUrl.pathToFileURL(repoLocalWasm);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
const location = globalThis.location;
|
|
46
|
+
if (location?.href) {
|
|
47
|
+
return new URL("./tswasm.wasm", location.href);
|
|
48
|
+
}
|
|
49
|
+
throw new Error("createCompiler requires options.wasm when tswasm.wasm cannot be resolved automatically");
|
|
50
|
+
}
|
|
51
|
+
async function createNativeCompile(wasmInput) {
|
|
52
|
+
if (!globalThis.Go) {
|
|
53
|
+
throw new Error("Go wasm runtime did not initialize");
|
|
54
|
+
}
|
|
55
|
+
const go = new globalThis.Go();
|
|
56
|
+
const instance = await instantiateWasm(wasmInput, go.importObject);
|
|
57
|
+
void go.run(instance).catch((error) => {
|
|
58
|
+
console.error("tswasm runtime exited", error);
|
|
59
|
+
});
|
|
60
|
+
return waitForNativeCompileRegistration();
|
|
61
|
+
}
|
|
62
|
+
async function waitForNativeCompileRegistration() {
|
|
63
|
+
for (let attempt = 0; attempt < 10; attempt++) {
|
|
64
|
+
const compile = globalThis.__tswasmCompile;
|
|
65
|
+
if (compile) {
|
|
66
|
+
return compile;
|
|
67
|
+
}
|
|
68
|
+
await Promise.resolve();
|
|
69
|
+
}
|
|
70
|
+
throw new Error("tswasm compiler did not register __tswasmCompile");
|
|
71
|
+
}
|
|
72
|
+
async function instantiateWasm(wasmInput, imports) {
|
|
73
|
+
if (wasmInput instanceof WebAssembly.Module) {
|
|
74
|
+
return WebAssembly.instantiate(wasmInput, imports);
|
|
75
|
+
}
|
|
76
|
+
const wasmBytes = await readWasmBytes(wasmInput);
|
|
77
|
+
const instantiated = await WebAssembly.instantiate(wasmBytes, imports);
|
|
78
|
+
return instantiated.instance;
|
|
79
|
+
}
|
|
80
|
+
async function readWasmBytes(input) {
|
|
81
|
+
const url = resolveWasmUrl(input);
|
|
82
|
+
if (url.protocol === "file:") {
|
|
83
|
+
const { readFile } = await importNodeFsPromises();
|
|
84
|
+
const bytes = await readFile(url);
|
|
85
|
+
return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength);
|
|
86
|
+
}
|
|
87
|
+
const response = await fetch(url);
|
|
88
|
+
if (!response.ok) {
|
|
89
|
+
throw new Error(`failed to load tswasm wasm: ${response.status}`);
|
|
90
|
+
}
|
|
91
|
+
return response.arrayBuffer();
|
|
92
|
+
}
|
|
93
|
+
function resolveWasmUrl(input) {
|
|
94
|
+
if (input instanceof URL) {
|
|
95
|
+
return input;
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
return new URL(input);
|
|
99
|
+
}
|
|
100
|
+
catch {
|
|
101
|
+
return new URL(input, defaultWasmUrl());
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async function importNodeFsPromises() {
|
|
105
|
+
const fs = nodeBuiltin("fs");
|
|
106
|
+
if (!fs?.promises?.readFile) {
|
|
107
|
+
throw new Error("file: wasm URLs require Node.js process.getBuiltinModule('fs')");
|
|
108
|
+
}
|
|
109
|
+
return fs.promises;
|
|
110
|
+
}
|
|
111
|
+
function nodeBuiltin(name) {
|
|
112
|
+
const nodeProcess = globalThis.process;
|
|
113
|
+
return nodeProcess?.getBuiltinModule?.(name);
|
|
114
|
+
}
|
package/dist/tswasm.wasm
ADDED
|
Binary file
|