@ttsc/unplugin 0.31.0 → 0.31.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (218) hide show
  1. package/lib/core/bun/bun.d.cts +3 -2
  2. package/lib/core/bun/bun.d.mts +3 -2
  3. package/lib/core/bun/bun.d.ts +3 -2
  4. package/lib/core/bun/bun.js +8 -4
  5. package/lib/core/bun/bun.js.map +1 -1
  6. package/lib/core/bun/bun.mjs +8 -4
  7. package/lib/core/bun/bun.mjs.map +1 -1
  8. package/lib/core/observer/createInputObserver.js +6 -5
  9. package/lib/core/observer/createInputObserver.js.map +1 -1
  10. package/lib/core/observer/createInputObserver.mjs +6 -5
  11. package/lib/core/observer/createInputObserver.mjs.map +1 -1
  12. package/lib/core/observer/openIsolatedRecursiveWatch.d.cts +11 -12
  13. package/lib/core/observer/openIsolatedRecursiveWatch.d.mts +11 -12
  14. package/lib/core/observer/openIsolatedRecursiveWatch.d.ts +11 -12
  15. package/lib/core/observer/openIsolatedRecursiveWatch.js +11 -12
  16. package/lib/core/observer/openIsolatedRecursiveWatch.js.map +1 -1
  17. package/lib/core/observer/openIsolatedRecursiveWatch.mjs +11 -12
  18. package/lib/core/observer/openIsolatedRecursiveWatch.mjs.map +1 -1
  19. package/lib/core/transform/cache/TtscCachedProjectTransform.d.cts +12 -3
  20. package/lib/core/transform/cache/TtscCachedProjectTransform.d.mts +12 -3
  21. package/lib/core/transform/cache/TtscCachedProjectTransform.d.ts +12 -3
  22. package/lib/core/transform/cache/selectCachedGenerationAction.d.cts +2 -0
  23. package/lib/core/transform/cache/selectCachedGenerationAction.d.mts +2 -0
  24. package/lib/core/transform/cache/selectCachedGenerationAction.d.ts +2 -0
  25. package/lib/core/transform/cache/selectCachedGenerationAction.js +1 -1
  26. package/lib/core/transform/cache/selectCachedGenerationAction.js.map +1 -1
  27. package/lib/core/transform/cache/selectCachedGenerationAction.mjs +1 -1
  28. package/lib/core/transform/cache/selectCachedGenerationAction.mjs.map +1 -1
  29. package/lib/core/transform/deliverCachedTransform.d.cts +36 -0
  30. package/lib/core/transform/deliverCachedTransform.d.mts +36 -0
  31. package/lib/core/transform/deliverCachedTransform.d.ts +36 -0
  32. package/lib/core/transform/deliverCachedTransform.js +73 -0
  33. package/lib/core/transform/deliverCachedTransform.js.map +1 -0
  34. package/lib/core/transform/deliverCachedTransform.mjs +71 -0
  35. package/lib/core/transform/deliverCachedTransform.mjs.map +1 -0
  36. package/lib/core/transform/envelope/selectDeclaredProjectInputKeys.d.cts +2 -2
  37. package/lib/core/transform/envelope/selectDeclaredProjectInputKeys.d.mts +2 -2
  38. package/lib/core/transform/envelope/selectDeclaredProjectInputKeys.d.ts +2 -2
  39. package/lib/core/transform/envelope/selectDeclaredProjectInputKeys.js +6 -2
  40. package/lib/core/transform/envelope/selectDeclaredProjectInputKeys.js.map +1 -1
  41. package/lib/core/transform/envelope/selectDeclaredProjectInputKeys.mjs +6 -2
  42. package/lib/core/transform/envelope/selectDeclaredProjectInputKeys.mjs.map +1 -1
  43. package/lib/core/transform/envelope/selectExternalInputPaths.d.cts +3 -5
  44. package/lib/core/transform/envelope/selectExternalInputPaths.d.mts +3 -5
  45. package/lib/core/transform/envelope/selectExternalInputPaths.d.ts +3 -5
  46. package/lib/core/transform/envelope/selectExternalInputPaths.js +8 -7
  47. package/lib/core/transform/envelope/selectExternalInputPaths.js.map +1 -1
  48. package/lib/core/transform/envelope/selectExternalInputPaths.mjs +8 -7
  49. package/lib/core/transform/envelope/selectExternalInputPaths.mjs.map +1 -1
  50. package/lib/core/transform/filesystem/TtscTransformFilesystemOperations.d.cts +15 -12
  51. package/lib/core/transform/filesystem/TtscTransformFilesystemOperations.d.mts +15 -12
  52. package/lib/core/transform/filesystem/TtscTransformFilesystemOperations.d.ts +15 -12
  53. package/lib/core/transform/generation/selectTransformAttemptDisposition.d.cts +3 -1
  54. package/lib/core/transform/generation/selectTransformAttemptDisposition.d.mts +3 -1
  55. package/lib/core/transform/generation/selectTransformAttemptDisposition.d.ts +3 -1
  56. package/lib/core/transform/generation/selectTransformAttemptDisposition.js +3 -1
  57. package/lib/core/transform/generation/selectTransformAttemptDisposition.js.map +1 -1
  58. package/lib/core/transform/generation/selectTransformAttemptDisposition.mjs +3 -1
  59. package/lib/core/transform/generation/selectTransformAttemptDisposition.mjs.map +1 -1
  60. package/lib/core/transform/generation/transformProject.d.cts +9 -7
  61. package/lib/core/transform/generation/transformProject.d.mts +9 -7
  62. package/lib/core/transform/generation/transformProject.d.ts +9 -7
  63. package/lib/core/transform/generation/transformProject.js +14 -9
  64. package/lib/core/transform/generation/transformProject.js.map +1 -1
  65. package/lib/core/transform/generation/transformProject.mjs +14 -9
  66. package/lib/core/transform/generation/transformProject.mjs.map +1 -1
  67. package/lib/core/transform/inputs/preparePluginBuildEnvironments.d.cts +11 -4
  68. package/lib/core/transform/inputs/preparePluginBuildEnvironments.d.mts +11 -4
  69. package/lib/core/transform/inputs/preparePluginBuildEnvironments.d.ts +11 -4
  70. package/lib/core/transform/inputs/preparePluginBuildEnvironments.js +44 -7
  71. package/lib/core/transform/inputs/preparePluginBuildEnvironments.js.map +1 -1
  72. package/lib/core/transform/inputs/preparePluginBuildEnvironments.mjs +44 -7
  73. package/lib/core/transform/inputs/preparePluginBuildEnvironments.mjs.map +1 -1
  74. package/lib/core/transform/tracker/broker/WatchBroker.d.cts +14 -4
  75. package/lib/core/transform/tracker/broker/WatchBroker.d.mts +14 -4
  76. package/lib/core/transform/tracker/broker/WatchBroker.d.ts +14 -4
  77. package/lib/core/transform/tracker/broker/WatchBrokerTransport.d.cts +63 -0
  78. package/lib/core/transform/tracker/broker/WatchBrokerTransport.d.mts +63 -0
  79. package/lib/core/transform/tracker/broker/WatchBrokerTransport.d.ts +63 -0
  80. package/lib/core/transform/tracker/broker/WatchBrokerTransport.js +89 -0
  81. package/lib/core/transform/tracker/broker/WatchBrokerTransport.js.map +1 -0
  82. package/lib/core/transform/tracker/broker/WatchBrokerTransport.mjs +89 -0
  83. package/lib/core/transform/tracker/broker/WatchBrokerTransport.mjs.map +1 -0
  84. package/lib/core/transform/tracker/broker/drainWatchBroker.d.cts +8 -8
  85. package/lib/core/transform/tracker/broker/drainWatchBroker.d.mts +8 -8
  86. package/lib/core/transform/tracker/broker/drainWatchBroker.d.ts +8 -8
  87. package/lib/core/transform/tracker/broker/drainWatchBroker.js +12 -13
  88. package/lib/core/transform/tracker/broker/drainWatchBroker.js.map +1 -1
  89. package/lib/core/transform/tracker/broker/drainWatchBroker.mjs +12 -13
  90. package/lib/core/transform/tracker/broker/drainWatchBroker.mjs.map +1 -1
  91. package/lib/core/transform/tracker/broker/getWatchBroker.d.cts +18 -15
  92. package/lib/core/transform/tracker/broker/getWatchBroker.d.mts +18 -15
  93. package/lib/core/transform/tracker/broker/getWatchBroker.d.ts +18 -15
  94. package/lib/core/transform/tracker/broker/getWatchBroker.js +87 -17
  95. package/lib/core/transform/tracker/broker/getWatchBroker.js.map +1 -1
  96. package/lib/core/transform/tracker/broker/getWatchBroker.mjs +87 -17
  97. package/lib/core/transform/tracker/broker/getWatchBroker.mjs.map +1 -1
  98. package/lib/core/transform/tracker/broker/openBrokeredWatch.d.cts +5 -5
  99. package/lib/core/transform/tracker/broker/openBrokeredWatch.d.mts +5 -5
  100. package/lib/core/transform/tracker/broker/openBrokeredWatch.d.ts +5 -5
  101. package/lib/core/transform/tracker/broker/openBrokeredWatch.js +11 -14
  102. package/lib/core/transform/tracker/broker/openBrokeredWatch.js.map +1 -1
  103. package/lib/core/transform/tracker/broker/openBrokeredWatch.mjs +11 -14
  104. package/lib/core/transform/tracker/broker/openBrokeredWatch.mjs.map +1 -1
  105. package/lib/core/transform/tracker/broker/usesWatchBroker.d.cts +7 -7
  106. package/lib/core/transform/tracker/broker/usesWatchBroker.d.mts +7 -7
  107. package/lib/core/transform/tracker/broker/usesWatchBroker.d.ts +7 -7
  108. package/lib/core/transform/tracker/broker/usesWatchBroker.js +7 -7
  109. package/lib/core/transform/tracker/broker/usesWatchBroker.mjs +7 -7
  110. package/lib/core/transform/tracker/broker/watchBrokerSource.d.cts +9 -10
  111. package/lib/core/transform/tracker/broker/watchBrokerSource.d.mts +9 -10
  112. package/lib/core/transform/tracker/broker/watchBrokerSource.d.ts +9 -10
  113. package/lib/core/transform/tracker/broker/watchBrokerSource.js +10 -11
  114. package/lib/core/transform/tracker/broker/watchBrokerSource.js.map +1 -1
  115. package/lib/core/transform/tracker/broker/watchBrokerSource.mjs +10 -11
  116. package/lib/core/transform/tracker/broker/watchBrokerSource.mjs.map +1 -1
  117. package/lib/core/transform/transformTtsc.d.cts +7 -4
  118. package/lib/core/transform/transformTtsc.d.mts +7 -4
  119. package/lib/core/transform/transformTtsc.d.ts +7 -4
  120. package/lib/core/transform/transformTtsc.js +37 -92
  121. package/lib/core/transform/transformTtsc.js.map +1 -1
  122. package/lib/core/transform/transformTtsc.mjs +37 -92
  123. package/lib/core/transform/transformTtsc.mjs.map +1 -1
  124. package/lib/core/transform/validation/TtscGenerationProof.d.cts +105 -0
  125. package/lib/core/transform/validation/TtscGenerationProof.d.mts +105 -0
  126. package/lib/core/transform/validation/TtscGenerationProof.d.ts +105 -0
  127. package/lib/core/transform/validation/TtscGenerationProof.js +149 -0
  128. package/lib/core/transform/validation/TtscGenerationProof.js.map +1 -0
  129. package/lib/core/transform/validation/TtscGenerationProof.mjs +149 -0
  130. package/lib/core/transform/validation/TtscGenerationProof.mjs.map +1 -0
  131. package/lib/core/transform/validation/matchesCachedSource.d.cts +18 -15
  132. package/lib/core/transform/validation/matchesCachedSource.d.mts +18 -15
  133. package/lib/core/transform/validation/matchesCachedSource.d.ts +18 -15
  134. package/lib/core/transform/validation/matchesCachedSource.js +28 -22
  135. package/lib/core/transform/validation/matchesCachedSource.js.map +1 -1
  136. package/lib/core/transform/validation/matchesCachedSource.mjs +28 -22
  137. package/lib/core/transform/validation/matchesCachedSource.mjs.map +1 -1
  138. package/lib/core/transform/validation/matchesCompleteInputSnapshot.d.cts +3 -2
  139. package/lib/core/transform/validation/matchesCompleteInputSnapshot.d.mts +3 -2
  140. package/lib/core/transform/validation/matchesCompleteInputSnapshot.d.ts +3 -2
  141. package/lib/core/transform/validation/matchesCompleteInputSnapshot.js +4 -4
  142. package/lib/core/transform/validation/matchesCompleteInputSnapshot.js.map +1 -1
  143. package/lib/core/transform/validation/matchesCompleteInputSnapshot.mjs +4 -4
  144. package/lib/core/transform/validation/matchesCompleteInputSnapshot.mjs.map +1 -1
  145. package/lib/core/transform/validation/matchesNarrowPersistentInputs.d.cts +2 -1
  146. package/lib/core/transform/validation/matchesNarrowPersistentInputs.d.mts +2 -1
  147. package/lib/core/transform/validation/matchesNarrowPersistentInputs.d.ts +2 -1
  148. package/lib/core/transform/validation/matchesNarrowPersistentInputs.js +2 -2
  149. package/lib/core/transform/validation/matchesNarrowPersistentInputs.js.map +1 -1
  150. package/lib/core/transform/validation/matchesNarrowPersistentInputs.mjs +2 -2
  151. package/lib/core/transform/validation/matchesNarrowPersistentInputs.mjs.map +1 -1
  152. package/lib/core/transform/validation/matchesUniversalHostInputTrees.d.cts +3 -2
  153. package/lib/core/transform/validation/matchesUniversalHostInputTrees.d.mts +3 -2
  154. package/lib/core/transform/validation/matchesUniversalHostInputTrees.d.ts +3 -2
  155. package/lib/core/transform/validation/matchesUniversalHostInputTrees.js +5 -3
  156. package/lib/core/transform/validation/matchesUniversalHostInputTrees.js.map +1 -1
  157. package/lib/core/transform/validation/matchesUniversalHostInputTrees.mjs +5 -3
  158. package/lib/core/transform/validation/matchesUniversalHostInputTrees.mjs.map +1 -1
  159. package/lib/core/transform/validation/matchesUniversalHostInputs.d.cts +3 -2
  160. package/lib/core/transform/validation/matchesUniversalHostInputs.d.mts +3 -2
  161. package/lib/core/transform/validation/matchesUniversalHostInputs.d.ts +3 -2
  162. package/lib/core/transform/validation/matchesUniversalHostInputs.js +5 -5
  163. package/lib/core/transform/validation/matchesUniversalHostInputs.js.map +1 -1
  164. package/lib/core/transform/validation/matchesUniversalHostInputs.mjs +5 -5
  165. package/lib/core/transform/validation/matchesUniversalHostInputs.mjs.map +1 -1
  166. package/lib/core/transform/validation/nativeInputPredicatesHold.d.cts +5 -4
  167. package/lib/core/transform/validation/nativeInputPredicatesHold.d.mts +5 -4
  168. package/lib/core/transform/validation/nativeInputPredicatesHold.d.ts +5 -4
  169. package/lib/core/transform/validation/nativeInputPredicatesHold.js +31 -12
  170. package/lib/core/transform/validation/nativeInputPredicatesHold.js.map +1 -1
  171. package/lib/core/transform/validation/nativeInputPredicatesHold.mjs +31 -12
  172. package/lib/core/transform/validation/nativeInputPredicatesHold.mjs.map +1 -1
  173. package/lib/core/transform/validation/notificationsProveProgramUnchanged.d.cts +2 -1
  174. package/lib/core/transform/validation/notificationsProveProgramUnchanged.d.mts +2 -1
  175. package/lib/core/transform/validation/notificationsProveProgramUnchanged.d.ts +2 -1
  176. package/lib/core/transform/validation/notificationsProveProgramUnchanged.js +2 -2
  177. package/lib/core/transform/validation/notificationsProveProgramUnchanged.js.map +1 -1
  178. package/lib/core/transform/validation/notificationsProveProgramUnchanged.mjs +2 -2
  179. package/lib/core/transform/validation/notificationsProveProgramUnchanged.mjs.map +1 -1
  180. package/lib/core/transform/watch/notifyWatchInputs.js +3 -0
  181. package/lib/core/transform/watch/notifyWatchInputs.js.map +1 -1
  182. package/lib/core/transform/watch/notifyWatchInputs.mjs +3 -0
  183. package/lib/core/transform/watch/notifyWatchInputs.mjs.map +1 -1
  184. package/lib/core/turbopack/turbopack.js +2 -1
  185. package/lib/core/turbopack/turbopack.js.map +1 -1
  186. package/lib/core/turbopack/turbopack.mjs +2 -1
  187. package/lib/core/turbopack/turbopack.mjs.map +1 -1
  188. package/package.json +3 -3
  189. package/src/core/bun/bun.ts +8 -4
  190. package/src/core/observer/createInputObserver.ts +6 -5
  191. package/src/core/observer/openIsolatedRecursiveWatch.ts +11 -12
  192. package/src/core/transform/cache/TtscCachedProjectTransform.ts +13 -3
  193. package/src/core/transform/cache/selectCachedGenerationAction.ts +9 -1
  194. package/src/core/transform/deliverCachedTransform.ts +97 -0
  195. package/src/core/transform/envelope/selectDeclaredProjectInputKeys.ts +5 -2
  196. package/src/core/transform/envelope/selectExternalInputPaths.ts +7 -7
  197. package/src/core/transform/filesystem/TtscTransformFilesystemOperations.ts +15 -12
  198. package/src/core/transform/generation/selectTransformAttemptDisposition.ts +3 -1
  199. package/src/core/transform/generation/transformProject.ts +13 -9
  200. package/src/core/transform/inputs/preparePluginBuildEnvironments.ts +41 -7
  201. package/src/core/transform/tracker/broker/WatchBroker.ts +15 -4
  202. package/src/core/transform/tracker/broker/WatchBrokerTransport.ts +82 -0
  203. package/src/core/transform/tracker/broker/drainWatchBroker.ts +12 -13
  204. package/src/core/transform/tracker/broker/getWatchBroker.ts +89 -18
  205. package/src/core/transform/tracker/broker/openBrokeredWatch.ts +11 -14
  206. package/src/core/transform/tracker/broker/usesWatchBroker.ts +7 -7
  207. package/src/core/transform/tracker/broker/watchBrokerSource.ts +10 -11
  208. package/src/core/transform/transformTtsc.ts +36 -92
  209. package/src/core/transform/validation/TtscGenerationProof.ts +201 -0
  210. package/src/core/transform/validation/matchesCachedSource.ts +27 -21
  211. package/src/core/transform/validation/matchesCompleteInputSnapshot.ts +5 -3
  212. package/src/core/transform/validation/matchesNarrowPersistentInputs.ts +3 -1
  213. package/src/core/transform/validation/matchesUniversalHostInputTrees.ts +6 -2
  214. package/src/core/transform/validation/matchesUniversalHostInputs.ts +6 -4
  215. package/src/core/transform/validation/nativeInputPredicatesHold.ts +36 -14
  216. package/src/core/transform/validation/notificationsProveProgramUnchanged.ts +3 -1
  217. package/src/core/transform/watch/notifyWatchInputs.ts +3 -0
  218. package/src/core/turbopack/turbopack.ts +2 -1
