@ttsc/wasm 0.12.2 → 0.12.4

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.
Files changed (39) hide show
  1. package/cmd/ttsc-wasm/main.go +101 -89
  2. package/cmd/ttsc-wasm/main_wasm.go +6 -4
  3. package/dist/ttsc.wasm +0 -0
  4. package/host/api.go +154 -145
  5. package/host/doc.go +12 -12
  6. package/host/host.go +236 -225
  7. package/host/host_native.go +5 -2
  8. package/host/plugin.go +31 -31
  9. package/lib/src/MemFS.d.ts +35 -0
  10. package/lib/src/MemFS.js +57 -4
  11. package/lib/src/MemFS.js.map +1 -1
  12. package/lib/src/api.d.ts +46 -13
  13. package/lib/src/api.js +7 -4
  14. package/lib/src/api.js.map +1 -1
  15. package/lib/src/index.d.ts +1 -1
  16. package/lib/src/index.js +10 -3
  17. package/lib/src/index.js.map +1 -1
  18. package/lib/src/instantiate.d.ts +10 -7
  19. package/lib/src/instantiate.js +20 -3
  20. package/lib/src/instantiate.js.map +1 -1
  21. package/package.json +2 -2
  22. package/shim-vendor/shim/ast/go.mod +9 -0
  23. package/shim-vendor/shim/ast/go.sum +20 -0
  24. package/shim-vendor/shim/ast/safe_text.go +86 -0
  25. package/shim-vendor/shim/ast/shim.go +24 -0
  26. package/shim-vendor/shim/ast/test/node_text_joins_multi_hop_qualified_name_test.go +32 -0
  27. package/shim-vendor/shim/ast/test/node_text_joins_one_hop_qualified_name_test.go +31 -0
  28. package/shim-vendor/shim/ast/test/node_text_returns_empty_for_nil_test.go +23 -0
  29. package/shim-vendor/shim/ast/test/node_text_returns_identifier_text_test.go +27 -0
  30. package/shim-vendor/shim/ast/test/node_text_skips_empty_qualified_left_test.go +30 -0
  31. package/shim-vendor/shim/checker/shim.go +35 -0
  32. package/shim-vendor/shim/core/shim.go +17 -0
  33. package/shim-vendor/shim/diagnosticwriter/shim.go +4 -0
  34. package/shim-vendor/shim/lsp/shim.go +3 -3
  35. package/shim-vendor/shim/printer/shim.go +20 -0
  36. package/src/MemFS.ts +92 -7
  37. package/src/api.ts +46 -13
  38. package/src/index.ts +1 -5
  39. package/src/instantiate.ts +37 -14
@@ -9,122 +9,134 @@
9
9
  package main
10
10
 
11
11
  import (
12
- "fmt"
13
- "io"
14
- "os"
15
- "runtime"
12
+ "fmt"
13
+ "io"
14
+ "os"
15
+ "runtime"
16
16
 
17
- "github.com/samchon/ttsc/packages/wasm/host"
17
+ "github.com/samchon/ttsc/packages/wasm/host"
18
18
  )
19
19
 
20
20
  // Build metadata. Overridden via -ldflags from build/build-wasm.cjs.
21
21
  var (
22
- version = "0.0.0-dev"
23
- commit = "dev"
24
- date = "unknown"
22
+ version = "0.0.0-dev"
23
+ commit = "dev"
24
+ date = "unknown"
25
25
  )
26
26
 
27
27
  func main() {
28
- os.Exit(run(os.Args[1:]))
28
+ os.Exit(run(os.Args[1:]))
29
29
  }
30
30
 
