typia 13.1.19 → 13.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/executable/FileSystemIdentity.d.ts +23 -0
- package/lib/executable/FileSystemIdentity.js +30 -0
- package/lib/executable/FileSystemIdentity.js.map +1 -1
- package/lib/executable/FileSystemIdentity.mjs +4 -0
- package/lib/executable/FileSystemIdentity.mjs.map +1 -1
- package/lib/executable/TypiaGenerateWizard.js +15 -9
- package/lib/executable/TypiaGenerateWizard.js.map +1 -1
- package/lib/executable/TypiaGenerateWizard.mjs +11 -7
- package/lib/executable/TypiaGenerateWizard.mjs.map +1 -1
- package/lib/http.d.ts +3 -3
- package/lib/http.js.map +1 -1
- package/lib/http.mjs.map +1 -1
- package/lib/internal/_ProtobufReader.d.ts +18 -3
- package/lib/internal/_ProtobufReader.js +39 -11
- package/lib/internal/_ProtobufReader.js.map +1 -1
- package/lib/internal/_ProtobufReader.mjs +37 -10
- package/lib/internal/_ProtobufReader.mjs.map +1 -1
- package/lib/internal/_assertGuard.js +13 -3
- package/lib/internal/_assertGuard.js.map +1 -1
- package/lib/internal/_assertGuard.mjs +4 -2
- package/lib/internal/_assertGuard.mjs.map +1 -1
- package/lib/internal/_isFormatIdnHostname.js +5 -1
- package/lib/internal/_isFormatIdnHostname.js.map +1 -1
- package/lib/internal/_isFormatIdnHostname.mjs +1 -1
- package/lib/internal/_isFormatIdnHostname.mjs.map +1 -1
- package/lib/internal/_isFormatTime.js +19 -2
- package/lib/internal/_isFormatTime.js.map +1 -1
- package/lib/internal/_isFormatTime.mjs +9 -2
- package/lib/internal/_isFormatTime.mjs.map +1 -1
- package/lib/internal/_jsonStringifyArray.d.ts +1 -0
- package/lib/internal/_jsonStringifyArray.js +48 -0
- package/lib/internal/_jsonStringifyArray.js.map +1 -0
- package/lib/internal/_jsonStringifyArray.mjs +40 -0
- package/lib/internal/_jsonStringifyArray.mjs.map +1 -0
- package/lib/internal/_jsonStringifyElement.d.ts +1 -0
- package/lib/internal/_jsonStringifyElement.js +23 -0
- package/lib/internal/_jsonStringifyElement.js.map +1 -0
- package/lib/internal/_jsonStringifyElement.mjs +23 -0
- package/lib/internal/_jsonStringifyElement.mjs.map +1 -0
- package/lib/internal/_jsonStringifyProperty.d.ts +1 -0
- package/lib/internal/_jsonStringifyProperty.js +31 -0
- package/lib/internal/_jsonStringifyProperty.js.map +1 -0
- package/lib/internal/_jsonStringifyProperty.mjs +31 -0
- package/lib/internal/_jsonStringifyProperty.mjs.map +1 -0
- package/lib/internal/_llmApplicationFinalize.js +1 -1
- package/lib/internal/_llmApplicationFinalize.js.map +1 -1
- package/lib/internal/_llmApplicationFinalize.mjs +1 -1
- package/lib/internal/_llmApplicationFinalize.mjs.map +1 -1
- package/lib/internal/_randomArray.js +37 -4
- package/lib/internal/_randomArray.js.map +1 -1
- package/lib/internal/_randomArray.mjs +16 -3
- package/lib/internal/_randomArray.mjs.map +1 -1
- package/lib/internal/_randomFormatByte.js +28 -2
- package/lib/internal/_randomFormatByte.js.map +1 -1
- package/lib/internal/_randomFormatByte.mjs +22 -3
- package/lib/internal/_randomFormatByte.mjs.map +1 -1
- package/lib/internal/_randomFormatDate.d.ts +3 -6
- package/lib/internal/_randomFormatDate.js +2 -10
- package/lib/internal/_randomFormatDate.js.map +1 -1
- package/lib/internal/_randomFormatDate.mjs +2 -6
- package/lib/internal/_randomFormatDate.mjs.map +1 -1
- package/lib/internal/_randomFormatDatetime.d.ts +3 -6
- package/lib/internal/_randomFormatDatetime.js +25 -8
- package/lib/internal/_randomFormatDatetime.js.map +1 -1
- package/lib/internal/_randomFormatDatetime.mjs +17 -7
- package/lib/internal/_randomFormatDatetime.mjs.map +1 -1
- package/lib/internal/_randomFormatDuration.js +23 -15
- package/lib/internal/_randomFormatDuration.js.map +1 -1
- package/lib/internal/_randomFormatDuration.mjs +23 -15
- package/lib/internal/_randomFormatDuration.mjs.map +1 -1
- package/lib/internal/_randomFormatHostname.d.ts +2 -2
- package/lib/internal/_randomFormatHostname.js +2 -2
- package/lib/internal/_randomFormatHostname.mjs +2 -2
- package/lib/internal/_randomFormatHostname.mjs.map +1 -1
- package/lib/internal/_randomFormatIdnHostname.js +9 -10
- package/lib/internal/_randomFormatIdnHostname.js.map +1 -1
- package/lib/internal/_randomFormatIdnHostname.mjs +3 -4
- package/lib/internal/_randomFormatIdnHostname.mjs.map +1 -1
- package/lib/internal/_randomFormatIpv4.js +31 -1
- package/lib/internal/_randomFormatIpv4.js.map +1 -1
- package/lib/internal/_randomFormatIpv4.mjs +23 -2
- package/lib/internal/_randomFormatIpv4.mjs.map +1 -1
- package/lib/internal/_randomFormatIpv6.js +57 -1
- package/lib/internal/_randomFormatIpv6.js.map +1 -1
- package/lib/internal/_randomFormatIpv6.mjs +45 -2
- package/lib/internal/_randomFormatIpv6.mjs.map +1 -1
- package/lib/internal/_randomFormatJsonPointer.js +14 -2
- package/lib/internal/_randomFormatJsonPointer.js.map +1 -1
- package/lib/internal/_randomFormatJsonPointer.mjs +13 -3
- package/lib/internal/_randomFormatJsonPointer.mjs.map +1 -1
- package/lib/internal/_randomFormatRegex.js +15 -2
- package/lib/internal/_randomFormatRegex.js.map +1 -1
- package/lib/internal/_randomFormatRegex.mjs +14 -3
- package/lib/internal/_randomFormatRegex.mjs.map +1 -1
- package/lib/internal/_randomFormatRelativeJsonPointer.js +19 -5
- package/lib/internal/_randomFormatRelativeJsonPointer.js.map +1 -1
- package/lib/internal/_randomFormatRelativeJsonPointer.mjs +21 -6
- package/lib/internal/_randomFormatRelativeJsonPointer.mjs.map +1 -1
- package/lib/internal/_randomFormatTime.js +38 -7
- package/lib/internal/_randomFormatTime.js.map +1 -1
- package/lib/internal/_randomFormatTime.mjs +40 -5
- package/lib/internal/_randomFormatTime.mjs.map +1 -1
- package/lib/internal/_randomPattern.js.map +1 -1
- package/lib/internal/_randomPattern.mjs.map +1 -1
- package/lib/internal/_randomStringLength.d.ts +41 -10
- package/lib/internal/_randomStringLength.js +49 -13
- package/lib/internal/_randomStringLength.js.map +1 -1
- package/lib/internal/_randomStringLength.mjs +48 -13
- package/lib/internal/_randomStringLength.mjs.map +1 -1
- package/lib/internal/private/__notationRename.js.map +1 -1
- package/lib/internal/private/__notationRename.mjs.map +1 -1
- package/lib/internal/private/__randomComposition.d.ts +31 -0
- package/lib/internal/private/__randomComposition.js +68 -0
- package/lib/internal/private/__randomComposition.js.map +1 -0
- package/lib/internal/private/__randomComposition.mjs +71 -0
- package/lib/internal/private/__randomComposition.mjs.map +1 -0
- package/lib/internal/private/__randomEpoch.d.ts +19 -0
- package/lib/internal/private/__randomEpoch.js +31 -0
- package/lib/internal/private/__randomEpoch.js.map +1 -0
- package/lib/internal/private/__randomEpoch.mjs +28 -0
- package/lib/internal/private/__randomEpoch.mjs.map +1 -0
- package/lib/json.d.ts +2 -2
- package/lib/json.js.map +1 -1
- package/lib/json.mjs.map +1 -1
- package/lib/module.d.ts +28 -13
- package/lib/module.js.map +1 -1
- package/lib/module.mjs.map +1 -1
- package/lib/notations.d.ts +4 -4
- package/lib/notations.js.map +1 -1
- package/lib/notations.mjs.map +1 -1
- package/lib/plain.d.ts +3 -3
- package/lib/plain.js.map +1 -1
- package/lib/plain.mjs.map +1 -1
- package/lib/protobuf.d.ts +2 -2
- package/lib/protobuf.js.map +1 -1
- package/lib/protobuf.mjs.map +1 -1
- package/native/cmd/ttsc-typia/assert_guard_factory_contract_test.go +17 -4
- package/native/cmd/ttsc-typia/build.go +3 -0
- package/native/cmd/ttsc-typia/callable_interface_function_semantics_transform_test.go +331 -0
- package/native/cmd/ttsc-typia/callable_type_literal_boundaries_transform_test.go +1184 -0
- package/native/cmd/ttsc-typia/compare_functional_union_membership_transform_test.go +434 -0
- package/native/cmd/ttsc-typia/compare_template_literal_union_transform_test.go +241 -0
- package/native/cmd/ttsc-typia/create_assert_error_factory_arity_test.go +309 -0
- package/native/cmd/ttsc-typia/default_library_spoof_native_identity_transform_test.go +216 -0
- package/native/cmd/ttsc-typia/json_schema_dynamic_key_determinism_transform_test.go +246 -0
- package/native/cmd/ttsc-typia/json_stringify_contextual_undefined_transform_test.go +556 -0
- package/native/cmd/ttsc-typia/lib_replacement_native_identity_transform_test.go +277 -0
- package/native/cmd/ttsc-typia/local_function_named_like_typia_operation_transform_test.go +185 -0
- package/native/cmd/ttsc-typia/native_named_intersection_union_transform_test.go +390 -0
- package/native/cmd/ttsc-typia/node_buffer_native_exports_is_transform_test.go +526 -0
- package/native/cmd/ttsc-typia/package_declaration_native_identity_is_transform_test.go +293 -0
- package/native/cmd/ttsc-typia/protobuf_diagnostic_code_transform_test.go +167 -0
- package/native/cmd/ttsc-typia/recursive_conditional_alias_name_transform_test.go +307 -0
- package/native/cmd/ttsc-typia/shadowed_typia_module_declaration_diagnostic_test.go +152 -0
- package/native/cmd/ttsc-typia/symbol_index_domain_transform_test.go +316 -0
- package/native/cmd/ttsc-typia/template_literal_type_tags_transform_test.go +1 -3
- package/native/cmd/ttsc-typia/transform.go +23 -0
- package/native/cmd/ttsc-typia/transform_helpers_test.go +166 -25
- package/native/cmd/ttsc-typia/user_global_native_identity_transform_test.go +484 -0
- package/native/core/factories/FormatCheatSheet.go +2 -2
- package/native/core/factories/MetadataCommentTagFactory.go +26 -11
- package/native/core/factories/ProtobufFactory.go +6 -1
- package/native/core/factories/factory_utility_coverage_test.go +896 -907
- package/native/core/factories/internal/metadata/MetadataHelper.go +190 -58
- package/native/core/factories/internal/metadata/emplace_metadata_object.go +25 -0
- package/native/core/factories/internal/metadata/iterate_metadata_function.go +1 -1
- package/native/core/factories/internal/metadata/iterate_metadata_intersection.go +103 -23
- package/native/core/factories/internal/metadata/iterate_metadata_map.go +3 -7
- package/native/core/factories/internal/metadata/iterate_metadata_native.go +32 -14
- package/native/core/factories/internal/metadata/iterate_metadata_set.go +3 -7
- package/native/core/factories/metadata_comment_tag_factory_coverage_test.go +2 -2
- package/native/core/programmers/RandomProgrammer.go +5 -2
- package/native/core/programmers/compare/CompareEqualProgrammer.go +27 -13
- package/native/core/programmers/helpers/FunctionProgrammer.go +6 -13
- package/native/core/programmers/helpers/StringifyJoinder.go +129 -50
- package/native/core/programmers/helpers/joiner_branch_coverage_test.go +116 -120
- package/native/core/programmers/iterate/iterate_check_coverage_test.go +76 -158
- package/native/core/programmers/iterate/iterate_utility_coverage_test.go +231 -270
- package/native/core/programmers/iterate/json_schema_object.go +49 -7
- package/native/core/programmers/iterate/json_schema_pattern_property_order_test.go +44 -0
- package/native/core/programmers/iterate/openapi_v3_downgrader.go +34 -1
- package/native/core/programmers/iterate/template_runtime_pattern.go +11 -0
- package/native/core/programmers/json/JsonStringifyProgrammer.go +47 -6
- package/native/core/programmers/llm/LlmApplicationProgrammer.go +9 -1
- package/native/core/programmers/protobuf/ProtobufMessageProgrammer.go +1 -1
- package/native/core/schemas/metadata/MetadataCollection.go +47 -14
- package/native/core/schemas/metadata/MetadataDefaultLibrary.go +81 -0
- package/native/core/schemas/metadata/MetadataObjectType.go +7 -18
- package/native/go.mod +4 -4
- package/native/transform/CallExpressionTransformer.go +167 -0
- package/native/transform/features/protobuf/ProtobufMessageTransformer.go +1 -1
- package/package.json +3 -7
- package/src/executable/FileSystemIdentity.ts +33 -0
- package/src/executable/TypiaGenerateWizard.ts +18 -12
- package/src/http.ts +18 -4
- package/src/internal/_ProtobufReader.ts +40 -11
- package/src/internal/_assertGuard.ts +13 -2
- package/src/internal/_isFormatIdnHostname.ts +5 -1
- package/src/internal/_isFormatTime.ts +19 -2
- package/src/internal/_jsonStringifyArray.ts +50 -0
- package/src/internal/_jsonStringifyElement.ts +19 -0
- package/src/internal/_jsonStringifyProperty.ts +30 -0
- package/src/internal/_llmApplicationFinalize.ts +6 -1
- package/src/internal/_randomArray.ts +42 -6
- package/src/internal/_randomFormatByte.ts +36 -4
- package/src/internal/_randomFormatDate.ts +4 -20
- package/src/internal/_randomFormatDatetime.ts +34 -20
- package/src/internal/_randomFormatDuration.ts +19 -4
- package/src/internal/_randomFormatHostname.ts +2 -2
- package/src/internal/_randomFormatIdnHostname.ts +8 -9
- package/src/internal/_randomFormatIpv4.ts +43 -3
- package/src/internal/_randomFormatIpv6.ts +67 -3
- package/src/internal/_randomFormatJsonPointer.ts +23 -3
- package/src/internal/_randomFormatRegex.ts +22 -6
- package/src/internal/_randomFormatRelativeJsonPointer.ts +23 -10
- package/src/internal/_randomFormatTime.ts +50 -12
- package/src/internal/_randomPattern.ts +4 -1
- package/src/internal/_randomStringLength.ts +61 -17
- package/src/internal/private/__notationRename.ts +1 -4
- package/src/internal/private/__randomComposition.ts +74 -0
- package/src/internal/private/__randomEpoch.ts +34 -0
- package/src/json.ts +16 -4
- package/src/module.ts +56 -22
- package/src/notations.ts +16 -4
- package/src/plain.ts +12 -3
- package/src/protobuf.ts +16 -4
- package/native/adapter/visit.go +0 -173
- package/native/adapter/visit_property_chain_edges_test.go +0 -129
- package/native/core/programmers/helpers/disable_function_programmer_declare.go +0 -10
- package/native/core/programmers/iterate/check_union_array_like.go +0 -422
- package/native/core/programmers/iterate/prune_object_properties.go +0 -105
- package/native/core/programmers/iterate/stringify_dynamic_properties.go +0 -219
- package/native/core/programmers/iterate/stringify_native.go +0 -14
- package/native/core/programmers/iterate/stringify_regular_properties.go +0 -112
- 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,185 @@
|
|
|
1
|
+
package main
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"encoding/json"
|
|
5
|
+
"os"
|
|
6
|
+
"path/filepath"
|
|
7
|
+
"strings"
|
|
8
|
+
"testing"
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
// TestLocalFunctionNamedLikeTypiaOperationTransform verifies the shadowed-typia
|
|
12
|
+
// diagnostic does not fire on a name collision (#2328).
|
|
13
|
+
//
|
|
14
|
+
// The diagnostic that reports a redeclared typia call keys off the called name,
|
|
15
|
+
// and those names are ordinary words: a project may well own its own
|
|
16
|
+
// `createAssert`, import one from an unrelated package, or augment typia with a
|
|
17
|
+
// name that only exists under one of its namespaces. Reporting any of them
|
|
18
|
+
// would break builds that are correct today, so the name alone must never be
|
|
19
|
+
// enough — the callee has to reach typia through typia's own module specifier
|
|
20
|
+
// and spell the operation in the namespace it lives in.
|
|
21
|
+
//
|
|
22
|
+
// 1. Build a project that defines a local `createAssert`, imports a `createIs`
|
|
23
|
+
// from a relative module and a `createValidate` from a package whose name
|
|
24
|
+
// merely begins with "typia", and augments typia with a root `parse` — an
|
|
25
|
+
// operation name that exists only under a namespace.
|
|
26
|
+
// 2. Require a clean no-emit build, which proves every decoy really resolves,
|
|
27
|
+
// and a project transform with no diagnostic.
|
|
28
|
+
// 3. Require the one genuine `typia.createIs` call in the same file to still
|
|
29
|
+
// be rewritten, so silence is not the transform giving up on the file.
|
|
30
|
+
func TestLocalFunctionNamedLikeTypiaOperationTransform(t *testing.T) {
|
|
31
|
+
project := localTypiaNameCollisionProject(t)
|
|
32
|
+
|
|
33
|
+
// A no-emit build reports semantic diagnostics as well as typia's own, so a
|
|
34
|
+
// decoy that silently stopped resolving fails here instead of turning the
|
|
35
|
+
// rest of this test into a tautology.
|
|
36
|
+
out, errText, code := ttscTypiaTestCapture(func() int {
|
|
37
|
+
return runBuild([]string{
|
|
38
|
+
"--cwd", project,
|
|
39
|
+
"--tsconfig", "tsconfig.json",
|
|
40
|
+
"--noEmit",
|
|
41
|
+
})
|
|
42
|
+
})
|
|
43
|
+
if code != 0 {
|
|
44
|
+
t.Fatalf("name collision fixture is not clean, got %d\nstdout=%s\nstderr=%s", code, out, errText)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
out, errText, code = ttscTypiaTestCapture(func() int {
|
|
48
|
+
return runTransform([]string{
|
|
49
|
+
"--cwd", project,
|
|
50
|
+
"--tsconfig", "tsconfig.json",
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
if code != 0 {
|
|
54
|
+
t.Fatalf("name collisions must not fail the transform, got %d\nstdout=%s\nstderr=%s", code, out, errText)
|
|
55
|
+
}
|
|
56
|
+
var result transformProjectOutput
|
|
57
|
+
if err := json.Unmarshal([]byte(out), &result); err != nil {
|
|
58
|
+
t.Fatalf("decode transform output: %v\n%s", err, out)
|
|
59
|
+
}
|
|
60
|
+
if len(result.Diagnostics) != 0 {
|
|
61
|
+
t.Fatalf("name collisions produced diagnostics: %+v", result.Diagnostics)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
js, errText, code := ttscTypiaTestCapture(func() int {
|
|
65
|
+
return runTransform([]string{
|
|
66
|
+
"--cwd", project,
|
|
67
|
+
"--tsconfig", "tsconfig.json",
|
|
68
|
+
"--file", "src/main.ts",
|
|
69
|
+
"--output", "js",
|
|
70
|
+
})
|
|
71
|
+
})
|
|
72
|
+
if code != 0 {
|
|
73
|
+
t.Fatalf("name collision fixture failed to emit: code=%d stderr=\n%s", code, errText)
|
|
74
|
+
}
|
|
75
|
+
// The genuine call becomes an inline validator; the decoys stay ordinary
|
|
76
|
+
// calls. Type arguments are erased either way, so the emitted body is the
|
|
77
|
+
// only evidence that the transform ran on one and not the others.
|
|
78
|
+
if !strings.Contains(js, `"number" === typeof`) {
|
|
79
|
+
t.Fatalf("the genuine typia call did not emit its validator:\n%s", js)
|
|
80
|
+
}
|
|
81
|
+
for _, decoy := range []string{"createAssert()", "createIs)()", "createValidate)()", "parse)(\"{}\")"} {
|
|
82
|
+
if !strings.Contains(js, decoy) {
|
|
83
|
+
t.Fatalf("decoy call %q was rewritten or lost:\n%s", decoy, js)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
func localTypiaNameCollisionProject(t *testing.T) string {
|
|
89
|
+
t.Helper()
|
|
90
|
+
dir := t.TempDir()
|
|
91
|
+
src := filepath.Join(dir, "src")
|
|
92
|
+
if err := os.MkdirAll(src, 0o755); err != nil {
|
|
93
|
+
t.Fatalf("mkdir fixture src: %v", err)
|
|
94
|
+
}
|
|
95
|
+
if err := os.WriteFile(filepath.Join(dir, "tsconfig.json"), []byte(transformDiagnosticTSConfig), 0o644); err != nil {
|
|
96
|
+
t.Fatalf("write tsconfig: %v", err)
|
|
97
|
+
}
|
|
98
|
+
ttscTypiaTestWriteFactoryStub(t, dir)
|
|
99
|
+
localTypiaNameCollisionWriteNeighborStub(t, dir)
|
|
100
|
+
for name, body := range map[string]string{
|
|
101
|
+
"helpers.ts": localTypiaNameCollisionHelpers,
|
|
102
|
+
"augmentation.ts": localTypiaNameCollisionAugmentation,
|
|
103
|
+
"main.ts": localTypiaNameCollisionSource,
|
|
104
|
+
} {
|
|
105
|
+
if err := os.WriteFile(filepath.Join(src, name), []byte(body), 0o644); err != nil {
|
|
106
|
+
t.Fatalf("write fixture %s: %v", name, err)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return dir
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// localTypiaNameCollisionWriteNeighborStub installs a package whose name merely
|
|
113
|
+
// begins with "typia" and exports an operation name typia owns. It pins the
|
|
114
|
+
// one-past-boundary of the specifier test: the call reaches the specifier check
|
|
115
|
+
// under a name that matches, and only the specifier can reject it.
|
|
116
|
+
func localTypiaNameCollisionWriteNeighborStub(t *testing.T, project string) {
|
|
117
|
+
t.Helper()
|
|
118
|
+
root := filepath.Join(project, "node_modules", "typia-neighbor")
|
|
119
|
+
if err := os.MkdirAll(root, 0o755); err != nil {
|
|
120
|
+
t.Fatalf("mkdir typia-neighbor stub: %v", err)
|
|
121
|
+
}
|
|
122
|
+
files := map[string]string{
|
|
123
|
+
"package.json": `{
|
|
124
|
+
"name": "typia-neighbor",
|
|
125
|
+
"version": "0.0.0-test",
|
|
126
|
+
"main": "./index.js",
|
|
127
|
+
"types": "./index.d.ts",
|
|
128
|
+
"exports": {
|
|
129
|
+
".": {
|
|
130
|
+
"types": "./index.d.ts",
|
|
131
|
+
"default": "./index.js"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
`,
|
|
136
|
+
"index.d.ts": "export declare function createValidate<T>(): (input: unknown) => T;\n",
|
|
137
|
+
"index.js": "exports.createValidate = () => (input) => input;\n",
|
|
138
|
+
}
|
|
139
|
+
for name, body := range files {
|
|
140
|
+
if err := os.WriteFile(filepath.Join(root, name), []byte(body), 0o644); err != nil {
|
|
141
|
+
t.Fatalf("write typia-neighbor stub %s: %v", name, err)
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const localTypiaNameCollisionHelpers = `export const createIs =
|
|
147
|
+
<T,>() =>
|
|
148
|
+
(input: unknown): input is T =>
|
|
149
|
+
input !== undefined;
|
|
150
|
+
`
|
|
151
|
+
|
|
152
|
+
// A module augmentation that adds a root-level `parse` to typia. The leading
|
|
153
|
+
// `import "typia"` makes this file a module, so the block merges with the
|
|
154
|
+
// installed typia instead of replacing it. `parse` is an operation name under
|
|
155
|
+
// the `llm` namespace and nowhere else, so a gate that matched a flat union of
|
|
156
|
+
// every namespace's names would report this call — a build that works today.
|
|
157
|
+
const localTypiaNameCollisionAugmentation = `import "typia";
|
|
158
|
+
|
|
159
|
+
declare module "typia" {
|
|
160
|
+
export function parse(text: string): unknown;
|
|
161
|
+
}
|
|
162
|
+
`
|
|
163
|
+
|
|
164
|
+
const localTypiaNameCollisionSource = `import { createValidate } from "typia-neighbor";
|
|
165
|
+
import { parse } from "typia";
|
|
166
|
+
import typia from "typia";
|
|
167
|
+
|
|
168
|
+
import "./augmentation";
|
|
169
|
+
import { createIs } from "./helpers";
|
|
170
|
+
|
|
171
|
+
export interface User {
|
|
172
|
+
id: number;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const createAssert =
|
|
176
|
+
<T,>() =>
|
|
177
|
+
(input: unknown): T =>
|
|
178
|
+
input as T;
|
|
179
|
+
|
|
180
|
+
export const localAssert = createAssert<User>();
|
|
181
|
+
export const relativeIs = createIs<User>();
|
|
182
|
+
export const neighborValidate = createValidate<User>();
|
|
183
|
+
export const augmented = parse("{}");
|
|
184
|
+
export const genuineIs = typia.createIs<User>();
|
|
185
|
+
`
|