@ttsc/unplugin 0.31.4 → 0.32.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/core/bridge/TtscProjectRecord.d.cts +8 -0
- package/lib/core/bridge/TtscProjectRecord.d.mts +8 -0
- package/lib/core/bridge/TtscProjectRecord.d.ts +8 -0
- package/lib/core/bridge/readProjectRecordFile.js +5 -1
- package/lib/core/bridge/readProjectRecordFile.js.map +1 -1
- package/lib/core/bridge/readProjectRecordFile.mjs +5 -1
- package/lib/core/bridge/readProjectRecordFile.mjs.map +1 -1
- package/lib/core/observer/WatchScope.d.cts +3 -3
- package/lib/core/observer/WatchScope.d.mts +3 -3
- package/lib/core/observer/WatchScope.d.ts +3 -3
- package/lib/core/observer/createInputObserver.d.cts +7 -8
- package/lib/core/observer/createInputObserver.d.mts +7 -8
- package/lib/core/observer/createInputObserver.d.ts +7 -8
- package/lib/core/observer/createInputObserver.js +7 -8
- package/lib/core/observer/createInputObserver.js.map +1 -1
- package/lib/core/observer/createInputObserver.mjs +7 -8
- package/lib/core/observer/createInputObserver.mjs.map +1 -1
- package/lib/core/transform/envelope/generationCaseSensitivity.d.cts +32 -0
- package/lib/core/transform/envelope/generationCaseSensitivity.d.mts +32 -0
- package/lib/core/transform/envelope/generationCaseSensitivity.d.ts +32 -0
- package/lib/core/transform/envelope/generationCaseSensitivity.js +39 -0
- package/lib/core/transform/envelope/generationCaseSensitivity.js.map +1 -0
- package/lib/core/transform/envelope/generationCaseSensitivity.mjs +37 -0
- package/lib/core/transform/envelope/generationCaseSensitivity.mjs.map +1 -0
- package/lib/core/transform/envelope/selectExternalInputPaths.js +2 -1
- package/lib/core/transform/envelope/selectExternalInputPaths.js.map +1 -1
- package/lib/core/transform/envelope/selectExternalInputPaths.mjs +2 -1
- package/lib/core/transform/envelope/selectExternalInputPaths.mjs.map +1 -1
- package/lib/core/transform/envelope/selectNotifiableAbsentInputs.js +2 -1
- package/lib/core/transform/envelope/selectNotifiableAbsentInputs.js.map +1 -1
- package/lib/core/transform/envelope/selectNotifiableAbsentInputs.mjs +2 -1
- package/lib/core/transform/envelope/selectNotifiableAbsentInputs.mjs.map +1 -1
- package/lib/core/transform/filesystem/createHostPathIdentityContext.d.cts +9 -1
- package/lib/core/transform/filesystem/createHostPathIdentityContext.d.mts +9 -1
- package/lib/core/transform/filesystem/createHostPathIdentityContext.d.ts +9 -1
- package/lib/core/transform/filesystem/createHostPathIdentityContext.js +10 -2
- package/lib/core/transform/filesystem/createHostPathIdentityContext.js.map +1 -1
- package/lib/core/transform/filesystem/createHostPathIdentityContext.mjs +10 -2
- package/lib/core/transform/filesystem/createHostPathIdentityContext.mjs.map +1 -1
- package/lib/core/transform/generation/captureTransformGeneration.js +10 -2
- package/lib/core/transform/generation/captureTransformGeneration.js.map +1 -1
- package/lib/core/transform/generation/captureTransformGeneration.mjs +10 -2
- package/lib/core/transform/generation/captureTransformGeneration.mjs.map +1 -1
- package/lib/core/transform/generation/selectPersistentHostInputs.js +2 -1
- package/lib/core/transform/generation/selectPersistentHostInputs.js.map +1 -1
- package/lib/core/transform/generation/selectPersistentHostInputs.mjs +2 -1
- package/lib/core/transform/generation/selectPersistentHostInputs.mjs.map +1 -1
- package/lib/core/transform/inputs/nativeInputPredicateState.js.map +1 -1
- package/lib/core/transform/inputs/nativeInputPredicateState.mjs.map +1 -1
- package/lib/core/transform/tracker/broker/watchBrokerSource.js +14 -0
- package/lib/core/transform/tracker/broker/watchBrokerSource.js.map +1 -1
- package/lib/core/transform/tracker/broker/watchBrokerSource.mjs +14 -0
- package/lib/core/transform/tracker/broker/watchBrokerSource.mjs.map +1 -1
- package/lib/core/transform/tracker/createHostInputMutationTracker.d.cts +7 -1
- package/lib/core/transform/tracker/createHostInputMutationTracker.d.mts +7 -1
- package/lib/core/transform/tracker/createHostInputMutationTracker.d.ts +7 -1
- package/lib/core/transform/tracker/createHostInputMutationTracker.js +28 -2
- package/lib/core/transform/tracker/createHostInputMutationTracker.js.map +1 -1
- package/lib/core/transform/tracker/createHostInputMutationTracker.mjs +28 -2
- package/lib/core/transform/tracker/createHostInputMutationTracker.mjs.map +1 -1
- package/lib/core/transform/tracker/createProjectMutationTracker.d.cts +10 -7
- package/lib/core/transform/tracker/createProjectMutationTracker.d.mts +10 -7
- package/lib/core/transform/tracker/createProjectMutationTracker.d.ts +10 -7
- package/lib/core/transform/tracker/createProjectMutationTracker.js +82 -38
- package/lib/core/transform/tracker/createProjectMutationTracker.js.map +1 -1
- package/lib/core/transform/tracker/createProjectMutationTracker.mjs +82 -38
- package/lib/core/transform/tracker/createProjectMutationTracker.mjs.map +1 -1
- package/lib/core/transform/transformTtsc.js +5 -1
- package/lib/core/transform/transformTtsc.js.map +1 -1
- package/lib/core/transform/transformTtsc.mjs +5 -1
- package/lib/core/transform/transformTtsc.mjs.map +1 -1
- package/lib/core/transform/watch/TtscWatchInputBaseline.d.cts +2 -1
- package/lib/core/transform/watch/TtscWatchInputBaseline.d.mts +2 -1
- package/lib/core/transform/watch/TtscWatchInputBaseline.d.ts +2 -1
- package/lib/core/transform/watch/isWatchInputKeyBaseline.js.map +1 -1
- package/lib/core/transform/watch/isWatchInputKeyBaseline.mjs.map +1 -1
- package/lib/core/transform/watch/notifyProjectRecord.d.cts +3 -4
- package/lib/core/transform/watch/notifyProjectRecord.d.mts +3 -4
- package/lib/core/transform/watch/notifyProjectRecord.d.ts +3 -4
- package/lib/core/transform/watch/notifyProjectRecord.js +5 -4
- package/lib/core/transform/watch/notifyProjectRecord.js.map +1 -1
- package/lib/core/transform/watch/notifyProjectRecord.mjs +5 -4
- package/lib/core/transform/watch/notifyProjectRecord.mjs.map +1 -1
- package/lib/core/transform/watch/recordedDependencyWitnesses.d.cts +30 -0
- package/lib/core/transform/watch/recordedDependencyWitnesses.d.mts +30 -0
- package/lib/core/transform/watch/recordedDependencyWitnesses.d.ts +30 -0
- package/lib/core/transform/watch/recordedDependencyWitnesses.js +51 -0
- package/lib/core/transform/watch/recordedDependencyWitnesses.js.map +1 -0
- package/lib/core/transform/watch/recordedDependencyWitnesses.mjs +49 -0
- package/lib/core/transform/watch/recordedDependencyWitnesses.mjs.map +1 -0
- package/lib/core/transform/watch/watchInputEvidenceMatchesBaseline.d.cts +1 -2
- package/lib/core/transform/watch/watchInputEvidenceMatchesBaseline.d.mts +1 -2
- package/lib/core/transform/watch/watchInputEvidenceMatchesBaseline.d.ts +1 -2
- package/lib/core/transform/watch/watchInputEvidenceMatchesBaseline.js +1 -2
- package/lib/core/transform/watch/watchInputEvidenceMatchesBaseline.js.map +1 -1
- package/lib/core/transform/watch/watchInputEvidenceMatchesBaseline.mjs +1 -2
- package/lib/core/transform/watch/watchInputEvidenceMatchesBaseline.mjs.map +1 -1
- package/lib/core/tsconfig/TsconfigReadTransaction.d.cts +11 -8
- package/lib/core/tsconfig/TsconfigReadTransaction.d.mts +11 -8
- package/lib/core/tsconfig/TsconfigReadTransaction.d.ts +11 -8
- package/lib/core/tsconfig/TsconfigReadTransaction.js +11 -8
- package/lib/core/tsconfig/TsconfigReadTransaction.js.map +1 -1
- package/lib/core/tsconfig/TsconfigReadTransaction.mjs +11 -8
- package/lib/core/tsconfig/TsconfigReadTransaction.mjs.map +1 -1
- package/lib/core/tsconfig/findDeclaredCompilerOption.d.cts +3 -2
- package/lib/core/tsconfig/findDeclaredCompilerOption.d.mts +3 -2
- package/lib/core/tsconfig/findDeclaredCompilerOption.d.ts +3 -2
- package/lib/core/tsconfig/findDeclaredCompilerOption.js +3 -2
- package/lib/core/tsconfig/findDeclaredCompilerOption.js.map +1 -1
- package/lib/core/tsconfig/findDeclaredCompilerOption.mjs +3 -2
- package/lib/core/tsconfig/findDeclaredCompilerOption.mjs.map +1 -1
- package/lib/core/tsconfig/findDeclaredFileSpecs.d.cts +3 -2
- package/lib/core/tsconfig/findDeclaredFileSpecs.d.mts +3 -2
- package/lib/core/tsconfig/findDeclaredFileSpecs.d.ts +3 -2
- package/lib/core/tsconfig/findDeclaredFileSpecs.js +3 -2
- package/lib/core/tsconfig/findDeclaredFileSpecs.js.map +1 -1
- package/lib/core/tsconfig/findDeclaredFileSpecs.mjs +3 -2
- package/lib/core/tsconfig/findDeclaredFileSpecs.mjs.map +1 -1
- package/lib/core/tsconfig/findDeclaredPaths.d.cts +3 -3
- package/lib/core/tsconfig/findDeclaredPaths.d.mts +3 -3
- package/lib/core/tsconfig/findDeclaredPaths.d.ts +3 -3
- package/lib/core/tsconfig/findDeclaredPaths.js +2 -2
- package/lib/core/tsconfig/findDeclaredPaths.mjs +2 -2
- package/lib/core/tsconfig/findDeclaredValue.d.cts +2 -1
- package/lib/core/tsconfig/findDeclaredValue.d.mts +2 -1
- package/lib/core/tsconfig/findDeclaredValue.d.ts +2 -1
- package/lib/core/tsconfig/findDeclaredValue.js +2 -1
- package/lib/core/tsconfig/findDeclaredValue.js.map +1 -1
- package/lib/core/tsconfig/findDeclaredValue.mjs +2 -1
- package/lib/core/tsconfig/findDeclaredValue.mjs.map +1 -1
- package/lib/core/tsconfig/readEffectiveTsconfigTemplateCompilerOptions.js +1 -1
- package/lib/core/tsconfig/readEffectiveTsconfigTemplateCompilerOptions.mjs +1 -1
- package/lib/core/tsconfig/readEffectiveTsconfigTemplateFileSpecs.d.cts +2 -2
- package/lib/core/tsconfig/readEffectiveTsconfigTemplateFileSpecs.d.mts +2 -2
- package/lib/core/tsconfig/readEffectiveTsconfigTemplateFileSpecs.d.ts +2 -2
- package/lib/core/tsconfig/readEffectiveTsconfigTemplateFileSpecs.js +2 -2
- package/lib/core/tsconfig/readEffectiveTsconfigTemplateFileSpecs.mjs +2 -2
- package/lib/core/tsconfig/readProjectMembershipPolicy.d.cts +3 -3
- package/lib/core/tsconfig/readProjectMembershipPolicy.d.mts +3 -3
- package/lib/core/tsconfig/readProjectMembershipPolicy.d.ts +3 -3
- package/lib/core/tsconfig/readProjectMembershipPolicy.js +4 -4
- package/lib/core/tsconfig/readProjectMembershipPolicy.mjs +4 -4
- package/package.json +4 -4
- package/src/core/bridge/TtscProjectRecord.ts +9 -0
- package/src/core/bridge/readProjectRecordFile.ts +5 -1
- package/src/core/observer/WatchScope.ts +3 -3
- package/src/core/observer/createInputObserver.ts +7 -8
- package/src/core/transform/envelope/generationCaseSensitivity.ts +46 -0
- package/src/core/transform/envelope/selectExternalInputPaths.ts +5 -1
- package/src/core/transform/envelope/selectNotifiableAbsentInputs.ts +5 -1
- package/src/core/transform/filesystem/createHostPathIdentityContext.ts +9 -1
- package/src/core/transform/generation/captureTransformGeneration.ts +10 -0
- package/src/core/transform/generation/selectPersistentHostInputs.ts +5 -1
- package/src/core/transform/inputs/nativeInputPredicateState.ts +1 -3
- package/src/core/transform/tracker/broker/watchBrokerSource.ts +14 -0
- package/src/core/transform/tracker/createHostInputMutationTracker.ts +28 -1
- package/src/core/transform/tracker/createProjectMutationTracker.ts +91 -42
- package/src/core/transform/transformTtsc.ts +5 -1
- package/src/core/transform/watch/TtscWatchInputBaseline.ts +2 -1
- package/src/core/transform/watch/isWatchInputKeyBaseline.ts +4 -2
- package/src/core/transform/watch/notifyProjectRecord.ts +5 -4
- package/src/core/transform/watch/recordedDependencyWitnesses.ts +50 -0
- package/src/core/transform/watch/watchInputEvidenceMatchesBaseline.ts +1 -2
- package/src/core/tsconfig/TsconfigReadTransaction.ts +11 -8
- package/src/core/tsconfig/findDeclaredCompilerOption.ts +3 -2
- package/src/core/tsconfig/findDeclaredFileSpecs.ts +3 -2
- package/src/core/tsconfig/findDeclaredPaths.ts +3 -3
- package/src/core/tsconfig/findDeclaredValue.ts +2 -1
- package/src/core/tsconfig/readEffectiveTsconfigTemplateCompilerOptions.ts +1 -1
- package/src/core/tsconfig/readEffectiveTsconfigTemplateFileSpecs.ts +2 -2
- package/src/core/tsconfig/readProjectMembershipPolicy.ts +4 -4
|
@@ -12,6 +12,7 @@ import { TRANSFORM_RESULT_MEMBERSHIP } from "../cache/TRANSFORM_RESULT_MEMBERSHI
|
|
|
12
12
|
import type { TtscCachedProjectTransform } from "../cache/TtscCachedProjectTransform";
|
|
13
13
|
import { refreshFilesystemClockReference } from "../clock/refreshFilesystemClockReference";
|
|
14
14
|
import { reportDivergentDelivery } from "../diagnostics/reportDivergentDelivery";
|
|
15
|
+
import { generationCaseSensitivity } from "../envelope/generationCaseSensitivity";
|
|
15
16
|
import { selectDeclaredProjectInputKeys } from "../envelope/selectDeclaredProjectInputKeys";
|
|
16
17
|
import { selectExternalInputPaths } from "../envelope/selectExternalInputPaths";
|
|
17
18
|
import { selectNotifiableAbsentInputs } from "../envelope/selectNotifiableAbsentInputs";
|
|
@@ -457,6 +458,13 @@ export async function captureTransformGeneration(props: {
|
|
|
457
458
|
clockReferenceDirectory ?? scratchDirectory,
|
|
458
459
|
props.filesystem,
|
|
459
460
|
);
|
|
461
|
+
// Every context capturing this generation below shares the generation's
|
|
462
|
+
// directory case answers, rather than each asking again (samchon/ttsc#1742).
|
|
463
|
+
const generationCase = generationCaseSensitivity({
|
|
464
|
+
filesystem: props.filesystem,
|
|
465
|
+
projectRoot,
|
|
466
|
+
result,
|
|
467
|
+
});
|
|
460
468
|
const persistentHostInputs = selectPersistentHostInputs({
|
|
461
469
|
filesystem: props.filesystem,
|
|
462
470
|
projectRoot,
|
|
@@ -518,6 +526,7 @@ export async function captureTransformGeneration(props: {
|
|
|
518
526
|
projectRoot,
|
|
519
527
|
result,
|
|
520
528
|
}),
|
|
529
|
+
generationCase,
|
|
521
530
|
)
|
|
522
531
|
: undefined;
|
|
523
532
|
compileTrace?.("bridge-tracker-lifecycle", {
|
|
@@ -566,6 +575,7 @@ export async function captureTransformGeneration(props: {
|
|
|
566
575
|
.filter((input) => !absentCandidates.has(input))
|
|
567
576
|
.map((input) => [path.resolve(input), "presence" as const]),
|
|
568
577
|
),
|
|
578
|
+
generationCase,
|
|
569
579
|
)
|
|
570
580
|
: undefined;
|
|
571
581
|
compileTrace?.("bridge-tracker-lifecycle", {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { ITtscCompilerTransformation } from "ttsc";
|
|
2
2
|
|
|
3
|
+
import { generationCaseSensitivity } from "../envelope/generationCaseSensitivity";
|
|
3
4
|
import { selectListedFiles } from "../envelope/selectListedFiles";
|
|
4
5
|
import type { TtscTransformFilesystemOperations } from "../filesystem/TtscTransformFilesystemOperations";
|
|
5
6
|
import { createHostPathIdentityContext } from "../filesystem/createHostPathIdentityContext";
|
|
@@ -43,7 +44,10 @@ export function selectPersistentHostInputs(props: {
|
|
|
43
44
|
props.temporaryTsconfig === undefined
|
|
44
45
|
)
|
|
45
46
|
return inputs;
|
|
46
|
-
const identities = createHostPathIdentityContext(
|
|
47
|
+
const identities = createHostPathIdentityContext(
|
|
48
|
+
props.filesystem,
|
|
49
|
+
generationCaseSensitivity(props),
|
|
50
|
+
);
|
|
47
51
|
const temporary =
|
|
48
52
|
props.temporaryTsconfig === undefined
|
|
49
53
|
? undefined
|
|
@@ -69,9 +69,7 @@ export function nativeInputPredicateState(
|
|
|
69
69
|
} else if (kind === "optional-file") {
|
|
70
70
|
try {
|
|
71
71
|
digest = filesystem.stat(file).isFile()
|
|
72
|
-
? hash(
|
|
73
|
-
Buffer.concat([Buffer.from("file\0"), readBytes()]),
|
|
74
|
-
)
|
|
72
|
+
? hash(Buffer.concat([Buffer.from("file\0"), readBytes()]))
|
|
75
73
|
: hash("missing\0");
|
|
76
74
|
} catch (error) {
|
|
77
75
|
if (!missing(error)) return undefined;
|
|
@@ -119,6 +119,8 @@ const registrations = new Map();
|
|
|
119
119
|
const DROPPED = 0x1 | 0x2 | 0x4 | 0x8 | 0x20 | 0x40 | 0x80;
|
|
120
120
|
const MODIFIED = 0x400 | 0x1000 | 0x2000 | 0x4000 | 0x8000;
|
|
121
121
|
const RENAMED = 0x100 | 0x200 | 0x800;
|
|
122
|
+
const CREATED = 0x100;
|
|
123
|
+
const MOVED = 0x200 | 0x800;
|
|
122
124
|
const fsevents = load();
|
|
123
125
|
let probeSequence = 0;
|
|
124
126
|
|
|
@@ -203,6 +205,8 @@ function stream(location, deliver, registration) {
|
|
|
203
205
|
const root = probe === undefined ? directory : probe.root;
|
|
204
206
|
const within = (parent, file) => file === parent || file.startsWith(parent.endsWith("/") ? parent : parent + "/");
|
|
205
207
|
const opened = { close: undefined, location: location.directory, pending: new Map(), probe, proven: probe === undefined };
|
|
208
|
+
// Anything born before this instant was not created in this stream.
|
|
209
|
+
const openedAt = Date.now();
|
|
206
210
|
const stop = fsevents.watch(root, (file, flags) => {
|
|
207
211
|
// Loss authority is independent of the path, including our own probe.
|
|
208
212
|
if ((flags & DROPPED) !== 0) {
|
|
@@ -232,6 +236,16 @@ function stream(location, deliver, registration) {
|
|
|
232
236
|
}
|
|
233
237
|
const filename = file.slice(directory.length + 1);
|
|
234
238
|
if (location.recursive !== true && filename.includes("/")) return;
|
|
239
|
+
// FSEvents keeps ItemCreated on later writes to a path it saw created, so a
|
|
240
|
+
// plain edit of a file older than this stream arrived as a rename, a
|
|
241
|
+
// membership change that replaced generations for an unrelated write. An
|
|
242
|
+
// object born before the stream opened was not created in it; its other
|
|
243
|
+
// flags decide. A removal or a rename keeps the event structural.
|
|
244
|
+
if ((flags & CREATED) !== 0 && (flags & MOVED) === 0 && (flags & MODIFIED) !== 0) {
|
|
245
|
+
try {
|
|
246
|
+
if (fs.lstatSync(file).birthtimeMs < openedAt) flags &= ~CREATED;
|
|
247
|
+
} catch {}
|
|
248
|
+
}
|
|
235
249
|
deliver((flags & MODIFIED) !== 0 && (flags & RENAMED) === 0 ? "change" : "rename", filename);
|
|
236
250
|
});
|
|
237
251
|
opened.close = () => {
|
|
@@ -114,12 +114,21 @@ export async function createHostInputMutationTracker(
|
|
|
114
114
|
* filesystem.
|
|
115
115
|
*/
|
|
116
116
|
scopes?: ReadonlyMap<string, TtscTrackedInputScope>,
|
|
117
|
+
/**
|
|
118
|
+
* The case answers of the generation this tracker watches, for its baseline
|
|
119
|
+
* (`generationCaseSensitivity`); omitted, the baseline observes for itself.
|
|
120
|
+
* An event's re-check always observes afresh.
|
|
121
|
+
*/
|
|
122
|
+
caseSensitive?: TtscTransformFilesystemOperations["caseSensitive"],
|
|
117
123
|
): Promise<TtscProjectMutationTracker> {
|
|
118
124
|
const paths =
|
|
119
125
|
(filesystem.platform ?? process.platform) === "win32"
|
|
120
126
|
? path.win32
|
|
121
127
|
: path.posix;
|
|
122
|
-
const identities = createHostPathIdentityContext(
|
|
128
|
+
const identities = createHostPathIdentityContext(
|
|
129
|
+
filesystem,
|
|
130
|
+
caseSensitive ?? filesystem.caseSensitive,
|
|
131
|
+
);
|
|
123
132
|
// The project root in both of its spellings: an input the compiler reported
|
|
124
133
|
// physically is the project's as much as one spelled as the project was
|
|
125
134
|
// named, and the root's observer is opened once, under the name.
|
|
@@ -399,6 +408,17 @@ export async function createHostInputMutationTracker(
|
|
|
399
408
|
* an event the backend could not attribute to a name may concern any input
|
|
400
409
|
* below the watched directory, so it always counts.
|
|
401
410
|
*/
|
|
411
|
+
// Whether a path names an existing object that no other name can reach:
|
|
412
|
+
// not a link, and not a file with a second hard link, whose writes could
|
|
413
|
+
// land on a tracked input without an event on its name.
|
|
414
|
+
const distinctExistingObject = (location: string): boolean => {
|
|
415
|
+
try {
|
|
416
|
+
const stats = filesystem.lstat(location);
|
|
417
|
+
return !stats.isSymbolicLink() && !(stats.isFile() && stats.nlink > 1n);
|
|
418
|
+
} catch {
|
|
419
|
+
return false;
|
|
420
|
+
}
|
|
421
|
+
};
|
|
402
422
|
const classify = (
|
|
403
423
|
directory: string,
|
|
404
424
|
filename: string | null,
|
|
@@ -477,6 +497,13 @@ export async function createHostInputMutationTracker(
|
|
|
477
497
|
return "mutation";
|
|
478
498
|
}
|
|
479
499
|
}
|
|
500
|
+
// An object that exists now resolves to its own identity under every alias,
|
|
501
|
+
// so one that is neither a link nor a second name of a file, and resolves
|
|
502
|
+
// to nothing tracked above, is a different object. A recursive backend
|
|
503
|
+
// (macOS, Windows) hears every write below the project root, and
|
|
504
|
+
// withdrawing authority for each sent every later delivery past its
|
|
505
|
+
// notifications.
|
|
506
|
+
if (distinctExistingObject(changed)) return undefined;
|
|
480
507
|
// A missing native alias cannot be recovered by current realpath. Neither
|
|
481
508
|
// ASCII spelling nor OS name proves this event unrelated to a tracked path.
|
|
482
509
|
// Keep exact metadata validation without inventing a membership mutation.
|
|
@@ -36,11 +36,14 @@ import { watchLocationIdentity } from "./watchLocationIdentity";
|
|
|
36
36
|
* recorded-state validation supplies the actual verdict. Content witnesses
|
|
37
37
|
* preserve captured native input aliases, then reject only an observed normal
|
|
38
38
|
* directory excluded in both lexical and native spellings. Unknown, missing and
|
|
39
|
-
* linked ancestry remains conservative. Membership rejection
|
|
40
|
-
* notification authority
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
39
|
+
* linked ancestry remains conservative. Membership rejection withdraws
|
|
40
|
+
* notification authority except below such a proven excluded directory, so a
|
|
41
|
+
* recursive backend's writes to a cache or output tree cost no proof, nor does
|
|
42
|
+
* an edit to an existing unlinked file whose every name the program cannot
|
|
43
|
+
* admit (samchon/ttsc#1737). Named events also compare current native identity
|
|
44
|
+
* and case policy with the retained identity transaction. Retargeting withdraws
|
|
45
|
+
* notification authority without changing the meaning of earlier recorded event
|
|
46
|
+
* spellings.
|
|
44
47
|
*
|
|
45
48
|
* @evidence contracts/common.md#principled-implementation
|
|
46
49
|
* The project walk and membership policy own structural relevance; content
|
|
@@ -48,8 +51,8 @@ import { watchLocationIdentity } from "./watchLocationIdentity";
|
|
|
48
51
|
* A lexical nonmatch is uncertainty rather than native alias exclusion.
|
|
49
52
|
* Changed native identity premises also withdraw notification proof while
|
|
50
53
|
* membership and content witnesses keep their independent classifications.
|
|
51
|
-
* Content exclusion
|
|
52
|
-
* spellings; captured native input aliases remain content witnesses.
|
|
54
|
+
* Content and membership exclusion require normal directory identity and both
|
|
55
|
+
* policy spellings; captured native input aliases remain content witnesses.
|
|
53
56
|
* @evidence contracts/common.md#clear-and-simple-design
|
|
54
57
|
* One root, directory index and filter set define the tracker; broker and local
|
|
55
58
|
* paths share those decisions rather than duplicating backend-specific policies.
|
|
@@ -145,6 +148,73 @@ export async function createProjectMutationTracker(
|
|
|
145
148
|
.filter((directory) => directory.relevant)
|
|
146
149
|
.map((directory) => paths.resolve(directory.path)),
|
|
147
150
|
);
|
|
151
|
+
// Whether an event path lies below a directory the walk excludes, proven by
|
|
152
|
+
// an observed normal directory excluded in both its lexical and its native
|
|
153
|
+
// spelling. A missing ancestor, one outside the root, or a link before that
|
|
154
|
+
// directory proves nothing. Content stops at the excluded directory, since a
|
|
155
|
+
// captured input reached through a deeper link is already caught by its
|
|
156
|
+
// identity above. Membership has no identity to catch a new file created
|
|
157
|
+
// through such a link (`node_modules/linked -> src`), so for it the whole
|
|
158
|
+
// path must be links-free.
|
|
159
|
+
const excludedFromWalk = (changed: string, wholePath: boolean): boolean => {
|
|
160
|
+
const relative = paths.relative(root, paths.dirname(changed));
|
|
161
|
+
if (
|
|
162
|
+
relative === ".." ||
|
|
163
|
+
relative.startsWith(".." + paths.sep) ||
|
|
164
|
+
paths.isAbsolute(relative)
|
|
165
|
+
)
|
|
166
|
+
return false;
|
|
167
|
+
let directory = root;
|
|
168
|
+
let excluded = false;
|
|
169
|
+
for (const component of relative.split(paths.sep).filter(Boolean)) {
|
|
170
|
+
directory = paths.join(directory, component);
|
|
171
|
+
try {
|
|
172
|
+
const before = filesystem.lstat(directory);
|
|
173
|
+
if (!before.isDirectory() || before.isSymbolicLink()) return false;
|
|
174
|
+
const physical = filesystem.realpath(directory);
|
|
175
|
+
const after = filesystem.lstat(directory);
|
|
176
|
+
if (
|
|
177
|
+
!after.isDirectory() ||
|
|
178
|
+
after.isSymbolicLink() ||
|
|
179
|
+
before.dev !== after.dev ||
|
|
180
|
+
before.ino !== after.ino
|
|
181
|
+
)
|
|
182
|
+
return false;
|
|
183
|
+
if (
|
|
184
|
+
!excluded &&
|
|
185
|
+
!isProjectWalkDirectory(directory, policy, filesystem.platform) &&
|
|
186
|
+
!isProjectWalkDirectory(physical, policy, filesystem.platform)
|
|
187
|
+
) {
|
|
188
|
+
if (!wholePath) return true;
|
|
189
|
+
excluded = true;
|
|
190
|
+
}
|
|
191
|
+
} catch {
|
|
192
|
+
// Missing/deleted ancestors and unknown native spellings remain events.
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return excluded;
|
|
197
|
+
};
|
|
198
|
+
// Whether an event names an existing file no spelling can make a program
|
|
199
|
+
// member: a regular file with no second hard link, whose own and physical
|
|
200
|
+
// names are both names the program cannot admit. A directory alias can move
|
|
201
|
+
// a file into the program but cannot rename it, and a removed name, a link
|
|
202
|
+
// or a directory stays conservative.
|
|
203
|
+
const existingNonProgramFile = (changed: string): boolean => {
|
|
204
|
+
try {
|
|
205
|
+
const stats = filesystem.lstat(changed);
|
|
206
|
+
if (!stats.isFile() || stats.nlink > 1n) return false;
|
|
207
|
+
return (
|
|
208
|
+
!isPossibleProgramFileName(paths.basename(changed), policy) &&
|
|
209
|
+
!isPossibleProgramFileName(
|
|
210
|
+
paths.basename(filesystem.realpath(changed)),
|
|
211
|
+
policy,
|
|
212
|
+
)
|
|
213
|
+
);
|
|
214
|
+
} catch {
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
217
|
+
};
|
|
148
218
|
const reportsMembership = (location: string, filename: string): boolean => {
|
|
149
219
|
const changed = paths.join(location, filename);
|
|
150
220
|
const current = createHostPathIdentityContext(filesystem);
|
|
@@ -169,8 +239,19 @@ export async function createProjectMutationTracker(
|
|
|
169
239
|
filesystem,
|
|
170
240
|
);
|
|
171
241
|
// Current realpath cannot identify a deleted alias. Policy checks only
|
|
172
|
-
// lexical spellings, so rejection cannot establish unchanged program state
|
|
173
|
-
|
|
242
|
+
// lexical spellings, so rejection cannot establish unchanged program state,
|
|
243
|
+
// except below a directory the walk provably excludes. A recursive backend
|
|
244
|
+
// (macOS, Windows) hears every write under the root, a cache or an output
|
|
245
|
+
// directory among them, and withdrawing authority for each sent every later
|
|
246
|
+
// delivery to the whole-snapshot proof. An existing file whose every name
|
|
247
|
+
// the program cannot admit is no member either, a stylesheet or an asset
|
|
248
|
+
// edited in a source directory among them, on every backend.
|
|
249
|
+
if (
|
|
250
|
+
!membership &&
|
|
251
|
+
!excludedFromWalk(changed, true) &&
|
|
252
|
+
!existingNonProgramFile(changed)
|
|
253
|
+
)
|
|
254
|
+
tracker.unverified = true;
|
|
174
255
|
return membership;
|
|
175
256
|
};
|
|
176
257
|
// Content belongs to the walk too. A recursive native backend can report
|
|
@@ -201,39 +282,7 @@ export async function createProjectMutationTracker(
|
|
|
201
282
|
tracker.unverified = true;
|
|
202
283
|
return true;
|
|
203
284
|
}
|
|
204
|
-
|
|
205
|
-
if (
|
|
206
|
-
relative === ".." ||
|
|
207
|
-
relative.startsWith(".." + paths.sep) ||
|
|
208
|
-
paths.isAbsolute(relative)
|
|
209
|
-
)
|
|
210
|
-
return true;
|
|
211
|
-
let directory = root;
|
|
212
|
-
for (const component of relative.split(paths.sep).filter(Boolean)) {
|
|
213
|
-
directory = paths.join(directory, component);
|
|
214
|
-
try {
|
|
215
|
-
const before = filesystem.lstat(directory);
|
|
216
|
-
if (!before.isDirectory() || before.isSymbolicLink()) return true;
|
|
217
|
-
const physical = filesystem.realpath(directory);
|
|
218
|
-
const after = filesystem.lstat(directory);
|
|
219
|
-
if (
|
|
220
|
-
!after.isDirectory() ||
|
|
221
|
-
after.isSymbolicLink() ||
|
|
222
|
-
before.dev !== after.dev ||
|
|
223
|
-
before.ino !== after.ino
|
|
224
|
-
)
|
|
225
|
-
return true;
|
|
226
|
-
if (
|
|
227
|
-
!isProjectWalkDirectory(directory, policy, filesystem.platform) &&
|
|
228
|
-
!isProjectWalkDirectory(physical, policy, filesystem.platform)
|
|
229
|
-
)
|
|
230
|
-
return false;
|
|
231
|
-
} catch {
|
|
232
|
-
// Missing/deleted ancestors and unknown native spellings remain events.
|
|
233
|
-
return true;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
return true;
|
|
285
|
+
return !excludedFromWalk(changed, false);
|
|
237
286
|
};
|
|
238
287
|
const reportsNewMembership = (
|
|
239
288
|
location: string,
|
|
@@ -33,6 +33,7 @@ import type { TtscTransformHooks } from "./watch/TtscTransformHooks";
|
|
|
33
33
|
import type { TtscWatchSelection } from "./watch/TtscWatchSelection";
|
|
34
34
|
import { notifyRejectedGenerationInputs } from "./watch/notifyRejectedGenerationInputs";
|
|
35
35
|
import { prepareProjectRecordDirectories } from "./watch/prepareProjectRecordDirectories";
|
|
36
|
+
import { recordedDependencyWitnesses } from "./watch/recordedDependencyWitnesses";
|
|
36
37
|
|
|
37
38
|
/**
|
|
38
39
|
* Apply the ttsc plugin transform to a single source file.
|
|
@@ -282,10 +283,13 @@ export async function transformTtsc(
|
|
|
282
283
|
cache === undefined
|
|
283
284
|
? undefined
|
|
284
285
|
: TRANSFORM_CACHE_CASE_POLICIES.get(cache)?.get(key),
|
|
286
|
+
// A cache without a list of its own takes the names the project's
|
|
287
|
+
// record carries from an earlier process (samchon/ttsc#1743).
|
|
285
288
|
witnessedDependencies:
|
|
286
289
|
cache === undefined
|
|
287
290
|
? undefined
|
|
288
|
-
: TRANSFORM_CACHE_DEPENDENCY_WITNESSES.get(cache)?.get(key)
|
|
291
|
+
: (TRANSFORM_CACHE_DEPENDENCY_WITNESSES.get(cache)?.get(key) ??
|
|
292
|
+
recordedDependencyWitnesses(hooks?.project, tsconfig)),
|
|
289
293
|
});
|
|
290
294
|
cache?.set(key, transformed);
|
|
291
295
|
}
|
|
@@ -23,7 +23,8 @@ import type { TtscWatchInputFileBaseline } from "./TtscWatchInputFileBaseline";
|
|
|
23
23
|
export interface TtscWatchInputBaseline extends TtscWatchInputFileBaseline {
|
|
24
24
|
/**
|
|
25
25
|
* Current version-one native codec facts, captured only for requested kinds.
|
|
26
|
-
* These observations do not certify a producer's identityStable flag or
|
|
26
|
+
* These observations do not certify a producer's identityStable flag or
|
|
27
|
+
* scope.
|
|
27
28
|
*/
|
|
28
29
|
nativePredicates?: Partial<
|
|
29
30
|
Record<
|
|
@@ -115,9 +115,11 @@ function isNativePredicateBaselines(value: unknown): boolean {
|
|
|
115
115
|
stableStringify(Object.keys(state).sort()) !==
|
|
116
116
|
stableStringify(["digest", "realpath"]) ||
|
|
117
117
|
!isContentHash(state.digest) ||
|
|
118
|
-
!(
|
|
118
|
+
!(
|
|
119
|
+
state.realpath === null ||
|
|
119
120
|
(typeof state.realpath === "string" &&
|
|
120
|
-
isAbsoluteFilesystemPath(state.realpath))
|
|
121
|
+
isAbsoluteFilesystemPath(state.realpath))
|
|
122
|
+
)
|
|
121
123
|
) {
|
|
122
124
|
return false;
|
|
123
125
|
}
|
|
@@ -73,10 +73,9 @@ const HANDED = new WeakMap<
|
|
|
73
73
|
* loses acceptance and enters persistence again without rereading generation
|
|
74
74
|
* inputs. Hosts and bridge readers own current byte proof, including concurrent
|
|
75
75
|
* changes and unreadable/torn bytes; availability here cannot exclude removal
|
|
76
|
-
* after the check. A host that keeps no
|
|
77
|
-
*
|
|
78
|
-
*
|
|
79
|
-
* (`TtscProjectRegistration.digest`).
|
|
76
|
+
* after the check. A host that keeps no snapshot of the file, Rollup's cache,
|
|
77
|
+
* is handed the digest of the bytes written for the generation to compare
|
|
78
|
+
* against instead (`TtscProjectRegistration.digest`).
|
|
80
79
|
*
|
|
81
80
|
* A record lives below the host's tool directory, or, when that cannot be
|
|
82
81
|
* written, below the fallback the host accepts (`fallbackToolDirectory`,
|
|
@@ -226,7 +225,9 @@ function recordOf(
|
|
|
226
225
|
cached: TtscCachedProjectTransform,
|
|
227
226
|
inputs: readonly TtscWatchInput[],
|
|
228
227
|
): TtscProjectRecord {
|
|
228
|
+
const dependencies = cached.externalDependencyInputs ?? [];
|
|
229
229
|
const record: TtscProjectRecord = {
|
|
230
|
+
...(dependencies.length === 0 ? {} : { dependencies }),
|
|
230
231
|
inputs: {},
|
|
231
232
|
membership:
|
|
232
233
|
cached.projectDirectories === undefined
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { projectRecordFile } from "../../bridge/projectRecordFile";
|
|
2
|
+
import { readProjectRecordFile } from "../../bridge/readProjectRecordFile";
|
|
3
|
+
import type { TtscTransformHooks } from "./TtscTransformHooks";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* The dependency-only paths the project record of `tsconfig` carries
|
|
7
|
+
* (`TtscProjectRecord.dependencies`), for a transform cache that has no witness
|
|
8
|
+
* list of its own yet.
|
|
9
|
+
*
|
|
10
|
+
* A compile learns a plugin-reported dependency path only from its own
|
|
11
|
+
* envelope, and one it had no witness for compiles again
|
|
12
|
+
* (`onlyLearnedCompileFacts`). A transform cache keeps the paths in memory
|
|
13
|
+
* (`TRANSFORM_CACHE_DEPENDENCY_WITNESSES`), so every new cache, a dev-server
|
|
14
|
+
* start or a build process, compiled such a project twice (samchon/ttsc#1743).
|
|
15
|
+
* The record the previous process wrote names them. They only say what to read:
|
|
16
|
+
* the capture still witnesses each path afresh, a path the compile no longer
|
|
17
|
+
* reports costs one read, and one the record does not name is retried as
|
|
18
|
+
* before.
|
|
19
|
+
*
|
|
20
|
+
* @param project The host's record directories, when it keeps records.
|
|
21
|
+
* @param tsconfig The project's tsconfig, as the adapter names it.
|
|
22
|
+
* @returns The record's paths, or `undefined` when no readable record names
|
|
23
|
+
* any.
|
|
24
|
+
* @evidence contracts/common.md#principled-implementation The record is the host's persisted project state, written from a completed generation; its paths are hints that the capture re-witnesses, never certified state.
|
|
25
|
+
* @evidence contracts/common.md#clear-and-simple-design One reader selects the first readable record of the host's directories, in the order the writer tries them.
|
|
26
|
+
* @evidence contracts/common.md#prohibited-implementation-shortcuts No witness or digest is taken from the record; an unreadable or absent record supplies nothing.
|
|
27
|
+
* @evidence contracts/common.md#meaningful-documentation Native paragraphs explain the doubled first compile, the hint semantics and the absent cases.
|
|
28
|
+
* @evidence contracts/portability.md#os-neutral-implementation Record paths come from the host's own directories through `projectRecordFile`.
|
|
29
|
+
* @evidence contracts/performance.md#efficient-algorithms At most two record reads and JSON parses, only when a cache has no witness list for the key.
|
|
30
|
+
* @evidence contracts/performance.md#reuse-equivalent-work A new process reuses the dependency names the last generation's record holds instead of compiling once to learn them.
|
|
31
|
+
* @evidenceExclude contracts/performance.md#bound-retention-and-release-resources The returned list belongs to the caller; nothing is retained here.
|
|
32
|
+
*/
|
|
33
|
+
export function recordedDependencyWitnesses(
|
|
34
|
+
project: TtscTransformHooks["project"],
|
|
35
|
+
tsconfig: string,
|
|
36
|
+
): readonly string[] | undefined {
|
|
37
|
+
if (project === undefined) return undefined;
|
|
38
|
+
for (const directory of [
|
|
39
|
+
project.toolDirectory,
|
|
40
|
+
...(project.fallbackToolDirectory === undefined
|
|
41
|
+
? []
|
|
42
|
+
: [project.fallbackToolDirectory]),
|
|
43
|
+
]) {
|
|
44
|
+
const record = readProjectRecordFile(
|
|
45
|
+
projectRecordFile(directory, tsconfig),
|
|
46
|
+
);
|
|
47
|
+
if (record !== undefined) return record.dependencies;
|
|
48
|
+
}
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
@@ -10,8 +10,7 @@ import { isWatchInputKeyBaseline } from "./isWatchInputKeyBaseline";
|
|
|
10
10
|
*
|
|
11
11
|
* A codec matches only the facts the baseline actually captured. Native,
|
|
12
12
|
* listing and plugin-tree observations require their optional payloads;
|
|
13
|
-
* membership is a
|
|
14
|
-
* separate project walk and cannot match one path's baseline.
|
|
13
|
+
* membership is a separate project walk and cannot match one path's baseline.
|
|
15
14
|
*
|
|
16
15
|
* @evidence contracts/common.md#principled-implementation Identity and every recorded codec fact must agree with a validated baseline; native predicates additionally require a supported version, stable producer identity, matching raw digest and physical target. Narrow discovery facts and absent optional native/listing/tree payloads cannot establish broader observations.
|
|
17
16
|
* @evidence contracts/common.md#clear-and-simple-design Codec branches reuse the strict baseline guard and native realpath comparator, with one private refinement exposing the broader carrier.
|
|
@@ -7,14 +7,16 @@ import { resolveExtendsConfig } from "./resolveExtendsConfig";
|
|
|
7
7
|
import { resolveRealPath } from "./resolveRealPath";
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* Share config observations and contextual selections within one synchronous
|
|
10
|
+
* Share config observations and contextual selections within one synchronous
|
|
11
|
+
* read.
|
|
11
12
|
*
|
|
12
13
|
* Lexical paths own parsing and relative extends resolution. Physical paths
|
|
13
14
|
* only guard ancestry cycles. A completed selection can be borrowed when the
|
|
14
15
|
* current ancestors intersect its encountered physical identities exactly as
|
|
15
16
|
* they did originally; otherwise a different cycle cut requires evaluation.
|
|
16
17
|
* Ordered source observations travel with a completed selection, including
|
|
17
|
-
* unresolved file candidates, so reuse preserves the caller's invalidation
|
|
18
|
+
* unresolved file candidates, so reuse preserves the caller's invalidation
|
|
19
|
+
* inputs.
|
|
18
20
|
*
|
|
19
21
|
* Create a new transaction for each independent freshness observation. This
|
|
20
22
|
* owner neither validates reuse across reads nor supplies compiler diagnostics.
|
|
@@ -94,12 +96,13 @@ export class TsconfigReadTransaction {
|
|
|
94
96
|
/**
|
|
95
97
|
* Select one declaration, preserving its lexical directory and observations.
|
|
96
98
|
*
|
|
97
|
-
* An undefined own selection inherits. Null masks inheritance without
|
|
98
|
-
* a value, as an invalid own file list does; a parent ignores that
|
|
99
|
-
* First queries search later bases first; last queries visit
|
|
100
|
-
* The caller's physical ancestor set is copied once and
|
|
101
|
-
* Selectors must preserve the parsed inputs and give the same
|
|
102
|
-
* the same source; query reuse does not repeat their
|
|
99
|
+
* An undefined own selection inherits. Null masks inheritance without
|
|
100
|
+
* supplying a value, as an invalid own file list does; a parent ignores that
|
|
101
|
+
* empty result. First queries search later bases first; last queries visit
|
|
102
|
+
* all bases forward. The caller's physical ancestor set is copied once and
|
|
103
|
+
* never mutated. Selectors must preserve the parsed inputs and give the same
|
|
104
|
+
* declaration for the same source; query reuse does not repeat their
|
|
105
|
+
* incidental effects.
|
|
103
106
|
*
|
|
104
107
|
* @evidence contracts/common.md#principled-implementation A completed answer is reusable only when its encountered physical identities have the same intersection with current ancestry. That preserves every observed cycle decision, including cuts; own declarations and first/last traversal retain lexical origins and key-specific precedence.
|
|
105
108
|
* @evidence contracts/common.md#clear-and-simple-design A query-local visitor owns selection and contextual completed answers; transaction nodes separately share lexical source, identity and edge observations across keys.
|
|
@@ -6,8 +6,9 @@ import { findDeclaredValue } from "./findDeclaredValue";
|
|
|
6
6
|
*
|
|
7
7
|
* Own key presence is significant even for null or undefined values; the caller
|
|
8
8
|
* decides whether the selected option value is usable. An optional
|
|
9
|
-
* decoded-source map or graph transaction belongs to one caller read;
|
|
10
|
-
* option searches retain their selectors and physical ancestry
|
|
9
|
+
* decoded-source map or graph transaction belongs to one caller read;
|
|
10
|
+
* independent option searches retain their selectors and physical ancestry
|
|
11
|
+
* contexts.
|
|
11
12
|
*
|
|
12
13
|
* @evidence contracts/common.md#principled-implementation
|
|
13
14
|
* A wrapper preserves key presence through the generic selector, so the own
|
|
@@ -13,8 +13,9 @@ import { TsconfigReadTransaction } from "./TsconfigReadTransaction";
|
|
|
13
13
|
* anchored at the named declaring config, including independent link aliases.
|
|
14
14
|
*
|
|
15
15
|
* @returns The list and its directory, undefined when no array is selected, or
|
|
16
|
-
* null when the root config cannot be read as an object. A supplied
|
|
17
|
-
* belongs to this freshness observation; later reads require a
|
|
16
|
+
* null when the root config cannot be read as an object. A supplied
|
|
17
|
+
* transaction belongs to this freshness observation; later reads require a
|
|
18
|
+
* fresh owner.
|
|
18
19
|
* @evidence contracts/common.md#principled-implementation
|
|
19
20
|
* Own invalid values stop inheritance at that node. Forward inherited
|
|
20
21
|
* traversal keeps the last array and ignores empty selections, preserving
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { TsconfigReadTransaction } from "./TsconfigReadTransaction";
|
|
2
1
|
import type { IDeclaredPaths } from "./IDeclaredPaths";
|
|
2
|
+
import { TsconfigReadTransaction } from "./TsconfigReadTransaction";
|
|
3
3
|
import { findDeclaredValue } from "./findDeclaredValue";
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -7,8 +7,8 @@ import { findDeclaredValue } from "./findDeclaredValue";
|
|
|
7
7
|
* rooted at `tsconfig`. The own config wins over its bases; within an `extends`
|
|
8
8
|
* array, later entries win over earlier ones. `seen` breaks circular chains;
|
|
9
9
|
* the compiler reports the actual config error. Optional decoded sources or
|
|
10
|
-
* graph observations share only within the caller's current read; physical
|
|
11
|
-
* guards remain branch-local.
|
|
10
|
+
* graph observations share only within the caller's current read; physical
|
|
11
|
+
* cycle guards remain branch-local.
|
|
12
12
|
*
|
|
13
13
|
* @evidence contracts/common.md#principled-implementation
|
|
14
14
|
* The selector accepts a non-array paths record and the shared value reader
|
|
@@ -7,7 +7,8 @@ import { TsconfigReadTransaction } from "./TsconfigReadTransaction";
|
|
|
7
7
|
* remain anchored at the named config; physical identity only cuts branch
|
|
8
8
|
* cycles. Independent aliases can therefore resolve different relative bases.
|
|
9
9
|
* Missing or malformed configs remain best-effort absence; the compiler owns
|
|
10
|
-
* configuration diagnostics. Unresolved file candidates remain observed
|
|
10
|
+
* configuration diagnostics. Unresolved file candidates remain observed
|
|
11
|
+
* inputs.
|
|
11
12
|
*
|
|
12
13
|
* A supplied transaction shares source, identity and edge observations across
|
|
13
14
|
* keys. A decoded-source map remains supported for callers that own that map;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
|
|
3
|
-
import { TsconfigReadTransaction } from "./TsconfigReadTransaction";
|
|
4
3
|
import { CONFIG_DIR_TEMPLATE_LIST_OPTIONS } from "./CONFIG_DIR_TEMPLATE_LIST_OPTIONS";
|
|
5
4
|
import { CONFIG_DIR_TEMPLATE_SCALAR_OPTIONS } from "./CONFIG_DIR_TEMPLATE_SCALAR_OPTIONS";
|
|
5
|
+
import { TsconfigReadTransaction } from "./TsconfigReadTransaction";
|
|
6
6
|
import { absolutizePathsTarget } from "./absolutizePathsTarget";
|
|
7
7
|
import { findDeclaredCompilerOption } from "./findDeclaredCompilerOption";
|
|
8
8
|
import { findDeclaredPaths } from "./findDeclaredPaths";
|
|
@@ -15,8 +15,8 @@ const CONFIG_DIR_TEMPLATE_FILE_SPECS = ["exclude", "files", "include"] as const;
|
|
|
15
15
|
* Lists use the compiler's last-inherited-array rule: a later base declaring
|
|
16
16
|
* null cannot erase an earlier array. Invalid elements are preserved so this
|
|
17
17
|
* overlay does not hide the compiler's configuration diagnostics. The three
|
|
18
|
-
* list searches share graph observations only within this call; a later call
|
|
19
|
-
* current bytes in a fresh transaction.
|
|
18
|
+
* list searches share graph observations only within this call; a later call
|
|
19
|
+
* reads current bytes in a fresh transaction.
|
|
20
20
|
*
|
|
21
21
|
* @param configDir The directory `${configDir}` stands for, as
|
|
22
22
|
* `readEffectiveTsconfigTemplateCompilerOptions` takes it.
|
|
@@ -2,9 +2,9 @@ import path from "node:path";
|
|
|
2
2
|
|
|
3
3
|
import { TYPESCRIPT_TRANSFORM_EXTENSIONS } from "../source/TYPESCRIPT_TRANSFORM_EXTENSIONS";
|
|
4
4
|
import type { ITtscProjectMembershipPolicy } from "./ITtscProjectMembershipPolicy";
|
|
5
|
-
import { TsconfigReadTransaction } from "./TsconfigReadTransaction";
|
|
6
5
|
import { JAVASCRIPT_INPUT_EXTENSIONS } from "./JAVASCRIPT_INPUT_EXTENSIONS";
|
|
7
6
|
import { OUTPUT_DIRECTORY_OPTIONS } from "./OUTPUT_DIRECTORY_OPTIONS";
|
|
7
|
+
import { TsconfigReadTransaction } from "./TsconfigReadTransaction";
|
|
8
8
|
import { absolutizePathsTarget } from "./absolutizePathsTarget";
|
|
9
9
|
import { findDeclaredFileSpecs } from "./findDeclaredFileSpecs";
|
|
10
10
|
import { findDeclaredValue } from "./findDeclaredValue";
|
|
@@ -40,9 +40,9 @@ const DEFAULT_INCLUDE_SPEC = "**/*";
|
|
|
40
40
|
* refuses to guess in the direction that loses correctness.
|
|
41
41
|
*
|
|
42
42
|
* Source, identity and extends observations share this transaction. Completed
|
|
43
|
-
* selections, including absence, require matching physical ancestry
|
|
44
|
-
* Later calls start fresh, so unchanged metadata cannot conceal
|
|
45
|
-
* text or resolution.
|
|
43
|
+
* selections, including absence, require matching physical ancestry
|
|
44
|
+
* intersections. Later calls start fresh, so unchanged metadata cannot conceal
|
|
45
|
+
* changed source text or resolution.
|
|
46
46
|
*
|
|
47
47
|
* @evidence contracts/common.md#principled-implementation
|
|
48
48
|
* Config-derived root specs, allowed extensions and exclusion provenance
|