goscript 0.1.4 → 0.2.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.
Files changed (270) hide show
  1. package/README.md +5 -2
  2. package/cmd/go_js_wasm_exec/main.go +201 -0
  3. package/cmd/go_js_wasm_exec/main_test.go +83 -0
  4. package/cmd/goscript/{cmd_compile.go → cmd-compile.go} +7 -0
  5. package/cmd/goscript/cmd-test.go +14 -0
  6. package/cmd/goscript/cmd-test_test.go +1 -1
  7. package/compiler/compile-request.go +12 -9
  8. package/compiler/compliance_test.go +0 -1
  9. package/compiler/config.go +2 -0
  10. package/compiler/gotest/request.go +28 -0
  11. package/compiler/gotest/runner.go +353 -27
  12. package/compiler/gotest/runner_test.go +273 -1
  13. package/compiler/gotest/testdata/browserapi/browserapi_test.go +20 -0
  14. package/compiler/gotest/testdata/browserapi/go.mod +3 -0
  15. package/compiler/lowered-program.go +24 -17
  16. package/compiler/lowering.go +392 -127
  17. package/compiler/lowering_bench_test.go +41 -27
  18. package/compiler/override-facts.go +15 -0
  19. package/compiler/override-parity-verifier.go +450 -0
  20. package/compiler/override-parity.go +122 -0
  21. package/compiler/override-registry_test.go +559 -0
  22. package/compiler/protobuf-ts-binding.go +514 -0
  23. package/compiler/protobuf-ts-binding_test.go +172 -0
  24. package/compiler/semantic-model-types.go +9 -4
  25. package/compiler/semantic-model.go +282 -70
  26. package/compiler/semantic-model_test.go +82 -1
  27. package/compiler/service.go +20 -1
  28. package/compiler/skeleton_test.go +62 -8
  29. package/compiler/typescript-emitter.go +128 -13
  30. package/dist/gs/builtin/slice.d.ts +2 -1
  31. package/dist/gs/builtin/slice.js +29 -4
  32. package/dist/gs/builtin/slice.js.map +1 -1
  33. package/dist/gs/builtin/type.d.ts +13 -5
  34. package/dist/gs/builtin/type.js +153 -60
  35. package/dist/gs/builtin/type.js.map +1 -1
  36. package/dist/gs/builtin/varRef.d.ts +11 -0
  37. package/dist/gs/builtin/varRef.js +57 -2
  38. package/dist/gs/builtin/varRef.js.map +1 -1
  39. package/dist/gs/bytes/buffer.gs.js +1 -1
  40. package/dist/gs/bytes/buffer.gs.js.map +1 -1
  41. package/dist/gs/bytes/reader.gs.js +1 -1
  42. package/dist/gs/bytes/reader.gs.js.map +1 -1
  43. package/dist/gs/compress/zlib/index.d.ts +10 -3
  44. package/dist/gs/compress/zlib/index.js +50 -16
  45. package/dist/gs/compress/zlib/index.js.map +1 -1
  46. package/dist/gs/encoding/json/index.d.ts +114 -0
  47. package/dist/gs/encoding/json/index.js +544 -36
  48. package/dist/gs/encoding/json/index.js.map +1 -1
  49. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.d.ts +100 -0
  50. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js +564 -0
  51. package/dist/gs/github.com/aperturerobotics/protobuf-go-lite/index.js.map +1 -1
  52. package/dist/gs/github.com/pkg/errors/errors.js +54 -30
  53. package/dist/gs/github.com/pkg/errors/errors.js.map +1 -1
  54. package/dist/gs/go/scanner/index.d.ts +2 -0
  55. package/dist/gs/go/scanner/index.js +29 -5
  56. package/dist/gs/go/scanner/index.js.map +1 -1
  57. package/dist/gs/go/token/index.js +22 -6
  58. package/dist/gs/go/token/index.js.map +1 -1
  59. package/dist/gs/hash/index.d.ts +6 -0
  60. package/dist/gs/hash/index.js +20 -0
  61. package/dist/gs/hash/index.js.map +1 -1
  62. package/dist/gs/internal/goarch/index.d.ts +43 -3
  63. package/dist/gs/internal/goarch/index.js +42 -10
  64. package/dist/gs/internal/goarch/index.js.map +1 -1
  65. package/dist/gs/io/fs/fs.js +26 -14
  66. package/dist/gs/io/fs/fs.js.map +1 -1
  67. package/dist/gs/io/fs/readdir.js +4 -2
  68. package/dist/gs/io/fs/readdir.js.map +1 -1
  69. package/dist/gs/io/fs/sub.js +8 -1
  70. package/dist/gs/io/fs/sub.js.map +1 -1
  71. package/dist/gs/io/io.d.ts +2 -0
  72. package/dist/gs/io/io.js.map +1 -1
  73. package/dist/gs/math/bits/index.d.ts +5 -0
  74. package/dist/gs/math/bits/index.js +16 -4
  75. package/dist/gs/math/bits/index.js.map +1 -1
  76. package/dist/gs/mime/index.d.ts +16 -0
  77. package/dist/gs/mime/index.js +315 -6
  78. package/dist/gs/mime/index.js.map +1 -1
  79. package/dist/gs/net/http/httptest/index.d.ts +12 -0
  80. package/dist/gs/net/http/httptest/index.js +85 -6
  81. package/dist/gs/net/http/httptest/index.js.map +1 -1
  82. package/dist/gs/net/http/index.d.ts +300 -5
  83. package/dist/gs/net/http/index.js +1598 -58
  84. package/dist/gs/net/http/index.js.map +1 -1
  85. package/dist/gs/os/dir_unix.gs.js +1 -1
  86. package/dist/gs/os/dir_unix.gs.js.map +1 -1
  87. package/dist/gs/os/error.gs.js +1 -1
  88. package/dist/gs/os/error.gs.js.map +1 -1
  89. package/dist/gs/os/exec.gs.d.ts +1 -0
  90. package/dist/gs/os/exec.gs.js +4 -8
  91. package/dist/gs/os/exec.gs.js.map +1 -1
  92. package/dist/gs/os/exec_posix.gs.js +1 -1
  93. package/dist/gs/os/exec_posix.gs.js.map +1 -1
  94. package/dist/gs/os/index.d.ts +1 -1
  95. package/dist/gs/os/index.js +1 -1
  96. package/dist/gs/os/index.js.map +1 -1
  97. package/dist/gs/os/proc.gs.d.ts +4 -0
  98. package/dist/gs/os/proc.gs.js +12 -6
  99. package/dist/gs/os/proc.gs.js.map +1 -1
  100. package/dist/gs/os/root_js.gs.js +1 -1
  101. package/dist/gs/os/root_js.gs.js.map +1 -1
  102. package/dist/gs/os/types.gs.js +1 -1
  103. package/dist/gs/os/types.gs.js.map +1 -1
  104. package/dist/gs/os/types_js.gs.js +1 -1
  105. package/dist/gs/os/types_js.gs.js.map +1 -1
  106. package/dist/gs/os/types_unix.gs.js +1 -1
  107. package/dist/gs/os/types_unix.gs.js.map +1 -1
  108. package/dist/gs/path/path.js +11 -7
  109. package/dist/gs/path/path.js.map +1 -1
  110. package/dist/gs/reflect/index.d.ts +5 -4
  111. package/dist/gs/reflect/index.js +4 -3
  112. package/dist/gs/reflect/index.js.map +1 -1
  113. package/dist/gs/reflect/map.js +15 -0
  114. package/dist/gs/reflect/map.js.map +1 -1
  115. package/dist/gs/reflect/type.d.ts +25 -6
  116. package/dist/gs/reflect/type.js +1418 -228
  117. package/dist/gs/reflect/type.js.map +1 -1
  118. package/dist/gs/reflect/types.d.ts +14 -6
  119. package/dist/gs/reflect/types.js +35 -1
  120. package/dist/gs/reflect/types.js.map +1 -1
  121. package/dist/gs/reflect/value.d.ts +1 -0
  122. package/dist/gs/reflect/value.js +83 -41
  123. package/dist/gs/reflect/value.js.map +1 -1
  124. package/dist/gs/reflect/visiblefields.js +4 -140
  125. package/dist/gs/reflect/visiblefields.js.map +1 -1
  126. package/dist/gs/runtime/pprof/index.d.ts +8 -2
  127. package/dist/gs/runtime/pprof/index.js +50 -30
  128. package/dist/gs/runtime/pprof/index.js.map +1 -1
  129. package/dist/gs/runtime/runtime.js +5 -4
  130. package/dist/gs/runtime/runtime.js.map +1 -1
  131. package/dist/gs/runtime/trace/index.js +5 -19
  132. package/dist/gs/runtime/trace/index.js.map +1 -1
  133. package/dist/gs/strconv/atoi.gs.js +1 -1
  134. package/dist/gs/strconv/atoi.gs.js.map +1 -1
  135. package/dist/gs/strconv/complex.gs.d.ts +3 -0
  136. package/dist/gs/strconv/complex.gs.js +148 -0
  137. package/dist/gs/strconv/complex.gs.js.map +1 -0
  138. package/dist/gs/strconv/index.d.ts +1 -0
  139. package/dist/gs/strconv/index.js +1 -0
  140. package/dist/gs/strconv/index.js.map +1 -1
  141. package/dist/gs/strings/builder.js +1 -1
  142. package/dist/gs/strings/reader.js +9 -5
  143. package/dist/gs/strings/reader.js.map +1 -1
  144. package/dist/gs/strings/replace.js +15 -7
  145. package/dist/gs/strings/replace.js.map +1 -1
  146. package/dist/gs/strings/strings.d.ts +5 -0
  147. package/dist/gs/strings/strings.js +57 -5
  148. package/dist/gs/strings/strings.js.map +1 -1
  149. package/dist/gs/sync/atomic/type.gs.js +9 -9
  150. package/dist/gs/sync/atomic/type.gs.js.map +1 -1
  151. package/dist/gs/sync/atomic/value.gs.js +2 -2
  152. package/dist/gs/sync/atomic/value.gs.js.map +1 -1
  153. package/dist/gs/syscall/env.js +22 -14
  154. package/dist/gs/syscall/env.js.map +1 -1
  155. package/dist/gs/testing/testing.js +55 -13
  156. package/dist/gs/testing/testing.js.map +1 -1
  157. package/dist/gs/time/time.d.ts +24 -1
  158. package/dist/gs/time/time.js +43 -3
  159. package/dist/gs/time/time.js.map +1 -1
  160. package/dist/gs/unique/index.js +7 -1
  161. package/dist/gs/unique/index.js.map +1 -1
  162. package/go.mod +3 -3
  163. package/go.sum +16 -0
  164. package/gs/builtin/runtime-contract.test.ts +218 -21
  165. package/gs/builtin/slice.ts +44 -4
  166. package/gs/builtin/type.ts +226 -59
  167. package/gs/builtin/varRef.ts +85 -2
  168. package/gs/bytes/buffer.gs.ts +1 -1
  169. package/gs/bytes/reader.gs.ts +1 -1
  170. package/gs/compress/zlib/index.test.ts +62 -1
  171. package/gs/compress/zlib/index.ts +53 -16
  172. package/gs/compress/zlib/parity.json +51 -0
  173. package/gs/encoding/json/index.test.ts +360 -6
  174. package/gs/encoding/json/index.ts +679 -38
  175. package/gs/encoding/json/parity.json +81 -0
  176. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.test.ts +211 -3
  177. package/gs/github.com/aperturerobotics/protobuf-go-lite/index.ts +857 -1
  178. package/gs/github.com/pkg/errors/errors.ts +54 -30
  179. package/gs/go/scanner/index.test.ts +39 -56
  180. package/gs/go/scanner/index.ts +33 -5
  181. package/gs/go/scanner/parity.json +27 -0
  182. package/gs/go/token/index.ts +22 -6
  183. package/gs/hash/index.test.ts +20 -33
  184. package/gs/hash/index.ts +28 -0
  185. package/gs/hash/parity.json +21 -0
  186. package/gs/internal/goarch/index.test.ts +32 -0
  187. package/gs/internal/goarch/index.ts +45 -13
  188. package/gs/internal/goarch/parity.json +144 -0
  189. package/gs/io/fs/fs.ts +26 -14
  190. package/gs/io/fs/readdir.ts +4 -4
  191. package/gs/io/fs/sub.ts +8 -1
  192. package/gs/io/io.ts +1 -0
  193. package/gs/io/parity.json +162 -0
  194. package/gs/math/bits/index.test.ts +14 -1
  195. package/gs/math/bits/index.ts +23 -4
  196. package/gs/math/bits/parity.json +156 -0
  197. package/gs/mime/index.test.ts +90 -0
  198. package/gs/mime/index.ts +369 -6
  199. package/gs/mime/parity.json +36 -0
  200. package/gs/net/http/httptest/index.test.ts +98 -2
  201. package/gs/net/http/httptest/index.ts +101 -6
  202. package/gs/net/http/httptest/parity.json +15 -0
  203. package/gs/net/http/index.test.ts +781 -12
  204. package/gs/net/http/index.ts +1860 -139
  205. package/gs/net/http/meta.json +16 -1
  206. package/gs/net/http/parity.json +193 -0
  207. package/gs/os/dir_unix.gs.ts +1 -1
  208. package/gs/os/error.gs.ts +1 -1
  209. package/gs/os/exec.gs.ts +4 -8
  210. package/gs/os/exec_posix.gs.ts +1 -1
  211. package/gs/os/index.test.ts +9 -0
  212. package/gs/os/index.ts +1 -0
  213. package/gs/os/parity.json +9 -0
  214. package/gs/os/proc.gs.ts +18 -5
  215. package/gs/os/proc.test.ts +26 -0
  216. package/gs/os/root_js.gs.ts +1 -1
  217. package/gs/os/types.gs.ts +1 -1
  218. package/gs/os/types_js.gs.ts +1 -1
  219. package/gs/os/types_unix.gs.ts +1 -1
  220. package/gs/path/path.ts +11 -7
  221. package/gs/reflect/field.test.ts +37 -15
  222. package/gs/reflect/function-types.test.ts +518 -22
  223. package/gs/reflect/index.ts +8 -6
  224. package/gs/reflect/map.ts +20 -0
  225. package/gs/reflect/meta.json +6 -4
  226. package/gs/reflect/parity.json +234 -0
  227. package/gs/reflect/sliceat.test.ts +156 -0
  228. package/gs/reflect/structof.test.ts +401 -0
  229. package/gs/reflect/type.ts +1897 -317
  230. package/gs/reflect/typefor.test.ts +510 -10
  231. package/gs/reflect/types.ts +43 -18
  232. package/gs/reflect/value.ts +105 -45
  233. package/gs/reflect/visiblefields.ts +5 -168
  234. package/gs/runtime/parity.json +24 -0
  235. package/gs/runtime/pprof/index.test.ts +29 -7
  236. package/gs/runtime/pprof/index.ts +56 -30
  237. package/gs/runtime/pprof/parity.json +27 -0
  238. package/gs/runtime/runtime.test.ts +3 -1
  239. package/gs/runtime/runtime.ts +4 -3
  240. package/gs/runtime/trace/index.test.ts +5 -3
  241. package/gs/runtime/trace/index.ts +8 -20
  242. package/gs/runtime/trace/parity.json +36 -0
  243. package/gs/strconv/atoi.gs.ts +1 -1
  244. package/gs/strconv/complex.gs.ts +174 -0
  245. package/gs/strconv/complex.test.ts +65 -0
  246. package/gs/strconv/index.ts +1 -0
  247. package/gs/strconv/parity.json +120 -0
  248. package/gs/strings/builder.ts +1 -1
  249. package/gs/strings/parity.json +186 -0
  250. package/gs/strings/reader.ts +9 -5
  251. package/gs/strings/replace.ts +15 -7
  252. package/gs/strings/strings.test.ts +22 -2
  253. package/gs/strings/strings.ts +64 -6
  254. package/gs/sync/atomic/type.gs.ts +9 -9
  255. package/gs/sync/atomic/value.gs.ts +2 -2
  256. package/gs/syscall/env.ts +29 -14
  257. package/gs/testing/testing.test.ts +67 -0
  258. package/gs/testing/testing.ts +87 -19
  259. package/gs/time/parity.json +225 -0
  260. package/gs/time/time.test.ts +20 -2
  261. package/gs/time/time.ts +49 -7
  262. package/gs/unique/index.ts +7 -1
  263. package/package.json +4 -2
  264. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.d.ts +0 -217
  265. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js +0 -926
  266. package/dist/gs/github.com/aperturerobotics/starpc/srpc/index.js.map +0 -1
  267. package/gs/github.com/aperturerobotics/starpc/srpc/index.test.ts +0 -38
  268. package/gs/github.com/aperturerobotics/starpc/srpc/index.ts +0 -1361
  269. package/gs/github.com/aperturerobotics/starpc/srpc/meta.json +0 -46
  270. /package/compiler/{wasm_api.go → wasm-api.go} +0 -0
