ttsc 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/cmd/ttsc/compiler_argument_cwd_test.go +38 -38
- package/cmd/ttscserver/main.go +2 -12
- package/cmd/ttscserver/resolve_launch_uses_native_flag_authority_test.go +7 -7
- package/driver/lsp.go +4 -43
- package/driver/rewrite.go +1 -1
- package/internal/e2etrace/completion_hints.go +3 -3
- package/internal/e2etrace/completion_hints_test.go +26 -12
- package/internal/graph/build.go +5 -6
- package/internal/graph/graph.go +3 -3
- package/internal/graph/line_model.go +2 -35
- package/internal/lspserver/lsp_clean_didopen_refreshes_compiler_state_test.go +13 -36
- package/internal/lspserver/lsp_hints_refresh_ignores_a_superseded_generation_test.go +9 -3
- package/internal/lspserver/lsp_plugin.go +19 -0
- package/internal/lspserver/lsp_proxy.go +9 -129
- package/internal/lspserver/lsp_server.go +0 -8
- package/internal/lspserver/lsp_watched_file_changes_reach_compiler_caches_test.go +6 -36
- package/internal/sourceprocess/windows_target_owns_suspended_admission_test.go +5 -5
- package/lib/compiler/internal/build/BuildExecution.js +11 -3
- package/lib/compiler/internal/build/BuildExecution.js.map +1 -1
- package/lib/compiler/internal/build/TsgoArguments.js.map +1 -1
- package/lib/compiler/internal/project/CompilerProjectSelection.d.ts +9 -8
- package/lib/compiler/internal/project/CompilerProjectSelection.js +11 -9
- package/lib/compiler/internal/project/CompilerProjectSelection.js.map +1 -1
- package/lib/compiler/internal/project/resolveOwningProjectConfig.d.ts +20 -8
- package/lib/compiler/internal/project/resolveOwningProjectConfig.js +21 -12
- package/lib/compiler/internal/project/resolveOwningProjectConfig.js.map +1 -1
- package/lib/compiler/internal/runSingleFileEmit.d.ts +5 -4
- package/lib/compiler/internal/runSingleFileEmit.js +5 -4
- package/lib/compiler/internal/runSingleFileEmit.js.map +1 -1
- package/lib/flags/ParseOptions.d.ts +2 -2
- package/lib/internal/E2ETrace.d.ts +1 -0
- package/lib/internal/E2ETrace.js.map +1 -1
- package/lib/internal/OwnedNativeProcess.d.ts +2 -2
- package/lib/internal/OwnedNativeProcess.js +2 -2
- package/lib/internal/SourceNativeRetirement.d.ts +8 -7
- package/lib/internal/SourceNativeRetirement.js +19 -10
- package/lib/internal/SourceNativeRetirement.js.map +1 -1
- package/lib/internal/TtsxNodeOptions.d.ts +79 -0
- package/lib/internal/TtsxNodeOptions.js +121 -0
- package/lib/internal/TtsxNodeOptions.js.map +1 -0
- package/lib/internal/javascriptRuntimeCapabilities.js +4 -1
- package/lib/internal/javascriptRuntimeCapabilities.js.map +1 -1
- package/lib/internal/parseWindowsDirectoryCaseSensitivity.d.ts +5 -5
- package/lib/internal/parseWindowsDirectoryCaseSensitivity.js +5 -5
- package/lib/internal/pathIdentity/createCaseSensitivityObservations.d.ts +35 -0
- package/lib/internal/pathIdentity/createCaseSensitivityObservations.js +209 -0
- package/lib/internal/pathIdentity/createCaseSensitivityObservations.js.map +1 -0
- package/lib/internal/pathIdentity/createFilesystemPathIdentityContext.js +2 -143
- package/lib/internal/pathIdentity/createFilesystemPathIdentityContext.js.map +1 -1
- package/lib/internal/probeLocalProcess.d.ts +5 -1
- package/lib/internal/probeLocalProcess.js +9 -7
- package/lib/internal/probeLocalProcess.js.map +1 -1
- package/lib/internal/projectInputPathIdentity.d.ts +1 -0
- package/lib/internal/projectInputPathIdentity.js +1 -0
- package/lib/internal/projectInputPathIdentity.js.map +1 -1
- package/lib/launcher/internal/parseTtsxCLI.d.ts +5 -4
- package/lib/launcher/internal/parseTtsxCLI.js +5 -4
- package/lib/launcher/internal/parseTtsxCLI.js.map +1 -1
- package/lib/launcher/internal/prepareExecution.js.map +1 -1
- package/lib/launcher/internal/resolveSingleFileOutput.d.ts +8 -9
- package/lib/launcher/internal/resolveSingleFileOutput.js +8 -9
- package/lib/launcher/internal/resolveSingleFileOutput.js.map +1 -1
- package/lib/launcher/internal/runTtsc.js +5 -5
- package/lib/launcher/internal/runTtsx.js +5 -2
- package/lib/launcher/internal/runTtsx.js.map +1 -1
- package/lib/launcher/internal/runtime/ProcessOwnedDirectory.d.ts +2 -0
- package/lib/launcher/internal/runtime/ProcessOwnedDirectory.js +2 -1
- package/lib/launcher/internal/runtime/ProcessOwnedDirectory.js.map +1 -1
- package/lib/launcher/internal/runtime/RuntimeEntrySources.d.ts +40 -0
- package/lib/launcher/internal/runtime/RuntimeEntrySources.js +57 -0
- package/lib/launcher/internal/runtime/RuntimeEntrySources.js.map +1 -0
- package/lib/launcher/internal/runtime/RuntimeProjectOwnership.d.ts +5 -4
- package/lib/launcher/internal/runtime/RuntimeProjectOwnership.js +8 -6
- package/lib/launcher/internal/runtime/RuntimeProjectOwnership.js.map +1 -1
- package/lib/launcher/internal/runtime/commonJsExportNames.d.ts +2 -1
- package/lib/launcher/internal/runtime/commonJsExportNames.js +2 -1
- package/lib/launcher/internal/runtime/commonJsExportNames.js.map +1 -1
- package/lib/launcher/internal/runtime/installRuntimeHooks.js +35 -9
- package/lib/launcher/internal/runtime/installRuntimeHooks.js.map +1 -1
- package/lib/launcher/internal/runtime/isLocalProcessGone.d.ts +1 -1
- package/lib/launcher/internal/runtime/isLocalProcessGone.js +4 -4
- package/lib/launcher/internal/runtime/isLocalProcessGone.js.map +1 -1
- package/lib/launcher/internal/runtime/resolveRuntimeCleanTargets.js +3 -1
- package/lib/launcher/internal/runtime/resolveRuntimeCleanTargets.js.map +1 -1
- package/lib/launcher/internal/watch/FseventsStreams.d.ts +2 -0
- package/lib/launcher/internal/watch/FseventsStreams.js +19 -0
- package/lib/launcher/internal/watch/FseventsStreams.js.map +1 -1
- package/lib/launcher/internal/watch/WatchTopology.d.ts +74 -12
- package/lib/launcher/internal/watch/WatchTopology.js +301 -92
- package/lib/launcher/internal/watch/WatchTopology.js.map +1 -1
- package/lib/launcher/internal/watch/projectInputReloadEventShouldNotify.d.ts +4 -1
- package/lib/launcher/internal/watch/projectInputReloadEventShouldNotify.js +3 -2
- package/lib/launcher/internal/watch/projectInputReloadEventShouldNotify.js.map +1 -1
- package/lib/plugin/internal/load/loadProjectPlugins.js +17 -9
- package/lib/plugin/internal/load/loadProjectPlugins.js.map +1 -1
- package/lib/plugin/internal/load/resolveNativeSource.js +2 -3
- package/lib/plugin/internal/load/resolveNativeSource.js.map +1 -1
- package/lib/plugin/internal/source/pluginModuleReplaceDirectories.d.ts +4 -1
- package/lib/plugin/internal/source/pluginModuleReplaceDirectories.js +9 -2
- package/lib/plugin/internal/source/pluginModuleReplaceDirectories.js.map +1 -1
- package/lib/structures/internal/TtscCommonOptions.d.ts +2 -2
- package/package.json +9 -9
- package/src/compiler/internal/build/BuildExecution.ts +15 -6
- package/src/compiler/internal/build/TsgoArguments.ts +4 -1
- package/src/compiler/internal/project/CompilerProjectSelection.ts +14 -14
- package/src/compiler/internal/project/resolveOwningProjectConfig.ts +29 -14
- package/src/compiler/internal/runSingleFileEmit.ts +11 -7
- package/src/flags/ParseOptions.ts +2 -2
- package/src/internal/E2ETrace.ts +5 -1
- package/src/internal/OwnedNativeProcess.ts +2 -2
- package/src/internal/SourceNativeRetirement.ts +42 -19
- package/src/internal/TtsxNodeOptions.ts +124 -0
- package/src/internal/javascriptRuntimeCapabilities.ts +6 -1
- package/src/internal/parseWindowsDirectoryCaseSensitivity.ts +5 -5
- package/src/internal/pathIdentity/createCaseSensitivityObservations.ts +242 -0
- package/src/internal/pathIdentity/createFilesystemPathIdentityContext.ts +2 -169
- package/src/internal/probeLocalProcess.ts +13 -8
- package/src/internal/projectInputPathIdentity.ts +1 -0
- package/src/launcher/internal/parseTtsxCLI.ts +5 -4
- package/src/launcher/internal/prepareExecution.ts +4 -1
- package/src/launcher/internal/resolveSingleFileOutput.ts +8 -9
- package/src/launcher/internal/runTtsc.ts +5 -5
- package/src/launcher/internal/runTtsx.ts +17 -8
- package/src/launcher/internal/runtime/ProcessOwnedDirectory.ts +5 -1
- package/src/launcher/internal/runtime/RuntimeEntrySources.ts +57 -0
- package/src/launcher/internal/runtime/RuntimeProjectOwnership.ts +23 -10
- package/src/launcher/internal/runtime/commonJsExportNames.ts +11 -4
- package/src/launcher/internal/runtime/installRuntimeHooks.ts +55 -13
- package/src/launcher/internal/runtime/isLocalProcessGone.ts +5 -3
- package/src/launcher/internal/runtime/resolveRuntimeCleanTargets.ts +17 -5
- package/src/launcher/internal/watch/FseventsStreams.ts +22 -0
- package/src/launcher/internal/watch/WatchTopology.ts +387 -99
- package/src/launcher/internal/watch/projectInputReloadEventShouldNotify.ts +14 -9
- package/src/plugin/internal/load/loadProjectPlugins.ts +17 -3
- package/src/plugin/internal/load/resolveNativeSource.ts +10 -4
- package/src/plugin/internal/source/pluginModuleReplaceDirectories.ts +10 -1
- package/src/structures/internal/TtscCommonOptions.ts +2 -2
- package/internal/graphsymbols/position_helpers_follow_ecma_line_terminators_test.go +0 -78
- package/internal/graphsymbols/provider.go +0 -650
- package/internal/lspserver/lsp_symbols.go +0 -212
|
@@ -34,14 +34,15 @@ import type { OwningModuleOptions } from "./OwningModuleOptions";
|
|
|
34
34
|
import { PluginDescriptorInputObservation } from "./PluginDescriptorInputObservation";
|
|
35
35
|
import type { ResolveResult } from "./ResolveResult";
|
|
36
36
|
import { RuntimeEmitProvenance } from "./RuntimeEmitProvenance";
|
|
37
|
+
import { RuntimeEntrySources } from "./RuntimeEntrySources";
|
|
37
38
|
import { RuntimeFilesystem } from "./RuntimeFilesystem";
|
|
38
39
|
import type { RuntimeHookOptions } from "./RuntimeHookOptions";
|
|
39
40
|
import { RuntimeIsolatedEmit } from "./RuntimeIsolatedEmit";
|
|
40
41
|
import { RuntimeLoaderCapabilities } from "./RuntimeLoaderCapabilities";
|
|
41
42
|
import type { RuntimeManifest } from "./RuntimeManifest";
|
|
42
43
|
import { RuntimeManifestRegistry } from "./RuntimeManifestRegistry";
|
|
43
|
-
import { RuntimeProjectOwnership } from "./RuntimeProjectOwnership";
|
|
44
44
|
import { RuntimeModuleFormat } from "./RuntimeModuleFormat";
|
|
45
|
+
import { RuntimeProjectOwnership } from "./RuntimeProjectOwnership";
|
|
45
46
|
import { checkNodeRuntimeSupport } from "./checkNodeRuntimeSupport";
|
|
46
47
|
import { commonJsExportNames } from "./commonJsExportNames";
|
|
47
48
|
import { commonJsImportFacade } from "./commonJsImportFacade";
|
|
@@ -390,7 +391,9 @@ function observePluginDescriptorResolutionCandidates(
|
|
|
390
391
|
appendPluginDescriptorInputs(
|
|
391
392
|
observation
|
|
392
393
|
.commit(
|
|
393
|
-
selectedURL === undefined
|
|
394
|
+
selectedURL === undefined
|
|
395
|
+
? undefined
|
|
396
|
+
: runtimeFilePath(selectedURL),
|
|
394
397
|
)
|
|
395
398
|
.map((record) => `${JSON.stringify({ parent, ...record })}\n`),
|
|
396
399
|
);
|
|
@@ -1003,13 +1006,17 @@ function servesCommonJsFromSource(url: string): boolean {
|
|
|
1003
1006
|
}
|
|
1004
1007
|
|
|
1005
1008
|
/** Scan both facade lanes from source paths using their actual require policy. */
|
|
1006
|
-
function runtimeCommonJsExportNames(
|
|
1009
|
+
function runtimeCommonJsExportNames(
|
|
1010
|
+
filename: string,
|
|
1011
|
+
source: string,
|
|
1012
|
+
): string[] {
|
|
1007
1013
|
return commonJsExportNames(
|
|
1008
1014
|
source,
|
|
1009
1015
|
filename,
|
|
1010
|
-
(target) =>
|
|
1011
|
-
|
|
1012
|
-
|
|
1016
|
+
(target) =>
|
|
1017
|
+
isTypeScriptSource(target)
|
|
1018
|
+
? emitCommonJsForNameScan(target)
|
|
1019
|
+
: readFileOrNull(target),
|
|
1013
1020
|
(parent, specifier) => {
|
|
1014
1021
|
const native = createRequire(parent).resolve;
|
|
1015
1022
|
return resolveCommonJsRequest(native, specifier, undefined, parent);
|
|
@@ -1227,20 +1234,20 @@ function resolveServedSource(
|
|
|
1227
1234
|
prepareAsEntry: boolean = false,
|
|
1228
1235
|
): ServedSource {
|
|
1229
1236
|
const real = realPath(filename);
|
|
1230
|
-
let served =
|
|
1237
|
+
let served = serveInlinedEntryEmit(real, prepareAsEntry);
|
|
1231
1238
|
if (served !== null) {
|
|
1232
|
-
return
|
|
1239
|
+
return served;
|
|
1233
1240
|
}
|
|
1234
1241
|
// Only the public preload can prepare a newly discovered root; direct ttsx
|
|
1235
1242
|
// prepared its one entry before the child started.
|
|
1236
1243
|
const prepareEntry = prepareAsEntry ? prepareRuntimeEntry : undefined;
|
|
1237
1244
|
if (prepareEntry !== undefined) {
|
|
1238
1245
|
RuntimeManifestRegistry.registerManifest(prepareEntry(real));
|
|
1239
|
-
served =
|
|
1246
|
+
served = serveInlinedEntryEmit(real, true);
|
|
1240
1247
|
if (served === null) {
|
|
1241
1248
|
throw new Error(`ttsx: prepared entry emit not found for ${filename}`);
|
|
1242
1249
|
}
|
|
1243
|
-
return
|
|
1250
|
+
return served;
|
|
1244
1251
|
}
|
|
1245
1252
|
const built = serveProjectEmit(real);
|
|
1246
1253
|
if (built !== null) {
|
|
@@ -1723,10 +1730,36 @@ class RuntimeEmitOwnershipError extends Error {}
|
|
|
1723
1730
|
* next lane and run something else.
|
|
1724
1731
|
*/
|
|
1725
1732
|
function serveEntryEmit(real: string): ServedSource | null {
|
|
1733
|
+
const owner = RuntimeManifestRegistry.findEntryEmit(real);
|
|
1734
|
+
return owner === null ? null : entryEmitSource(owner, real);
|
|
1735
|
+
}
|
|
1736
|
+
|
|
1737
|
+
/**
|
|
1738
|
+
* {@link serveEntryEmit} with the emit's source map inlined, as a module load
|
|
1739
|
+
* serves it. A checked entry build's emit is immutable for the run, so an entry
|
|
1740
|
+
* load, which Node 22.15 repeats for the process entry, reads and source-maps
|
|
1741
|
+
* each emitted file once (`RuntimeEntrySources`, samchon/ttsc#1749). Other
|
|
1742
|
+
* modules are not remembered: Node keeps each loaded module, and holding every
|
|
1743
|
+
* served text beside it would retain the whole program's emit.
|
|
1744
|
+
*/
|
|
1745
|
+
function serveInlinedEntryEmit(
|
|
1746
|
+
real: string,
|
|
1747
|
+
entry: boolean,
|
|
1748
|
+
): ServedSource | null {
|
|
1726
1749
|
const owner = RuntimeManifestRegistry.findEntryEmit(real);
|
|
1727
1750
|
if (owner === null) {
|
|
1728
1751
|
return null;
|
|
1729
1752
|
}
|
|
1753
|
+
const prepare = () => withInlineSourceMap(entryEmitSource(owner, real));
|
|
1754
|
+
return entry
|
|
1755
|
+
? RuntimeEntrySources.serve(owner.manifest, owner.emittedFile, prepare)
|
|
1756
|
+
: prepare();
|
|
1757
|
+
}
|
|
1758
|
+
|
|
1759
|
+
function entryEmitSource(
|
|
1760
|
+
owner: NonNullable<ReturnType<typeof RuntimeManifestRegistry.findEntryEmit>>,
|
|
1761
|
+
real: string,
|
|
1762
|
+
): ServedSource {
|
|
1730
1763
|
return {
|
|
1731
1764
|
emittedFile: owner.emittedFile,
|
|
1732
1765
|
moduleOptions: owner.manifest.moduleOptions ?? {},
|
|
@@ -2339,16 +2372,25 @@ function owningTsconfig(real: string): string | null {
|
|
|
2339
2372
|
recordPluginDescriptorProjectInputs,
|
|
2340
2373
|
);
|
|
2341
2374
|
if (nearest === null) return null;
|
|
2342
|
-
//
|
|
2343
|
-
// reference roots
|
|
2344
|
-
//
|
|
2375
|
+
// The project this selects is built once per process (`ensureProjectBuilt`),
|
|
2376
|
+
// so the reference roots that select it are kept for the process as well;
|
|
2377
|
+
// re-expanding them for every module cost a compiler run per referenced
|
|
2378
|
+
// project (samchon/ttsc#1747). A file created after an expansion is still
|
|
2379
|
+
// expanded for afresh.
|
|
2345
2380
|
return resolveOwningProjectConfig({
|
|
2381
|
+
expansions: ownerExpansions,
|
|
2346
2382
|
file: real,
|
|
2347
2383
|
onConfig: (config) => recordPluginDescriptorProjectInputs([config]),
|
|
2348
2384
|
tsconfig: nearest,
|
|
2349
2385
|
});
|
|
2350
2386
|
}
|
|
2351
2387
|
|
|
2388
|
+
/** Reference roots `owningTsconfig` expanded in this process, by config. */
|
|
2389
|
+
const ownerExpansions = new Map<
|
|
2390
|
+
string,
|
|
2391
|
+
{ files: readonly string[]; takenAt: number }
|
|
2392
|
+
>();
|
|
2393
|
+
|
|
2352
2394
|
function readFileOrNull(file: string | null): string | null {
|
|
2353
2395
|
if (file === null) {
|
|
2354
2396
|
return null;
|
|
@@ -40,14 +40,16 @@ export function isLocalProcessGone(
|
|
|
40
40
|
observe?: (
|
|
41
41
|
result: "remote" | "present" | "absent" | "unknown",
|
|
42
42
|
errorCode?: string,
|
|
43
|
+
state?: string,
|
|
43
44
|
) => void,
|
|
44
45
|
): boolean {
|
|
45
46
|
const report = (
|
|
46
47
|
result: "remote" | "present" | "absent" | "unknown",
|
|
47
48
|
errorCode?: string,
|
|
49
|
+
state?: string,
|
|
48
50
|
): void => {
|
|
49
51
|
try {
|
|
50
|
-
observe?.(result, errorCode);
|
|
52
|
+
observe?.(result, errorCode, state);
|
|
51
53
|
} catch {
|
|
52
54
|
// Diagnostics own no policy.
|
|
53
55
|
}
|
|
@@ -56,7 +58,7 @@ export function isLocalProcessGone(
|
|
|
56
58
|
report("remote");
|
|
57
59
|
return false;
|
|
58
60
|
}
|
|
59
|
-
const { result, errorCode } = probeLocalProcess(owner.pid);
|
|
60
|
-
report(result, errorCode);
|
|
61
|
+
const { result, errorCode, state } = probeLocalProcess(owner.pid);
|
|
62
|
+
report(result, errorCode, state);
|
|
61
63
|
return result === "absent";
|
|
62
64
|
}
|
|
@@ -67,13 +67,22 @@ export function resolveRuntimeCleanTargets(cacheRoot: string): {
|
|
|
67
67
|
const removable: string[] = [];
|
|
68
68
|
for (const entry of entries) {
|
|
69
69
|
const directory = path.join(physicalRuns, entry);
|
|
70
|
-
const observe = E2ETrace.runtimeCleanup(
|
|
70
|
+
const observe = E2ETrace.runtimeCleanup(
|
|
71
|
+
directory,
|
|
72
|
+
runtime,
|
|
73
|
+
"runtime-clean-selection",
|
|
74
|
+
);
|
|
71
75
|
observe?.("selection-started");
|
|
72
76
|
let ownership: ReturnType<typeof ProcessOwnedDirectory.ownership>;
|
|
73
77
|
try {
|
|
74
|
-
ownership = ProcessOwnedDirectory.ownership(
|
|
75
|
-
|
|
76
|
-
|
|
78
|
+
ownership = ProcessOwnedDirectory.ownership(
|
|
79
|
+
directory,
|
|
80
|
+
false,
|
|
81
|
+
observe === undefined
|
|
82
|
+
? undefined
|
|
83
|
+
: (observation) =>
|
|
84
|
+
observe("owner-observation", undefined, undefined, observation),
|
|
85
|
+
);
|
|
77
86
|
} catch (cause) {
|
|
78
87
|
observe?.("selection-failed", undefined, cause);
|
|
79
88
|
throw cause;
|
|
@@ -81,7 +90,10 @@ export function resolveRuntimeCleanTargets(cacheRoot: string): {
|
|
|
81
90
|
observe?.("ownership", ownership);
|
|
82
91
|
if (ownership !== "abandoned") kept.push(directory);
|
|
83
92
|
else removable.push(directory);
|
|
84
|
-
observe?.(
|
|
93
|
+
observe?.(
|
|
94
|
+
ownership === "abandoned" ? "removal-selected" : "retention-selected",
|
|
95
|
+
ownership,
|
|
96
|
+
);
|
|
85
97
|
}
|
|
86
98
|
return {
|
|
87
99
|
kept,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { EventEmitter } from "node:events";
|
|
2
|
+
import fs from "node:fs";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
|
|
4
5
|
import type { DirectoryWatcher } from "./DirectoryWatcher";
|
|
@@ -116,6 +117,7 @@ export class FseventsStreams {
|
|
|
116
117
|
const displaced = [...(this.descendants.get(directory) ?? [])];
|
|
117
118
|
const stream: Stream = {
|
|
118
119
|
active: true,
|
|
120
|
+
openedAt: Date.now(),
|
|
119
121
|
root: directory,
|
|
120
122
|
stop: () => undefined,
|
|
121
123
|
watches: new Map(),
|
|
@@ -209,6 +211,9 @@ type Watch = {
|
|
|
209
211
|
|
|
210
212
|
type Stream = {
|
|
211
213
|
active: boolean;
|
|
214
|
+
|
|
215
|
+
/** When the stream opened; nothing born before it was created in it. */
|
|
216
|
+
openedAt: number;
|
|
212
217
|
root: string;
|
|
213
218
|
stop: () => unknown;
|
|
214
219
|
watches: Map<string, Set<Watch>>;
|
|
@@ -218,6 +223,8 @@ type Stream = {
|
|
|
218
223
|
const GAP = 0x1 | 0x2 | 0x4 | 0x8 | 0x20 | 0x40 | 0x80;
|
|
219
224
|
const MODIFIED = 0x400 | 0x1000 | 0x2000 | 0x4000 | 0x8000;
|
|
220
225
|
const RENAMED = 0x100 | 0x200 | 0x800;
|
|
226
|
+
const CREATED = 0x100;
|
|
227
|
+
const MOVED = 0x200 | 0x800;
|
|
221
228
|
|
|
222
229
|
function addWatch(stream: Stream, watch: Watch): void {
|
|
223
230
|
const watches = stream.watches.get(watch.directory) ?? new Set<Watch>();
|
|
@@ -248,6 +255,21 @@ function deliver(stream: Stream, file: string, flags: number): void {
|
|
|
248
255
|
deliverGap(stream);
|
|
249
256
|
return;
|
|
250
257
|
}
|
|
258
|
+
// FSEvents keeps ItemCreated on later writes to a path it saw created, so a
|
|
259
|
+
// plain edit of a file older than this stream arrived as a rename. An object
|
|
260
|
+
// born before the stream opened was not created in it; its other flags
|
|
261
|
+
// decide. A removal or a rename keeps the event structural.
|
|
262
|
+
if (
|
|
263
|
+
(flags & CREATED) !== 0 &&
|
|
264
|
+
(flags & MOVED) === 0 &&
|
|
265
|
+
(flags & MODIFIED) !== 0
|
|
266
|
+
) {
|
|
267
|
+
try {
|
|
268
|
+
if (fs.lstatSync(target).birthtimeMs < stream.openedAt) flags &= ~CREATED;
|
|
269
|
+
} catch {
|
|
270
|
+
// A path gone by now keeps its creation flag.
|
|
271
|
+
}
|
|
272
|
+
}
|
|
251
273
|
const event =
|
|
252
274
|
(flags & MODIFIED) !== 0 && (flags & RENAMED) === 0 ? "change" : "rename";
|
|
253
275
|
const deliveries: Array<{ name: string; watch: Watch }> = [];
|