typia 13.1.19 → 13.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 (169) hide show
  1. package/lib/executable/FileSystemIdentity.d.ts +23 -0
  2. package/lib/executable/FileSystemIdentity.js +30 -0
  3. package/lib/executable/FileSystemIdentity.js.map +1 -1
  4. package/lib/executable/FileSystemIdentity.mjs +4 -0
  5. package/lib/executable/FileSystemIdentity.mjs.map +1 -1
  6. package/lib/executable/TypiaGenerateWizard.js +15 -9
  7. package/lib/executable/TypiaGenerateWizard.js.map +1 -1
  8. package/lib/executable/TypiaGenerateWizard.mjs +11 -7
  9. package/lib/executable/TypiaGenerateWizard.mjs.map +1 -1
  10. package/lib/internal/_ProtobufReader.d.ts +18 -3
  11. package/lib/internal/_ProtobufReader.js +39 -11
  12. package/lib/internal/_ProtobufReader.js.map +1 -1
  13. package/lib/internal/_ProtobufReader.mjs +37 -10
  14. package/lib/internal/_ProtobufReader.mjs.map +1 -1
  15. package/lib/internal/_jsonStringifyArray.d.ts +1 -0
  16. package/lib/internal/_jsonStringifyArray.js +48 -0
  17. package/lib/internal/_jsonStringifyArray.js.map +1 -0
  18. package/lib/internal/_jsonStringifyArray.mjs +40 -0
  19. package/lib/internal/_jsonStringifyArray.mjs.map +1 -0
  20. package/lib/internal/_jsonStringifyElement.d.ts +1 -0
  21. package/lib/internal/_jsonStringifyElement.js +23 -0
  22. package/lib/internal/_jsonStringifyElement.js.map +1 -0
  23. package/lib/internal/_jsonStringifyElement.mjs +23 -0
  24. package/lib/internal/_jsonStringifyElement.mjs.map +1 -0
  25. package/lib/internal/_jsonStringifyProperty.d.ts +1 -0
  26. package/lib/internal/_jsonStringifyProperty.js +31 -0
  27. package/lib/internal/_jsonStringifyProperty.js.map +1 -0
  28. package/lib/internal/_jsonStringifyProperty.mjs +31 -0
  29. package/lib/internal/_jsonStringifyProperty.mjs.map +1 -0
  30. package/lib/internal/_llmApplicationFinalize.js +1 -1
  31. package/lib/internal/_llmApplicationFinalize.js.map +1 -1
  32. package/lib/internal/_llmApplicationFinalize.mjs +1 -1
  33. package/lib/internal/_llmApplicationFinalize.mjs.map +1 -1
  34. package/lib/internal/_randomFormatByte.js +24 -1
  35. package/lib/internal/_randomFormatByte.js.map +1 -1
  36. package/lib/internal/_randomFormatByte.mjs +20 -2
  37. package/lib/internal/_randomFormatByte.mjs.map +1 -1
  38. package/lib/internal/_randomFormatDate.d.ts +3 -6
  39. package/lib/internal/_randomFormatDate.js +2 -10
  40. package/lib/internal/_randomFormatDate.js.map +1 -1
  41. package/lib/internal/_randomFormatDate.mjs +2 -6
  42. package/lib/internal/_randomFormatDate.mjs.map +1 -1
  43. package/lib/internal/_randomFormatDatetime.d.ts +3 -6
  44. package/lib/internal/_randomFormatDatetime.js +25 -8
  45. package/lib/internal/_randomFormatDatetime.js.map +1 -1
  46. package/lib/internal/_randomFormatDatetime.mjs +17 -7
  47. package/lib/internal/_randomFormatDatetime.mjs.map +1 -1
  48. package/lib/internal/_randomFormatDuration.js +23 -15
  49. package/lib/internal/_randomFormatDuration.js.map +1 -1
  50. package/lib/internal/_randomFormatDuration.mjs +23 -15
  51. package/lib/internal/_randomFormatDuration.mjs.map +1 -1
  52. package/lib/internal/_randomFormatIpv4.js +31 -1
  53. package/lib/internal/_randomFormatIpv4.js.map +1 -1
  54. package/lib/internal/_randomFormatIpv4.mjs +23 -2
  55. package/lib/internal/_randomFormatIpv4.mjs.map +1 -1
  56. package/lib/internal/_randomFormatIpv6.js +57 -1
  57. package/lib/internal/_randomFormatIpv6.js.map +1 -1
  58. package/lib/internal/_randomFormatIpv6.mjs +45 -2
  59. package/lib/internal/_randomFormatIpv6.mjs.map +1 -1
  60. package/lib/internal/_randomFormatJsonPointer.js +14 -2
  61. package/lib/internal/_randomFormatJsonPointer.js.map +1 -1
  62. package/lib/internal/_randomFormatJsonPointer.mjs +13 -3
  63. package/lib/internal/_randomFormatJsonPointer.mjs.map +1 -1
  64. package/lib/internal/_randomFormatRegex.js +14 -1
  65. package/lib/internal/_randomFormatRegex.js.map +1 -1
  66. package/lib/internal/_randomFormatRegex.mjs +14 -2
  67. package/lib/internal/_randomFormatRegex.mjs.map +1 -1
  68. package/lib/internal/_randomFormatRelativeJsonPointer.js +19 -5
  69. package/lib/internal/_randomFormatRelativeJsonPointer.js.map +1 -1
  70. package/lib/internal/_randomFormatRelativeJsonPointer.mjs +21 -6
  71. package/lib/internal/_randomFormatRelativeJsonPointer.mjs.map +1 -1
  72. package/lib/internal/_randomFormatTime.js +33 -7
  73. package/lib/internal/_randomFormatTime.js.map +1 -1
  74. package/lib/internal/_randomFormatTime.mjs +37 -5
  75. package/lib/internal/_randomFormatTime.mjs.map +1 -1
  76. package/lib/internal/_randomPattern.js.map +1 -1
  77. package/lib/internal/_randomPattern.mjs.map +1 -1
  78. package/lib/internal/_randomStringLength.d.ts +41 -10
  79. package/lib/internal/_randomStringLength.js +49 -13
  80. package/lib/internal/_randomStringLength.js.map +1 -1
  81. package/lib/internal/_randomStringLength.mjs +48 -13
  82. package/lib/internal/_randomStringLength.mjs.map +1 -1
  83. package/lib/internal/private/__notationRename.js.map +1 -1
  84. package/lib/internal/private/__notationRename.mjs.map +1 -1
  85. package/lib/internal/private/__randomComposition.d.ts +23 -0
  86. package/lib/internal/private/__randomComposition.js +48 -0
  87. package/lib/internal/private/__randomComposition.js.map +1 -0
  88. package/lib/internal/private/__randomComposition.mjs +54 -0
  89. package/lib/internal/private/__randomComposition.mjs.map +1 -0
  90. package/lib/internal/private/__randomEpoch.d.ts +19 -0
  91. package/lib/internal/private/__randomEpoch.js +31 -0
  92. package/lib/internal/private/__randomEpoch.js.map +1 -0
  93. package/lib/internal/private/__randomEpoch.mjs +28 -0
  94. package/lib/internal/private/__randomEpoch.mjs.map +1 -0
  95. package/native/cmd/ttsc-typia/build.go +3 -0
  96. package/native/cmd/ttsc-typia/callable_interface_function_semantics_transform_test.go +331 -0
  97. package/native/cmd/ttsc-typia/callable_type_literal_boundaries_transform_test.go +1184 -0
  98. package/native/cmd/ttsc-typia/compare_functional_union_membership_transform_test.go +434 -0
  99. package/native/cmd/ttsc-typia/compare_template_literal_union_transform_test.go +241 -0
  100. package/native/cmd/ttsc-typia/default_library_spoof_native_identity_transform_test.go +216 -0
  101. package/native/cmd/ttsc-typia/json_schema_dynamic_key_determinism_transform_test.go +246 -0
  102. package/native/cmd/ttsc-typia/json_stringify_contextual_undefined_transform_test.go +556 -0
  103. package/native/cmd/ttsc-typia/lib_replacement_native_identity_transform_test.go +277 -0
  104. package/native/cmd/ttsc-typia/native_named_intersection_union_transform_test.go +390 -0
  105. package/native/cmd/ttsc-typia/node_buffer_native_exports_is_transform_test.go +526 -0
  106. package/native/cmd/ttsc-typia/package_declaration_native_identity_is_transform_test.go +293 -0
  107. package/native/cmd/ttsc-typia/protobuf_diagnostic_code_transform_test.go +167 -0
  108. package/native/cmd/ttsc-typia/symbol_index_domain_transform_test.go +316 -0
  109. package/native/cmd/ttsc-typia/transform.go +23 -0
  110. package/native/cmd/ttsc-typia/transform_helpers_test.go +77 -2
  111. package/native/cmd/ttsc-typia/user_global_native_identity_transform_test.go +484 -0
  112. package/native/core/factories/ProtobufFactory.go +6 -1
  113. package/native/core/factories/internal/metadata/MetadataHelper.go +185 -30
  114. package/native/core/factories/internal/metadata/emplace_metadata_object.go +25 -0
  115. package/native/core/factories/internal/metadata/iterate_metadata_function.go +1 -1
  116. package/native/core/factories/internal/metadata/iterate_metadata_intersection.go +103 -23
  117. package/native/core/factories/internal/metadata/iterate_metadata_map.go +3 -7
  118. package/native/core/factories/internal/metadata/iterate_metadata_native.go +32 -14
  119. package/native/core/factories/internal/metadata/iterate_metadata_set.go +3 -7
  120. package/native/core/programmers/compare/CompareEqualProgrammer.go +27 -13
  121. package/native/core/programmers/helpers/FunctionProgrammer.go +6 -13
  122. package/native/core/programmers/helpers/StringifyJoinder.go +129 -50
  123. package/native/core/programmers/helpers/joiner_branch_coverage_test.go +116 -120
  124. package/native/core/programmers/iterate/iterate_check_coverage_test.go +76 -158
  125. package/native/core/programmers/iterate/iterate_utility_coverage_test.go +231 -270
  126. package/native/core/programmers/iterate/json_schema_object.go +49 -7
  127. package/native/core/programmers/iterate/json_schema_pattern_property_order_test.go +44 -0
  128. package/native/core/programmers/iterate/openapi_v3_downgrader.go +34 -1
  129. package/native/core/programmers/iterate/template_runtime_pattern.go +11 -0
  130. package/native/core/programmers/json/JsonStringifyProgrammer.go +47 -6
  131. package/native/core/programmers/llm/LlmApplicationProgrammer.go +9 -1
  132. package/native/core/programmers/protobuf/ProtobufMessageProgrammer.go +1 -1
  133. package/native/core/schemas/metadata/MetadataCollection.go +0 -9
  134. package/native/core/schemas/metadata/MetadataDefaultLibrary.go +81 -0
  135. package/native/core/schemas/metadata/MetadataObjectType.go +7 -18
  136. package/native/go.mod +4 -4
  137. package/native/transform/features/protobuf/ProtobufMessageTransformer.go +1 -1
  138. package/package.json +3 -7
  139. package/src/executable/FileSystemIdentity.ts +33 -0
  140. package/src/executable/TypiaGenerateWizard.ts +18 -12
  141. package/src/internal/_ProtobufReader.ts +40 -11
  142. package/src/internal/_jsonStringifyArray.ts +50 -0
  143. package/src/internal/_jsonStringifyElement.ts +19 -0
  144. package/src/internal/_jsonStringifyProperty.ts +30 -0
  145. package/src/internal/_llmApplicationFinalize.ts +6 -1
  146. package/src/internal/_randomFormatByte.ts +30 -3
  147. package/src/internal/_randomFormatDate.ts +4 -20
  148. package/src/internal/_randomFormatDatetime.ts +34 -20
  149. package/src/internal/_randomFormatDuration.ts +19 -4
  150. package/src/internal/_randomFormatIpv4.ts +43 -3
  151. package/src/internal/_randomFormatIpv6.ts +67 -3
  152. package/src/internal/_randomFormatJsonPointer.ts +23 -3
  153. package/src/internal/_randomFormatRegex.ts +21 -3
  154. package/src/internal/_randomFormatRelativeJsonPointer.ts +23 -10
  155. package/src/internal/_randomFormatTime.ts +45 -12
  156. package/src/internal/_randomPattern.ts +4 -1
  157. package/src/internal/_randomStringLength.ts +61 -17
  158. package/src/internal/private/__notationRename.ts +1 -4
  159. package/src/internal/private/__randomComposition.ts +50 -0
  160. package/src/internal/private/__randomEpoch.ts +34 -0
  161. package/native/adapter/visit.go +0 -173
  162. package/native/adapter/visit_property_chain_edges_test.go +0 -129
  163. package/native/core/programmers/helpers/disable_function_programmer_declare.go +0 -10
  164. package/native/core/programmers/iterate/check_union_array_like.go +0 -422
  165. package/native/core/programmers/iterate/prune_object_properties.go +0 -105
  166. package/native/core/programmers/iterate/stringify_dynamic_properties.go +0 -219
  167. package/native/core/programmers/iterate/stringify_native.go +0 -14
  168. package/native/core/programmers/iterate/stringify_regular_properties.go +0 -112
  169. package/native/core/schemas/metadata/MetadataApplication.go +0 -41
