@ttsc/wasm 0.12.2 → 0.12.3

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/dist/ttsc.wasm CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttsc/wasm",
3
- "version": "0.12.2",
3
+ "version": "0.12.3",
4
4
  "description": "Build in-browser ttsc playgrounds. Compose ttsc + typescript-go with your own plugins via the Go host helper.",
5
5
  "main": "lib/src/index.js",
6
6
  "types": "lib/src/index.d.ts",
@@ -38,7 +38,7 @@
38
38
  "homepage": "https://ttsc.dev",
39
39
  "devDependencies": {
40
40
  "@types/node": "^25.3.0",
41
- "@typescript/native-preview": "7.0.0-dev.20260515.1",
41
+ "@typescript/native-preview": "7.0.0-dev.20260518.1",
42
42
  "rimraf": "^6.1.2"
43
43
  },
44
44
  "scripts": {
@@ -3,3 +3,12 @@ module github.com/microsoft/typescript-go/shim/ast
3
3
  go 1.26
4
4
 
5
5
  require github.com/microsoft/typescript-go v0.0.0-20260429010842-56ab4af42157
6
+
7
+ require (
8
+ github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433 // indirect
9
+ github.com/klauspost/cpuid/v2 v2.2.10 // indirect
10
+ github.com/zeebo/xxh3 v1.1.0 // indirect
11
+ golang.org/x/sync v0.20.0 // indirect
12
+ golang.org/x/sys v0.43.0 // indirect
13
+ golang.org/x/text v0.36.0 // indirect
14
+ )
@@ -0,0 +1,20 @@
1
+ github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433 h1:vymEbVwYFP/L05h5TKQxvkXoKxNvTpjxYKdF1Nlwuao=
2
+ github.com/go-json-experiment/json v0.0.0-20260214004413-d219187c3433/go.mod h1:tphK2c80bpPhMOI4v6bIc2xWywPfbqi1Z06+RcrMkDg=
3
+ github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
4
+ github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
5
+ github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
6
+ github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
7
+ github.com/microsoft/typescript-go v0.0.0-20260429010842-56ab4af42157 h1:llOMPhKDiQ+UEJiAaQuuWaJOTg5V7tNNTEf9JPWoYSY=
8
+ github.com/microsoft/typescript-go v0.0.0-20260429010842-56ab4af42157/go.mod h1:m8YA0PMC7ti0GW0RI05D6fEcjQeu98XVS+FWF+VDW2k=
9
+ github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
10
+ github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0=
11
+ github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs=
12
+ github.com/zeebo/xxh3 v1.1.0/go.mod h1:IisAie1LELR4xhVinxWS5+zf1lA4p0MW4T+w+W07F5s=
13
+ golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4=
14
+ golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
15
+ golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI=
16
+ golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw=
17
+ golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg=
18
+ golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164=
19
+ gotest.tools/v3 v3.5.2 h1:7koQfIKdy+I8UTetycgUqXWSDwpgv193Ka+qRsmBY8Q=
20
+ gotest.tools/v3 v3.5.2/go.mod h1:LtdLGcnqToBH83WByAAi/wiwSFCArdFIUV/xxN4pcjA=
@@ -0,0 +1,86 @@
1
+ // gen_shims:hand-maintained
2
+ //
3
+ // Total-function replacement for upstream `(*Node).Text()`.
4
+ //
5
+ // Upstream panics for any Kind missing from its switch — most notably
6
+ // KindQualifiedName, which surfaces in JSDoc parameter names (`@param
7
+ // obj.field`) and dotted entity references. NodeText handles
8
+ // QualifiedName by recursing on the left subtree and joining with the
9
+ // right identifier, and falls back to the source-text slice for any
10
+ // other Kind so downstream code can treat the helper as a total
11
+ // function over *Node instead of guarding each call site.
12
+
13
+ package ast
14
+
15
+ import (
16
+ "strings"
17
+
18
+ innerast "github.com/microsoft/typescript-go/internal/ast"
19
+ )
20
+
21
+ // NodeText returns the identifier-like text of a node. It mirrors
22
+ // upstream `(*Node).Text()` where upstream has an arm, adds a
23
+ // QualifiedName arm that joins `left.right`, and falls back to the
24
+ // node's source slice for any other Kind. Returns "" for nil.
25
+ func NodeText(n *Node) string {
26
+ if n == nil {
27
+ return ""
28
+ }
29
+ switch n.Kind {
30
+ case KindIdentifier,
31
+ innerast.KindPrivateIdentifier,
32
+ KindStringLiteral,
33
+ KindNumericLiteral,
34
+ KindBigIntLiteral,
35
+ KindNoSubstitutionTemplateLiteral,
36
+ KindTemplateHead,
37
+ KindTemplateMiddle,
38
+ KindTemplateTail,
39
+ innerast.KindRegularExpressionLiteral,
40
+ innerast.KindJsxNamespacedName,
41
+ innerast.KindJSDocText,
42
+ innerast.KindJSDocLink,
43
+ innerast.KindJSDocLinkCode,
44
+ innerast.KindJSDocLinkPlain,
45
+ innerast.KindMetaProperty:
46
+ return n.Text()
47
+ case KindQualifiedName:
48
+ qn := n.AsQualifiedName()
49
+ if qn == nil {
50
+ return ""
51
+ }
52
+ left := NodeText(qn.Left)
53
+ right := ""
54
+ if qn.Right != nil {
55
+ right = qn.Right.Text()
56
+ }
57
+ switch {
58
+ case left == "" && right == "":
59
+ return ""
60
+ case left == "":
61
+ return right
62
+ case right == "":
63
+ return left
64
+ default:
65
+ return left + "." + right
66
+ }
67
+ }
68
+ return nodeSourceText(n)
69
+ }
70
+
71
+ // nodeSourceText returns the verbatim source slice covered by the node's
72
+ // position range, trimmed of surrounding whitespace. Same byte range
73
+ // scanner.GetTextOfNode would read; safe for any Kind because it does
74
+ // not inspect per-Kind data fields.
75
+ func nodeSourceText(n *innerast.Node) string {
76
+ file := innerast.GetSourceFileOfNode(n)
77
+ if file == nil {
78
+ return ""
79
+ }
80
+ text := file.Text()
81
+ pos, end := n.Pos(), n.End()
82
+ if pos < 0 || end > len(text) || pos >= end {
83
+ return ""
84
+ }
85
+ return strings.TrimSpace(text[pos:end])
86
+ }
@@ -0,0 +1,32 @@
1
+ package ast_test
2
+
3
+ import (
4
+ "testing"
5
+
6
+ shimast "github.com/microsoft/typescript-go/shim/ast"
7
+ )
8
+
9
+ // TestNodeTextJoinsMultiHopQualifiedName verifies NodeText joins a
10
+ // multi-hop QualifiedName as "A.B.C".
11
+ //
12
+ // Locks the recursion in the QualifiedName arm. QualifiedName.Left is an
13
+ // *EntityName (Identifier OR QualifiedName), so a non-recursive
14
+ // implementation would silently drop everything but the final two
15
+ // segments — breaking dotted references like
16
+ // `IShoppingCoupon.IDirection.Inner` that show up in real-world JSDoc
17
+ // and type-argument positions.
18
+ //
19
+ // 1. Construct A.B then ((A.B).C) via NewQualifiedName.
20
+ // 2. Call NodeText on the outer node.
21
+ // 3. Assert the result is "A.B.C".
22
+ func TestNodeTextJoinsMultiHopQualifiedName(t *testing.T) {
23
+ factory := shimast.NewNodeFactory(shimast.NodeFactoryHooks{})
24
+ a := factory.NewIdentifier("A")
25
+ b := factory.NewIdentifier("B")
26
+ c := factory.NewIdentifier("C")
27
+ ab := factory.NewQualifiedName(a, b)
28
+ abc := factory.NewQualifiedName(ab, c)
29
+ if got := shimast.NodeText(abc); got != "A.B.C" {
30
+ t.Fatalf("NodeText(A.B.C) = %q, want %q", got, "A.B.C")
31
+ }
32
+ }
@@ -0,0 +1,31 @@
1
+ package ast_test
2
+
3
+ import (
4
+ "testing"
5
+
6
+ shimast "github.com/microsoft/typescript-go/shim/ast"
7
+ )
8
+
9
+ // TestNodeTextJoinsOneHopQualifiedName verifies NodeText joins a one-hop
10
+ // QualifiedName as "left.right".
11
+ //
12
+ // Locks the QualifiedName arm that upstream lacks: upstream's
13
+ // (*Node).Text() panics with `Unhandled case in Node.Text:
14
+ // *ast.QualifiedName` because the switch has no arm for the Kind. typia's
15
+ // metadata_js_doc_parameter_name calls Text() on a JSDoc tag's Name()
16
+ // which is a QualifiedName for `@param obj.field description`, so the
17
+ // panic surfaces inside the nestia/typia build pipeline. NodeText must
18
+ // turn a `Foo.Bar` qualified name into the dotted string.
19
+ //
20
+ // 1. Construct Foo.Bar via NewQualifiedName(Foo, Bar).
21
+ // 2. Call NodeText on the qualified node.
22
+ // 3. Assert the result is "Foo.Bar".
23
+ func TestNodeTextJoinsOneHopQualifiedName(t *testing.T) {
24
+ factory := shimast.NewNodeFactory(shimast.NodeFactoryHooks{})
25
+ left := factory.NewIdentifier("Foo")
26
+ right := factory.NewIdentifier("Bar")
27
+ qn := factory.NewQualifiedName(left, right)
28
+ if got := shimast.NodeText(qn); got != "Foo.Bar" {
29
+ t.Fatalf("NodeText(Foo.Bar) = %q, want %q", got, "Foo.Bar")
30
+ }
31
+ }
@@ -0,0 +1,23 @@
1
+ package ast_test
2
+
3
+ import (
4
+ "testing"
5
+
6
+ shimast "github.com/microsoft/typescript-go/shim/ast"
7
+ )
8
+
9
+ // TestNodeTextReturnsEmptyForNil verifies NodeText returns "" for a nil node.
10
+ //
11
+ // Locks the nil-guard at the top of NodeText. The helper is a total function
12
+ // over *Node — typia's JSDoc parameter-name extractor calls it without
13
+ // checking — so a nil-deref here would be a behaviour change for every
14
+ // caller. The empty-string contract is the only signal that lets callers
15
+ // skip "no parameter name" entries cleanly.
16
+ //
17
+ // 1. Call NodeText(nil).
18
+ // 2. Assert the result is "".
19
+ func TestNodeTextReturnsEmptyForNil(t *testing.T) {
20
+ if got := shimast.NodeText(nil); got != "" {
21
+ t.Fatalf("NodeText(nil) = %q, want %q", got, "")
22
+ }
23
+ }
@@ -0,0 +1,27 @@
1
+ package ast_test
2
+
3
+ import (
4
+ "testing"
5
+
6
+ shimast "github.com/microsoft/typescript-go/shim/ast"
7
+ )
8
+
9
+ // TestNodeTextReturnsIdentifierText verifies NodeText returns the
10
+ // identifier text when the node Kind already has an upstream Text() arm.
11
+ //
12
+ // Covers the delegated branch: for Kinds upstream supports (Identifier,
13
+ // StringLiteral, template parts, …), NodeText must forward to the
14
+ // upstream method verbatim. Falling back to the source slice would
15
+ // return "" for synthesised nodes that have no source range, breaking
16
+ // every factory-built tree we hand to the typia metadata factory.
17
+ //
18
+ // 1. Construct a synthesised Identifier via NewIdentifier("Foo").
19
+ // 2. Call NodeText on it.
20
+ // 3. Assert the result is "Foo".
21
+ func TestNodeTextReturnsIdentifierText(t *testing.T) {
22
+ factory := shimast.NewNodeFactory(shimast.NodeFactoryHooks{})
23
+ id := factory.NewIdentifier("Foo")
24
+ if got := shimast.NodeText(id); got != "Foo" {
25
+ t.Fatalf("NodeText(Identifier) = %q, want %q", got, "Foo")
26
+ }
27
+ }
@@ -0,0 +1,30 @@
1
+ package ast_test
2
+
3
+ import (
4
+ "testing"
5
+
6
+ shimast "github.com/microsoft/typescript-go/shim/ast"
7
+ )
8
+
9
+ // TestNodeTextSkipsEmptyQualifiedLeft verifies NodeText does not emit a
10
+ // stray leading "." when the left segment of a QualifiedName resolves
11
+ // to the empty string.
12
+ //
13
+ // Parser recovery (and synthesised trees) can produce a QualifiedName
14
+ // whose Left identifier carries empty text. A naive `left + "." + right`
15
+ // concatenation would yield `.Inner`, which downstream code (the typia
16
+ // metadata factory uses this as a map key) would treat as a distinct
17
+ // parameter name. The arm has to drop the empty segment instead.
18
+ //
19
+ // 1. Build a QualifiedName whose Left is an Identifier created with "".
20
+ // 2. Call NodeText on the qualified node.
21
+ // 3. Assert the result is the right-hand text with no leading dot.
22
+ func TestNodeTextSkipsEmptyQualifiedLeft(t *testing.T) {
23
+ factory := shimast.NewNodeFactory(shimast.NodeFactoryHooks{})
24
+ left := factory.NewIdentifier("")
25
+ right := factory.NewIdentifier("Inner")
26
+ qn := factory.NewQualifiedName(left, right)
27
+ if got := shimast.NodeText(qn); got != "Inner" {
28
+ t.Fatalf("NodeText(<empty>.Inner) = %q, want %q", got, "Inner")
29
+ }
30
+ }