31
+ // run is the testable core of main. It dispatches the first argument as a
32
+ // subcommand and returns the OS exit code.
31
33
  func run(args []string) int {
32
- if len(args) == 0 {
33
- printHelp(os.Stdout)
34
- return 0
35
- }
36
- switch args[0] {
37
- case "-h", "--help", "help":
38
- printHelp(os.Stdout)
39
- return 0
40
- case "-v", "--version", "version":
41
- printVersion(os.Stdout)
42
- return 0
43
- case "build":
44
- return runBuild(args[1:])
45
- case "check":
46
- return runCheck(args[1:])
47
- case "transform":
48
- return runTransform(args[1:])
49
- default:
50
- fmt.Fprintf(os.Stderr, "ttsc-wasm: unknown command %q\n", args[0])
51
- printHelp(os.Stderr)
52
- return 2
53
- }
34
+ if len(args) == 0 {
35
+ printHelp(os.Stdout)
36
+ return 0
37
+ }
38
+ switch args[0] {
39
+ case "-h", "--help", "help":
40
+ printHelp(os.Stdout)
41
+ return 0
42
+ case "-v", "--version", "version":
43
+ printVersion(os.Stdout)
44
+ return 0
45
+ case "build":
46
+ return runBuild(args[1:])
47
+ case "check":
48
+ return runCheck(args[1:])
49
+ case "transform":
50
+ return runTransform(args[1:])
51
+ default:
52
+ fmt.Fprintf(os.Stderr, "ttsc-wasm: unknown command %q\n", args[0])
53
+ printHelp(os.Stderr)
54
+ return 2
55
+ }
54
56
  }
55
57
 
58
+ // runBuild invokes host.Build and writes the JSON result to stdout.
56
59
  func runBuild(args []string) int {
57
- cwd, tsconfig := parseProject(args)
58
- data, code, err := host.Build(cwd, tsconfig)
59
- if err != nil {
60
- fmt.Fprintf(os.Stderr, "ttsc-wasm build: %v\n", err)
61
- return 2
62
- }
63
- _, _ = os.Stdout.Write(append(data, '\n'))
64
- return code
60
+ cwd, tsconfig := parseProject(args)
61
+ data, code, err := host.Build(cwd, tsconfig)
62
+ if err != nil {
63
+ fmt.Fprintf(os.Stderr, "ttsc-wasm build: %v\n", err)
64
+ return 2
65
+ }
66
+ _, _ = os.Stdout.Write(append(data, '\n'))
67
+ return code
65
68
  }
66
69
 
70
+ // runCheck invokes host.Check and writes the JSON result to stdout.
67
71
  func runCheck(args []string) int {
68
- cwd, tsconfig := parseProject(args)
69
- data, code, err := host.Check(cwd, tsconfig)
70
- if err != nil {
71
- fmt.Fprintf(os.Stderr, "ttsc-wasm check: %v\n", err)
72
- return 2
73
- }
74
- _, _ = os.Stdout.Write(append(data, '\n'))
75
- return code
72
+ cwd, tsconfig := parseProject(args)
73
+ data, code, err := host.Check(cwd, tsconfig)
74
+ if err != nil {
75
+ fmt.Fprintf(os.Stderr, "ttsc-wasm check: %v\n", err)
76
+ return 2
77
+ }
78
+ _, _ = os.Stdout.Write(append(data, '\n'))
79
+ return code
76
80
  }
77
81
 
82
+ // runTransform invokes host.Transform and writes the JSON result to stdout.
78
83
  func runTransform(args []string) int {
79
- cwd, tsconfig := parseProject(args)
80
- data, code, err := host.Transform(cwd, tsconfig)
81
- if err != nil {
82
- fmt.Fprintf(os.Stderr, "ttsc-wasm transform: %v\n", err)
83
- return 2
84
- }
85
- _, _ = os.Stdout.Write(append(data, '\n'))
86
- return code
84
+ cwd, tsconfig := parseProject(args)
85
+ data, code, err := host.Transform(cwd, tsconfig)
86
+ if err != nil {
87
+ fmt.Fprintf(os.Stderr, "ttsc-wasm transform: %v\n", err)
88
+ return 2
89
+ }
90
+ _, _ = os.Stdout.Write(append(data, '\n'))
91
+ return code
87
92
  }
88
93
 