@@ -1,16 +1,17 @@
1
1
  import { WATCH_PROBE_TIMEOUT_MS } from "./WATCH_PROBE_TIMEOUT_MS";
2
2
  import type { WatchBroker } from "./WatchBroker";
3
+ import { WatchBrokerTransport } from "./WatchBrokerTransport";
3
4
 
4
5
  /**
5
6
  * Ask the watch broker to acknowledge, and resolve with whether it did.
6
7
  *
7
- * The child answers after two turns of its own loop, so a watch callback it had
8
- * already queued has run, and the ordered IPC channel puts every message it
9
- * sent before the reply ahead of the reply. That is the same proof an
10
- * in-process watcher gets from a macrotask turn, rather than the fixed wait
11
- * this replaces, which guessed at the crossing (samchon/ttsc#1272). On macOS
12
- * the child answers once each stream it can prove has delivered a probe, which
13
- * takes the service's latency (samchon/ttsc#1453).
8
+ * Windows answers after consuming currently queued native completions to an
9
+ * observed empty port. macOS answers once each provable stream has delivered a
10
+ * probe, including the service's latency (#1453). Ordered transport applies
11
+ * every preceding event before the reply. These are current backend frontiers,
12
+ * not atomic timestamp classification of concurrent writes. The optional direct
13
+ * fs.watch program retains its explicit two-turn frontier for protocol tests;
14
+ * it does not supply Windows production proof (#1719).
14
15
  *
15
16
  * A broker that never answers must not hold a delivery, so the wait gives up
16
17
  * after a threshold of twice the probe timeout: the child itself gives up on a
@@ -50,7 +51,7 @@ import type { WatchBroker } from "./WatchBroker";
50
51
  * Native paragraphs and parameters explain ordering, coverage, sharing and
51
52
  * false deadlines under the documentation skill.
52
53
  * @evidence contracts/portability.md#os-neutral-implementation
53
- * OS-neutral host delivery delegates Windows loop ordering and macOS stream
54
+ * OS-neutral host delivery delegates Windows completion-port drainage and macOS stream
54
55
  * probing to the native broker rather than applying one universal timing guess.
55
56
  * @evidence contracts/performance.md#efficient-algorithms
56
57
  * A covering memo query uses fixed identity/id lookup. New requests copy all N
@@ -123,8 +124,7 @@ function startWatchBrokerDrain(
123
124
  broker.drainScopes?.delete(id);
124
125
  broker.pendingDrains -= 1;
125
126
  if (broker.pendingDrains === 0 && broker.pendingRegistrations === 0) {
126
- broker.child.unref();
127
- broker.child.channel?.unref?.();
127
+ WatchBrokerTransport.reference(broker, false);
128
128
  }
129
129
  resolve(answered);
130
130
  };
@@ -134,12 +134,11 @@ function startWatchBrokerDrain(
134
134
  // the reference the loop can empty while a delivery waits here, and the
135
135
  // process exits mid-build with nothing to report.
136
136
  broker.pendingDrains += 1;
137
- broker.child.ref();
138
- broker.child.channel?.ref?.();
137
+ WatchBrokerTransport.reference(broker, true);
139
138
  const timer = setTimeout(() => release(false), timeout);
140
139
  broker.drains.set(id, release);
141
140
  (broker.drainScopes ??= new Map()).set(id, scope);
142
- if (broker.child.send?.({ id, op: "drain" }) !== true) {
141
+ if (WatchBrokerTransport.send(broker, { id, op: "drain" }) !== true) {
143
142
  release(false);
144
143
  }
145
144
  });
@@ -1,3 +1,6 @@
1
+ import readline from "node:readline";
2
+ import { resolveBinary } from "ttsc/binary";
3
+
1
4
  import { traceProcessSpawn } from "../../../tracing/traceProcessSpawn";
2
5
  import { WATCH_BROKER } from "./WATCH_BROKER";
3
6
  import type { WatchBroker } from "./WatchBroker";
@@ -13,11 +16,11 @@ import { watchBrokerSource } from "./watchBrokerSource";
13
16
  * caller-supplied watch capabilities can bypass it. Isolation has a reason on
14
17
  * each native backend:
15
18
  *
16
- * - Node's Windows fs-event backend can hit a native assertion that aborts the
17
- * whole process when a watched temporary tree is deleted. In the child that
18
- * crash becomes an ordinary exit that fails the affected trackers, and those
19
- * generations fall back to proving themselves from recorded state instead of
20
- * taking the host down.
19
+ * - Windows runs ttsc's native completion-port helper directly. Its directory
20
+ * filter excludes access-time notifications: reads must not masquerade as
21
+ * writes (#1719). Actual writes, metadata changes, native loss and failed
22
+ * coverage remain observable; equal bytes cannot erase an A-B-A event. No
23
+ * Node fs-event handle is opened in the host or an intermediate process.
21
24
  * - On macOS, libuv serves every directory watch of one event loop through a
22
25
  * single FSEventStream and re-creates it whenever any watch in that loop
23
26
  * opens or closes, losing the events in between (samchon/ttsc#1418), and it
@@ -26,10 +29,11 @@ import { watchBrokerSource } from "./watchBrokerSource";
26
29
  * passes each drop on as a gap (samchon/ttsc#1425); see
27
30
  * {@link watchBrokerSource}.
28
31
  *
29
- * Registration/drain owners unreference the child and IPC channel after their
32
+ * Registration/drain owners unreference the child and its transport after their
30
33
  * outstanding acknowledgments finish; startup itself returns a referenced
31
- * child. Last-registration closure attempts disconnection and termination. This
32
- * accessor has no independent shutdown deadline or exit wait.
34
+ * child. Last-registration closure ends the request stream and attempts
35
+ * termination. This accessor has no independent shutdown deadline or exit
36
+ * wait.
33
37
  *
34
38
  * @evidence contracts/common.md#principled-implementation
35
39
  * Native watches run in a protocol child. Error/exit dispatch reports failure
@@ -45,13 +49,15 @@ import { watchBrokerSource } from "./watchBrokerSource";
45
49
  * Native platform-reason list and lifecycle paragraph explain isolation and
46
50
  * process ownership under the documentation skill.
47
51
  * @evidence contracts/portability.md#os-neutral-implementation
48
- * OS-neutral startup uses this process's executable and argument-array spawn;
49
- * native FSEvents loading and platform differences remain in this boundary.
52
+ * Windows resolves the same ttsc binary as its compiler owner and uses the
53
+ * native __watch command; macOS uses this runtime and supported FSEvents.
54
+ * Argument-array spawn, hidden Windows processes and ordered transport stay
55
+ * inside this boundary.
50
56
  * @evidence contracts/performance.md#efficient-algorithms
51
- * A current-holder read is fixed work. Cold startup includes optional native
52
- * module resolution/warning, child source construction and native process/IPC
53
- * creation; resolution/path/source bytes and process startup cost do not
54
- * vanish into one spawn call. Failure visits R registrations and D drain
57
+ * A current-holder read is fixed work. Windows cold startup resolves the ttsc
58
+ * binary and opens native protocol pipes; macOS resolves the optional binding,
59
+ * reports missing capability and constructs its child program and IPC channel.
60
+ * Resolution/path/source bytes and native process startup cost remain real. Failure visits R registrations and D drain
55
61
  * callbacks, whose native/reference/sink work remains delegated; it does not
56
62
  * enumerate watched source trees.
57
63
  * Enabled private tracing serializes the actual executable/source argv and
@@ -63,7 +69,7 @@ import { watchBrokerSource } from "./watchBrokerSource";
63
69
  * a health certificate; binding installation changes are not re-resolved
64
70
  * while it remains current, and sink exceptions can interrupt failure handling.
65
71
  * @evidence contracts/performance.md#bound-retention-and-release-resources
66
- * One current module holder retains a child and registration/drain maps;
72
+ * One current module holder retains a direct child and registration/drain maps;
67
73
  * those populations and caller-retained retired brokers have no cap here.
68
74
  * Request owners manage references/timers, and last closure attempts native
69
75
  * disconnection/kill rather than proving exit. Completed failure routing
@@ -77,11 +83,17 @@ export function getWatchBroker(): WatchBroker {
77
83
  const fsevents =
78
84
  process.platform === "darwin" ? fseventsBindingPath() : undefined;
79
85
  if (fsevents === null) warnMissingFseventsBinding();
86
+ const native = process.platform === "win32";
87
+ const binary = native ? resolveBinary() : process.execPath;
88
+ if (binary === null)
89
+ throw new Error("No ttsc native watch helper is available");
80
90
  const child = traceProcessSpawn(
81
- process.execPath,
82
- ["-e", watchBrokerSource(fsevents)],
91
+ binary,
92
+ native ? ["__watch"] : ["-e", watchBrokerSource(fsevents)],
83
93
  {
84
- stdio: ["ignore", "ignore", "ignore", "ipc"],
94
+ stdio: native
95
+ ? ["pipe", "pipe", "ignore"]
96
+ : ["ignore", "ignore", "ignore", "ipc"],
85
97
  windowsHide: true,
86
98
  },
87
99
  );
@@ -110,6 +122,65 @@ export function getWatchBroker(): WatchBroker {
110
122
  WATCH_BROKER.current = undefined;
111
123
  }
112
124
  };
125
+ if (native) {
126
+ // All Windows registrations share one direct native child. No Node watcher,
127
+ // nested child, global runtime patch, or access-time system change is needed.
128
+ const input = child.stdin;
129
+ const output = child.stdout;
130
+ if (input === null || output === null) {
131
+ child.kill();
132
+ throw new Error("The native watch helper has no protocol pipes");
133
+ }
134
+ broker.transport = {
135
+ send(message) {
136
+ if (input.destroyed || input.writableEnded) return false;
137
+ // write(false) means buffered backpressure, not refusal. The callback
138
+ // reports a real transport failure to every still-live registration.
139
+ input.write(JSON.stringify(message) + "\n", (error) => {
140
+ if (error !== null && error !== undefined) {
141
+ fail();
142
+ child.kill();
143
+ }
144
+ });
145
+ return true;
146
+ },
147
+ reference(active) {
148
+ const pipe = output as typeof output & {
149
+ ref?: () => void;
150
+ unref?: () => void;
151
+ };
152
+ if (active) {
153
+ child.ref();
154
+ pipe.ref?.();
155
+ } else {
156
+ child.unref();
157
+ pipe.unref?.();
158
+ }
159
+ },
160
+ close() {
161
+ input.end();
162
+ },
163
+ };
164
+ const lost = (): void => {
165
+ fail();
166
+ child.kill();
167
+ };
168
+ input.on("error", lost);
169
+ output.on("error", lost);
170
+ output.on("end", lost);
171
+ readline
172
+ .createInterface({ input: output, crlfDelay: Infinity })
173
+ .on("line", (line) => {
174
+ let message: unknown;
175
+ try {
176
+ message = JSON.parse(line) as unknown;
177
+ } catch {
178
+ lost();
179
+ return;
180
+ }
181
+ routeWatchBrokerMessage(broker, message);
182
+ });
183
+ }
113
184
  child.on("error", fail);
114
185
  child.on("exit", fail);
115
186
  child.on("message", (message: unknown) =>
@@ -7,6 +7,7 @@ import { WATCH_PROBE_DIRECTORY_PREFIX } from "./WATCH_PROBE_DIRECTORY_PREFIX";
7
7
  import { WATCH_PROBE_TIMEOUT_MS } from "./WATCH_PROBE_TIMEOUT_MS";
8
8
  import type { WatchBrokerLocation } from "./WatchBrokerLocation";
9
9
  import type { WatchBrokerSink } from "./WatchBrokerSink";
10
+ import { WatchBrokerTransport } from "./WatchBrokerTransport";
10
11
  import { drainWatchBroker } from "./drainWatchBroker";
11
12
  import { getWatchBroker } from "./getWatchBroker";
12
13
  import { probeForLocation } from "./probeForLocation";
@@ -16,11 +17,11 @@ import { sweepAbandonedWatchProbes } from "./sweepAbandonedWatchProbes";
16
17
  * Open directory watches in the isolated watch process for one sink, and report
17
18
  * when they hear.
18
19
  *
19
- * On Windows, Node's fs-event backend can assert in native code when a watched
20
- * temporary tree is deleted. Isolation turns that unrecoverable process abort
21
- * into an ordinary broker exit and a conservative fallback in the host. On
22
- * macOS, each registration's watches are streams of their own, started before
23
- * the child reports ready, and a dropped event reaches the sink as a gap
20
+ * On Windows, ttsc's native helper owns completion-port directory subscriptions
21
+ * and omits access-only notifications (#1719). Native loss and failure withdraw
22
+ * coverage; actual change events remain authoritative even after A-B-A writes.
23
+ * On macOS, each registration's watches are streams of their own, started
24
+ * before the child reports ready, and a dropped event reaches the sink as a gap
24
25
  * (samchon/ttsc#1425). A stream that can be probed reports ready only once its
25
26
  * opening probe came back through it; the child suppresses ordinary callbacks
26
27
  * received before that probe. This is its backend protocol, not a guarantee
@@ -143,10 +144,7 @@ export function openBrokeredWatch(
143
144
  };
144
145
  });
145
146
  broker.pendingRegistrations += 1;
146
- broker.child.ref();
147
- // Bun's IPC channel omits Node's Control.ref/unref methods. The child itself
148
- // still owns the outstanding acknowledgement on that runtime.
149
- broker.child.channel?.ref?.();
147
+ WatchBrokerTransport.reference(broker, true);
150
148
  const id = broker.nextId++;
151
149
  let resolveReady!: () => void;
152
150
  const answered = new Promise<void>((resolve) => {
@@ -166,7 +164,7 @@ export function openBrokeredWatch(
166
164
  let failed = false;
167
165
  let failure: unknown;
168
166
  try {
169
- broker.child.send?.({ id, op: "remove" });
167
+ WatchBrokerTransport.send(broker, { id, op: "remove" });
170
168
  } catch (error) {
171
169
  failed = true;
172
170
  failure = error;
@@ -176,7 +174,7 @@ export function openBrokeredWatch(
176
174
  WATCH_BROKER.current = undefined;
177
175
  }
178
176
  try {
179
- broker.child.disconnect?.();
177
+ WatchBrokerTransport.close(broker);
180
178
  } catch (error) {
181
179
  if (!failed) {
182
180
  failed = true;
@@ -194,7 +192,7 @@ export function openBrokeredWatch(
194
192
  }
195
193
  if (failed) throw failure;
196
194
  };
197
- broker.child.send?.({
195
+ WatchBrokerTransport.send(broker, {
198
196
  allEvents: options.allEvents,
199
197
  locations: normalized,
200
198
  id,
@@ -226,8 +224,7 @@ export function openBrokeredWatch(
226
224
  // a reply over an unreferenced channel lets the loop empty and the process
227
225
  // exit mid-build.
228
226
  if (broker.pendingRegistrations === 0 && broker.pendingDrains === 0) {
229
- broker.child.unref();
230
- broker.child.channel?.unref?.();
227
+ WatchBrokerTransport.reference(broker, false);
231
228
  }
232
229
  });
233
230
  return {
@@ -4,13 +4,13 @@ import type { TtscTransformFilesystemOperations } from "../../filesystem/TtscTra
4
4
  * Whether a tracker over `filesystem` opens its watches in the isolated watch
5
5
  * broker rather than in this process.
6
6
  *
7
- * The host filesystem on Windows and macOS does: Windows so that a native
8
- * fs-event abort cannot take the host down, and macOS so that each watch is its
9
- * own FSEventStream, whose dropped events are reported, rather than one libuv
10
- * re-creates whenever any watch in the host opens or closes, and whose drops it
11
- * discards (samchon/ttsc#1418, samchon/ttsc#1425). An embedder that supplies
12
- * its own `watch` retains that capability, including for a host-filesystem
13
- * view.
7
+ * The host filesystem on Windows and macOS does: Windows so that native
8
+ * mutation filters exclude access-time noise without a Node fs-event handle,
9
+ * and macOS so that each watch is its own FSEventStream, whose dropped events
10
+ * are reported, rather than one libuv re-creates whenever any watch in the host
11
+ * opens or closes, and whose drops it discards (samchon/ttsc#1418,
12
+ * samchon/ttsc#1425). An embedder that supplies its own `watch` retains that
13
+ * capability, including for a host-filesystem view.
14
14
  *
15
15
  * @evidence contracts/common.md#principled-implementation
16
16
  * A supplied filesystem watcher is authoritative; only the native host
@@ -8,13 +8,10 @@ import { WATCH_PROBE_TIMEOUT_MS } from "./WATCH_PROBE_TIMEOUT_MS";
8
8
  * frontier described below; a reply alone does not certify every scope, since
9
9
  * probe-dependent streams can be named unproven and gaps withdraw authority.
10
10
  *
11
- * On Windows the watches are `fs.watch`. A drain yields through two immediate
12
- * turns to allow the loop to poll and deliver queued callbacks before replying.
13
- * The real Windows scenario checks two hundred synchronous write/drain pairs;
14
- * the scripted unit checks this scheduling boundary separately. These checks
15
- * are not a universal kernel-order proof: FIFO completion-port queueing alone
16
- * does not guarantee dequeue order or establish when notification completion
17
- * becomes observable relative to a write and IPC request.
11
+ * Windows production registrations use ttsc's native helper, not this program
12
+ * (#1719). The optional fs.watch backend remains an explicit direct program
13
+ * capability used by its scripted protocol tests; it never supplies Windows
14
+ * production cache proof. Its drain yields through two immediate turns.
18
15
  *
19
16
  * On macOS the watches go through the `fsevents` binding, one FSEventStream per
20
17
  * location, instead of relying on `fs.watch` for stream and loss authority
@@ -59,11 +56,13 @@ import { WATCH_PROBE_TIMEOUT_MS } from "./WATCH_PROBE_TIMEOUT_MS";
59
56
  * The child protocol keeps per-registration streams and ordered drains;
60
57
  * macOS proof requires clean probe delivery. Loss flags withdraw coverage
61
58
  * before probe recognition, so matching a probe name cannot erase that warning.
62
- * The Windows two-turn frontier retains its runtime/backend ordering premise;
59
+ * The optional fs.watch two-turn frontier retains its runtime/backend ordering premise;
63
60
  * this source does not independently prove kernel completeness.
64
61
  * @evidence contracts/common.md#clear-and-simple-design
65
- * One maintained child program serves both native backends; this function only
66
- * injects resolved capability and the shared timeout, with JSON-safe path encoding.
62
+ * One maintained child program serves macOS and the explicitly selected
63
+ * fs.watch protocol capability; Windows production uses its native helper.
64
+ * This function injects resolved capability and the shared timeout with
65
+ * JSON-safe path encoding.
67
66
  * @evidence contracts/common.md#prohibited-implementation-shortcuts
68
67
  * Native flags and deadlines express backend contracts, not fixture-specific
69
68
  * repairs. Missing bindings and probes report uncertainty rather than silent success.
@@ -351,7 +350,7 @@ function drain(requestId) {
351
350
  entry.abandon();
352
351
  }
353
352
  }
354
- // Windows watches, and streams already proven, answer after two turns: the
353
+ // Explicit fs.watch watches, and streams already proven, answer after two turns: the
355
354
  // first lets the loop poll for completions the kernel had already queued,
356
355
  // the second answers after their callbacks.
357
356
  outstanding += 1;
@@ -10,37 +10,28 @@ import { TRANSFORM_RESULT_FILESYSTEM } from "./cache/TRANSFORM_RESULT_FILESYSTEM
10
10
  import type { TtscTransformCache } from "./cache/TtscTransformCache";
11
11
  import { awaitOrEvict } from "./cache/awaitOrEvict";
12
12
  import { createTransformCacheKey } from "./cache/createTransformCacheKey";
13
- import { disposeCachedTransform } from "./cache/disposeCachedTransform";
14
13
  import { evictGeneration } from "./cache/evictGeneration";
15
14
  import { replaysTerminalGeneration } from "./cache/replaysTerminalGeneration";
16
15
  import { selectCachedGenerationAction } from "./cache/selectCachedGenerationAction";
17
- import { selectOrEvict } from "./cache/selectOrEvict";
18
16
  import { transformCacheEpoch } from "./cache/transformCacheEpoch";
19
17
  import { transformCacheTrustsNotifications } from "./cache/transformCacheTrustsNotifications";
20
18
  import { transformFilesystem } from "./cache/transformFilesystem";
21
19
  import { withdrawGenerationNotifications } from "./cache/withdrawGenerationNotifications";
22
- import { reportMissingProgramOutput } from "./diagnostics/reportMissingProgramOutput";
23
- import { reportSuccessDiagnostics } from "./diagnostics/reportSuccessDiagnostics";
24
- import type { TtscTransformedOutput } from "./envelope/TtscTransformedOutput";
25
- import { TtscMissingProgramOutputError } from "./errors/TtscMissingProgramOutputError";
20
+ import { deliverCachedTransform } from "./deliverCachedTransform";
26
21
  import { TtscUnstableGenerationError } from "./errors/TtscUnstableGenerationError";
27
22
  import { transformProject } from "./generation/transformProject";
28
23
  import { preparePluginBuildEnvironments } from "./inputs/preparePluginBuildEnvironments";
29
24
  import { TRANSFORM_CACHE_SESSIONS } from "./session/TRANSFORM_CACHE_SESSIONS";
30
25
  import { settleProjectMutationEvents } from "./tracker/settleProjectMutationEvents";
31
26
  import { resolveProjectSelection } from "./tsconfig/resolveProjectSelection";
32
- import { createTransformResult } from "./utils/createTransformResult";
33
27
  import { isDeclarationFile } from "./utils/isDeclarationFile";
34
28
  import { isHostWrapperQuery } from "./utils/isHostWrapperQuery";
35
29
  import { pluginsAreDisabled } from "./utils/pluginsAreDisabled";
36
30
  import { stripQuery } from "./utils/stripQuery";
37
- import { markCachedSourceServed } from "./validation/markCachedSourceServed";
31
+ import { TtscGenerationProof } from "./validation/TtscGenerationProof";
38
32
  import type { TtscTransformHooks } from "./watch/TtscTransformHooks";
39
33
  import type { TtscWatchSelection } from "./watch/TtscWatchSelection";
40
- import { notifyFailedGenerationInputs } from "./watch/notifyFailedGenerationInputs";
41
34
  import { notifyRejectedGenerationInputs } from "./watch/notifyRejectedGenerationInputs";
42
- import { notifyVolatileDelivery } from "./watch/notifyVolatileDelivery";
43
- import { notifyWatchInputs } from "./watch/notifyWatchInputs";
44
35
  import { prepareProjectRecordDirectories } from "./watch/prepareProjectRecordDirectories";
45
36
 
46
37
  /**
@@ -78,7 +69,7 @@ import { prepareProjectRecordDirectories } from "./watch/prepareProjectRecordDir
78
69
  * per build, not per compilation.
79
70
  * @evidence contracts/common.md#principled-implementation Project selection and generation-qualified cache admission preserve compiler disk authority; fresh-only success additionally needs an explicit nonwatching lifecycle, coherent project declaration and actual host-cache withdrawal, because incomplete observation cannot support watch invalidation.
80
71
  * @evidence contracts/common.md#clear-and-simple-design One delivery coordinator composes project selection, cache admission, compilation, output selection and host notifications; dedicated owners handle proof and lifetime internals.
81
- * @evidence contracts/common.md#prohibited-implementation-shortcuts Wrapper modules cannot poison source baselines and incomplete generations cannot authorize reuse; a separately admitted fresh-only result is evicted before capability checks, unknown or watching lifecycles fail explicitly, and unsupported withdrawal cannot be replaced by a fake record or guessed dependency closure.
72
+ * @evidence contracts/common.md#prohibited-implementation-shortcuts Wrapper modules cannot poison source baselines; incomplete local results can share only explicitly nonwatching first deliveries in their exact pass. Unknown/watching lifecycles or unsupported withdrawal reject and evict them rather than invent persistent records or dependency closure.
82
73
  * @evidence contracts/common.md#meaningful-documentation Native paragraphs and argument tags explain project scope, no-transform outcomes, cache epochs and per-build notification responsibilities with links to maintained reference context.
83
74
  * @evidence contracts/performance.md#efficient-algorithms
84
75
  * Selection/key construction pays ancestor/config/alias/option/path text work.
@@ -86,15 +77,18 @@ import { prepareProjectRecordDirectories } from "./watch/prepareProjectRecordDir
86
77
  * replay source/project/external/universal proofs before selecting output.
87
78
  * In-flight/valid completed reuse avoids compilation, not those checks or
88
79
  * output/map/notification/record work. Capture misses pay whole native compile
89
- * and input populations; concurrent supersession can repeat the outer loop
80
+ * and input populations. The common proof owner skips redundant environment
81
+ * preparation for proven first deliveries and shares synchronous native proof
82
+ * queries; persistent/repeated delivery establishes fresh authority. Concurrent supersession can repeat the outer loop
90
83
  * without a delivery-level retry/time bound here.
91
84
  * @evidence contracts/performance.md#reuse-equivalent-work Cache identity covers config/options/plugins/aliases; current generations, pass-qualified terminal verdicts and in-flight Promises are shared only while their source and dependency proof remains valid.
92
85
  * @evidence contracts/performance.md#bound-retention-and-release-resources
93
86
  * Optional cache state retains current generation Promises/results and
94
87
  * per-key dependency/case facts without a byte/key cap here. Native tasks
95
88
  * belong to compiler/capture owners; uncached captures retain no notification
96
- * or persistent clock probe. Fresh-only delivery detaches its generation
97
- * before host callbacks; eviction/disposal attempt independent resource release
89
+ * or persistent clock probe. Fresh-only delivery releases capture resources,
90
+ * retaining only an explicitly admitted local pass result; rejected or failed
91
+ * incomplete handoff detaches its generation. Eviction/disposal attempt independent resource release
98
92
  * and native failures need not close every handle or remove every probe.
99
93
  * @evidence contracts/portability.md#os-neutral-implementation Native module paths and project coordinates use supported path/filesystem abstractions, while actual case policy and watcher capability come from generation proof rather than OS-name assumptions.
100
94
  */
