typescript 7.1.0-dev.20260924.1 → 7.1.0-dev.20260925.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.
@@ -21,7 +21,7 @@ import { TypePredicateKind } from "#enums/typePredicateKind";
21
21
  import { ModifierFlags, unescapeLeadingUnderscores, } from "../../ast/index.js";
22
22
  import { assertNever } from "../../internal/utils.js";
23
23
  import { encodeNode, uint8ArrayToBase64, } from "../node/encoder.js";
24
- import { decodeNode, getNodeId, parseNodeHandle, readParseOptionsKey, readSourceFileHash, RemoteSourceFile, } from "../node/node.js";
24
+ import { decodeNode, getNodeId, parseNodeHandle, readParseOptionsKey, readSourceFileHash, readSourceFileLease, RemoteSourceFile, } from "../node/node.js";
25
25
  import { Wtf8Decoder } from "../node/wtf8.js";
26
26
  import { createGetCanonicalFileName, toPath, } from "../path.js";
27
27
  import { resolveFileName, toCreateSnapshotRequest, } from "../proto.js";
@@ -59,6 +59,7 @@ export class API {
59
59
  initialized = false;
60
60
  initializing;
61
61
  activeSnapshots = new Map();
62
+ activeSourceFileLeases = new Map();
62
63
  printer;
63
64
  internal;
64
65
  constructor(options = {}) {
@@ -185,6 +186,10 @@ export class API {
185
186
  return yield* apiRequest("parseJsonConfigFileContent", { json, ...options });
186
187
  });
187
188
  }