94
+ // parseProject extracts --cwd and --tsconfig from args, defaulting to the
95
+ // process working directory and "tsconfig.json" respectively. Both the
96
+ // `--flag value` and `--flag=value` forms are accepted.
89
97
  func parseProject(args []string) (string, string) {
90
- cwd, _ := os.Getwd()
91
- tsconfig := "tsconfig.json"
92
- for i := 0; i < len(args); i++ {
93
- arg := args[i]
94
- switch {
95
- case arg == "--cwd" && i+1 < len(args):
96
- cwd = args[i+1]
97
- i++
98
- case len(arg) > len("--cwd=") && arg[:6] == "--cwd=":
99
- cwd = arg[6:]
100
- case arg == "--tsconfig" && i+1 < len(args):
101
- tsconfig = args[i+1]
102
- i++
103
- case len(arg) > len("--tsconfig=") && arg[:11] == "--tsconfig=":
104
- tsconfig = arg[11:]
105
- }
106
- }
107
- return cwd, tsconfig
98
+ cwd, _ := os.Getwd()
99
+ tsconfig := "tsconfig.json"
100
+ const cwdPrefix = "--cwd="
101
+ const tsconfigPrefix = "--tsconfig="
102
+ for i := 0; i < len(args); i++ {
103
+ arg := args[i]
104
+ switch {
105
+ case arg == "--cwd" && i+1 < len(args):
106
+ cwd = args[i+1]
107
+ i++
108
+ case len(arg) > len(cwdPrefix) && arg[:len(cwdPrefix)] == cwdPrefix:
109
+ cwd = arg[len(cwdPrefix):]
110
+ case arg == "--tsconfig" && i+1 < len(args):
111
+ tsconfig = args[i+1]
112
+ i++
113
+ case len(arg) > len(tsconfigPrefix) && arg[:len(tsconfigPrefix)] == tsconfigPrefix:
114
+ tsconfig = arg[len(tsconfigPrefix):]
115
+ }
116
+ }
117
+ return cwd, tsconfig
108
118
  }
109
119
 
120
+ // printHelp writes the usage summary to w.
110
121
  func printHelp(w io.Writer) {
111
- fmt.Fprintln(w, "Usage: ttsc-wasm <command> [--cwd=<dir>] [--tsconfig=<path>]")
112
- fmt.Fprintln(w, "Commands:")
113
- fmt.Fprintln(w, " build compile a project and print the JSON result")
114
- fmt.Fprintln(w, " check type-check a project without emit")
115
- fmt.Fprintln(w, " transform return every source file the program saw")
116
- fmt.Fprintln(w, " version print version banner")
122
+ fmt.Fprintln(w, "Usage: ttsc-wasm <command> [--cwd=<dir>] [--tsconfig=<path>]")
123
+ fmt.Fprintln(w, "Commands:")
124
+ fmt.Fprintln(w, " build compile a project and print the JSON result")
125
+ fmt.Fprintln(w, " check type-check a project without emit")
126
+ fmt.Fprintln(w, " transform return every source file the program saw")
127
+ fmt.Fprintln(w, " version print version banner")
117
128
  }
118
129
 
130
+ // printVersion writes the build metadata banner to w.
119
131
  func printVersion(w io.Writer) {
120
- fmt.Fprintf(
121
- w,
122
- "ttsc-wasm %s (commit %s, built %s, %s/%s, go %s)\n",
123
- version,
124
- commit,
125
- date,
126
- runtime.GOOS,
127
- runtime.GOARCH,
128
- runtime.Version(),
129
- )
132
+ fmt.Fprintf(
133
+ w,
134
+ "ttsc-wasm %s (commit %s, built %s, %s/%s, go %s)\n",
135
+ version,
136
+ commit,
137
+ date,
138
+ runtime.GOOS,
139
+ runtime.GOARCH,
140
+ runtime.Version(),
141
+ )
130
142
  }
@@ -7,11 +7,13 @@
7
7
  package main
8
8
 
9
9
  import (
10
- "github.com/samchon/ttsc/packages/wasm/host"
10
+ "github.com/samchon/ttsc/packages/wasm/host"
11
11
  )
12
12
 
13
+ // main installs the base ttsc API on globalThis and blocks forever.
14
+ // Expose never returns; the select{} inside it keeps the wasm runtime alive.
13
15
  func main() {
14
- host.Expose("ttsc", host.Config{
15
- Plugins: nil,
16
- })
16
+ host.Expose("ttsc", host.Config{
17
+ Plugins: nil,
18
+ })
17
19
  }