@@ -218,15 +212,18 @@ export async function transformTtsc(
218
212
  if (!transformCacheTrustsNotifications(cache)) {
219
213
  withdrawGenerationNotifications(cached);
220
214
  }
221
- await preparePluginBuildEnvironments(cached.result, filesystem, cached);
222
- if (cache?.get(key) !== transformed) continue;
223
215
  if (epoch === undefined) {
224
216
  await settleProjectMutationEvents(cached);
225
217
  if (cache?.get(key) !== transformed) {
226
218
  continue;
227
219
  }
228
220
  }
221
+ await TtscGenerationProof.prepare(cached, file, epoch);
222
+ if (cache?.get(key) !== transformed) continue;
223
+ // No await between this observation and synchronous admission.
224
+ const proof = TtscGenerationProof.create(cached, file, epoch);
229
225
  const action = selectCachedGenerationAction({
226
+ proof,
230
227
  cache,
231
228
  cached,
232
229
  epoch,
@@ -239,36 +236,17 @@ export async function transformTtsc(
239
236
  continue;
240
237
  }
241
238
  if (action === "serve") {
242
- reportSuccessDiagnostics(cached, epoch);
243
- // A resolved `"exception"` / `"failure"` envelope makes this throw;
244
- // that is a failed generation too, so it is retained for this pass or
245
- // evicted outside one before being surfaced.
246
- let output: TtscTransformedOutput;
247
- try {
248
- output = selectOrEvict(cache, key, transformed, epoch, {
249
- file,
250
- projectRoot: cached.projectRoot,
251
- result: cached.result,
252
- tsconfig: cached.tsconfig,
253
- });
254
- } catch (error) {
255
- if (!(error instanceof TtscMissingProgramOutputError)) {
256
- notifyFailedGenerationInputs(hooks, cached, file, watchSelection);
257
- throw error;
258
- }
259
- // The compile is fine and simply has nothing for this module, so the
260
- // module goes back to the host untransformed rather than failing the
261
- // build (samchon/ttsc#1308). Its project config and selection inputs
262
- // still decide whether a later generation will contain this module,
263
- // so hosts must receive the same universal watch-input batch.
264
- reportMissingProgramOutput(cached, error, epoch);
265
- notifyWatchInputs(hooks, cached, file, watchSelection);
266
- markCachedSourceServed(cached, file);
267
- return undefined;
268
- }
269
- notifyWatchInputs(hooks, cached, file, watchSelection);
270
- markCachedSourceServed(cached, file);
271
- return createTransformResult(file, source, output);
239
+ return deliverCachedTransform({
240
+ cache,
241
+ cached,
242
+ generation: transformed,
243
+ key,
244
+ epoch,
245
+ file,
246
+ source,
247
+ hooks,
248
+ selection: watchSelection,
249
+ });
272
250
  }
273
251
  transformed = undefined;
274
252
  }
@@ -336,50 +314,16 @@ export async function transformTtsc(
336
314
  policies.set(key, reported);
337
315
  }
338
316
  }
339
- const { projectRoot, result } = cached;
340
- if (cached.freshDeliveryOnly === true) {
341
- // This delivery owns a newly compiled answer, but unavailable observer
342
- // authority cannot certify any later resident or host-cache delivery.
343
- // Eviction schedules resource release even if a host callback throws.
344
- if (cache === undefined) disposeCachedTransform(cached);
345
- else evictGeneration(cache, key, generation);
346
- if (
347
- result.type === "success" &&
348
- (hooks?.watching !== false ||
349
- hooks.markVolatile === undefined ||
350
- (hooks.project?.watching !== undefined &&
351
- hooks.project.watching !== hooks.watching))
352
- ) {
353
- throw new Error(
354
- "@ttsc/unplugin: plugin input observation is unavailable; fresh output " +
355
- "requires an explicitly nonwatching host with supported cache withdrawal. " +
356
- "Watching, unknown or contradictory lifecycles cannot safely observe its changes.",
357
- );
358
- }
359
- hooks?.markVolatile?.();
360
- }
361
- reportSuccessDiagnostics(cached, epoch);
362
- let output: TtscTransformedOutput;
363
- try {
364
- output = selectOrEvict(cache, key, generation, epoch, {
365
- file,
366
- projectRoot,
367
- result,
368
- tsconfig: cached.tsconfig,
369
- });
370
- } catch (error) {
371
- if (!(error instanceof TtscMissingProgramOutputError)) {
372
- notifyFailedGenerationInputs(hooks, cached, file, watchSelection);
373
- throw error;
374
- }
375
- reportMissingProgramOutput(cached, error, epoch);
376
- notifyWatchInputs(hooks, cached, file, watchSelection);
377
- markCachedSourceServed(cached, file);
378
- return undefined;
379
- }
380
- notifyWatchInputs(hooks, cached, file, watchSelection);
381
- markCachedSourceServed(cached, file);
382
- notifyVolatileDelivery(hooks, cached, file);
383
- return createTransformResult(file, source, output);
317
+ return deliverCachedTransform({
318
+ cache,
319
+ cached,
320
+ generation,
321
+ key,
322
+ epoch,
323
+ file,
324
+ source,
325
+ hooks,
326
+ selection: watchSelection,
327
+ });
384
328
  }
385
329
  }