189
+ /**
190
+ * Create and retain a source file independently of a program.
191
+ * Dispose the returned lease when the source file no longer needs to remain available remotely.
192
+ */
188
193
  get createSourceFile() {
189
194
  const owner = this;
190
195
  return cacheGeneratorMethod(owner, "createSourceFile", function (fileName, sourceText, options = {}) {
@@ -193,16 +198,20 @@ export class API {
193
198
  if (!data) {
194
199
  throw new Error("createSourceFile returned no source file");
195
200
  }
196
- return new RemoteSourceFile(data, owner.decoder, owner.client.getTimingCollector());
201
+ return owner.retainSourceFileResponse(data);
197
202
  }, function* (fileName, sourceText, options = {}) {
198
203
  yield* owner.ensureInitialized.gen();
199
204
  const data = sourceFileResponseToUint8Array(yield* apiRequest("createSourceFile", { fileName, sourceText, options }));
200
205
  if (!data) {
201
206
  throw new Error("createSourceFile returned no source file");
202
207
  }
203
- return new RemoteSourceFile(data, owner.decoder, owner.client.getTimingCollector());
208
+ return owner.retainSourceFileResponse(data);
204
209
  });
205
210
  }
211
+ /**
212
+ * Read, create, and retain a source file independently of a program.
213
+ * Dispose the returned lease when the source file no longer needs to remain available remotely.
214
+ */
206
215
  get createSourceFileFromFile() {
207
216
  const owner = this;
208
217
  return cacheGeneratorMethod(owner, "createSourceFileFromFile", function (file, options = {}) {
@@ -211,16 +220,37 @@ export class API {
211
220
  if (!data) {
212
221
  throw new Error("createSourceFileFromFile returned no source file");
213
222
  }
214
- return new RemoteSourceFile(data, owner.decoder, owner.client.getTimingCollector());
223
+ return owner.retainSourceFileResponse(data);
215
224
  }, function* (file, options = {}) {
216
225
  yield* owner.ensureInitialized.gen();
217
226
  const data = sourceFileResponseToUint8Array(yield* apiRequest("createSourceFileFromFile", { fileName: resolveFileName(file), options }));
218
227
  if (!data) {
219
228
  throw new Error("createSourceFileFromFile returned no source file");
220
229
  }
221
- return new RemoteSourceFile(data, owner.decoder, owner.client.getTimingCollector());
230
+ return owner.retainSourceFileResponse(data);
222
231
  });
223
232
  }
233
+ retainSourceFileResponse(data) {
234
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
235
+ const lease = readSourceFileLease(view);
236
+ try {
237
+ const decoded = new RemoteSourceFile(data, this.decoder, this.client.getTimingCollector());
238
+ const sourceFile = this.sourceFileCache.setForLease(decoded.path, decoded, readParseOptionsKey(view), readSourceFileHash(view), lease);
239
+ const retained = new RetainedSourceFile(sourceFile, lease, this.client, () => {
240
+ this.activeSourceFileLeases.delete(lease);
241
+ this.sourceFileCache.releaseLease(lease);
242
+ });
243
+ this.activeSourceFileLeases.set(lease, retained);
244
+ return retained;
245
+ }
246
+ catch (error) {
247
+ try {
248
+ this.client.apiRequest("releaseSourceFile", { lease });
249
+ }
250
+ catch { }
251
+ throw error;
252
+ }
253
+ }
224
254
  get transpileModule() {
225
255
  const owner = this;
226
256
  return cacheGeneratorMethod(owner, "transpileModule", function (input, options = {}) {
@@ -420,26 +450,38 @@ export class API {
420
450
  get close() {
421
451
  const owner = this;
422
452
  return cacheGeneratorMethod(owner, "close", function () {
423
- // Dispose all active snapshots
424
453
  try {
425
- for (const snapshot of [...owner.activeSnapshots.values()]) {
426
- snapshot.dispose();
454
+ for (const retained of [...owner.activeSourceFileLeases.values()]) {
455
+ retained.dispose();
427
456
  }
428
- owner.sourceFileCache.clear();
429
457
  }
430
458
  finally {
431
- owner.client.close(); // always close the underlying connection
459
+ try {
460
+ for (const snapshot of [...owner.activeSnapshots.values()]) {
461
+ snapshot.dispose();
462
+ }
463
+ owner.sourceFileCache.clear();
464
+ }
465
+ finally {
466
+ owner.client.close(); // always close the underlying connection
467
+ }
432
468
  }
433
469
  }, function* () {
434
- // Dispose all active snapshots
435
470
  try {
436
- for (const snapshot of [...owner.activeSnapshots.values()]) {
437
- yield* snapshot.dispose.gen();
471
+ for (const retained of [...owner.activeSourceFileLeases.values()]) {
472
+ yield* retained.dispose.gen();
438
473
  }
439
- owner.sourceFileCache.clear();
440
474
  }
441
475
  finally {
442
- owner.client.close(); // always close the underlying connection
476
+ try {
477
+ for (const snapshot of [...owner.activeSnapshots.values()]) {
478
+ yield* snapshot.dispose.gen();
479
+ }
480
+ owner.sourceFileCache.clear();
481
+ }
482
+ finally {
483
+ owner.client.close(); // always close the underlying connection
484
+ }
443
485
  }
444
486
  });
445
487
  }
@@ -582,6 +624,56 @@ export class API {
582
624
  });
583
625
  }
584
626
  }
627
+ /** An independently retained source file and its disposable remote-lifetime lease. */
628
+ export class RetainedSourceFile {
629
+ sourceFile;
630
+ lease;
631
+ client;
632
+ onDispose;
633
+ disposed = false;
634
+ disposePromise;
635
+ constructor(sourceFile, lease, client, onDispose) {
636
+ this.sourceFile = sourceFile;
637
+ this.lease = lease;
638
+ this.client = client;
639
+ this.onDispose = onDispose;
640
+ }
641
+ [globalThis.Symbol.dispose]() {
642
+ this.dispose();
643
+ }
644
+ get dispose() {
645
+ const owner = this;
646
+ return cacheGeneratorMethod(owner, "dispose", function () {
647
+ return owner.disposePromise ??= owner.disposeWorker();
648
+ }, function* () {
649
+ return owner.disposePromise ??= yield* owner.disposeWorker.gen();
650
+ });
651
+ }
652
+ get disposeWorker() {
653
+ const owner = this;
654
+ return cacheGeneratorMethod(owner, "disposeWorker", function () {
655
+ if (owner.disposed)
656
+ return;
657
+ owner.disposed = true;
658
+ try {
659
+ owner.client.apiRequest("releaseSourceFile", { lease: owner.lease });
660
+ }
661
+ finally {
662
+ owner.onDispose();
663
+ }
664
+ }, function* () {
665
+ if (owner.disposed)
666
+ return;
667
+ owner.disposed = true;
668
+ try {
669
+ yield* apiRequest("releaseSourceFile", { lease: owner.lease });
670
+ }
671
+ finally {
672
+ owner.onDispose();
673
+ }
674
+ });
675
+ }
676
+ }
585
677
  export class InternalAPI {
586
678
  client;
587
679
  ensureInitialized;