package/dist/ttsc.wasm CHANGED
Binary file
package/host/api.go CHANGED
@@ -6,14 +6,14 @@
6
6
  package host
7
7
 
8
8
  import (
9
- "encoding/json"
10
- "fmt"
11
- "path/filepath"
12
- "strings"
9
+ "encoding/json"
10
+ "fmt"
11
+ "path/filepath"
12
+ "strings"
13
13
 
14
- shimcompiler "github.com/microsoft/typescript-go/shim/compiler"
14
+ shimcompiler "github.com/microsoft/typescript-go/shim/compiler"
15
15
 
16
- "github.com/samchon/ttsc/packages/ttsc/driver"
16
+ "github.com/samchon/ttsc/packages/ttsc/driver"
17
17
  )
18
18
 
19
19
  // APIResult is the JSON shape every plugin-dispatch endpoint returns to the
@@ -21,185 +21,194 @@ import (
21
21
  // usage error, 3 runtime error). `stdout` / `stderr` are raw strings the
22
22
  // caller can render in a console panel.
23
23
  type APIResult struct {
24
- Code int `json:"code"`
25
- Stdout string `json:"stdout"`
26
- Stderr string `json:"stderr"`
24
+ Code int `json:"code"`
25
+ Stdout string `json:"stdout"`
26
+ Stderr string `json:"stderr"`
27
27
  }
28
28
 
29
29
  // CompileResult mirrors `ttsc api-compile`. Field names are TypeScript-style
30
30
  // so JS callers can use it directly without remapping.
31
31
  type CompileResult struct {
32
- Diagnostics []CompileDiagnostic `json:"diagnostics,omitempty"`
33
- // Output maps cwd-relative paths to emitted JS / d.ts text. Empty when
34
- // the program produced no files (e.g. `noEmit` projects).
35
- Output map[string]string `json:"output"`
32
+ Diagnostics []CompileDiagnostic `json:"diagnostics,omitempty"`
33
+ // Output maps cwd-relative paths to emitted JS / d.ts text. Empty when
34
+ // the program produced no files (e.g. `noEmit` projects).
35
+ Output map[string]string `json:"output"`
36
36
  }
37
37
 
38
38
  // TransformResult is the no-emit companion. The `typescript` map keys files
39
39
  // the same way `output` does in compile mode.
40
40
  type TransformResult struct {
41
- Diagnostics []CompileDiagnostic `json:"diagnostics,omitempty"`
42
- TypeScript map[string]string `json:"typescript"`
41
+ Diagnostics []CompileDiagnostic `json:"diagnostics,omitempty"`
42
+ TypeScript map[string]string `json:"typescript"`
43
43
  }
44
44
 
45
45
  // CompileDiagnostic is the public TypeScript-side diagnostic DTO. Mirrors the
46
46
  // shape `ttsc api-compile` writes so the JS host can render it without
47
47
  // remapping fields.
48
48
  type CompileDiagnostic struct {
49
- File *string `json:"file"`
50
- Category string `json:"category"`
51
- Code int32 `json:"code"`
52
- Start *int `json:"start,omitempty"`
53
- Length *int `json:"length,omitempty"`
54
- Line int `json:"line,omitempty"`
55
- Character int `json:"character,omitempty"`
56
- MessageText string `json:"messageText"`
49
+ File *string `json:"file"`
50
+ Category string `json:"category"`
51
+ Code int32 `json:"code"`
52
+ Start *int `json:"start,omitempty"`
53
+ Length *int `json:"length,omitempty"`
54
+ Line int `json:"line,omitempty"`
55
+ Character int `json:"character,omitempty"`
56
+ MessageText string `json:"messageText"`
57
57
  }
58
58
 
59
59
  // Build runs `ttsc build`-shaped emit: load the project, emit JS, return the
60
60
  // emitted text map + diagnostics as JSON. `cwd` must be an absolute path
61
61
  // inside the host filesystem; `tsconfigPath` may be relative to cwd.
62
62
  func Build(cwd, tsconfigPath string) ([]byte, int, error) {
63
- prog, diags, err := driver.LoadProgram(cwd, tsconfigPath, driver.LoadProgramOptions{
64
- ForceEmit: true,
65
- })
66
- if err != nil {
67
- return nil, 2, err
68
- }
69
- if prog != nil {
70
- defer prog.Close()
71
- diags = append(diags, prog.Diagnostics()...)
72
- }
73
- output := map[string]string{}
74
- if prog != nil {
75
- rewrites := driver.NewRewriteSet()
76
- writeFile := shimcompiler.WriteFile(
77
- func(fileName, text string, _ *shimcompiler.WriteFileData) error {
78
- output[apiOutputKey(cwd, fileName)] = text
79
- return nil
80
- },
81
- )
82
- _, emitDiags, eerr := prog.EmitAll(rewrites, writeFile)
83
- if eerr != nil {
84
- return nil, 3, fmt.Errorf("emit failed: %w", eerr)
85
- }
86
- diags = append(diags, emitDiags...)
87
- }
88
- result := CompileResult{
89
- Diagnostics: make([]CompileDiagnostic, 0, len(diags)),
90
- Output: output,
91
- }
92
- for _, d := range diags {
93
- result.Diagnostics = append(result.Diagnostics, toAPIDiagnostic(d))
94
- }
95
- data, err := json.Marshal(result)
96
- if err != nil {
97
- return nil, 3, fmt.Errorf("result marshal failed: %w", err)
98
- }
99
- code := 0
100
- if driver.CountErrors(diags) > 0 {
101
- code = 2
102
- }
103
- return data, code, nil
63
+ prog, diags, err := driver.LoadProgram(cwd, tsconfigPath, driver.LoadProgramOptions{
64
+ ForceEmit: true,
65
+ })
66
+ if err != nil {
67
+ return nil, 2, err
68
+ }
69
+ if prog != nil {
70
+ defer prog.Close()
71
+ diags = append(diags, prog.Diagnostics()...)
72
+ }
73
+ output := map[string]string{}
74
+ if prog != nil {
75
+ rewrites := driver.NewRewriteSet()
76
+ writeFile := shimcompiler.WriteFile(
77
+ func(fileName, text string, _ *shimcompiler.WriteFileData) error {
78
+ output[apiOutputKey(cwd, fileName)] = text
79
+ return nil
80
+ },
81
+ )
82
+ _, emitDiags, eerr := prog.EmitAll(rewrites, writeFile)
83
+ if eerr != nil {
84
+ return nil, 3, fmt.Errorf("emit failed: %w", eerr)
85
+ }
86
+ diags = append(diags, emitDiags...)
87
+ }
88
+ result := CompileResult{
89
+ Diagnostics: make([]CompileDiagnostic, 0, len(diags)),
90
+ Output: output,
91
+ }
92
+ for _, d := range diags {
93
+ result.Diagnostics = append(result.Diagnostics, toAPIDiagnostic(d))
94
+ }
95
+ data, err := json.Marshal(result)
96
+ if err != nil {
97
+ return nil, 3, fmt.Errorf("result marshal failed: %w", err)
98
+ }
99
+ code := 0
100
+ if driver.CountErrors(diags) > 0 {
101
+ code = 2
102
+ }
103
+ return data, code, nil
104
104
  }
105
105
 
106
106
  // Check runs the typecheck pipeline without emitting JS. The returned JSON
107
107
  // has the same shape as Build but with an empty `output` map.
108
108
  func Check(cwd, tsconfigPath string) ([]byte, int, error) {
109
- prog, diags, err := driver.LoadProgram(cwd, tsconfigPath, driver.LoadProgramOptions{
110
- ForceNoEmit: true,
111
- })
112
- if err != nil {
113
- return nil, 2, err
114
- }
115
- if prog != nil {
116
- defer prog.Close()
117
- diags = append(diags, prog.Diagnostics()...)
118
- }
119
- result := CompileResult{
120
- Diagnostics: make([]CompileDiagnostic, 0, len(diags)),
121
- Output: map[string]string{},
122
- }
123
- for _, d := range diags {
124
- result.Diagnostics = append(result.Diagnostics, toAPIDiagnostic(d))
125
- }
126
- data, err := json.Marshal(result)
127
- if err != nil {
128
- return nil, 3, fmt.Errorf("result marshal failed: %w", err)
129
- }
130
- code := 0
131
- if driver.CountErrors(diags) > 0 {
132
- code = 2
133
- }
134
- return data, code, nil
109
+ prog, diags, err := driver.LoadProgram(cwd, tsconfigPath, driver.LoadProgramOptions{
110
+ ForceNoEmit: true,
111
+ })
112
+ if err != nil {
113
+ return nil, 2, err
114
+ }
115
+ if prog != nil {
116
+ defer prog.Close()
117
+ diags = append(diags, prog.Diagnostics()...)
118
+ }
119
+ result := CompileResult{
120
+ Diagnostics: make([]CompileDiagnostic, 0, len(diags)),
121
+ Output: map[string]string{},
122
+ }
123
+ for _, d := range diags {
124
+ result.Diagnostics = append(result.Diagnostics, toAPIDiagnostic(d))
125
+ }
126
+ data, err := json.Marshal(result)
127
+ if err != nil {
128
+ return nil, 3, fmt.Errorf("result marshal failed: %w", err)
129
+ }
130
+ code := 0
131
+ if driver.CountErrors(diags) > 0 {
132
+ code = 2
133
+ }
134
+ return data, code, nil
135
135
  }
136
136
 
137
137
  // Transform returns every source file the program saw, keyed by
138
138
  // project-relative path. The playground uses this to render the TS view
139
139
  // after source rewrites (e.g. paths rewriting) have been applied.
140
140
  func Transform(cwd, tsconfigPath string) ([]byte, int, error) {
141
- prog, diags, err := driver.LoadProgram(cwd, tsconfigPath, driver.LoadProgramOptions{
142
- ForceNoEmit: true,
143
- })
144
- if err != nil {
145
- return nil, 2, err
146
- }
147
- typescript := map[string]string{}
148
- if prog != nil {
149
- defer prog.Close()
150
- for _, file := range prog.SourceFiles() {
151
- typescript[apiOutputKey(cwd, file.FileName())] = file.Text()
152
- }
153
- diags = append(diags, prog.Diagnostics()...)
154
- }
155
- result := TransformResult{
156
- Diagnostics: make([]CompileDiagnostic, 0, len(diags)),
157
- TypeScript: typescript,
158
- }
159
- for _, d := range diags {
160
- result.Diagnostics = append(result.Diagnostics, toAPIDiagnostic(d))
161
- }
162
- data, err := json.Marshal(result)
163
- if err != nil {
164
- return nil, 3, fmt.Errorf("result marshal failed: %w", err)
165
- }
166
- code := 0
167
- if driver.CountErrors(diags) > 0 {
168
- code = 2
169
- }
170
- return data, code, nil
141
+ prog, diags, err := driver.LoadProgram(cwd, tsconfigPath, driver.LoadProgramOptions{
142
+ ForceNoEmit: true,
143
+ })
144
+ if err != nil {
145
+ return nil, 2, err
146
+ }
147
+ typescript := map[string]string{}
148
+ if prog != nil {
149
+ defer prog.Close()
150
+ for _, file := range prog.SourceFiles() {
151
+ typescript[apiOutputKey(cwd, file.FileName())] = file.Text()
152
+ }
153
+ diags = append(diags, prog.Diagnostics()...)
154
+ }
155
+ result := TransformResult{
156
+ Diagnostics: make([]CompileDiagnostic, 0, len(diags)),
157
+ TypeScript: typescript,
158
+ }
159
+ for _, d := range diags {
160
+ result.Diagnostics = append(result.Diagnostics, toAPIDiagnostic(d))
161
+ }
162
+ data, err := json.Marshal(result)
163
+ if err != nil {
164
+ return nil, 3, fmt.Errorf("result marshal failed: %w", err)
165
+ }
166
+ code := 0
167
+ if driver.CountErrors(diags) > 0 {
168
+ code = 2
169
+ }
170
+ return data, code, nil
171
171
  }
172
172
 
173
+ // toAPIDiagnostic converts a driver.Diagnostic into the JSON-serialisable
174
+ // CompileDiagnostic. File paths are normalised to forward slashes so the JS
175
+ // host can compare them against its own MemFS paths.
173
176
  func toAPIDiagnostic(diag driver.Diagnostic) CompileDiagnostic {
174
- var file *string
175
- if diag.File != "" {
176
- value := filepath.ToSlash(diag.File)
177
- file = &value
178
- }
179
- category := "error"
180
- if diag.Severity == driver.SeverityWarning {
181
- category = "warning"
182
- }
183
- return CompileDiagnostic{
184
- File: file,
185
- Category: category,
186
- Code: diag.Code,
187
- Start: diag.Start,
188
- Length: diag.Length,
189
- Line: diag.Line,
190
- Character: diag.Column,
191
- MessageText: diag.Message,
192
- }
177
+ var file *string
178
+ if diag.File != "" {
179
+ value := filepath.ToSlash(diag.File)
180
+ file = &value
181
+ }
182
+ category := "error"
183
+ if diag.Severity == driver.SeverityWarning {
184
+ category = "warning"
185
+ }
186
+ return CompileDiagnostic{
187
+ File: file,
188
+ Category: category,
189
+ Code: diag.Code,
190
+ Start: diag.Start,
191
+ Length: diag.Length,
192
+ Line: diag.Line,
193
+ Character: diag.Column,
194
+ MessageText: diag.Message,
195
+ }
193
196
  }
194
197
 
198
+ // apiOutputKey returns the map key used in CompileResult.Output and
199
+ // TransformResult.TypeScript. Paths inside cwd are made project-relative;
200
+ // paths outside cwd (e.g. lib files) are returned as absolute slash paths.
195
201
  func apiOutputKey(cwd, fileName string) string {
196
- rel, err := filepath.Rel(cwd, fileName)
197
- if err != nil || isOutsideRelativePath(rel) {
198
- return filepath.ToSlash(fileName)
199
- }
200
- return filepath.ToSlash(rel)
202
+ rel, err := filepath.Rel(cwd, fileName)
203
+ if err != nil || isOutsideRelativePath(rel) {
204
+ return filepath.ToSlash(fileName)
205
+ }
206
+ return filepath.ToSlash(rel)
201
207
  }
202
208
 
209
+ // isOutsideRelativePath reports whether rel escapes the base directory (i.e.
210
+ // starts with ".."). Such paths should not be presented as project-relative
211
+ // keys to the JS caller.
203
212
  func isOutsideRelativePath(rel string) bool {
204
- return rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator))
213
+ return rel == ".." || strings.HasPrefix(rel, ".."+string(filepath.Separator))
205
214
  }
package/host/doc.go CHANGED
@@ -3,20 +3,20 @@
3
3
  //
4
4
  // A consumer wasm looks like this:
5
5
  //
6
- // //go:build js
7
- // package main
6
+ // //go:build js
7
+ // package main
8
8
  //
9
- // import (
10
- // "github.com/samchon/ttsc/packages/wasm/host"
11
- // yourplugin "example.com/your/plugin"
12
- // )
9
+ // import (
10
+ // "github.com/samchon/ttsc/packages/wasm/host"
11
+ // yourplugin "example.com/your/plugin"
12
+ // )
13
13
  //
14
- // func main() {
15
- // host.Expose("yourApi", host.Config{
16
- // Plugins: []host.Plugin{yourplugin.New()},
17
- // })
18
- // select {}
19
- // }
14
+ // func main() {
15
+ // // Expose never returns; it installs the JS API and blocks forever.
16
+ // host.Expose("yourApi", host.Config{
17
+ // Plugins: []host.Plugin{yourplugin.New()},
18
+ // })
19
+ // }
20
20
  //
21
21
  // Expose binds `globalThis[name]` to an object that exposes ttsc's base
22
22
  // project commands (build, check, transform, version) plus a `plugin(name,