ttsc 0.27.0 → 0.28.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/cmd/graphbench/main.go +26 -16
- package/cmd/graphdump/main.go +37 -12
- package/cmd/graphdump/run_declares_the_capability_its_output_carries_test.go +137 -0
- package/cmd/graphdump/run_reports_an_unknown_flag_without_exiting_the_process_test.go +56 -0
- package/cmd/graphdump/run_reports_an_unloadable_project_without_printing_a_dump_test.go +46 -0
- package/cmd/ttsc/api_transform.go +17 -6
- package/cmd/ttscgraph/dump.go +43 -11
- package/cmd/ttscgraph/run_dump_claims_artifacts_only_when_it_asked_test.go +135 -0
- package/cmd/ttscgraph/run_dump_declares_the_capability_its_output_carries_test.go +96 -0
- package/cmd/ttscgraph/serve.go +253 -25
- package/cmd/ttscgraph/serve_adopts_a_republished_artifact_set_test.go +348 -0
- package/cmd/ttscgraph/serve_projects_an_artifact_no_source_owns_test.go +90 -0
- package/cmd/ttscgraph/serve_shards.go +31 -9
- package/driver/config_discovery.go +121 -0
- package/driver/emit_plugin.go +57 -8
- package/driver/plugins.go +125 -14
- package/driver/transform_dependencies.go +283 -0
- package/driver/transform_dependencies_declares_every_file_without_a_contributor_test.go +28 -0
- package/driver/transform_dependencies_drops_a_self_reported_dependency_test.go +21 -0
- package/driver/transform_dependencies_keys_a_reported_path_like_the_envelope_test.go +46 -0
- package/driver/transform_dependencies_requires_every_contributor_to_declare_test.go +38 -0
- package/driver/transform_dependencies_stays_silent_for_an_undeclared_contributor_test.go +23 -0
- package/driver/transform_dependencies_withdraws_completeness_after_an_unusable_dependency_test.go +37 -0
- package/internal/graph/artifacts.go +230 -0
- package/internal/graph/artifacts_index_what_a_plugin_published_test.go +154 -0
- package/internal/graph/artifacts_survive_a_partial_rebuild_test.go +89 -0
- package/internal/graph/build.go +35 -0
- package/internal/graph/build_releases_the_scratch_it_no_longer_reads_test.go +118 -0
- package/internal/graph/doc_refs_are_the_use_the_checker_already_counts_test.go +93 -0
- package/internal/graph/doc_refs_resolve_documentation_links_test.go +335 -0
- package/internal/graph/doc_tags.go +416 -0
- package/internal/graph/doc_tags_are_claimed_before_they_are_read_test.go +131 -0
- package/internal/graph/doc_tags_capture_every_unrecognized_tag_test.go +165 -0
- package/internal/graph/doc_tags_read_only_what_the_parser_attached_test.go +97 -0
- package/internal/graph/doc_tags_stop_at_the_external_boundary_test.go +59 -0
- package/internal/graph/doc_tags_survive_line_endings_and_repeated_blocks_test.go +146 -0
- package/internal/graph/dump.go +60 -13
- package/internal/graph/dump_checkout_paths_are_stable_test.go +2 -2
- package/internal/graph/dump_paths.go +2 -2
- package/internal/graph/dump_paths_are_portable_and_injective_test.go +1 -1
- package/internal/graph/edge_kinds_names_every_declared_kind_test.go +49 -0
- package/internal/graph/edges.go +1 -0
- package/internal/graph/graph.go +79 -4
- package/internal/graph/provenance.go +29 -2
- package/lib/compiler/internal/project/createNativeProjectContextArgs.d.ts +9 -0
- package/lib/compiler/internal/project/createNativeProjectContextArgs.js +16 -4
- package/lib/compiler/internal/project/createNativeProjectContextArgs.js.map +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/lib/index.js.map +1 -1
- package/lib/launcher/internal/runtimeHooks.d.ts +10 -2
- package/lib/launcher/internal/runtimeHooks.js +93 -2
- package/lib/launcher/internal/runtimeHooks.js.map +1 -1
- package/lib/plugin/internal/capabilityResolutionCache.d.ts +76 -0
- package/lib/plugin/internal/capabilityResolutionCache.js +224 -0
- package/lib/plugin/internal/capabilityResolutionCache.js.map +1 -0
- package/lib/plugin/resolveCapabilityPlugins.d.ts +55 -0
- package/lib/plugin/resolveCapabilityPlugins.js +118 -0
- package/lib/plugin/resolveCapabilityPlugins.js.map +1 -0
- package/lib/structures/ITtscCompilerTransformation.d.ts +7 -0
- package/package.json +8 -8
- package/shim/ast/parent.go +16 -3
- package/shim/checker/enums_gen.go +11 -0
- package/shim/checker/shim.go +3 -0
- package/shim/compiler/emithook.go +10 -0
- package/src/compiler/internal/project/createNativeProjectContextArgs.ts +19 -4
- package/src/index.ts +1 -0
- package/src/launcher/internal/runtimeHooks.ts +111 -2
- package/src/plugin/internal/capabilityResolutionCache.ts +305 -0
- package/src/plugin/resolveCapabilityPlugins.ts +171 -0
- package/src/structures/ITtscCompilerTransformation.ts +7 -0
- package/tools/shim_audit/baseline.json +0 -1
- package/utility/host.go +15 -6
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
package graph
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"os"
|
|
5
|
+
"regexp"
|
|
6
|
+
"slices"
|
|
7
|
+
"testing"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
// TestEdgeKindsNamesEveryDeclaredKind verifies that EdgeKinds returns exactly the
|
|
11
|
+
// EdgeKind constants this package declares.
|
|
12
|
+
//
|
|
13
|
+
// EdgeKinds exists so a consumer reporting per-kind numbers can seed every family
|
|
14
|
+
// rather than only the ones a particular project contains. That guarantee is only
|
|
15
|
+
// worth having if the list cannot fall behind the constants: a kind added to the
|
|
16
|
+
// block and not to the list is reported as absent rather than as zero, which is
|
|
17
|
+
// the defect the list was introduced to end. Go has no reflection over a const
|
|
18
|
+
// block, so the declarations are read from the source that makes them.
|
|
19
|
+
//
|
|
20
|
+
// 1. Read the EdgeKind constant block from graph.go.
|
|
21
|
+
// 2. Collect every declared wire value.
|
|
22
|
+
// 3. Assert EdgeKinds returns that set, with no extra and no missing member.
|
|
23
|
+
func TestEdgeKindsNamesEveryDeclaredKind(t *testing.T) {
|
|
24
|
+
source, err := os.ReadFile("graph.go")
|
|
25
|
+
if err != nil {
|
|
26
|
+
t.Fatal(err)
|
|
27
|
+
}
|
|
28
|
+
matches := regexp.MustCompile(`(?m)^\s*Edge\w+ EdgeKind = "([a-z-]+)"`).
|
|
29
|
+
FindAllStringSubmatch(string(source), -1)
|
|
30
|
+
if len(matches) == 0 {
|
|
31
|
+
t.Fatal("no EdgeKind constant declarations were found in graph.go")
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
declared := make([]string, 0, len(matches))
|
|
35
|
+
for _, match := range matches {
|
|
36
|
+
declared = append(declared, match[1])
|
|
37
|
+
}
|
|
38
|
+
returned := make([]string, 0, len(EdgeKinds()))
|
|
39
|
+
for _, kind := range EdgeKinds() {
|
|
40
|
+
returned = append(returned, string(kind))
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
slices.Sort(declared)
|
|
44
|
+
slices.Sort(returned)
|
|
45
|
+
if !slices.Equal(declared, returned) {
|
|
46
|
+
t.Fatalf("EdgeKinds returns %v, but graph.go declares %v; a kind missing "+
|
|
47
|
+
"from the list is reported as absent rather than as zero", returned, declared)
|
|
48
|
+
}
|
|
49
|
+
}
|
package/internal/graph/edges.go
CHANGED
|
@@ -31,6 +31,7 @@ func (g *Graph) addEdges(prog *driver.Program, selected map[string]bool, partial
|
|
|
31
31
|
g.collectHeritage(checker, file)
|
|
32
32
|
g.collectCalls(checker, file)
|
|
33
33
|
g.collectTypeRefs(checker, file)
|
|
34
|
+
g.collectDocRefs(checker, file)
|
|
34
35
|
g.collectLiterals(checker, file)
|
|
35
36
|
if file.Statements != nil {
|
|
36
37
|
g.collectDecorators(file.FileName(), file.Statements.Nodes)
|
package/internal/graph/graph.go
CHANGED
|
@@ -24,6 +24,18 @@ const (
|
|
|
24
24
|
// imports from. A barrel declares nothing, so this is the only node it has,
|
|
25
25
|
// and it is the node a package.json entry path resolves to.
|
|
26
26
|
NodeModule NodeKind = "module"
|
|
27
|
+
// The artifact kinds. These are not declarations and they are not this
|
|
28
|
+
// Program's facts: a plugin materialized them from a Markdown document, a
|
|
29
|
+
// Prisma schema, or an API document, and the graph indexes what it was handed
|
|
30
|
+
// without interpreting any of it. Their ids are the address a citation names
|
|
31
|
+
// rather than the `path#name:kind` grammar, which is why a consumer parsing an
|
|
32
|
+
// id gates on the kind first.
|
|
33
|
+
NodeMarkdownDocument NodeKind = "markdown_document"
|
|
34
|
+
NodeMarkdownSection NodeKind = "markdown_section"
|
|
35
|
+
NodePrismaModel NodeKind = "prisma_model"
|
|
36
|
+
NodePrismaColumn NodeKind = "prisma_column"
|
|
37
|
+
NodePrismaRelation NodeKind = "prisma_relation"
|
|
38
|
+
NodeSwaggerOperation NodeKind = "swagger_operation"
|
|
27
39
|
)
|
|
28
40
|
|
|
29
41
|
// Node is one declared symbol. Its ID is position-invariant, built from the file
|
|
@@ -39,10 +51,22 @@ type Node struct {
|
|
|
39
51
|
// (`"a.b"` → Name `C.a.b`), so the simple/qualified boundary cannot be
|
|
40
52
|
// recovered from Name by splitting on a dot. Recording it here keeps the dump
|
|
41
53
|
// split exact instead of guessing.
|
|
42
|
-
Simple
|
|
43
|
-
Kind
|
|
44
|
-
File
|
|
45
|
-
|
|
54
|
+
Simple string
|
|
55
|
+
Kind NodeKind
|
|
56
|
+
File string
|
|
57
|
+
// ArtifactLine is the 1-based line a published artifact starts on, and is 0
|
|
58
|
+
// for every declaration — a declaration carries a real span, resolved from the
|
|
59
|
+
// compiler, and does not need this. It exists because an artifact has no AST
|
|
60
|
+
// position to take a span from: the plugin that parsed the document reports
|
|
61
|
+
// where the heading is, and that single number is the whole span an index
|
|
62
|
+
// carries. The section's content is read from the file when someone needs it,
|
|
63
|
+
// exactly as a function body is.
|
|
64
|
+
ArtifactLine int
|
|
65
|
+
// ArtifactParent is the id of the artifact containing this one — a section's
|
|
66
|
+
// document or enclosing section, a column's model. Empty for every
|
|
67
|
+
// declaration, whose containment the TypeScript memory layer synthesizes.
|
|
68
|
+
ArtifactParent string
|
|
69
|
+
External bool
|
|
46
70
|
// Exported marks a node that is part of its module's export surface, resolved
|
|
47
71
|
// through the checker's export table so a re-export (`export { Foo } from`) or
|
|
48
72
|
// a barrel (`export *`) counts, not only an inline `export` modifier. It is
|
|
@@ -163,6 +187,19 @@ const (
|
|
|
163
187
|
// type it mentions (a parameter, return, property, or alias type). It is not a
|
|
164
188
|
// runtime call, so an impact query can filter value edges from type edges.
|
|
165
189
|
EdgeTypeRef EdgeKind = "type-ref"
|
|
190
|
+
// EdgeDocRef is a reference from a declaration to a symbol its own
|
|
191
|
+
// documentation names through an inline link. The checker resolves the name
|
|
192
|
+
// and counts it as a use — an import that exists only to support one survives
|
|
193
|
+
// `noUnusedLocals` — so the relationship is a compiler fact like every other
|
|
194
|
+
// edge here, and it was the one class of resolved reference the graph held no
|
|
195
|
+
// edge for.
|
|
196
|
+
//
|
|
197
|
+
// It is its own kind rather than a type-ref because it is not a type
|
|
198
|
+
// position: a link may name a function, and a consumer filtering type edges
|
|
199
|
+
// from value edges would be told a documentation mention is one or the other
|
|
200
|
+
// when it is neither. The tag around the link decides nothing; a link under
|
|
201
|
+
// `@evidence`, under `@see`, or in ordinary prose is one relation.
|
|
202
|
+
EdgeDocRef EdgeKind = "doc-ref"
|
|
166
203
|
// EdgeExports runs from a module to a declaration its export table resolves
|
|
167
204
|
// to, through re-exports and barrels. It records which surface a symbol is
|
|
168
205
|
// public on, which the Exported flag cannot: a package's front door and its
|
|
@@ -170,6 +207,24 @@ const (
|
|
|
170
207
|
EdgeExports EdgeKind = "exports"
|
|
171
208
|
)
|
|
172
209
|
|
|
210
|
+
// EdgeKinds returns every kind Build can put on an edge, in declaration order.
|
|
211
|
+
//
|
|
212
|
+
// A consumer that reports per-kind numbers needs the whole vocabulary rather
|
|
213
|
+
// than the subset a particular project happens to contain: counting only what
|
|
214
|
+
// was seen makes the reported shape depend on the project measured, and a
|
|
215
|
+
// family that dropped to zero disappears instead of reading zero.
|
|
216
|
+
func EdgeKinds() []EdgeKind {
|
|
217
|
+
return []EdgeKind{
|
|
218
|
+
EdgeHeritage,
|
|
219
|
+
EdgeMemberRelation,
|
|
220
|
+
EdgeValueCall,
|
|
221
|
+
EdgeValueAccess,
|
|
222
|
+
EdgeTypeRef,
|
|
223
|
+
EdgeDocRef,
|
|
224
|
+
EdgeExports,
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
173
228
|
// Edge is a directed, checker-resolved relationship from one node to another,
|
|
174
229
|
// both referenced by Node.ID. File, Pos, and End bound the source expression
|
|
175
230
|
// that produced the edge. File is empty when the From node names it and is set
|
|
@@ -204,6 +259,26 @@ type Graph struct {
|
|
|
204
259
|
// re-parsing source. It is dump-only metadata, separate from Edges so the
|
|
205
260
|
// existing checker-resolved relationships are untouched.
|
|
206
261
|
Decorators []*Decorator
|
|
262
|
+
// DocTags holds the documentation tags TypeScript does not recognize, written
|
|
263
|
+
// on the workspace's declarations and captured verbatim so the JSON dump can
|
|
264
|
+
// attach them to each target node. A convention that attaches a declaration to
|
|
265
|
+
// something outside the type system — a specification section, an API
|
|
266
|
+
// operation, a reference document — writes it here and nowhere the graph could
|
|
267
|
+
// otherwise see. Dump-only metadata, separate from Edges for the same reason
|
|
268
|
+
// Decorators is.
|
|
269
|
+
DocTags []*DocTag
|
|
270
|
+
// docTagPositions deduplicates DocTags by where each tag is written, so a
|
|
271
|
+
// declaration presented to putDeclaredNode more than once contributes its tags
|
|
272
|
+
// once. Build-only, like bodyNodes.
|
|
273
|
+
docTagPositions map[docTagKey]struct{}
|
|
274
|
+
// docHosts are the declarations the node pass found documentation on, paired
|
|
275
|
+
// with the node it attributed them to and keyed by their file. The edge pass
|
|
276
|
+
// resolves documentation links from this set rather than from a walk of its
|
|
277
|
+
// own, so both halves of a citation cover the same declarations, and it asks
|
|
278
|
+
// per file so a project's whole documented population is never rescanned for
|
|
279
|
+
// each one. Build-only.
|
|
280
|
+
docHosts map[string][]docHost
|
|
281
|
+
docHostPositions map[docTagKey]struct{}
|
|
207
282
|
// bodyNodes tracks whether a callable node's display span is the overload
|
|
208
283
|
// implementation rather than an overload signature. It is build-only metadata
|
|
209
284
|
// and intentionally stays out of JSON dumps.
|
|
@@ -15,7 +15,7 @@ import (
|
|
|
15
15
|
// field is added, removed, or given a new meaning, independently of the serve
|
|
16
16
|
// envelope's protocol version: a one-shot `ttscgraph dump` written to a file has
|
|
17
17
|
// a schema but never rode the protocol.
|
|
18
|
-
const DumpSchemaVersion =
|
|
18
|
+
const DumpSchemaVersion = 8
|
|
19
19
|
|
|
20
20
|
// The capabilities a snapshot can declare. Each names one class of evidence a
|
|
21
21
|
// consumer may rely on when, and only when, the snapshot lists it.
|
|
@@ -26,6 +26,13 @@ const (
|
|
|
26
26
|
// CapabilitySourceDigests means Sources covers every file the program
|
|
27
27
|
// loaded, each with the digest of the text the checker read.
|
|
28
28
|
CapabilitySourceDigests = "sourceDigests"
|
|
29
|
+
// CapabilityArtifactNodes means the producer asked the project's configured
|
|
30
|
+
// plugins for the artifacts a citation can name, so a dump carrying none is a
|
|
31
|
+
// project that publishes none rather than a producer that never looked. The
|
|
32
|
+
// two states are otherwise the same absent nodes, and a consumer honouring the
|
|
33
|
+
// difference is the whole reason a capability is declared rather than
|
|
34
|
+
// inferred.
|
|
35
|
+
CapabilityArtifactNodes = "artifactNodes"
|
|
29
36
|
// CapabilityDiskDigests means Sources also carries each file's on-disk
|
|
30
37
|
// digest, so an empty one genuinely means the file could not be read.
|
|
31
38
|
//
|
|
@@ -37,6 +44,15 @@ const (
|
|
|
37
44
|
// CapabilityDiagnostics means Diagnostics is the compiler's complete
|
|
38
45
|
// findings for this generation, as opposed to not having been collected.
|
|
39
46
|
CapabilityDiagnostics = "diagnostics"
|
|
47
|
+
// CapabilityDocTags means every node carries the documentation tags
|
|
48
|
+
// TypeScript does not recognize, so an absent `docTags` genuinely means the
|
|
49
|
+
// declaration carries none.
|
|
50
|
+
//
|
|
51
|
+
// It is a separate claim rather than an inference from emptiness for the
|
|
52
|
+
// reason CapabilityDiskDigests is: a producer built before the field existed
|
|
53
|
+
// emits nothing, and a consumer reading that as "this declaration cites
|
|
54
|
+
// nothing" would answer a citation question with a confident, wrong "no".
|
|
55
|
+
CapabilityDocTags = "docTags"
|
|
40
56
|
)
|
|
41
57
|
|
|
42
58
|
// Provenance is the snapshot's evidence about the program that produced it.
|
|
@@ -67,6 +83,17 @@ type Provenance struct {
|
|
|
67
83
|
// Producer identifies the binary and the checker behind the facts.
|
|
68
84
|
Producer Producer `json:"producer"`
|
|
69
85
|
|
|
86
|
+
// ArtifactProducer identifies the second producer behind the artifact nodes,
|
|
87
|
+
// and is absent when the dump carries none.
|
|
88
|
+
//
|
|
89
|
+
// Every other fact here came from one Program. These did not: a plugin parsed
|
|
90
|
+
// documents this Program never read, in a process of its own, and saying so is
|
|
91
|
+
// what keeps the dump's one-generation contract honest instead of letting an
|
|
92
|
+
// overlay ride the same claim as the compiler's facts. A consumer that must
|
|
93
|
+
// not mix the two reads this field; one that only answers "what does this
|
|
94
|
+
// address name" does not care.
|
|
95
|
+
ArtifactProducer *Producer `json:"artifactProducer,omitempty"`
|
|
96
|
+
|
|
70
97
|
// Universe fingerprints the inputs that decide which files are in the
|
|
71
98
|
// program at all, as opposed to what is inside them.
|
|
72
99
|
Universe Universe `json:"universe"`
|
|
@@ -219,7 +246,7 @@ func TypescriptVersion() string { return shimcore.Version() }
|
|
|
219
246
|
|
|
220
247
|
// NewProvenance assembles the evidence for a snapshot while retaining the
|
|
221
248
|
// compiler's physical paths. NewDump projects those paths together with every
|
|
222
|
-
// node, edge, span, and diagnostic through its one cached
|
|
249
|
+
// node, edge, span, and diagnostic through its one cached path mapper.
|
|
223
250
|
// texts maps a source file's path to the text the checker read (as SourceTexts
|
|
224
251
|
// returns it); disk maps that path to the hex digest of its on-disk bytes, and
|
|
225
252
|
// a path absent from it is reported with an empty Disk. configs and roots come
|
|
@@ -1,3 +1,12 @@
|
|
|
1
1
|
import type { ITtscParsedProjectConfig } from "../../../structures/internal/ITtscParsedProjectConfig";
|
|
2
2
|
/** Serialize the retained project identity for a native sidecar invocation. */
|
|
3
3
|
export declare function createNativeProjectContextArgs(project: ITtscParsedProjectConfig, pluginConfigOrigin?: string): string[];
|
|
4
|
+
/**
|
|
5
|
+
* The identity payload itself, for a caller that spawns a sidecar without going
|
|
6
|
+
* through the compiler's own argument list.
|
|
7
|
+
*
|
|
8
|
+
* Split from the flag so there is still exactly one place that decides what a
|
|
9
|
+
* sidecar is told about the project. A second caller assembling the same JSON,
|
|
10
|
+
* or slicing it back out of the flag, is how the two drift.
|
|
11
|
+
*/
|
|
12
|
+
export declare function createNativeProjectContextJson(project: ITtscParsedProjectConfig, pluginConfigOrigin?: string): string;
|
|
@@ -1,14 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createNativeProjectContextArgs = createNativeProjectContextArgs;
|
|
4
|
+
exports.createNativeProjectContextJson = createNativeProjectContextJson;
|
|
4
5
|
/** Serialize the retained project identity for a native sidecar invocation. */
|
|
5
6
|
function createNativeProjectContextArgs(project, pluginConfigOrigin) {
|
|
6
7
|
return [
|
|
7
8
|
"--project-context-json=" +
|
|
8
|
-
|
|
9
|
-
...project.identity,
|
|
10
|
-
...(pluginConfigOrigin === undefined ? {} : { pluginConfigOrigin }),
|
|
11
|
-
}),
|
|
9
|
+
createNativeProjectContextJson(project, pluginConfigOrigin),
|
|
12
10
|
];
|
|
13
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* The identity payload itself, for a caller that spawns a sidecar without going
|
|
14
|
+
* through the compiler's own argument list.
|
|
15
|
+
*
|
|
16
|
+
* Split from the flag so there is still exactly one place that decides what a
|
|
17
|
+
* sidecar is told about the project. A second caller assembling the same JSON,
|
|
18
|
+
* or slicing it back out of the flag, is how the two drift.
|
|
19
|
+
*/
|
|
20
|
+
function createNativeProjectContextJson(project, pluginConfigOrigin) {
|
|
21
|
+
return JSON.stringify({
|
|
22
|
+
...project.identity,
|
|
23
|
+
...(pluginConfigOrigin === undefined ? {} : { pluginConfigOrigin }),
|
|
24
|
+
});
|
|
25
|
+
}
|
|
14
26
|
//# sourceMappingURL=createNativeProjectContextArgs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createNativeProjectContextArgs.js","sourceRoot":"","sources":["../../../../src/compiler/internal/project/createNativeProjectContextArgs.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"createNativeProjectContextArgs.js","sourceRoot":"","sources":["../../../../src/compiler/internal/project/createNativeProjectContextArgs.ts"],"names":[],"mappings":";;;;AAEA,+EAA+E;AAC/E,wCACE,OAAiC,EACjC,kBAA2B;IAE3B,OAAO;QACL,yBAAyB;YACvB,8BAA8B,CAAC,OAAO,EAAE,kBAAkB,CAAC;KAC9D,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,wCACE,OAAiC,EACjC,kBAA2B;IAE3B,OAAO,IAAI,CAAC,SAAS,CAAC;QACpB,GAAG,OAAO,CAAC,QAAQ;QACnB,GAAG,CAAC,kBAAkB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC;KACpE,CAAC,CAAC;AACL,CAAC"}
|
package/lib/index.d.ts
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* project parsing helpers, and native build helpers stay internal so the public
|
|
7
7
|
* package surface remains small and stable.
|
|
8
8
|
*/
|
|
9
|
+
export * from "./plugin/resolveCapabilityPlugins";
|
|
9
10
|
export * from "./TtscCompiler";
|
|
10
11
|
export * from "./TtscService";
|
|
11
12
|
export * from "./structures/index";
|
package/lib/index.js
CHANGED
|
@@ -22,6 +22,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
22
22
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
23
23
|
};
|
|
24
24
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
__exportStar(require("./plugin/resolveCapabilityPlugins"), exports);
|
|
25
26
|
__exportStar(require("./TtscCompiler"), exports);
|
|
26
27
|
__exportStar(require("./TtscService"), exports);
|
|
27
28
|
__exportStar(require("./structures/index"), exports);
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;;;;;;;;;;;;;;AAEH,iDAA+B;AAC/B,gDAA8B;AAC9B,qDAAmC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;;;;;;;;;;;;;;AAEH,oEAAkD;AAClD,iDAA+B;AAC/B,gDAA8B;AAC9B,qDAAmC"}
|
|
@@ -75,8 +75,16 @@ export interface RuntimeHookOptions {
|
|
|
75
75
|
* `require()` made from inside a CommonJS module that was itself reached
|
|
76
76
|
* through an ESM `import` (the interop translator loads it on the raw CJS
|
|
77
77
|
* path). The ESM graph goes through `registerHooks`; the CommonJS `require`
|
|
78
|
-
* graph goes through `Module._extensions` — the
|
|
79
|
-
*
|
|
78
|
+
* graph goes through `Module._extensions` and `Module._resolveFilename` — the
|
|
79
|
+
* canonical loader extension points `ts-node`/`tsx` use for the same reason.
|
|
80
|
+
*
|
|
81
|
+
* Both halves of that second graph are required, and they answer different
|
|
82
|
+
* questions. `_extensions` decides how a file that was _found_ is compiled, and
|
|
83
|
+
* Node reuses its keys when it probes an extensionless request, so
|
|
84
|
+
* `require("./x")` reaches `x.ts` for free. Nothing there resolves a request
|
|
85
|
+
* that already carries an extension: `require("./x.js")` backed only by `x.ts`
|
|
86
|
+
* is a resolution failure before any compiler is consulted, which is why the
|
|
87
|
+
* rescue is installed on `_resolveFilename` as well (samchon/ttsc#1280).
|
|
80
88
|
*/
|
|
81
89
|
export declare function installRuntimeHooks(options?: RuntimeHookOptions): void;
|
|
82
90
|
/**
|
|
@@ -182,8 +182,16 @@ let prepareRuntimeEntry;
|
|
|
182
182
|
* `require()` made from inside a CommonJS module that was itself reached
|
|
183
183
|
* through an ESM `import` (the interop translator loads it on the raw CJS
|
|
184
184
|
* path). The ESM graph goes through `registerHooks`; the CommonJS `require`
|
|
185
|
-
* graph goes through `Module._extensions` — the
|
|
186
|
-
*
|
|
185
|
+
* graph goes through `Module._extensions` and `Module._resolveFilename` — the
|
|
186
|
+
* canonical loader extension points `ts-node`/`tsx` use for the same reason.
|
|
187
|
+
*
|
|
188
|
+
* Both halves of that second graph are required, and they answer different
|
|
189
|
+
* questions. `_extensions` decides how a file that was _found_ is compiled, and
|
|
190
|
+
* Node reuses its keys when it probes an extensionless request, so
|
|
191
|
+
* `require("./x")` reaches `x.ts` for free. Nothing there resolves a request
|
|
192
|
+
* that already carries an extension: `require("./x.js")` backed only by `x.ts`
|
|
193
|
+
* is a resolution failure before any compiler is consulted, which is why the
|
|
194
|
+
* rescue is installed on `_resolveFilename` as well (samchon/ttsc#1280).
|
|
187
195
|
*/
|
|
188
196
|
function installRuntimeHooks(options = {}) {
|
|
189
197
|
if (options.prepareEntry !== undefined) {
|
|
@@ -203,6 +211,7 @@ function installRuntimeHooks(options = {}) {
|
|
|
203
211
|
}
|
|
204
212
|
(0, node_module_1.registerHooks)({ load, resolve });
|
|
205
213
|
installCommonJsHook();
|
|
214
|
+
installCommonJsResolveHook();
|
|
206
215
|
}
|
|
207
216
|
/**
|
|
208
217
|
* Register a CommonJS `require` handler for each TypeScript source extension so
|
|
@@ -219,6 +228,88 @@ function installCommonJsHook() {
|
|
|
219
228
|
extensions[extension] = compile;
|
|
220
229
|
}
|
|
221
230
|
}
|
|
231
|
+
/**
|
|
232
|
+
* Map a JavaScript spelling back to its TypeScript source on the CommonJS
|
|
233
|
+
* resolution path, so `require("./x.js")` finds `x.ts` when nothing emitted
|
|
234
|
+
* `x.js`.
|
|
235
|
+
*
|
|
236
|
+
* TypeScript asks authors to write the emitted `.js` extension in a relative
|
|
237
|
+
* specifier, so this spelling is the documented one rather than a mistake, and
|
|
238
|
+
* the ESM `resolve` hook has always rescued it. The CommonJS graph could not,
|
|
239
|
+
* and on Node 22 that graph is reached by every `require()` inside a CommonJS
|
|
240
|
+
* module the ESM loader evaluated — `module.registerHooks` sees the `import()`
|
|
241
|
+
* of that module and nothing within it. Node 24 routes the same `require`
|
|
242
|
+
* through the hooks, which is why the gap was only ever visible on the oldest
|
|
243
|
+
* runtime ttsx supports (`engines.node` is `>=22.15.0`).
|
|
244
|
+
*
|
|
245
|
+
* The wrapper only ever answers a request Node's own resolver already refused,
|
|
246
|
+
* so a resolution that succeeds is never perturbed, and a request no candidate
|
|
247
|
+
* satisfies rethrows Node's original error with its `MODULE_NOT_FOUND` code and
|
|
248
|
+
* `requireStack` intact. `require.resolve` shares this entry point and is
|
|
249
|
+
* rescued with it, except in its `{ paths }` form, which resolves against the
|
|
250
|
+
* caller's list rather than the parent this reads.
|
|
251
|
+
*/
|
|
252
|
+
function installCommonJsResolveHook() {
|
|
253
|
+
const internals = node_module_1.Module;
|
|
254
|
+
const original = internals._resolveFilename;
|
|
255
|
+
internals._resolveFilename = function resolveFilename(request, parent, isMain, options) {
|
|
256
|
+
try {
|
|
257
|
+
return original.call(this, request, parent, isMain, options);
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
const rescued = rescueCommonJsRequest(request, parent, options);
|
|
261
|
+
if (rescued === null) {
|
|
262
|
+
throw error;
|
|
263
|
+
}
|
|
264
|
+
return rescued;
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* The TypeScript source a refused CommonJS request names, or `null`.
|
|
270
|
+
*
|
|
271
|
+
* Only a relative or absolute request can be rescued: a bare specifier is a
|
|
272
|
+
* package lookup, whose own resolver already probed every extension the
|
|
273
|
+
* installed `_extensions` keys declare.
|
|
274
|
+
*
|
|
275
|
+
* Two shapes decline before that. `_resolveFilename` is an internal entry point
|
|
276
|
+
* anything may call, so a non-string request reaches here as readily as a
|
|
277
|
+
* specifier does, and reading it would replace Node's own argument error with a
|
|
278
|
+
* `TypeError` from this file. And `require.resolve(request, { paths })`
|
|
279
|
+
* resolves against the caller's list, which this rescue does not consult, so
|
|
280
|
+
* answering it from the parent's directory would be a different question's
|
|
281
|
+
* answer.
|
|
282
|
+
*/
|
|
283
|
+
function rescueCommonJsRequest(request, parent, options) {
|
|
284
|
+
if (typeof request !== "string") {
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
287
|
+
if (typeof options === "object" &&
|
|
288
|
+
options !== null &&
|
|
289
|
+
Array.isArray(options.paths)) {
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
let base;
|
|
293
|
+
if (node_path_1.default.isAbsolute(request)) {
|
|
294
|
+
base = request;
|
|
295
|
+
}
|
|
296
|
+
else if (isRelativeSpecifier(request)) {
|
|
297
|
+
const from = parent?.filename;
|
|
298
|
+
if (typeof from !== "string") {
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
base = node_path_1.default.resolve(node_path_1.default.dirname(from), request);
|
|
302
|
+
}
|
|
303
|
+
else {
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
for (const candidate of typescriptSourcesForJavaScriptSpecifier(base)) {
|
|
307
|
+
if (isFile(candidate)) {
|
|
308
|
+
return candidate;
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
222
313
|
/**
|
|
223
314
|
* The module format of the entry source file, derived from the entry project's
|
|
224
315
|
* compiler options (via the runtime manifest) the same way the served files are
|