@@ -0,0 +1,401 @@
1
+ import { describe, expect, it } from 'vitest'
2
+
3
+ import * as $ from '@goscript/builtin/index.js'
4
+ import { Marshal } from '@goscript/encoding/json/index.js'
5
+
6
+ import { New, Zero } from './value.js'
7
+ import { MapOf, PointerTo, StructOf, TypeFor, TypeOf } from './type.js'
8
+ import { StructField, StructTag } from './types.js'
9
+ import { VisibleFields } from './visiblefields.js'
10
+
11
+ class EmbeddedWithMethod {
12
+ public String(): string {
13
+ return 'embedded'
14
+ }
15
+ }
16
+
17
+ describe('StructOf', () => {
18
+ it('creates descriptor-backed dynamic struct values', () => {
19
+ const typ = StructOf(
20
+ $.arrayToSlice([
21
+ new StructField({
22
+ Name: 'Name',
23
+ Type: TypeOf(''),
24
+ Tag: new StructTag('json:"name"'),
25
+ }),
26
+ new StructField({
27
+ Name: 'Count',
28
+ Type: TypeOf(0),
29
+ Tag: new StructTag('json:"count"'),
30
+ }),
31
+ ]),
32
+ )
33
+
34
+ expect(typ.Name()).toBe('')
35
+ expect(typ.PkgPath()).toBe('')
36
+ expect(typ.NumField()).toBe(2)
37
+ expect(typ.Field(0).Name).toBe('Name')
38
+ expect(typ.Field(0).Index).toEqual([0])
39
+ expect(typ.Field(1).Offset).toBeGreaterThan(0)
40
+ expect(TypeOf(Zero(typ).Interface()).String()).toBe(typ.String())
41
+
42
+ const value = New(typ).Elem()
43
+ value.Field(0).SetString('Ada')
44
+ value.FieldByName('Count').SetInt(3)
45
+
46
+ const [data, err] = Marshal(value.Interface())
47
+ expect(err).toBeNull()
48
+ expect($.bytesToString(data)).toBe('{"name":"Ada","count":3}')
49
+
50
+ const clone = $.cloneStructValue(value.Interface()) as any
51
+ expect(TypeOf(clone).String()).toBe(typ.String())
52
+ expect(clone.Name).toBe('Ada')
53
+ expect(clone.Count).toBe(3)
54
+ value.FieldByName('Count').SetInt(4)
55
+ expect(clone.Count).toBe(3)
56
+ })
57
+
58
+ it('rejects invalid field descriptors before creating a type', () => {
59
+ const intType = TypeOf(0)
60
+
61
+ expect(() =>
62
+ StructOf($.arrayToSlice([new StructField({ Name: '', Type: intType })])),
63
+ ).toThrow(/field 0 has no name/)
64
+ expect(() =>
65
+ StructOf(
66
+ $.arrayToSlice([new StructField({ Name: '1Name', Type: intType })]),
67
+ ),
68
+ ).toThrow(/field 0 has invalid name/)
69
+ expect(() =>
70
+ StructOf(
71
+ $.arrayToSlice([
72
+ new StructField({ Name: 'Missing', Type: null as any }),
73
+ ]),
74
+ ),
75
+ ).toThrow(/field 0 has no type/)
76
+ expect(() =>
77
+ StructOf(
78
+ $.arrayToSlice([
79
+ new StructField({ Name: 'Name', Type: intType }),
80
+ new StructField({ Name: 'Name', Type: intType }),
81
+ ]),
82
+ ),
83
+ ).toThrow(/duplicate field Name/)
84
+ })
85
+
86
+ it('enforces package-path and unexported field rules', () => {
87
+ const intType = TypeOf(0)
88
+
89
+ expect(() =>
90
+ StructOf(
91
+ $.arrayToSlice([new StructField({ Name: 'secret', Type: intType })]),
92
+ ),
93
+ ).toThrow(/field "secret" is unexported but missing PkgPath/)
94
+ expect(() =>
95
+ StructOf($.arrayToSlice([new StructField({ Name: '_', Type: intType })])),
96
+ ).toThrow(/field "_" is unexported but missing PkgPath/)
97
+ expect(() =>
98
+ StructOf(
99
+ $.arrayToSlice([
100
+ new StructField({
101
+ Name: 'Embedded',
102
+ Type: intType,
103
+ PkgPath: 'main',
104
+ Anonymous: true,
105
+ }),
106
+ ]),
107
+ ),
108
+ ).toThrow(/anonymous but has PkgPath set/)
109
+ expect(() =>
110
+ StructOf(
111
+ $.arrayToSlice([
112
+ new StructField({
113
+ Name: 'left',
114
+ Type: intType,
115
+ PkgPath: 'main',
116
+ }),
117
+ new StructField({
118
+ Name: 'right',
119
+ Type: intType,
120
+ PkgPath: 'other',
121
+ }),
122
+ ]),
123
+ ),
124
+ ).toThrow(/fields with different PkgPath main and other/)
125
+
126
+ const typ = StructOf(
127
+ $.arrayToSlice([
128
+ new StructField({ Name: '_', Type: intType, PkgPath: 'main' }),
129
+ new StructField({ Name: '_', Type: intType, PkgPath: 'main' }),
130
+ new StructField({ Name: 'secret', Type: intType, PkgPath: 'main' }),
131
+ ]),
132
+ )
133
+ expect(typ.NumField()).toBe(3)
134
+ expect(typ.Field(2).IsExported()).toBe(false)
135
+ })
136
+
137
+ it('rejects illegal anonymous fields and embedded method cases', () => {
138
+ const intType = TypeOf(0)
139
+ const embeddedInfo = $.registerStructType(
140
+ 'main.EmbeddedWithMethod',
141
+ new EmbeddedWithMethod(),
142
+ [
143
+ {
144
+ name: 'String',
145
+ args: [],
146
+ returns: [{ type: { kind: $.TypeKind.Basic, name: 'string' } }],
147
+ },
148
+ ],
149
+ EmbeddedWithMethod,
150
+ [],
151
+ )
152
+ ;(EmbeddedWithMethod as any).__typeInfo = embeddedInfo
153
+ const embeddedType = TypeOf(new EmbeddedWithMethod())
154
+ const embeddedPointer = PointerTo(embeddedType)!
155
+
156
+ expect(() =>
157
+ StructOf(
158
+ $.arrayToSlice([
159
+ new StructField({
160
+ Name: 'EmbeddedWithMethod',
161
+ Type: embeddedPointer,
162
+ Anonymous: true,
163
+ }),
164
+ ]),
165
+ ),
166
+ ).toThrow(/embedded type with methods/)
167
+ expect(() =>
168
+ StructOf(
169
+ $.arrayToSlice([
170
+ new StructField({
171
+ Name: 'EmbeddedWithMethod',
172
+ Type: embeddedType,
173
+ Anonymous: true,
174
+ }),
175
+ ]),
176
+ ),
177
+ ).toThrow(/embedded type with methods/)
178
+ expect(() =>
179
+ StructOf(
180
+ $.arrayToSlice([
181
+ new StructField({
182
+ Name: 'IntPtr',
183
+ Type: PointerTo(PointerTo(intType)!)!,
184
+ Anonymous: true,
185
+ }),
186
+ ]),
187
+ ),
188
+ ).toThrow(/illegal embedded field type/)
189
+ expect(() =>
190
+ StructOf(
191
+ $.arrayToSlice([
192
+ new StructField({
193
+ Name: 'EmbeddedWithMethod',
194
+ Type: embeddedPointer,
195
+ Anonymous: true,
196
+ }),
197
+ new StructField({ Name: 'Count', Type: intType }),
198
+ ]),
199
+ ),
200
+ ).toThrow(/embedded type with methods/)
201
+ expect(() =>
202
+ StructOf(
203
+ $.arrayToSlice([
204
+ new StructField({ Name: 'Count', Type: intType }),
205
+ new StructField({
206
+ Name: 'EmbeddedWithMethod',
207
+ Type: embeddedPointer,
208
+ Anonymous: true,
209
+ }),
210
+ ]),
211
+ ),
212
+ ).toThrow(/embedded type with methods/)
213
+ expect(() =>
214
+ StructOf(
215
+ $.arrayToSlice([
216
+ new StructField({
217
+ Name: 'EmbeddedWithMethod',
218
+ Type: embeddedType,
219
+ Anonymous: true,
220
+ }),
221
+ new StructField({ Name: 'Count', Type: intType }),
222
+ ]),
223
+ ),
224
+ ).toThrow(/embedded type with methods/)
225
+ })
226
+
227
+ it('computes dynamic layout, identity, and comparability from descriptors', () => {
228
+ const byteType = TypeFor({
229
+ T: { type: { kind: $.TypeKind.Basic, name: 'uint8' } },
230
+ } as any)
231
+ const intType = TypeOf(0)
232
+ const layout = StructOf(
233
+ $.arrayToSlice([
234
+ new StructField({
235
+ Name: 'A',
236
+ Type: byteType,
237
+ Offset: 99,
238
+ Index: [9],
239
+ }),
240
+ new StructField({ Name: 'B', Type: intType }),
241
+ ]),
242
+ )
243
+
244
+ expect(layout.Name()).toBe('')
245
+ expect(layout.PkgPath()).toBe('')
246
+ expect(layout.String()).toBe('struct { A uint8; B int }')
247
+ expect(layout.Field(0).Offset).toBe(0)
248
+ expect(layout.Field(0).Index).toEqual([0])
249
+ expect(layout.Field(1).Offset).toBe(8)
250
+ expect(layout.Size()).toBe(16)
251
+ expect(
252
+ StructOf(
253
+ $.arrayToSlice([
254
+ new StructField({ Name: 'A', Type: byteType }),
255
+ new StructField({ Name: 'B', Type: intType }),
256
+ ]),
257
+ ),
258
+ ).toBe(layout)
259
+
260
+ const pkgA = StructOf(
261
+ $.arrayToSlice([
262
+ new StructField({ Name: 'x', Type: intType, PkgPath: 'a' }),
263
+ ]),
264
+ )
265
+ const pkgB = StructOf(
266
+ $.arrayToSlice([
267
+ new StructField({ Name: 'x', Type: intType, PkgPath: 'b' }),
268
+ ]),
269
+ )
270
+ expect(pkgA.String()).toBe(pkgB.String())
271
+ expect(pkgA).not.toBe(pkgB)
272
+ expect(pkgA.AssignableTo(pkgB)).toBe(false)
273
+ expect(pkgB.AssignableTo(pkgA)).toBe(false)
274
+ expect(() => New(pkgA).Elem().Set(New(pkgB).Elem())).toThrow(
275
+ /reflect: assign to wrong type/,
276
+ )
277
+
278
+ expect(
279
+ StructOf(
280
+ $.arrayToSlice([new StructField({ Name: 'Name', Type: TypeOf('') })]),
281
+ ).Comparable(),
282
+ ).toBe(true)
283
+ expect(
284
+ StructOf(
285
+ $.arrayToSlice([
286
+ new StructField({
287
+ Name: 'Values',
288
+ Type: MapOf(TypeOf(''), intType),
289
+ }),
290
+ ]),
291
+ ).Comparable(),
292
+ ).toBe(false)
293
+ })
294
+
295
+ it('assigns unnamed dynamic structs to named structs with matching underlying fields', () => {
296
+ class NamedLayout {
297
+ public X = 0
298
+ }
299
+
300
+ const intType = TypeOf(0)
301
+ $.registerStructType(
302
+ 'main.NamedLayout',
303
+ new NamedLayout(),
304
+ [],
305
+ NamedLayout,
306
+ [
307
+ {
308
+ name: 'X',
309
+ key: 'X',
310
+ type: { kind: $.TypeKind.Basic, name: 'int' },
311
+ },
312
+ ],
313
+ )
314
+ const namedType = TypeFor({
315
+ T: { type: 'main.NamedLayout', zero: () => new NamedLayout() },
316
+ })
317
+ const dynamicType = StructOf(
318
+ $.arrayToSlice([new StructField({ Name: 'X', Type: intType })]),
319
+ )
320
+
321
+ expect(dynamicType.AssignableTo(namedType)).toBe(true)
322
+ expect(namedType.AssignableTo(dynamicType)).toBe(true)
323
+ })
324
+
325
+ it('walks embedded dynamic fields in visible-field order', () => {
326
+ const intType = TypeOf(0)
327
+ const stringType = TypeOf('')
328
+ const inner = StructOf(
329
+ $.arrayToSlice([
330
+ new StructField({ Name: 'ID', Type: intType }),
331
+ new StructField({ Name: 'Label', Type: stringType }),
332
+ ]),
333
+ )
334
+ const outer = StructOf(
335
+ $.arrayToSlice([
336
+ new StructField({ Name: 'Inner', Type: inner, Anonymous: true }),
337
+ new StructField({ Name: 'Count', Type: intType }),
338
+ ]),
339
+ )
340
+
341
+ expect(
342
+ $.asArray(VisibleFields(outer)).map((field) => [field.Name, field.Index]),
343
+ ).toEqual([
344
+ ['Inner', [0]],
345
+ ['ID', [0, 0]],
346
+ ['Label', [0, 1]],
347
+ ['Count', [1]],
348
+ ])
349
+
350
+ const value = New(outer).Elem()
351
+ value.FieldByIndex($.arrayToSlice([0, 0])).SetInt(7)
352
+ value.FieldByName('Label').SetString('seven')
353
+ expect(value.FieldByName('ID').Int()).toBe(7)
354
+ expect(value.FieldByIndex($.arrayToSlice([0, 1])).String()).toBe('seven')
355
+ })
356
+
357
+ it('hides deeper embedded fields and cancels duplicate same-depth names', () => {
358
+ const intType = TypeOf(0)
359
+ const stringType = TypeOf('')
360
+ const inner = StructOf(
361
+ $.arrayToSlice([
362
+ new StructField({ Name: 'Name', Type: stringType }),
363
+ new StructField({ Name: 'Depth', Type: intType }),
364
+ ]),
365
+ )
366
+ const hidden = StructOf(
367
+ $.arrayToSlice([
368
+ new StructField({ Name: 'Inner', Type: inner, Anonymous: true }),
369
+ new StructField({ Name: 'Name', Type: intType }),
370
+ ]),
371
+ )
372
+ expect(
373
+ $.asArray(VisibleFields(hidden)).map((field) => [
374
+ field.Name,
375
+ field.Index,
376
+ ]),
377
+ ).toEqual([
378
+ ['Inner', [0]],
379
+ ['Depth', [0, 1]],
380
+ ['Name', [1]],
381
+ ])
382
+ expect(hidden.FieldByName('Name')[0].Index).toEqual([1])
383
+
384
+ const left = StructOf(
385
+ $.arrayToSlice([new StructField({ Name: 'X', Type: intType })]),
386
+ )
387
+ const right = StructOf(
388
+ $.arrayToSlice([new StructField({ Name: 'X', Type: intType })]),
389
+ )
390
+ const canceled = StructOf(
391
+ $.arrayToSlice([
392
+ new StructField({ Name: 'Left', Type: left, Anonymous: true }),
393
+ new StructField({ Name: 'Right', Type: right, Anonymous: true }),
394
+ ]),
395
+ )
396
+ expect(
397
+ $.asArray(VisibleFields(canceled)).map((field) => field.Name),
398
+ ).toEqual(['Left', 'Right'])
399
+ expect(canceled.FieldByName('X')[1]).toBe(false)
400
+ })
401
+ })