@@ -0,0 +1,277 @@
1
+ package main
2
+
3
+ import (
4
+ "fmt"
5
+ "os"
6
+ "os/exec"
7
+ "path/filepath"
8
+ "strings"
9
+ "testing"
10
+ )
11
+
12
+ // TestLibReplacementNativeIdentityTransform keeps a `libReplacement` project's
13
+ // natives native even though their declaration file lives in node_modules
14
+ // (#2200).
15
+ //
16
+ // Runtime-native identity requires a runtime authority to declare the global, so
17
+ // which files count as a TypeScript default library became load-bearing. Under
18
+ // `libReplacement` the compiler resolves `lib.es2015.collection.d.ts` to
19
+ // `@typescript/lib-es2015/collection`, an ordinary package file whose name does
20
+ // not even begin with `lib.` — so a file-name rule answers "not a default
21
+ // library" and would demote Map, Set, WeakMap, and WeakSet to structural checks
22
+ // that accept any object. Only the program's own classification is right here,
23
+ // and this fixture is what proves the transform consults it.
24
+ //
25
+ // 1. Publish `@typescript/lib-es2015/collection.d.ts` carrying the real
26
+ // Map/Set/WeakMap/WeakSet declarations plus a probe interface that exists
27
+ // nowhere else, and enable `libReplacement`.
28
+ // 2. Transform validators for the four replaced collection natives, for Date
29
+ // and Uint8Array as bundled-library controls, and for the probe.
30
+ // 3. Require the probe to transform at all, which fails unless the replacement
31
+ // file — not the bundled lib — is what the program loaded.
32
+ // 4. Require every native to keep its `instanceof` check and execute all of
33
+ // them in Node against real instances and plain objects.
34
+ func TestLibReplacementNativeIdentityTransform(t *testing.T) {
35
+ project := libReplacementNativeIdentityProject(t)
36
+ js, errText, code := ttscTypiaTestCapture(func() int {
37
+ return runTransform([]string{
38
+ "--cwd", project,
39
+ "--tsconfig", "tsconfig.json",
40
+ "--file", "src/input.ts",
41
+ "--output", "js",
42
+ })
43
+ })
44
+ if code != 0 {
45
+ t.Fatalf("lib replacement transform failed: code=%d stderr=\n%s", code, errText)
46
+ }
47
+
48
+ failures := []string{}
49
+ if !strings.Contains(js, "libReplacementMarker") {
50
+ failures = append(failures, "emit lost the replacement-only probe member; the project did not load the replaced lib file")
51
+ }
52
+ for _, kept := range []string{
53
+ "instanceof Map",
54
+ "instanceof Set",
55
+ "instanceof WeakMap",
56
+ "instanceof WeakSet",
57
+ "instanceof Date",
58
+ "instanceof Uint8Array",
59
+ } {
60
+ if !strings.Contains(js, kept) {
61
+ failures = append(failures, fmt.Sprintf("replaced or bundled default library native lost %q", kept))
62
+ }
63
+ }
64
+
65
+ output, runtimeErr := libReplacementNativeIdentityRun(t, project, js)
66
+ if runtimeErr != nil {
67
+ failures = append(failures, fmt.Sprintf("runtime matrix failed: %v\n%s", runtimeErr, output))
68
+ }
69
+ if expected := "RAN 13 REPLACEMENT CASES"; !strings.Contains(output, expected) {
70
+ failures = append(failures, fmt.Sprintf("replacement runner did not report %q; got:\n%s", expected, output))
71
+ }
72
+ if len(failures) != 0 {
73
+ t.Fatalf("lib replacement native identity mismatches:\n%s\n\nemit:\n%s", strings.Join(failures, "\n"), js)
74
+ }
75
+ }
76
+
77
+ func libReplacementNativeIdentityProject(t *testing.T) string {
78
+ t.Helper()
79
+ root := ttscTypiaTestRepoRoot(t)
80
+ base := filepath.Join(root, "packages", "typia", "native", ".tmp-ttsc-typia-tests")
81
+ if err := os.MkdirAll(base, 0o755); err != nil {
82
+ t.Fatalf("mkdir temp base: %v", err)
83
+ }
84
+ dir, err := os.MkdirTemp(base, "lib-replacement-native-identity-")
85
+ if err != nil {
86
+ t.Fatalf("create temp fixture: %v", err)
87
+ }
88
+ t.Cleanup(func() {
89
+ _ = os.RemoveAll(dir)
90
+ })
91
+ for name, content := range map[string]string{
92
+ "tsconfig.json": libReplacementNativeIdentityTSConfig,
93
+ "node_modules/@typescript/lib-es2015/package.json": libReplacementNativeIdentityPackageJSON,
94
+ "node_modules/@typescript/lib-es2015/collection.d.ts": libReplacementNativeIdentityCollectionLib,
95
+ "src/input.ts": libReplacementNativeIdentitySource,
96
+ } {
97
+ path := filepath.Join(dir, filepath.FromSlash(name))
98
+ if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
99
+ t.Fatalf("mkdir fixture path %s: %v", filepath.Dir(path), err)
100
+ }
101
+ if err := os.WriteFile(path, []byte(content), 0o644); err != nil {
102
+ t.Fatalf("write fixture file %s: %v", path, err)
103
+ }
104
+ }
105
+ return dir
106
+ }
107
+
108
+ func libReplacementNativeIdentityRun(t *testing.T, project string, js string) (string, error) {
109
+ t.Helper()
110
+ node, err := exec.LookPath("node")
111
+ if err != nil {
112
+ t.Skip("node executable not found")
113
+ return "", nil
114
+ }
115
+ runtimeDir := filepath.Join(project, "runtime")
116
+ if err := os.MkdirAll(runtimeDir, 0o755); err != nil {
117
+ t.Fatalf("mkdir runtime dir: %v", err)
118
+ }
119
+ ttscTypiaTestWriteCommonRuntimeStubs(t, runtimeDir)
120
+ for name, content := range map[string]string{
121
+ "input.cjs": ttscTypiaTestRewriteCommonJS(t, js),
122
+ "run.cjs": libReplacementNativeIdentityRuntimeRunner,
123
+ } {
124
+ if err := os.WriteFile(filepath.Join(runtimeDir, name), []byte(content), 0o644); err != nil {
125
+ t.Fatalf("write runtime file %s: %v", name, err)
126
+ }
127
+ }
128
+ cmd := exec.Command(node, filepath.Join(runtimeDir, "run.cjs"))
129
+ cmd.Dir = runtimeDir
130
+ output, err := cmd.CombinedOutput()
131
+ return string(output), err
132
+ }
133
+
134
+ const libReplacementNativeIdentityTSConfig = `{
135
+ "compilerOptions": {
136
+ "target": "ES2022",
137
+ "module": "commonjs",
138
+ "moduleResolution": "bundler",
139
+ "ignoreDeprecations": "6.0",
140
+ "lib": ["ES2022"],
141
+ "types": [],
142
+ "libReplacement": true,
143
+ "esModuleInterop": true,
144
+ "strict": true,
145
+ "skipLibCheck": true
146
+ },
147
+ "include": ["src"]
148
+ }
149
+ `
150
+
151
+ const libReplacementNativeIdentityPackageJSON = `{
152
+ "name": "@typescript/lib-es2015",
153
+ "version": "1.0.0"
154
+ }
155
+ `
156
+
157
+ // libReplacementNativeIdentityCollectionLib is the replacement TypeScript loads
158
+ // instead of its bundled `lib.es2015.collection.d.ts`. The collection
159
+ // declarations are transcribed from that file so the rest of the standard
160
+ // library still typechecks against them; `LibReplacementProbe` is the one
161
+ // addition, and it is what proves the program loaded this file.
162
+ const libReplacementNativeIdentityCollectionLib = `interface LibReplacementProbe {
163
+ libReplacementMarker: string;
164
+ }
165
+
166
+ interface Map<K, V> {
167
+ clear(): void;
168
+ delete(key: K): boolean;
169
+ forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void, thisArg?: any): void;
170
+ get(key: K): V | undefined;
171
+ has(key: K): boolean;
172
+ set(key: K, value: V): this;
173
+ readonly size: number;
174
+ }
175
+
176
+ interface MapConstructor {
177
+ new (): Map<any, any>;
178
+ new <K, V>(entries?: readonly (readonly [K, V])[] | null): Map<K, V>;
179
+ readonly prototype: Map<any, any>;
180
+ }
181
+ declare var Map: MapConstructor;
182
+
183
+ interface ReadonlyMap<K, V> {
184
+ forEach(callbackfn: (value: V, key: K, map: ReadonlyMap<K, V>) => void, thisArg?: any): void;
185
+ get(key: K): V | undefined;
186
+ has(key: K): boolean;
187
+ readonly size: number;
188
+ }
189
+
190
+ interface WeakMap<K extends WeakKey, V> {
191
+ delete(key: K): boolean;
192
+ get(key: K): V | undefined;
193
+ has(key: K): boolean;
194
+ set(key: K, value: V): this;
195
+ }
196
+
197
+ interface WeakMapConstructor {
198
+ new <K extends WeakKey = WeakKey, V = any>(entries?: readonly (readonly [K, V])[] | null): WeakMap<K, V>;
199
+ readonly prototype: WeakMap<WeakKey, any>;
200
+ }
201
+ declare var WeakMap: WeakMapConstructor;
202
+
203
+ interface Set<T> {
204
+ add(value: T): this;
205
+ clear(): void;
206
+ delete(value: T): boolean;
207
+ forEach(callbackfn: (value: T, value2: T, set: Set<T>) => void, thisArg?: any): void;
208
+ has(value: T): boolean;
209
+ readonly size: number;
210
+ }
211
+
212
+ interface SetConstructor {
213
+ new <T = any>(values?: readonly T[] | null): Set<T>;
214
+ readonly prototype: Set<any>;
215
+ }
216
+ declare var Set: SetConstructor;
217
+
218
+ interface ReadonlySet<T> {
219
+ forEach(callbackfn: (value: T, value2: T, set: ReadonlySet<T>) => void, thisArg?: any): void;
220
+ has(value: T): boolean;
221
+ readonly size: number;
222
+ }
223
+
224
+ interface WeakSet<T extends WeakKey> {
225
+ add(value: T): this;
226
+ delete(value: T): boolean;
227
+ has(value: T): boolean;
228
+ }
229
+
230
+ interface WeakSetConstructor {
231
+ new <T extends WeakKey = WeakKey>(values?: readonly T[] | null): WeakSet<T>;
232
+ readonly prototype: WeakSet<WeakKey>;
233
+ }
234
+ declare var WeakSet: WeakSetConstructor;
235
+ `
236
+
237
+ const libReplacementNativeIdentitySource = `import typia from "typia";
238
+
239
+ export const createdIsProbe = typia.createIs<LibReplacementProbe>();
240
+ export const createdIsMap = typia.createIs<Map<string, number>>();
241
+ export const createdIsSet = typia.createIs<Set<string>>();
242
+ export const createdIsWeakMap = typia.createIs<WeakMap<object, string>>();
243
+ export const createdIsWeakSet = typia.createIs<WeakSet<object>>();
244
+ export const createdIsDate = typia.createIs<Date>();
245
+ export const createdIsBytes = typia.createIs<Uint8Array>();
246
+ `
247
+
248
+ const libReplacementNativeIdentityRuntimeRunner = `const validators = require("./input.cjs");
249
+
250
+ let ran = 0;
251
+ const failures = [];
252
+ const eq = (name, actual, expected) => {
253
+ ran += 1;
254
+ if (actual !== expected) {
255
+ failures.push(name + ": expected " + expected + " but got " + actual);
256
+ }
257
+ };
258
+
259
+ eq("probe structural", validators.createdIsProbe({ libReplacementMarker: "x" }), true);
260
+ eq("Map real", validators.createdIsMap(new Map([["x", 1]])), true);
261
+ eq("Map plain", validators.createdIsMap({}), false);
262
+ eq("Set real", validators.createdIsSet(new Set(["x"])), true);
263
+ eq("Set plain", validators.createdIsSet({}), false);
264
+ eq("WeakMap real", validators.createdIsWeakMap(new WeakMap()), true);
265
+ eq("WeakMap plain", validators.createdIsWeakMap({}), false);
266
+ eq("WeakSet real", validators.createdIsWeakSet(new WeakSet()), true);
267
+ eq("WeakSet plain", validators.createdIsWeakSet({}), false);
268
+ eq("Date real", validators.createdIsDate(new Date()), true);
269
+ eq("Date plain", validators.createdIsDate({}), false);
270
+ eq("Uint8Array real", validators.createdIsBytes(new Uint8Array(1)), true);
271
+ eq("Uint8Array plain", validators.createdIsBytes({}), false);
272
+
273
+ console.log("RAN " + ran + " REPLACEMENT CASES");
274
+ if (failures.length !== 0) {
275
+ throw new Error("MISMATCHES:\n" + failures.join("\n"));
276
+ }
277
+ `
@@ -0,0 +1,390 @@
1
+ package main
2
+
3
+ import (
4
+ "os"
5
+ "os/exec"
6
+ "path/filepath"
7
+ "strings"
8
+ "testing"
9
+ )
10
+
11
+ // TestNativeNamedIntersectionUnionTransform verifies a structural intersection
12
+ // keeps its object identity when a user declaration shares a native name.
13
+ //
14
+ // The standalone local Date and Date intersection already use structural
15
+ // metadata. Union composition must retain that classification instead of
16
+ // pruning the inhabited arm as a native/object conflict. Native-named local
17
+ // String and Number declarations must follow the same structural path, while
18
+ // genuine native wrappers and impossible intersections retain their existing
19
+ // pruning paths.
20
+ //
21
+ // 1. Transform standalone, union, genuine-native, impossible, and colliding
22
+ // native-name controls.
23
+ // 2. Inspect each union factory to prove local structural arms are retained
24
+ // while genuine wrappers and existing collection arms keep their emit.
25
+ // 3. Execute both valid arms, invalid near-misses, and pruning controls.
26
+ func TestNativeNamedIntersectionUnionTransform(t *testing.T) {
27
+ project := nativeNamedIntersectionUnionProject(t)
28
+ js := nativeNamedIntersectionUnionTransform(t, project)
29
+
30
+ localUnion := nativeNamedIntersectionUnionExport(t, js, "isLocalUnion", "isLocalMapUnion")
31
+ for _, retained := range []string{"input.stamp", "input.label", "input.ok"} {
32
+ if !strings.Contains(localUnion, retained) {
33
+ t.Errorf("local structural union lost %q in emitted factory:\n%s", retained, localUnion)
34
+ }
35
+ }
36
+ if strings.Contains(localUnion, "instanceof Date") {
37
+ t.Errorf("local structural union was emitted as a genuine Date:\n%s", localUnion)
38
+ }
39
+
40
+ localWrapperUnions := []struct {
41
+ name string
42
+ next string
43
+ members []string
44
+ native string
45
+ }{
46
+ {"isLocalStringUnion", "isLocalNumberUnion", []string{"input.stringValue", "input.label", "input.stringOk"}, "String"},
47
+ {"isLocalNumberUnion", "isLocalMapUnion", []string{"input.numberValue", "input.label", "input.numberOk"}, "Number"},
48
+ }
49
+ for _, control := range localWrapperUnions {
50
+ segment := nativeNamedIntersectionUnionExport(t, js, control.name, control.next)
51
+ for _, retained := range control.members {
52
+ if !strings.Contains(segment, retained) {
53
+ t.Errorf("%s lost structural member %q in emitted factory:\n%s", control.name, retained, segment)
54
+ }
55
+ }
56
+ if strings.Contains(segment, "instanceof "+control.native) {
57
+ t.Errorf("%s was emitted as a genuine %s wrapper:\n%s", control.name, control.native, segment)
58
+ }
59
+ }
60
+
61
+ collectionUnions := []struct {
62
+ name string
63
+ next string
64
+ members []string
65
+ }{
66
+ {"isLocalMapUnion", "isLocalSetUnion", []string{"input.brandMap", "input.valueMap", "input.label", "input.mapOk"}},
67
+ {"isLocalSetUnion", "isLocalWeakMapUnion", []string{"input.brandSet", "input.label", "input.setOk"}},
68
+ {"isLocalWeakMapUnion", "isLocalWeakSetUnion", []string{"input.brandWeakMap", "input.valueWeakMap", "input.label", "input.weakMapOk"}},
69
+ {"isLocalWeakSetUnion", "isNativeDate", []string{"input.brandWeakSet", "input.label", "input.weakSetOk"}},
70
+ }
71
+ for _, control := range collectionUnions {
72
+ segment := nativeNamedIntersectionUnionExport(t, js, control.name, control.next)
73
+ for _, retained := range control.members {
74
+ if !strings.Contains(segment, retained) {
75
+ t.Fatalf("%s lost structural member %q in emitted factory:\n%s", control.name, retained, segment)
76
+ }
77
+ }
78
+ }
79
+
80
+ nativeDate := nativeNamedIntersectionUnionExport(t, js, "isNativeDate", "isNativeIntersectionUnion")
81
+ if !strings.Contains(nativeDate, "instanceof Date") {
82
+ t.Fatalf("genuine Date lost its native identity in emitted factory:\n%s", nativeDate)
83
+ }
84
+
85
+ nativeUnion := nativeNamedIntersectionUnionExport(t, js, "isNativeIntersectionUnion", "isNativeStringIntersectionUnion")
86
+ for _, pruned := range []string{"instanceof Date", "input.label"} {
87
+ if strings.Contains(nativeUnion, pruned) {
88
+ t.Fatalf("genuine native intersection unexpectedly survived union pruning as %q:\n%s", pruned, nativeUnion)
89
+ }
90
+ }
91
+ if !strings.Contains(nativeUnion, "input.ok") {
92
+ t.Fatalf("genuine native intersection control lost its inhabited object arm:\n%s", nativeUnion)
93
+ }
94
+
95
+ nativeWrapperUnions := []struct {
96
+ name string
97
+ next string
98
+ native string
99
+ other string
100
+ }{
101
+ {"isNativeStringIntersectionUnion", "isNativeNumberIntersectionUnion", "String", "nativeStringOk"},
102
+ {"isNativeNumberIntersectionUnion", "isImpossibleUnion", "Number", "nativeNumberOk"},
103
+ }
104
+ for _, control := range nativeWrapperUnions {
105
+ segment := nativeNamedIntersectionUnionExport(t, js, control.name, control.next)
106
+ for _, pruned := range []string{"instanceof " + control.native, "input.label"} {
107
+ if strings.Contains(segment, pruned) {
108
+ t.Fatalf("genuine %s wrapper intersection unexpectedly survived union pruning as %q:\n%s", control.native, pruned, segment)
109
+ }
110
+ }
111
+ if !strings.Contains(segment, "input."+control.other) {
112
+ t.Fatalf("genuine %s wrapper control lost its inhabited object arm:\n%s", control.native, segment)
113
+ }
114
+ }
115
+
116
+ impossibleUnion := nativeNamedIntersectionUnionExport(t, js, "isImpossibleUnion", "")
117
+ if strings.Contains(impossibleUnion, "input.data") {
118
+ t.Fatalf("impossible intersection unexpectedly survived union pruning:\n%s", impossibleUnion)
119
+ }
120
+ if !strings.Contains(impossibleUnion, "input.ok") {
121
+ t.Fatalf("impossible intersection control lost its inhabited object arm:\n%s", impossibleUnion)
122
+ }
123
+
124
+ nativeNamedIntersectionUnionRunRuntimeCases(t, project, js)
125
+ }
126
+
127
+ func nativeNamedIntersectionUnionProject(t *testing.T) string {
128
+ t.Helper()
129
+ root := ttscTypiaTestRepoRoot(t)
130
+ base := filepath.Join(root, "packages", "typia", "native", ".tmp-ttsc-typia-tests")
131
+ if err := os.MkdirAll(base, 0o755); err != nil {
132
+ t.Fatalf("mkdir temp base: %v", err)
133
+ }
134
+ dir, err := os.MkdirTemp(base, "native-named-intersection-union-")
135
+ if err != nil {
136
+ t.Fatalf("create temp fixture: %v", err)
137
+ }
138
+ t.Cleanup(func() { _ = os.RemoveAll(dir) })
139
+ src := filepath.Join(dir, "src")
140
+ if err := os.MkdirAll(src, 0o755); err != nil {
141
+ t.Fatalf("mkdir fixture src: %v", err)
142
+ }
143
+ if err := os.WriteFile(filepath.Join(dir, "tsconfig.json"), []byte(nativeNamedIntersectionUnionTSConfig), 0o644); err != nil {
144
+ t.Fatalf("write tsconfig: %v", err)
145
+ }
146
+ if err := os.WriteFile(filepath.Join(src, "main.ts"), []byte(nativeNamedIntersectionUnionSource), 0o644); err != nil {
147
+ t.Fatalf("write source: %v", err)
148
+ }
149
+ return dir
150
+ }
151
+
152
+ func nativeNamedIntersectionUnionTransform(t *testing.T, project string) string {
153
+ t.Helper()
154
+ out, errText, code := ttscTypiaTestCapture(func() int {
155
+ return runTransform([]string{
156
+ "--cwd", project,
157
+ "--tsconfig", "tsconfig.json",
158
+ "--file", "src/main.ts",
159
+ "--output", "js",
160
+ })
161
+ })
162
+ if code != 0 {
163
+ t.Fatalf("native-named intersection union transform failed: code=%d stderr=\n%s", code, errText)
164
+ }
165
+ return out
166
+ }
167
+
168
+ func nativeNamedIntersectionUnionExport(t *testing.T, js string, name string, next string) string {
169
+ t.Helper()
170
+ marker := "exports." + name + " = (() =>"
171
+ start := strings.Index(js, marker)
172
+ if start == -1 {
173
+ t.Fatalf("emitted JavaScript has no %s factory:\n%s", name, js)
174
+ }
175
+ segment := js[start:]
176
+ if next != "" {
177
+ end := strings.Index(segment, "exports."+next+" = (() =>")
178
+ if end == -1 {
179
+ t.Fatalf("emitted JavaScript has no %s boundary after %s:\n%s", next, name, js)
180
+ }
181
+ segment = segment[:end]
182
+ }
183
+ return segment
184
+ }
185
+
186
+ func nativeNamedIntersectionUnionRunRuntimeCases(t *testing.T, project string, js string) {
187
+ t.Helper()
188
+ node, err := exec.LookPath("node")
189
+ if err != nil {
190
+ t.Skip("node executable not found")
191
+ }
192
+ runtimeDir := filepath.Join(project, "runtime")
193
+ if err := os.MkdirAll(runtimeDir, 0o755); err != nil {
194
+ t.Fatalf("mkdir runtime dir: %v", err)
195
+ }
196
+ ttscTypiaTestWriteCommonRuntimeStubs(t, runtimeDir)
197
+ if err := os.WriteFile(filepath.Join(runtimeDir, "main.cjs"), []byte(ttscTypiaTestRewriteCommonJS(t, js)), 0o644); err != nil {
198
+ t.Fatalf("write runtime module: %v", err)
199
+ }
200
+ runner := filepath.Join(runtimeDir, "run.cjs")
201
+ if err := os.WriteFile(runner, []byte(nativeNamedIntersectionUnionRuntimeRunner), 0o644); err != nil {
202
+ t.Fatalf("write runtime runner: %v", err)
203
+ }
204
+ cmd := exec.Command(node, runner)
205
+ cmd.Dir = runtimeDir
206
+ output, err := cmd.CombinedOutput()
207
+ if err != nil {
208
+ t.Fatalf("native-named intersection union runtime cases failed: %v\n%s", err, output)
209
+ }
210
+ if !strings.Contains(string(output), "RAN 44 CASES") {
211
+ t.Fatalf("runtime runner did not report all cases:\n%s", output)
212
+ }
213
+ }
214
+
215
+ const nativeNamedIntersectionUnionTSConfig = `{
216
+ "compilerOptions": {
217
+ "target": "ES2022",
218
+ "module": "commonjs",
219
+ "moduleResolution": "bundler",
220
+ "ignoreDeprecations": "6.0",
221
+ "types": ["*"],
222
+ "esModuleInterop": true,
223
+ "strict": true,
224
+ "skipLibCheck": true
225
+ },
226
+ "include": ["src"]
227
+ }
228
+ `
229
+
230
+ const nativeNamedIntersectionUnionSource = `import typia from "typia";
231
+
232
+ interface Date {
233
+ stamp: number;
234
+ }
235
+ interface String {
236
+ stringValue: string;
237
+ }
238
+ interface Number {
239
+ numberValue: number;
240
+ }
241
+ interface Map<K, V> {
242
+ brandMap: K;
243
+ valueMap: V;
244
+ }
245
+ interface Set<T> {
246
+ brandSet: T;
247
+ }
248
+ interface WeakMap<K extends object, V> {
249
+ brandWeakMap: K;
250
+ valueWeakMap: V;
251
+ }
252
+ interface WeakSet<T extends object> {
253
+ brandWeakSet: T;
254
+ }
255
+ type LocalIntersection = Date & { label: string };
256
+ type LocalUnion = LocalIntersection | { ok: boolean };
257
+ type LocalStringUnion =
258
+ | (String & { label: string })
259
+ | { stringOk: boolean };
260
+ type LocalNumberUnion =
261
+ | (Number & { label: string })
262
+ | { numberOk: boolean };
263
+ type LocalMapUnion =
264
+ | (Map<string, number> & { label: string })
265
+ | { mapOk: boolean };
266
+ type LocalSetUnion =
267
+ | (Set<string> & { label: string })
268
+ | { setOk: boolean };
269
+ type LocalWeakMapUnion =
270
+ | (WeakMap<object, string> & { label: string })
271
+ | { weakMapOk: boolean };
272
+ type LocalWeakSetUnion =
273
+ | (WeakSet<object> & { label: string })
274
+ | { weakSetOk: boolean };
275
+
276
+ type NativeDate = InstanceType<typeof globalThis.Date>;
277
+ type NativeIntersectionUnion =
278
+ | (NativeDate & { label: string })
279
+ | { ok: boolean };
280
+ type NativeString = InstanceType<typeof globalThis.String>;
281
+ type NativeNumber = InstanceType<typeof globalThis.Number>;
282
+ type NativeStringIntersectionUnion =
283
+ | (NativeString & { label: string })
284
+ | { nativeStringOk: boolean };
285
+ type NativeNumberIntersectionUnion =
286
+ | (NativeNumber & { label: string })
287
+ | { nativeNumberOk: boolean };
288
+ type ImpossibleUnion =
289
+ | (string & { data: number })
290
+ | { ok: boolean };
291
+
292
+ export const isLocalDate = typia.createIs<Date>();
293
+ export const isLocalIntersection = typia.createIs<LocalIntersection>();
294
+ export const isLocalUnion = typia.createIs<LocalUnion>();
295
+ export const isLocalStringUnion = typia.createIs<LocalStringUnion>();
296
+ export const isLocalNumberUnion = typia.createIs<LocalNumberUnion>();
297
+ export const isLocalMapUnion = typia.createIs<LocalMapUnion>();
298
+ export const isLocalSetUnion = typia.createIs<LocalSetUnion>();
299
+ export const isLocalWeakMapUnion = typia.createIs<LocalWeakMapUnion>();
300
+ export const isLocalWeakSetUnion = typia.createIs<LocalWeakSetUnion>();
301
+ export const isNativeDate = typia.createIs<NativeDate>();
302
+ export const isNativeIntersectionUnion =
303
+ typia.createIs<NativeIntersectionUnion>();
304
+ export const isNativeStringIntersectionUnion =
305
+ typia.createIs<NativeStringIntersectionUnion>();
306
+ export const isNativeNumberIntersectionUnion =
307
+ typia.createIs<NativeNumberIntersectionUnion>();
308
+ export const isImpossibleUnion = typia.createIs<ImpossibleUnion>();
309
+ `
310
+
311
+ const nativeNamedIntersectionUnionRuntimeRunner = `const mod = require("./main.cjs");
312
+
313
+ let ran = 0;
314
+ const failures = [];
315
+ const check = (label, actual, expected) => {
316
+ ran += 1;
317
+ if (actual !== expected) {
318
+ failures.push(label + ": expected " + expected + " but got " + actual);
319
+ }
320
+ };
321
+
322
+ check("local Date valid", mod.isLocalDate({ stamp: 1 }), true);
323
+ check("local Date native", mod.isLocalDate(new Date(0)), false);
324
+ check("local Date missing stamp", mod.isLocalDate({}), false);
325
+
326
+ check("local intersection valid", mod.isLocalIntersection({ stamp: 1, label: "x" }), true);
327
+ check("local intersection missing label", mod.isLocalIntersection({ stamp: 1 }), false);
328
+ check("local intersection missing stamp", mod.isLocalIntersection({ label: "x" }), false);
329
+
330
+ check("local union structural arm", mod.isLocalUnion({ stamp: 1, label: "x" }), true);
331
+ check("local union other arm", mod.isLocalUnion({ ok: true }), true);
332
+ check("local union near-miss", mod.isLocalUnion({ stamp: 1 }), false);
333
+ check("local union bad other arm", mod.isLocalUnion({ ok: "yes" }), false);
334
+
335
+ check("local String union structural arm", mod.isLocalStringUnion({ stringValue: "x", label: "s" }), true);
336
+ check("local String union other arm", mod.isLocalStringUnion({ stringOk: true }), true);
337
+ check("local String union near-miss", mod.isLocalStringUnion({ stringValue: "x" }), false);
338
+ check("local String union bad other arm", mod.isLocalStringUnion({ stringOk: "yes" }), false);
339
+ check("local Number union structural arm", mod.isLocalNumberUnion({ numberValue: 1, label: "n" }), true);
340
+ check("local Number union other arm", mod.isLocalNumberUnion({ numberOk: true }), true);
341
+ check("local Number union near-miss", mod.isLocalNumberUnion({ numberValue: 1 }), false);
342
+ check("local Number union bad other arm", mod.isLocalNumberUnion({ numberOk: "yes" }), false);
343
+
344
+ check("local Map union structural arm", mod.isLocalMapUnion({ brandMap: "x", valueMap: 1, label: "m" }), true);
345
+ check("local Map union other arm", mod.isLocalMapUnion({ mapOk: true }), true);
346
+ check("local Map union near-miss", mod.isLocalMapUnion({ brandMap: "x", valueMap: 1 }), false);
347
+ check("local Set union structural arm", mod.isLocalSetUnion({ brandSet: "x", label: "s" }), true);
348
+ check("local Set union other arm", mod.isLocalSetUnion({ setOk: true }), true);
349
+ check("local Set union near-miss", mod.isLocalSetUnion({ brandSet: "x" }), false);
350
+ check("local WeakMap union structural arm", mod.isLocalWeakMapUnion({ brandWeakMap: {}, valueWeakMap: "x", label: "wm" }), true);
351
+ check("local WeakMap union other arm", mod.isLocalWeakMapUnion({ weakMapOk: true }), true);
352
+ check("local WeakMap union near-miss", mod.isLocalWeakMapUnion({ brandWeakMap: {}, valueWeakMap: "x" }), false);
353
+ check("local WeakSet union structural arm", mod.isLocalWeakSetUnion({ brandWeakSet: {}, label: "ws" }), true);
354
+ check("local WeakSet union other arm", mod.isLocalWeakSetUnion({ weakSetOk: true }), true);
355
+ check("local WeakSet union near-miss", mod.isLocalWeakSetUnion({ brandWeakSet: {} }), false);
356
+
357
+ check("genuine Date", mod.isNativeDate(new Date(0)), true);
358
+ check("genuine Date plain object", mod.isNativeDate({}), false);
359
+ check(
360
+ "genuine native intersection pruned",
361
+ mod.isNativeIntersectionUnion(Object.assign(new Date(0), { label: "x" })),
362
+ false,
363
+ );
364
+ check("genuine native union other arm", mod.isNativeIntersectionUnion({ ok: true }), true);
365
+ check("genuine native plain near-miss", mod.isNativeIntersectionUnion({ label: "x" }), false);
366
+
367
+ check(
368
+ "genuine String wrapper intersection pruned",
369
+ mod.isNativeStringIntersectionUnion(Object.assign(new String("x"), { label: "s" })),
370
+ false,
371
+ );
372
+ check("genuine String wrapper union other arm", mod.isNativeStringIntersectionUnion({ nativeStringOk: true }), true);
373
+ check("genuine String wrapper plain near-miss", mod.isNativeStringIntersectionUnion({ label: "s" }), false);
374
+ check(
375
+ "genuine Number wrapper intersection pruned",
376
+ mod.isNativeNumberIntersectionUnion(Object.assign(new Number(1), { label: "n" })),
377
+ false,
378
+ );
379
+ check("genuine Number wrapper union other arm", mod.isNativeNumberIntersectionUnion({ nativeNumberOk: true }), true);
380
+ check("genuine Number wrapper plain near-miss", mod.isNativeNumberIntersectionUnion({ label: "n" }), false);
381
+
382
+ check("impossible union other arm", mod.isImpossibleUnion({ ok: true }), true);
383
+ check("impossible union primitive", mod.isImpossibleUnion("x"), false);
384
+ check("impossible union object", mod.isImpossibleUnion({ data: 1 }), false);
385
+
386
+ console.log("RAN " + ran + " CASES");
387
+ if (failures.length !== 0) {
388
+ throw new Error("MISMATCHES:\n" + failures.join("\n"));
389
+ }
390
+ `