@ttsc/wasm 0.18.4 → 0.19.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/README.md +10 -4
- package/dist/go.mod +1 -0
- package/dist/ttsc.wasm +0 -0
- package/go.mod +1 -0
- package/host/api.go +1 -1
- package/host/host.go +15 -108
- package/host/plugin.go +115 -47
- package/lib/src/MemFSError.js +4 -0
- package/lib/src/MemFSError.js.map +1 -1
- package/lib/src/bootTtsc.js +93 -37
- package/lib/src/bootTtsc.js.map +1 -1
- package/lib/src/createMemFS.js +173 -10
- package/lib/src/createMemFS.js.map +1 -1
- package/package.json +1 -1
- package/shim-vendor/shim/ast/lint.go +10 -0
- package/shim-vendor/shim/ast/shim.go +44 -0
- package/shim-vendor/shim/checker/enums_gen.go +19 -0
- package/shim-vendor/shim/checker/shim.go +130 -0
- package/shim-vendor/shim/diagnosticwriter/lint.go +30 -3
- package/shim-vendor/shim/scanner/regexp.go +27 -0
- package/src/MemFSError.ts +4 -0
- package/src/bootTtsc.ts +115 -47
- package/src/createMemFS.ts +170 -10
- package/shim-vendor/shim/checker/signature_api_completeness.go +0 -58
package/README.md
CHANGED
|
@@ -47,6 +47,7 @@ The native sibling `main.go` is recommended when you want `go run ./cmd/your-was
|
|
|
47
47
|
package main
|
|
48
48
|
|
|
49
49
|
import (
|
|
50
|
+
"context"
|
|
50
51
|
"fmt"
|
|
51
52
|
"os"
|
|
52
53
|
|
|
@@ -60,7 +61,10 @@ func main() {
|
|
|
60
61
|
name, command := os.Args[1], os.Args[2]
|
|
61
62
|
for _, p := range plugins {
|
|
62
63
|
if p.Name() == name {
|
|
63
|
-
|
|
64
|
+
result := host.InvokePlugin(context.Background(), p, command, os.Args[3:])
|
|
65
|
+
fmt.Fprint(os.Stdout, result.Stdout)
|
|
66
|
+
fmt.Fprint(os.Stderr, result.Stderr)
|
|
67
|
+
os.Exit(result.Code)
|
|
64
68
|
}
|
|
65
69
|
}
|
|
66
70
|
}
|
|
@@ -169,12 +173,14 @@ Verbs and payload types:
|
|
|
169
173
|
|
|
170
174
|
```go
|
|
171
175
|
type Plugin interface {
|
|
172
|
-
Name() string
|
|
173
|
-
Run(
|
|
176
|
+
Name() string
|
|
177
|
+
Run(invocation *PluginInvocation) int
|
|
174
178
|
}
|
|
175
179
|
```
|
|
176
180
|
|
|
177
|
-
The host installs `globalThis[apiName].plugin({ name, command, ...opts })` that translates the JS options object into
|
|
181
|
+
The host installs `globalThis[apiName].plugin({ name, command, ...opts })` that translates the JS options object into `invocation.Command` and CLI-shaped `invocation.Args`. Write output to `invocation.Stdout` and `invocation.Stderr`. Utility-backed plugins can call `utility.RunBuildWithIO(invocation.Args, invocation.Stdout, invocation.Stderr)` so the native command and browser adapter share implementation without replacing process-global streams.
|
|
182
|
+
|
|
183
|
+
Use `invocation.Go` for asynchronous work that belongs to the result. Register it before `Run` returns; the host waits for registered work, closes registration when `Run` returns, and rejects later writes to the invocation streams.
|
|
178
184
|
|
|
179
185
|
## Published-tarball Go module layout
|
|
180
186
|
|
package/dist/go.mod
CHANGED
|
@@ -39,6 +39,7 @@ require (
|
|
|
39
39
|
github.com/microsoft/typescript-go/shim/checker v0.0.0 // indirect
|
|
40
40
|
github.com/microsoft/typescript-go/shim/core v0.0.0 // indirect
|
|
41
41
|
github.com/microsoft/typescript-go/shim/diagnosticwriter v0.0.0 // indirect
|
|
42
|
+
github.com/microsoft/typescript-go/shim/parser v0.0.0 // indirect
|
|
42
43
|
github.com/microsoft/typescript-go/shim/printer v0.0.0 // indirect
|
|
43
44
|
github.com/microsoft/typescript-go/shim/tsoptions v0.0.0 // indirect
|
|
44
45
|
github.com/microsoft/typescript-go/shim/tspath v0.0.0 // indirect
|
package/dist/ttsc.wasm
CHANGED
|
Binary file
|
package/go.mod
CHANGED
|
@@ -39,6 +39,7 @@ require (
|
|
|
39
39
|
github.com/microsoft/typescript-go/shim/checker v0.0.0 // indirect
|
|
40
40
|
github.com/microsoft/typescript-go/shim/core v0.0.0 // indirect
|
|
41
41
|
github.com/microsoft/typescript-go/shim/diagnosticwriter v0.0.0 // indirect
|
|
42
|
+
github.com/microsoft/typescript-go/shim/parser v0.0.0 // indirect
|
|
42
43
|
github.com/microsoft/typescript-go/shim/printer v0.0.0 // indirect
|
|
43
44
|
github.com/microsoft/typescript-go/shim/tsoptions v0.0.0 // indirect
|
|
44
45
|
github.com/microsoft/typescript-go/shim/tspath v0.0.0 // indirect
|
package/host/api.go
CHANGED
|
@@ -16,7 +16,7 @@ import (
|
|
|
16
16
|
"github.com/samchon/ttsc/packages/ttsc/driver"
|
|
17
17
|
)
|
|
18
18
|
|
|
19
|
-
// APIResult is the stdout/stderr capture returned by
|
|
19
|
+
// APIResult is the stdout/stderr capture returned by InvokePlugin. The
|
|
20
20
|
// js/wasm binding wraps it in the same JS result envelope that build/check/
|
|
21
21
|
// transform use, adding `result` when an endpoint has a JSON payload. `code`
|
|
22
22
|
// follows the native CLI exit-code contract (0 success, 2 compiler/config/
|
package/host/host.go
CHANGED
|
@@ -10,10 +10,10 @@
|
|
|
10
10
|
package host
|
|
11
11
|
|
|
12
12
|
import (
|
|
13
|
+
"context"
|
|
13
14
|
"fmt"
|
|
14
15
|
"os"
|
|
15
16
|
"runtime"
|
|
16
|
-
"sync"
|
|
17
17
|
"sync/atomic"
|
|
18
18
|
"syscall/js"
|
|
19
19
|
"time"
|
|
@@ -81,7 +81,19 @@ func Expose(apiName string, cfg Config) {
|
|
|
81
81
|
continue
|
|
82
82
|
}
|
|
83
83
|
if _, dup := plugins[name]; dup {
|
|
84
|
-
|
|
84
|
+
// A duplicate plugin name is a host-configuration error, but panicking
|
|
85
|
+
// here would terminate the Go runtime before any Ready/Failed signal is
|
|
86
|
+
// installed, leaving bootTtsc's `await ready` pending forever with no
|
|
87
|
+
// observable cause. Mirror the double-Expose path: surface the cause via
|
|
88
|
+
// console.error + the JS-visible Failed bridge, then return without
|
|
89
|
+
// starting the keepalive runtime so the boot rejects with the real
|
|
90
|
+
// reason instead of a generic "exited before readiness" error.
|
|
91
|
+
msg := fmt.Sprintf("host.Expose: duplicate plugin name %q", name)
|
|
92
|
+
fmt.Fprintln(os.Stderr, msg)
|
|
93
|
+
if failed := js.Global().Get(apiName + "Failed"); failed.Type() == js.TypeFunction {
|
|
94
|
+
failed.Invoke(js.Global().Get("Error").New(msg))
|
|
95
|
+
}
|
|
96
|
+
return
|
|
85
97
|
}
|
|
86
98
|
plugins[name] = p
|
|
87
99
|
pluginNames = append(pluginNames, name)
|
|
@@ -168,9 +180,7 @@ func jsPluginDispatch(plugins map[string]Plugin) func(this js.Value, args []js.V
|
|
|
168
180
|
return errorPromise(2, fmt.Sprintf("host: unknown plugin %q", name))
|
|
169
181
|
}
|
|
170
182
|
return makePromise(func() any {
|
|
171
|
-
res :=
|
|
172
|
-
return plugin.Run(command, argv)
|
|
173
|
-
})
|
|
183
|
+
res := InvokePlugin(context.Background(), plugin, command, argv)
|
|
174
184
|
return js.ValueOf(map[string]any{
|
|
175
185
|
"code": res.Code,
|
|
176
186
|
"stdout": res.Stdout,
|
|
@@ -312,106 +322,3 @@ func stringProp(obj js.Value, key string) string {
|
|
|
312
322
|
}
|
|
313
323
|
return v.String()
|
|
314
324
|
}
|
|
315
|
-
|
|
316
|
-
// runWithCapturedIO redirects os.Stdout / os.Stderr to temp MemFS files for
|
|
317
|
-
// the duration of `task`. Plugin Run methods write to os.Stdout / os.Stderr
|
|
318
|
-
// the same way the native sidecar binaries do; capturing the output lets the
|
|
319
|
-
// JS host render it in a console panel without spawning a subprocess.
|
|
320
|
-
//
|
|
321
|
-
// We use MemFS temp files instead of os.Pipe because Go's js/wasm runtime
|
|
322
|
-
// returns `pipe: not implemented on js` for `syscall.Pipe` — pipes are not
|
|
323
|
-
// supported on the wasm target. The temp-file approach works because the
|
|
324
|
-
// MemFS shim implements file open/write/read.
|
|
325
|
-
func runWithCapturedIO(task func() int) APIResult {
|
|
326
|
-
captureMu.Lock()
|
|
327
|
-
defer captureMu.Unlock()
|
|
328
|
-
|
|
329
|
-
prevOut, prevErr := os.Stdout, os.Stderr
|
|
330
|
-
// The defer is a safety net: if an early return skips the explicit restore
|
|
331
|
-
// below, os.Stdout/os.Stderr are still restored. The explicit restore that
|
|
332
|
-
// follows the task call is a no-op for the defer but makes the happy path
|
|
333
|
-
// readable without tracing the defer.
|
|
334
|
-
defer func() {
|
|
335
|
-
os.Stdout = prevOut
|
|
336
|
-
os.Stderr = prevErr
|
|
337
|
-
}()
|
|
338
|
-
|
|
339
|
-
stdoutPath := fmt.Sprintf("/tmp/ttsc-host-capture-%d-%d.stdout", os.Getpid(), captureCounter.Add(1))
|
|
340
|
-
stderrPath := fmt.Sprintf("/tmp/ttsc-host-capture-%d-%d.stderr", os.Getpid(), captureCounter.Add(1))
|
|
341
|
-
|
|
342
|
-
outFile, outErr := os.Create(stdoutPath)
|
|
343
|
-
errFile, errErr := os.Create(stderrPath)
|
|
344
|
-
if outErr != nil || errErr != nil {
|
|
345
|
-
// Fall back to the original streams. Better to lose capture than the
|
|
346
|
-
// call. The MemFS writeSync shim surfaces the failure to the host
|
|
347
|
-
// console so the regression is visible.
|
|
348
|
-
if outErr != nil {
|
|
349
|
-
fmt.Fprintf(prevErr, "host.runWithCapturedIO: stdout temp file failed: %v\n", outErr)
|
|
350
|
-
}
|
|
351
|
-
if errErr != nil {
|
|
352
|
-
fmt.Fprintf(prevErr, "host.runWithCapturedIO: stderr temp file failed: %v\n", errErr)
|
|
353
|
-
}
|
|
354
|
-
if outFile != nil {
|
|
355
|
-
_ = outFile.Close()
|
|
356
|
-
_ = os.Remove(stdoutPath)
|
|
357
|
-
}
|
|
358
|
-
if errFile != nil {
|
|
359
|
-
_ = errFile.Close()
|
|
360
|
-
_ = os.Remove(stderrPath)
|
|
361
|
-
}
|
|
362
|
-
return APIResult{Code: task()}
|
|
363
|
-
}
|
|
364
|
-
capturing := false
|
|
365
|
-
defer func() {
|
|
366
|
-
if capturing {
|
|
367
|
-
os.Stdout = prevOut
|
|
368
|
-
os.Stderr = prevErr
|
|
369
|
-
}
|
|
370
|
-
if outFile != nil {
|
|
371
|
-
_ = outFile.Close()
|
|
372
|
-
}
|
|
373
|
-
if errFile != nil {
|
|
374
|
-
_ = errFile.Close()
|
|
375
|
-
}
|
|
376
|
-
_ = os.Remove(stdoutPath)
|
|
377
|
-
_ = os.Remove(stderrPath)
|
|
378
|
-
}()
|
|
379
|
-
|
|
380
|
-
os.Stdout = outFile
|
|
381
|
-
os.Stderr = errFile
|
|
382
|
-
capturing = true
|
|
383
|
-
|
|
384
|
-
code := task()
|
|
385
|
-
|
|
386
|
-
// Sync + close BEFORE swapping back, so the plugin's last writes hit the
|
|
387
|
-
// file before we read it.
|
|
388
|
-
_ = outFile.Sync()
|
|
389
|
-
_ = errFile.Sync()
|
|
390
|
-
_ = outFile.Close()
|
|
391
|
-
outFile = nil
|
|
392
|
-
_ = errFile.Close()
|
|
393
|
-
errFile = nil
|
|
394
|
-
|
|
395
|
-
os.Stdout = prevOut
|
|
396
|
-
os.Stderr = prevErr
|
|
397
|
-
capturing = false
|
|
398
|
-
|
|
399
|
-
stdoutBytes, _ := os.ReadFile(stdoutPath)
|
|
400
|
-
stderrBytes, _ := os.ReadFile(stderrPath)
|
|
401
|
-
|
|
402
|
-
return APIResult{
|
|
403
|
-
Code: code,
|
|
404
|
-
Stdout: string(stdoutBytes),
|
|
405
|
-
Stderr: string(stderrBytes),
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
// captureCounter avoids temp-file name collisions when plugin dispatches
|
|
410
|
-
// overlap (multiple goroutines could be in runWithCapturedIO concurrently
|
|
411
|
-
// from independent JS callers).
|
|
412
|
-
var captureCounter atomic.Uint64
|
|
413
|
-
|
|
414
|
-
// captureMu serializes temporary replacement of package-global stdout/stderr.
|
|
415
|
-
// The temp filenames are unique, but os.Stdout/os.Stderr themselves are shared
|
|
416
|
-
// process state in the wasm runtime.
|
|
417
|
-
var captureMu sync.Mutex
|
package/host/plugin.go
CHANGED
|
@@ -1,60 +1,128 @@
|
|
|
1
1
|
package host
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
import (
|
|
4
|
+
"bytes"
|
|
5
|
+
"context"
|
|
6
|
+
"io"
|
|
7
|
+
"sync"
|
|
8
|
+
)
|
|
9
|
+
|
|
6
10
|
// Plugin is the in-process equivalent of ttsc's native CLI sidecar.
|
|
7
11
|
//
|
|
8
|
-
// The
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
// A typical Plugin implementation in the consumer wasm is a thin adapter that
|
|
14
|
-
// forwards to the same Run* function the native sidecar's `main.go` calls:
|
|
15
|
-
//
|
|
16
|
-
// type bannerPlugin struct{}
|
|
17
|
-
//
|
|
18
|
-
// func (bannerPlugin) Name() string { return "@ttsc/banner" }
|
|
19
|
-
// func (bannerPlugin) Run(command string, args []string) int {
|
|
20
|
-
// switch command {
|
|
21
|
-
// case "build": return utility.RunBuild(args)
|
|
22
|
-
// case "check": return utility.RunCheck(args)
|
|
23
|
-
// case "transform": return utility.RunTransform(args)
|
|
24
|
-
// default: return 2
|
|
25
|
-
// }
|
|
26
|
-
// }
|
|
27
|
-
//
|
|
28
|
-
// The host installs the package-level writers in `runWithCapturedIO` before
|
|
29
|
-
// calling Run, so anything the plugin writes to ttsc's `stdout` / `stderr`
|
|
30
|
-
// streams is captured and returned to the JS caller.
|
|
12
|
+
// The browser cannot spawn plugin binaries, so a consumer wasm links their Go
|
|
13
|
+
// adapters and registers them with Config. Every run receives invocation-owned
|
|
14
|
+
// streams; a plugin must write only to those streams, never os.Stdout or
|
|
15
|
+
// os.Stderr.
|
|
31
16
|
type Plugin interface {
|
|
32
|
-
// Name is the npm-style plugin id
|
|
33
|
-
// passes this exact string when dispatching:
|
|
34
|
-
// `api.plugin({ name: "@ttsc/banner", command: "build", ...opts })`.
|
|
35
|
-
// Names must be unique within a Config.
|
|
17
|
+
// Name is the npm-style plugin id passed to api.plugin.
|
|
36
18
|
Name() string
|
|
37
19
|
|
|
38
|
-
// Run dispatches
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
20
|
+
// Run dispatches one subcommand and returns the native CLI exit code.
|
|
21
|
+
Run(invocation *PluginInvocation) int
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// PluginInvocation owns all mutable state for one plugin call.
|
|
25
|
+
//
|
|
26
|
+
// A plugin that needs asynchronous work must register it with Go before Run
|
|
27
|
+
// returns. InvokePlugin waits for every registered function. Registration
|
|
28
|
+
// after Run returns is rejected, and writes made after the invocation closes
|
|
29
|
+
// return io.ErrClosedPipe. This gives child goroutines an explicit ownership
|
|
30
|
+
// boundary without sharing process-global output state.
|
|
31
|
+
type PluginInvocation struct {
|
|
32
|
+
Context context.Context
|
|
33
|
+
Command string
|
|
34
|
+
Args []string
|
|
35
|
+
Stdout io.Writer
|
|
36
|
+
Stderr io.Writer
|
|
37
|
+
|
|
38
|
+
childrenMu sync.Mutex
|
|
39
|
+
children sync.WaitGroup
|
|
40
|
+
acceptingChild bool
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Go registers and starts invocation-owned asynchronous work. It returns false
|
|
44
|
+
// when Run has already returned and the ownership boundary is closed.
|
|
45
|
+
func (invocation *PluginInvocation) Go(task func(context.Context)) bool {
|
|
46
|
+
if task == nil {
|
|
47
|
+
return false
|
|
48
|
+
}
|
|
49
|
+
invocation.childrenMu.Lock()
|
|
50
|
+
if !invocation.acceptingChild {
|
|
51
|
+
invocation.childrenMu.Unlock()
|
|
52
|
+
return false
|
|
53
|
+
}
|
|
54
|
+
invocation.children.Add(1)
|
|
55
|
+
invocation.childrenMu.Unlock()
|
|
56
|
+
go func() {
|
|
57
|
+
defer invocation.children.Done()
|
|
58
|
+
task(invocation.Context)
|
|
59
|
+
}()
|
|
60
|
+
return true
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// InvokePlugin executes one plugin call and captures its request-owned output.
|
|
64
|
+
// Independent invocations may run concurrently without sharing buffers.
|
|
65
|
+
func InvokePlugin(ctx context.Context, plugin Plugin, command string, args []string) APIResult {
|
|
66
|
+
if ctx == nil {
|
|
67
|
+
ctx = context.Background()
|
|
68
|
+
}
|
|
69
|
+
stdout := &invocationBuffer{}
|
|
70
|
+
stderr := &invocationBuffer{}
|
|
71
|
+
invocation := &PluginInvocation{
|
|
72
|
+
Context: ctx,
|
|
73
|
+
Command: command,
|
|
74
|
+
Args: append([]string(nil), args...),
|
|
75
|
+
Stdout: stdout,
|
|
76
|
+
Stderr: stderr,
|
|
77
|
+
acceptingChild: true,
|
|
78
|
+
}
|
|
79
|
+
code := plugin.Run(invocation)
|
|
80
|
+
|
|
81
|
+
invocation.childrenMu.Lock()
|
|
82
|
+
invocation.acceptingChild = false
|
|
83
|
+
invocation.childrenMu.Unlock()
|
|
84
|
+
invocation.children.Wait()
|
|
85
|
+
|
|
86
|
+
stdout.close()
|
|
87
|
+
stderr.close()
|
|
88
|
+
return APIResult{
|
|
89
|
+
Code: code,
|
|
90
|
+
Stdout: stdout.String(),
|
|
91
|
+
Stderr: stderr.String(),
|
|
92
|
+
}
|
|
50
93
|
}
|
|
51
94
|
|
|
52
95
|
// Config carries the optional registrations the host applies before binding
|
|
53
|
-
//
|
|
96
|
+
// globalThis[name]. Pass Config{} for a vanilla ttsc + tsgo wasm.
|
|
54
97
|
type Config struct {
|
|
55
|
-
// Plugins are dispatched through `api.plugin({ name, command, ...opts })` from
|
|
56
|
-
// JS. Their Run methods share the same `os.Stdout` / `os.Stderr` streams
|
|
57
|
-
// the base build/check/transform endpoints use, so diagnostics render
|
|
58
|
-
// the same way no matter which lane produced them.
|
|
59
98
|
Plugins []Plugin
|
|
60
99
|
}
|
|
100
|
+
|
|
101
|
+
// invocationBuffer serializes writers owned by one invocation. Closing it
|
|
102
|
+
// prevents an unregistered or late goroutine from modifying a completed result.
|
|
103
|
+
type invocationBuffer struct {
|
|
104
|
+
mu sync.Mutex
|
|
105
|
+
data bytes.Buffer
|
|
106
|
+
closed bool
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
func (buffer *invocationBuffer) Write(data []byte) (int, error) {
|
|
110
|
+
buffer.mu.Lock()
|
|
111
|
+
defer buffer.mu.Unlock()
|
|
112
|
+
if buffer.closed {
|
|
113
|
+
return 0, io.ErrClosedPipe
|
|
114
|
+
}
|
|
115
|
+
return buffer.data.Write(data)
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
func (buffer *invocationBuffer) String() string {
|
|
119
|
+
buffer.mu.Lock()
|
|
120
|
+
defer buffer.mu.Unlock()
|
|
121
|
+
return buffer.data.String()
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
func (buffer *invocationBuffer) close() {
|
|
125
|
+
buffer.mu.Lock()
|
|
126
|
+
buffer.closed = true
|
|
127
|
+
buffer.mu.Unlock()
|
|
128
|
+
}
|
package/lib/src/MemFSError.js
CHANGED
|
@@ -30,6 +30,8 @@ function errnoForCode(code) {
|
|
|
30
30
|
return -2;
|
|
31
31
|
case "EBADF":
|
|
32
32
|
return -9;
|
|
33
|
+
case "EBUSY":
|
|
34
|
+
return -16;
|
|
33
35
|
case "EEXIST":
|
|
34
36
|
return -17;
|
|
35
37
|
case "ENOTDIR":
|
|
@@ -40,6 +42,8 @@ function errnoForCode(code) {
|
|
|
40
42
|
return -22;
|
|
41
43
|
case "ESPIPE":
|
|
42
44
|
return -29;
|
|
45
|
+
case "ENOTEMPTY":
|
|
46
|
+
return -39;
|
|
43
47
|
default:
|
|
44
48
|
return -1;
|
|
45
49
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MemFSError.js","sourceRoot":"","sources":["../../src/MemFSError.ts"],"names":[],"mappings":";;;AAAA;;;;;;;GAOG;AACH,gBAAwB,SAAQ,KAAK;IAC5B,IAAI,CAAS;IACb,KAAK,CAAS;IACd,IAAI,CAAU;IACd,OAAO,CAAU;IACxB,YAAY,IAAY,EAAE,OAAe,EAAE,IAAa;QACtD,KAAK,CAAC,GAAG,IAAI,KAAK,OAAO,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;;AAED,kFAAkF;AAClF,SAAS,YAAY,CAAC,IAAY;IAChC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,CAAC,CAAC,CAAC;QACZ,KAAK,OAAO;YACV,OAAO,CAAC,CAAC,CAAC;QACZ,KAAK,QAAQ;YACX,OAAO,CAAC,EAAE,CAAC;QACb,KAAK,SAAS;YACZ,OAAO,CAAC,EAAE,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,CAAC,EAAE,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,CAAC,EAAE,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,CAAC,EAAE,CAAC;QACb;YACE,OAAO,CAAC,CAAC,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"MemFSError.js","sourceRoot":"","sources":["../../src/MemFSError.ts"],"names":[],"mappings":";;;AAAA;;;;;;;GAOG;AACH,gBAAwB,SAAQ,KAAK;IAC5B,IAAI,CAAS;IACb,KAAK,CAAS;IACd,IAAI,CAAU;IACd,OAAO,CAAU;IACxB,YAAY,IAAY,EAAE,OAAe,EAAE,IAAa;QACtD,KAAK,CAAC,GAAG,IAAI,KAAK,OAAO,IAAI,IAAI,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC;QAClD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CACF;;AAED,kFAAkF;AAClF,SAAS,YAAY,CAAC,IAAY;IAChC,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,CAAC,CAAC,CAAC;QACZ,KAAK,OAAO;YACV,OAAO,CAAC,CAAC,CAAC;QACZ,KAAK,OAAO;YACV,OAAO,CAAC,EAAE,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,CAAC,EAAE,CAAC;QACb,KAAK,SAAS;YACZ,OAAO,CAAC,EAAE,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,CAAC,EAAE,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,CAAC,EAAE,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,CAAC,EAAE,CAAC;QACb,KAAK,WAAW;YACd,OAAO,CAAC,EAAE,CAAC;QACb;YACE,OAAO,CAAC,CAAC,CAAC;IACd,CAAC;AACH,CAAC"}
|
package/lib/src/bootTtsc.js
CHANGED
|
@@ -95,46 +95,102 @@ async function bootTtscOnce(options, apiName) {
|
|
|
95
95
|
const wasmExecUrl = options.wasmExecUrl ?? defaultWasmExecUrl(wasmUrl);
|
|
96
96
|
const host = options.host ?? (0, createMemFS_1.createMemFS)();
|
|
97
97
|
const globalAny = globalThis;
|
|
98
|
-
//
|
|
99
|
-
//
|
|
100
|
-
|
|
98
|
+
// Install fs / process only if they aren't already in place, and remember
|
|
99
|
+
// whether THIS attempt installed them. The Go runtime this boot starts reads
|
|
100
|
+
// `globalThis.fs` when it runs, so the returned `host` must be the exact host
|
|
101
|
+
// backing those globals. A caller booting a second wasm over the same MemFS
|
|
102
|
+
// (or reusing one host across retries) reuses the same shims. When an earlier
|
|
103
|
+
// failed attempt already installed a different host's shims, those are torn
|
|
104
|
+
// down on failure below so this attempt can install its own.
|
|
105
|
+
const installedFs = !globalAny.fs;
|
|
106
|
+
const installedProcess = !globalAny.process;
|
|
107
|
+
let processShim;
|
|
108
|
+
if (installedFs)
|
|
101
109
|
globalAny.fs = host.fs;
|
|
102
|
-
if (
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
// module-eval time, so this import must follow the assignment above.
|
|
106
|
-
importScripts(wasmExecUrl);
|
|
107
|
-
// Race the Ready resolver against a Failed signal so a wasm-side fault
|
|
108
|
-
// (e.g. `host.Expose` refusing a duplicate call) surfaces here instead of
|
|
109
|
-
// hanging on `await ready` forever. `go.run` is fire-and-forget so its
|
|
110
|
-
// own rejection cannot reach this promise without an explicit channel.
|
|
111
|
-
const ready = new Promise((resolve, reject) => {
|
|
112
|
-
globalAny[apiName + "Ready"] = () => {
|
|
113
|
-
delete globalAny[apiName + "Failed"];
|
|
114
|
-
resolve();
|
|
115
|
-
};
|
|
116
|
-
globalAny[apiName + "Failed"] = (err) => {
|
|
117
|
-
delete globalAny[apiName + "Ready"];
|
|
118
|
-
reject(err instanceof Error ? err : new Error(String(err)));
|
|
119
|
-
};
|
|
120
|
-
});
|
|
121
|
-
const goCtor = globalAny.Go;
|
|
122
|
-
if (typeof goCtor !== "function") {
|
|
123
|
-
throw new Error(`bootTtsc: globalThis.Go was not installed by ${wasmExecUrl} — the file may not have loaded (CSP block, wrong content type, 404), or it is not the wasm_exec.js shipped with the Go toolchain.`);
|
|
110
|
+
if (installedProcess) {
|
|
111
|
+
processShim = createProcessShim();
|
|
112
|
+
globalAny.process = processShim;
|
|
124
113
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
114
|
+
// Any failure after global installation must leave the globals as this
|
|
115
|
+
// attempt found them, so a retry installs its own host's fs (and the returned
|
|
116
|
+
// host keeps matching the runtime's filesystem). Only remove what we
|
|
117
|
+
// installed and only while it is still ours — never stomp a foreign fs or one
|
|
118
|
+
// a concurrently-booted runtime already claimed.
|
|
119
|
+
const restoreGlobals = () => {
|
|
120
|
+
if (installedFs && globalAny.fs === host.fs)
|
|
121
|
+
delete globalAny.fs;
|
|
122
|
+
if (installedProcess && globalAny.process === processShim)
|
|
123
|
+
delete globalAny.process;
|
|
124
|
+
};
|
|
125
|
+
try {
|
|
126
|
+
// wasm_exec.js installs `globalThis.Go`. It also reads globalThis.fs at
|
|
127
|
+
// module-eval time, so this import must follow the assignment above.
|
|
128
|
+
importScripts(wasmExecUrl);
|
|
129
|
+
// Race the Ready resolver against a Failed signal so a wasm-side fault
|
|
130
|
+
// (e.g. `host.Expose` refusing a duplicate call) surfaces here instead of
|
|
131
|
+
// hanging on `await ready` forever.
|
|
132
|
+
let readyCb;
|
|
133
|
+
let failedCb;
|
|
134
|
+
const ready = new Promise((resolve, reject) => {
|
|
135
|
+
readyCb = () => {
|
|
136
|
+
delete globalAny[apiName + "Failed"];
|
|
137
|
+
resolve();
|
|
138
|
+
};
|
|
139
|
+
failedCb = (err) => {
|
|
140
|
+
delete globalAny[apiName + "Ready"];
|
|
141
|
+
reject(err instanceof Error ? err : new Error(String(err)));
|
|
142
|
+
};
|
|
143
|
+
globalAny[apiName + "Ready"] = readyCb;
|
|
144
|
+
globalAny[apiName + "Failed"] = failedCb;
|
|
145
|
+
});
|
|
146
|
+
const goCtor = globalAny.Go;
|
|
147
|
+
if (typeof goCtor !== "function") {
|
|
148
|
+
throw new Error(`bootTtsc: globalThis.Go was not installed by ${wasmExecUrl} — the file may not have loaded (CSP block, wrong content type, 404), or it is not the wasm_exec.js shipped with the Go toolchain.`);
|
|
149
|
+
}
|
|
150
|
+
const go = new goCtor();
|
|
151
|
+
const response = await fetch(wasmUrl);
|
|
152
|
+
if (!response.ok) {
|
|
153
|
+
throw new Error(`bootTtsc: failed to fetch ${wasmUrl}: ${response.status}`);
|
|
154
|
+
}
|
|
155
|
+
const wasm = await WebAssembly.instantiateStreaming(response, go.importObject);
|
|
156
|
+
// A normal host keeps `go.run` pending forever after signaling Ready, so a
|
|
157
|
+
// settlement (fulfil OR reject) BEFORE Ready means the Go runtime exited or
|
|
158
|
+
// panicked before it could register — e.g. an early `host.Expose` panic
|
|
159
|
+
// that never reached the Failed bridge. Race that early exit against
|
|
160
|
+
// readiness so the boot rejects with an actionable cause instead of hanging.
|
|
161
|
+
// The standard Go runner discards the exit code, so an unknown early exit
|
|
162
|
+
// can only synthesize a generic message; known host validation failures
|
|
163
|
+
// reject through Failed above and keep their original cause.
|
|
164
|
+
const runPromise = Promise.resolve(go.run(wasm.instance));
|
|
165
|
+
const earlyExit = runPromise.then(() => {
|
|
166
|
+
throw new Error(`bootTtsc: the ${apiName} wasm runtime exited before signaling readiness (the host may have panicked; check the wasm stderr).`);
|
|
167
|
+
}, (err) => {
|
|
168
|
+
throw new Error(`bootTtsc: the ${apiName} wasm runtime failed before signaling readiness: ${err instanceof Error ? err.message : String(err)}`);
|
|
169
|
+
});
|
|
170
|
+
// When Ready wins, the long-running runtime's eventual `go.run` settlement
|
|
171
|
+
// must not surface as an unhandled rejection. Attach a terminal handler to
|
|
172
|
+
// the losing branch.
|
|
173
|
+
earlyExit.catch(() => { });
|
|
174
|
+
try {
|
|
175
|
+
await Promise.race([ready, earlyExit]);
|
|
176
|
+
}
|
|
177
|
+
finally {
|
|
178
|
+
// Drop this attempt's readiness bridge so a later boot for the same
|
|
179
|
+
// apiName installs a clean pair and no stale resolver survives.
|
|
180
|
+
if (globalAny[apiName + "Ready"] === readyCb)
|
|
181
|
+
delete globalAny[apiName + "Ready"];
|
|
182
|
+
if (globalAny[apiName + "Failed"] === failedCb)
|
|
183
|
+
delete globalAny[apiName + "Failed"];
|
|
184
|
+
}
|
|
185
|
+
const api = globalAny[apiName];
|
|
186
|
+
if (!api)
|
|
187
|
+
throw new Error(`bootTtsc: ${apiName} global was not set — was the wasm built with host.Expose(${JSON.stringify(apiName)}, ...)?`);
|
|
188
|
+
return { api, host };
|
|
189
|
+
}
|
|
190
|
+
catch (err) {
|
|
191
|
+
restoreGlobals();
|
|
192
|
+
throw err;
|
|
129
193
|
}
|
|
130
|
-
const wasm = await WebAssembly.instantiateStreaming(response, go.importObject);
|
|
131
|
-
// go.run never resolves until the wasm exits; we don't await it.
|
|
132
|
-
void go.run(wasm.instance);
|
|
133
|
-
await ready;
|
|
134
|
-
const api = globalAny[apiName];
|
|
135
|
-
if (!api)
|
|
136
|
-
throw new Error(`bootTtsc: ${apiName} global was not set — was the wasm built with host.Expose(${JSON.stringify(apiName)}, ...)?`);
|
|
137
|
-
return { api, host };
|
|
138
194
|
}
|
|
139
195
|
/**
|
|
140
196
|
* Derive the `wasm_exec.js` URL from the wasm URL by replacing the filename.
|
package/lib/src/bootTtsc.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootTtsc.js","sourceRoot":"","sources":["../../src/bootTtsc.ts"],"names":[],"mappings":";;;AAAA,0DAA0D;AAC1D,EAAE;AACF,8EAA8E;AAC9E,2EAA2E;AAC3E,uCAAuC;AACvC,EAAE;AACF,uEAAuE;AACvE,4EAA4E;AAC5E,4EAA4E;AAC5E,+CAA4C;AAO5C;;;;;;;GAOG;AACH,MAAM,aAAa,GAAG,IAAI,GAAG,EAAgC,CAAC;AAE9D;;;;;;;GAOG;AACH,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAA4B,CAAC;AAE/D,SAAS,OAAO,CAAC,OAAe,EAAE,OAAe;IAC/C,OAAO,GAAG,OAAO,IAAI,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC;AACjD,CAAC;AAED;;;;;;GAMG;AACH,SAAS,cAAc,CAAC,OAAe;IACrC,IAAI,CAAC;QACH,MAAM,IAAI,GACR,OAAO,QAAQ,KAAK,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC;QACpE,OAAO,IAAI,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,OAAO,CAAC;IACjB,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,kBAAyB,OAAyB;IAChD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,MAAM,CAAC;IAC1C,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACxC,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,MAAM,KAAK,GAAG,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IACnE,MAAM,OAAO,GAAG,KAAK;SAClB,KAAK,CAAC,GAAG,EAAE;QACV,iEAAiE;IACnE,CAAC,CAAC;SACD,IAAI,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;SAC1C,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;QACb,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1B,MAAM,GAAG,CAAC;IACZ,CAAC,CAAC,CAAC;IACL,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;IAChC,sEAAsE;IACtE,kEAAkE;IAClE,sEAAsE;IACtE,gDAAgD;IAChD,kBAAkB,CAAC,GAAG,CACpB,OAAO,EACP,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CACxB,CAAC;IACF,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,KAAK,UAAU,YAAY,CACzB,OAAyB,EACzB,OAAe;IAEf,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAChC,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAEvE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,IAAA,yBAAW,GAAE,CAAC;IAC3C,MAAM,SAAS,GAAG,UAAqC,CAAC;IACxD,
|
|
1
|
+
{"version":3,"file":"bootTtsc.js","sourceRoot":"","sources":["../../src/bootTtsc.ts"],"names":[],"mappings":"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"}
|