@fluidframework/container-loader 2.0.0-internal.4.4.1 → 2.0.0-internal.5.0.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 (84) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/README.md +6 -3
  3. package/dist/connectionManager.d.ts +3 -2
  4. package/dist/connectionManager.d.ts.map +1 -1
  5. package/dist/connectionManager.js.map +1 -1
  6. package/dist/connectionStateHandler.d.ts +4 -3
  7. package/dist/connectionStateHandler.d.ts.map +1 -1
  8. package/dist/connectionStateHandler.js.map +1 -1
  9. package/dist/container.d.ts +62 -36
  10. package/dist/container.d.ts.map +1 -1
  11. package/dist/container.js +63 -83
  12. package/dist/container.js.map +1 -1
  13. package/dist/containerContext.d.ts +2 -2
  14. package/dist/containerContext.d.ts.map +1 -1
  15. package/dist/containerContext.js +3 -7
  16. package/dist/containerContext.js.map +1 -1
  17. package/dist/containerStorageAdapter.d.ts +3 -3
  18. package/dist/containerStorageAdapter.d.ts.map +1 -1
  19. package/dist/containerStorageAdapter.js.map +1 -1
  20. package/dist/deltaManager.d.ts +3 -2
  21. package/dist/deltaManager.d.ts.map +1 -1
  22. package/dist/deltaManager.js +0 -1
  23. package/dist/deltaManager.js.map +1 -1
  24. package/dist/index.d.ts +1 -2
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js.map +1 -1
  27. package/dist/loader.d.ts +9 -5
  28. package/dist/loader.d.ts.map +1 -1
  29. package/dist/loader.js +28 -34
  30. package/dist/loader.js.map +1 -1
  31. package/dist/packageVersion.d.ts +1 -1
  32. package/dist/packageVersion.js +1 -1
  33. package/dist/packageVersion.js.map +1 -1
  34. package/dist/retriableDocumentStorageService.d.ts +3 -2
  35. package/dist/retriableDocumentStorageService.d.ts.map +1 -1
  36. package/dist/retriableDocumentStorageService.js.map +1 -1
  37. package/lib/connectionManager.d.ts +3 -2
  38. package/lib/connectionManager.d.ts.map +1 -1
  39. package/lib/connectionManager.js +1 -1
  40. package/lib/connectionManager.js.map +1 -1
  41. package/lib/connectionStateHandler.d.ts +4 -3
  42. package/lib/connectionStateHandler.d.ts.map +1 -1
  43. package/lib/connectionStateHandler.js +1 -1
  44. package/lib/connectionStateHandler.js.map +1 -1
  45. package/lib/container.d.ts +62 -36
  46. package/lib/container.d.ts.map +1 -1
  47. package/lib/container.js +64 -84
  48. package/lib/container.js.map +1 -1
  49. package/lib/containerContext.d.ts +2 -2
  50. package/lib/containerContext.d.ts.map +1 -1
  51. package/lib/containerContext.js +3 -7
  52. package/lib/containerContext.js.map +1 -1
  53. package/lib/containerStorageAdapter.d.ts +3 -3
  54. package/lib/containerStorageAdapter.d.ts.map +1 -1
  55. package/lib/containerStorageAdapter.js.map +1 -1
  56. package/lib/deltaManager.d.ts +3 -2
  57. package/lib/deltaManager.d.ts.map +1 -1
  58. package/lib/deltaManager.js +1 -2
  59. package/lib/deltaManager.js.map +1 -1
  60. package/lib/index.d.ts +1 -2
  61. package/lib/index.d.ts.map +1 -1
  62. package/lib/index.js +1 -1
  63. package/lib/index.js.map +1 -1
  64. package/lib/loader.d.ts +9 -5
  65. package/lib/loader.d.ts.map +1 -1
  66. package/lib/loader.js +28 -34
  67. package/lib/loader.js.map +1 -1
  68. package/lib/packageVersion.d.ts +1 -1
  69. package/lib/packageVersion.js +1 -1
  70. package/lib/packageVersion.js.map +1 -1
  71. package/lib/retriableDocumentStorageService.d.ts +3 -2
  72. package/lib/retriableDocumentStorageService.d.ts.map +1 -1
  73. package/lib/retriableDocumentStorageService.js.map +1 -1
  74. package/package.json +27 -10
  75. package/src/connectionManager.ts +7 -7
  76. package/src/connectionStateHandler.ts +7 -7
  77. package/src/container.ts +140 -125
  78. package/src/containerContext.ts +3 -9
  79. package/src/containerStorageAdapter.ts +4 -4
  80. package/src/deltaManager.ts +7 -4
  81. package/src/index.ts +1 -8
  82. package/src/loader.ts +56 -47
  83. package/src/packageVersion.ts +1 -1
  84. package/src/retriableDocumentStorageService.ts +3 -2
package/lib/container.js CHANGED
@@ -8,7 +8,7 @@ import { v4 as uuid } from "uuid";
8
8
  import { assert, performance, unreachableCase } from "@fluidframework/common-utils";
9
9
  import { AttachState, isFluidCodeDetails, } from "@fluidframework/container-definitions";
10
10
  import { GenericError, UsageError } from "@fluidframework/container-utils";
11
- import { readAndParse, OnlineStatus, isOnline, ensureFluidResolvedUrl, combineAppAndProtocolSummary, runWithRetry, isFluidResolvedUrl, isCombinedAppAndProtocolSummary, } from "@fluidframework/driver-utils";
11
+ import { readAndParse, OnlineStatus, isOnline, combineAppAndProtocolSummary, runWithRetry, isCombinedAppAndProtocolSummary, } from "@fluidframework/driver-utils";
12
12
  import { MessageType, SummaryType, } from "@fluidframework/protocol-definitions";
13
13
  import { ChildLogger, EventEmitterWithErrorHandling, PerformanceEvent, raiseConnectedEvent, TelemetryLogger, connectedEventName, normalizeError, loggerToMonitoringContext, wrapError, } from "@fluidframework/telemetry-utils";
14
14
  import { Audience } from "./audience";
@@ -119,14 +119,11 @@ export async function ReportIfTooLong(logger, eventName, action) {
119
119
  }
120
120
  }
121
121
  const summarizerClientType = "summarizer";
122
- /**
123
- * @deprecated - In the next release Container will no longer be exported, IContainer should be used in its place.
124
- */
125
122
  export class Container extends EventEmitterWithErrorHandling {
126
123
  /**
127
124
  * @internal
128
125
  */
129
- constructor(loader, config, protocolHandlerBuilder) {
126
+ constructor(createProps, loadProps) {
130
127
  var _a, _b, _c;
131
128
  super((name, error) => {
132
129
  this.mc.logger.sendErrorEvent({
@@ -134,8 +131,7 @@ export class Container extends EventEmitterWithErrorHandling {
134
131
  name: typeof name === "string" ? name : undefined,
135
132
  }, error);
136
133
  });
137
- this.loader = loader;
138
- this.protocolHandlerBuilder = protocolHandlerBuilder;
134
+ this.createProps = createProps;
139
135
  // Tells if container can reconnect on losing fist connection
140
136
  // If false, container gets closed on loss of connection.
141
137
  this._canReconnect = true;
@@ -166,10 +162,9 @@ export class Container extends EventEmitterWithErrorHandling {
166
162
  this.savedOps = [];
167
163
  this.setAutoReconnectTime = performance.now();
168
164
  this._disposed = false;
169
- this.clientDetailsOverride = config.clientDetailsOverride;
170
- this._resolvedUrl = config.resolvedUrl;
171
- if (config.canReconnect !== undefined) {
172
- this._canReconnect = config.canReconnect;
165
+ this.clientDetailsOverride = createProps.clientDetailsOverride;
166
+ if (createProps.canReconnect !== undefined) {
167
+ this._canReconnect = createProps.canReconnect;
173
168
  }
174
169
  // Create logger for data stores to use
175
170
  const type = this.client.details.type;
@@ -177,15 +172,15 @@ export class Container extends EventEmitterWithErrorHandling {
177
172
  const clientType = `${interactive ? "interactive" : "noninteractive"}${type !== undefined && type !== "" ? `/${type}` : ""}`;
178
173
  // Need to use the property getter for docId because for detached flow we don't have the docId initially.
179
174
  // We assign the id later so property getter is used.
180
- this.subLogger = ChildLogger.create(loader.services.subLogger, undefined, {
175
+ this.subLogger = ChildLogger.create(createProps.subLogger, undefined, {
181
176
  all: {
182
177
  clientType,
183
178
  containerId: uuid(),
184
- docId: () => { var _a, _b; return (_b = (_a = this._resolvedUrl) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : undefined; },
179
+ docId: () => { var _a; return (_a = this.resolvedUrl) === null || _a === void 0 ? void 0 : _a.id; },
185
180
  containerAttachState: () => this._attachState,
186
181
  containerLifecycleState: () => this._lifecycleState,
187
182
  containerConnectionState: () => ConnectionState[this.connectionState],
188
- serializedContainer: config.serializedContainerState !== undefined,
183
+ serializedContainer: (loadProps === null || loadProps === void 0 ? void 0 : loadProps.pendingLocalState) !== undefined,
189
184
  },
190
185
  // we need to be judicious with our logging here to avoid generating too much data
191
186
  // all data logged here should be broadly applicable, and not specific to a
@@ -211,7 +206,7 @@ export class Container extends EventEmitterWithErrorHandling {
211
206
  // Warning: this is only a shallow clone. Mutation of any individual loader option will mutate it for
212
207
  // all clients that were loaded from the same loader (including summarizer clients).
213
208
  // Tracking alternative ways to handle this in AB#4129.
214
- this.options = Object.assign({}, this.loader.services.options);
209
+ this.options = Object.assign({}, this.createProps.options);
215
210
  this._deltaManager = this.createDeltaManager();
216
211
  this.connectionStateHandler = createConnectionStateHandler({
217
212
  logger: this.mc.logger,
@@ -227,7 +222,7 @@ export class Container extends EventEmitterWithErrorHandling {
227
222
  }
228
223
  },
229
224
  shouldClientJoinWrite: () => this._deltaManager.connectionManager.shouldJoinWrite(),
230
- maxClientLeaveWaitTime: this.loader.services.options.maxClientLeaveWaitTime,
225
+ maxClientLeaveWaitTime: this.createProps.options.maxClientLeaveWaitTime,
231
226
  logConnectionIssue: (eventName, category, details) => {
232
227
  const mode = this.connectionMode;
233
228
  // We get here when socket does not receive any ops on "write" connection, including
@@ -251,7 +246,7 @@ export class Container extends EventEmitterWithErrorHandling {
251
246
  this.connect();
252
247
  }
253
248
  },
254
- }, this.deltaManager, (_a = config.serializedContainerState) === null || _a === void 0 ? void 0 : _a.clientId);
249
+ }, this.deltaManager, (_a = loadProps === null || loadProps === void 0 ? void 0 : loadProps.pendingLocalState) === null || _a === void 0 ? void 0 : _a.clientId);
255
250
  this.on(savedContainerEvent, () => {
256
251
  this.connectionStateHandler.containerSaved();
257
252
  });
@@ -263,8 +258,8 @@ export class Container extends EventEmitterWithErrorHandling {
263
258
  : combineAppAndProtocolSummary(summaryTree, this.captureProtocolSummary());
264
259
  // Whether the combined summary tree has been forced on by either the loader option or the monitoring context.
265
260
  // Even if not forced on via this flag, combined summaries may still be enabled by service policy.
266
- const forceEnableSummarizeProtocolTree = (_b = this.mc.config.getBoolean("Fluid.Container.summarizeProtocolTree2")) !== null && _b !== void 0 ? _b : this.loader.services.options.summarizeProtocolTree;
267
- this.storageAdapter = new ContainerStorageAdapter(this.loader.services.detachedBlobStorage, this.mc.logger, (_c = config.serializedContainerState) === null || _c === void 0 ? void 0 : _c.snapshotBlobs, addProtocolSummaryIfMissing, forceEnableSummarizeProtocolTree);
261
+ const forceEnableSummarizeProtocolTree = (_b = this.mc.config.getBoolean("Fluid.Container.summarizeProtocolTree2")) !== null && _b !== void 0 ? _b : this.createProps.options.summarizeProtocolTree;
262
+ this.storageAdapter = new ContainerStorageAdapter(this.createProps.detachedBlobStorage, this.mc.logger, (_c = loadProps === null || loadProps === void 0 ? void 0 : loadProps.pendingLocalState) === null || _c === void 0 ? void 0 : _c.snapshotBlobs, addProtocolSummaryIfMissing, forceEnableSummarizeProtocolTree);
268
263
  const isDomAvailable = typeof document === "object" &&
269
264
  document !== null &&
270
265
  typeof document.addEventListener === "function" &&
@@ -286,37 +281,34 @@ export class Container extends EventEmitterWithErrorHandling {
286
281
  document.addEventListener("visibilitychange", this.visibilityEventHandler);
287
282
  }
288
283
  }
284
+ static async clone(container, loadProps, createParamOverrides) {
285
+ return this.load(loadProps, Object.assign(Object.assign({}, container.createProps), createParamOverrides));
286
+ }
289
287
  /**
290
288
  * Load an existing container.
291
289
  * @internal
292
290
  */
293
- static async load(loader, loadOptions, pendingLocalState, protocolHandlerBuilder) {
294
- const container = new Container(loader, {
295
- clientDetailsOverride: loadOptions.clientDetailsOverride,
296
- resolvedUrl: loadOptions.resolvedUrl,
297
- canReconnect: loadOptions.canReconnect,
298
- serializedContainerState: pendingLocalState,
299
- }, protocolHandlerBuilder);
291
+ static async load(loadProps, createProps) {
292
+ const { version, pendingLocalState, loadMode, resolvedUrl } = loadProps;
293
+ const container = new Container(createProps, loadProps);
300
294
  return PerformanceEvent.timedExecAsync(container.mc.logger, { eventName: "Load" }, async (event) => new Promise((resolve, reject) => {
301
- var _a, _b;
302
- const version = loadOptions.version;
303
295
  const defaultMode = { opsBeforeReturn: "cached" };
304
296
  // if we have pendingLocalState, anything we cached is not useful and we shouldn't wait for connection
305
297
  // to return container, so ignore this value and use undefined for opsBeforeReturn
306
298
  const mode = pendingLocalState
307
- ? Object.assign(Object.assign({}, ((_a = loadOptions.loadMode) !== null && _a !== void 0 ? _a : defaultMode)), { opsBeforeReturn: undefined }) : (_b = loadOptions.loadMode) !== null && _b !== void 0 ? _b : defaultMode;
299
+ ? Object.assign(Object.assign({}, (loadMode !== null && loadMode !== void 0 ? loadMode : defaultMode)), { opsBeforeReturn: undefined }) : loadMode !== null && loadMode !== void 0 ? loadMode : defaultMode;
308
300
  const onClosed = (err) => {
309
301
  // pre-0.58 error message: containerClosedWithoutErrorDuringLoad
310
302
  reject(err !== null && err !== void 0 ? err : new GenericError("Container closed without error during load"));
311
303
  };
312
304
  container.on("closed", onClosed);
313
305
  container
314
- .load(version, mode, pendingLocalState)
306
+ .load(version, mode, resolvedUrl, pendingLocalState)
315
307
  .finally(() => {
316
308
  container.removeListener("closed", onClosed);
317
309
  })
318
310
  .then((props) => {
319
- event.end(Object.assign(Object.assign({}, props), loadOptions.loadMode));
311
+ event.end(Object.assign(Object.assign({}, props), loadMode));
320
312
  resolve(container);
321
313
  }, (error) => {
322
314
  const err = normalizeError(error);
@@ -331,8 +323,8 @@ export class Container extends EventEmitterWithErrorHandling {
331
323
  /**
332
324
  * Create a new container in a detached state.
333
325
  */
334
- static async createDetached(loader, codeDetails, protocolHandlerBuilder) {
335
- const container = new Container(loader, {}, protocolHandlerBuilder);
326
+ static async createDetached(createProps, codeDetails) {
327
+ const container = new Container(createProps);
336
328
  return PerformanceEvent.timedExecAsync(container.mc.logger, { eventName: "CreateDetached" }, async (_event) => {
337
329
  await container.createDetached(codeDetails);
338
330
  return container;
@@ -342,8 +334,8 @@ export class Container extends EventEmitterWithErrorHandling {
342
334
  * Create a new container in a detached state that is initialized with a
343
335
  * snapshot from a previous detached container.
344
336
  */
345
- static async rehydrateDetachedFromSnapshot(loader, snapshot, protocolHandlerBuilder) {
346
- const container = new Container(loader, {}, protocolHandlerBuilder);
337
+ static async rehydrateDetachedFromSnapshot(createProps, snapshot) {
338
+ const container = new Container(createProps);
347
339
  return PerformanceEvent.timedExecAsync(container.mc.logger, { eventName: "RehydrateDetachedFromSnapshot" }, async (_event) => {
348
340
  const deserializedSummary = JSON.parse(snapshot);
349
341
  await container.rehydrateDetachedFromSnapshot(deserializedSummary);
@@ -387,7 +379,19 @@ export class Container extends EventEmitterWithErrorHandling {
387
379
  return this;
388
380
  }
389
381
  get resolvedUrl() {
390
- return this._resolvedUrl;
382
+ var _a;
383
+ /**
384
+ * All attached containers will have a document service,
385
+ * this is required, as attached containers are attached to
386
+ * a service. Detached containers will neither have a document
387
+ * service or a resolved url as they only exist locally.
388
+ * in order to create a document service a resolved url must
389
+ * first be obtained, this is how the container is identified.
390
+ * Because of this, the document service's resolved url
391
+ * is always the same as the containers, as we had to
392
+ * obtain the resolved url, and then create the service from it.
393
+ */
394
+ return (_a = this.service) === null || _a === void 0 ? void 0 : _a.resolvedUrl;
391
395
  }
392
396
  get loadedFromVersion() {
393
397
  return this._loadedFromVersion;
@@ -474,16 +478,16 @@ export class Container extends EventEmitterWithErrorHandling {
474
478
  return this._dirtyContainer;
475
479
  }
476
480
  get serviceFactory() {
477
- return this.loader.services.documentServiceFactory;
481
+ return this.createProps.documentServiceFactory;
478
482
  }
479
483
  get urlResolver() {
480
- return this.loader.services.urlResolver;
484
+ return this.createProps.urlResolver;
481
485
  }
482
486
  get scope() {
483
- return this.loader.services.scope;
487
+ return this.createProps.scope;
484
488
  }
485
489
  get codeLoader() {
486
- return this.loader.services.codeLoader;
490
+ return this.createProps.codeLoader;
487
491
  }
488
492
  /**
489
493
  * {@inheritDoc @fluidframework/container-definitions#IContainer.entryPoint}
@@ -540,7 +544,7 @@ export class Container extends EventEmitterWithErrorHandling {
540
544
  assert(this._lifecycleState === "closed" || this._lifecycleState === "disposed", 0x314 /* Container properly closed */);
541
545
  }
542
546
  closeCore(error) {
543
- var _a, _b, _c;
547
+ var _a;
544
548
  assert(!this.closed, 0x315 /* re-entrancy */);
545
549
  try {
546
550
  // Ensure that we raise all key events even if one of these throws
@@ -558,12 +562,6 @@ export class Container extends EventEmitterWithErrorHandling {
558
562
  this._lifecycleState = "closing";
559
563
  (_a = this._protocolHandler) === null || _a === void 0 ? void 0 : _a.close();
560
564
  this.connectionStateHandler.dispose();
561
- (_b = this._context) === null || _b === void 0 ? void 0 : _b.dispose(error !== undefined ? new Error(error.message) : undefined);
562
- this.storageAdapter.dispose();
563
- // Notify storage about critical errors. They may be due to disconnect between client & server knowledge
564
- // about file, like file being overwritten in storage, but client having stale local cache.
565
- // Driver need to ensure all caches are cleared on critical errors
566
- (_c = this.service) === null || _c === void 0 ? void 0 : _c.dispose(error);
567
565
  }
568
566
  catch (exception) {
569
567
  this.mc.logger.sendErrorEvent({ eventName: "ContainerCloseException" }, exception);
@@ -652,8 +650,7 @@ export class Container extends EventEmitterWithErrorHandling {
652
650
  const appSummary = this.context.createSummary();
653
651
  const protocolSummary = this.captureProtocolSummary();
654
652
  const combinedSummary = combineAppAndProtocolSummary(appSummary, protocolSummary);
655
- if (this.loader.services.detachedBlobStorage &&
656
- this.loader.services.detachedBlobStorage.size > 0) {
653
+ if (this.createProps.detachedBlobStorage && this.createProps.detachedBlobStorage.size > 0) {
657
654
  combinedSummary.tree[".hasAttachmentBlobs"] = {
658
655
  type: SummaryType.Blob,
659
656
  content: "true",
@@ -672,8 +669,8 @@ export class Container extends EventEmitterWithErrorHandling {
672
669
  assert(this._attachState === AttachState.Detached && !this.attachStarted, 0x205 /* "attach() called more than once" */);
673
670
  this.attachStarted = true;
674
671
  // If attachment blobs were uploaded in detached state we will go through a different attach flow
675
- const hasAttachmentBlobs = this.loader.services.detachedBlobStorage !== undefined &&
676
- this.loader.services.detachedBlobStorage.size > 0;
672
+ const hasAttachmentBlobs = this.createProps.detachedBlobStorage !== undefined &&
673
+ this.createProps.detachedBlobStorage.size > 0;
677
674
  try {
678
675
  assert(this.deltaManager.inbound.length === 0, 0x0d6 /* "Inbound queue should be empty when attaching" */);
679
676
  let summary;
@@ -697,31 +694,28 @@ export class Container extends EventEmitterWithErrorHandling {
697
694
  }
698
695
  }
699
696
  // Actually go and create the resolved document
700
- const createNewResolvedUrl = await this.urlResolver.resolve(request);
701
- ensureFluidResolvedUrl(createNewResolvedUrl);
702
697
  if (this.service === undefined) {
703
- assert(this.client.details.type !== summarizerClientType, 0x2c4 /* "client should not be summarizer before container is created" */);
698
+ const createNewResolvedUrl = await this.urlResolver.resolve(request);
699
+ assert(this.client.details.type !== summarizerClientType &&
700
+ createNewResolvedUrl !== undefined, 0x2c4 /* "client should not be summarizer before container is created" */);
704
701
  this.service = await runWithRetry(async () => this.serviceFactory.createContainer(summary, createNewResolvedUrl, this.subLogger, false), "containerAttach", this.mc.logger, {
705
702
  cancel: this.closeSignal,
706
703
  });
707
704
  }
708
- const resolvedUrl = this.service.resolvedUrl;
709
- ensureFluidResolvedUrl(resolvedUrl);
710
- this._resolvedUrl = resolvedUrl;
711
705
  await this.storageAdapter.connectToService(this.service);
712
706
  if (hasAttachmentBlobs) {
713
707
  // upload blobs to storage
714
- assert(!!this.loader.services.detachedBlobStorage, 0x24e /* "assertion for type narrowing" */);
708
+ assert(!!this.createProps.detachedBlobStorage, 0x24e /* "assertion for type narrowing" */);
715
709
  // build a table mapping IDs assigned locally to IDs assigned by storage and pass it to runtime to
716
710
  // support blob handles that only know about the local IDs
717
711
  const redirectTable = new Map();
718
712
  // if new blobs are added while uploading, upload them too
719
- while (redirectTable.size < this.loader.services.detachedBlobStorage.size) {
720
- const newIds = this.loader.services.detachedBlobStorage
713
+ while (redirectTable.size < this.createProps.detachedBlobStorage.size) {
714
+ const newIds = this.createProps.detachedBlobStorage
721
715
  .getBlobIds()
722
716
  .filter((id) => !redirectTable.has(id));
723
717
  for (const id of newIds) {
724
- const blob = await this.loader.services.detachedBlobStorage.readBlob(id);
718
+ const blob = await this.createProps.detachedBlobStorage.readBlob(id);
725
719
  const response = await this.storageAdapter.createBlob(blob);
726
720
  redirectTable.set(id, response.id);
727
721
  }
@@ -756,12 +750,8 @@ export class Container extends EventEmitterWithErrorHandling {
756
750
  catch (error) {
757
751
  // add resolved URL on error object so that host has the ability to find this document and delete it
758
752
  const newError = normalizeError(error);
759
- const resolvedUrl = this.resolvedUrl;
760
- if (isFluidResolvedUrl(resolvedUrl)) {
761
- newError.addTelemetryProperties({ resolvedUrl: resolvedUrl.url });
762
- }
753
+ newError.addTelemetryProperties({ resolvedUrl: (_a = this.resolvedUrl) === null || _a === void 0 ? void 0 : _a.url });
763
754
  this.close(newError);
764
- (_a = this.dispose) === null || _a === void 0 ? void 0 : _a.call(this, newError);
765
755
  throw newError;
766
756
  }
767
757
  }, { start: true, end: true, cancel: "generic" });
@@ -856,7 +846,6 @@ export class Container extends EventEmitterWithErrorHandling {
856
846
  .catch(() => false);
857
847
  }
858
848
  async processCodeProposal() {
859
- var _a;
860
849
  const codeDetails = this.getCodeDetailsFromQuorum();
861
850
  await Promise.all([
862
851
  this.deltaManager.inbound.pause(),
@@ -870,7 +859,6 @@ export class Container extends EventEmitterWithErrorHandling {
870
859
  // pre-0.58 error message: existingContextDoesNotSatisfyIncomingProposal
871
860
  const error = new GenericError("Existing context does not satisfy incoming proposal");
872
861
  this.close(error);
873
- (_a = this.dispose) === null || _a === void 0 ? void 0 : _a.call(this, error);
874
862
  }
875
863
  async getVersion(version) {
876
864
  const versions = await this.storageAdapter.getVersions(version, 1);
@@ -894,12 +882,9 @@ export class Container extends EventEmitterWithErrorHandling {
894
882
  *
895
883
  * @param specifiedVersion - Version SHA to load snapshot. If not specified, will fetch the latest snapshot.
896
884
  */
897
- async load(specifiedVersion, loadMode, pendingLocalState) {
885
+ async load(specifiedVersion, loadMode, resolvedUrl, pendingLocalState) {
898
886
  var _a;
899
- if (this._resolvedUrl === undefined) {
900
- throw new Error("Attempting to load without a resolved url");
901
- }
902
- this.service = await this.serviceFactory.createDocumentService(this._resolvedUrl, this.subLogger, this.client.details.type === summarizerClientType);
887
+ this.service = await this.serviceFactory.createDocumentService(resolvedUrl, this.subLogger, this.client.details.type === summarizerClientType);
903
888
  // Ideally we always connect as "read" by default.
904
889
  // Currently that works with SPO & r11s, because we get "write" connection when connecting to non-existing file.
905
890
  // We should not rely on it by (one of them will address the issue, but we need to address both)
@@ -925,9 +910,7 @@ export class Container extends EventEmitterWithErrorHandling {
925
910
  else {
926
911
  // if we have pendingLocalState we can load without storage; don't wait for connection
927
912
  this.storageAdapter.connectToService(this.service).catch((error) => {
928
- var _a;
929
913
  this.close(error);
930
- (_a = this.dispose) === null || _a === void 0 ? void 0 : _a.call(this, error);
931
914
  });
932
915
  }
933
916
  this._attachState = AttachState.Attached;
@@ -1053,8 +1036,8 @@ export class Container extends EventEmitterWithErrorHandling {
1053
1036
  }
1054
1037
  async rehydrateDetachedFromSnapshot(detachedContainerSnapshot) {
1055
1038
  if (detachedContainerSnapshot.tree[".hasAttachmentBlobs"] !== undefined) {
1056
- assert(!!this.loader.services.detachedBlobStorage &&
1057
- this.loader.services.detachedBlobStorage.size > 0, 0x250 /* "serialized container with attachment blobs must be rehydrated with detached blob storage" */);
1039
+ assert(!!this.createProps.detachedBlobStorage &&
1040
+ this.createProps.detachedBlobStorage.size > 0, 0x250 /* "serialized container with attachment blobs must be rehydrated with detached blob storage" */);
1058
1041
  delete detachedContainerSnapshot.tree[".hasAttachmentBlobs"];
1059
1042
  }
1060
1043
  const snapshotTree = getSnapshotTreeFromSerializedContainer(detachedContainerSnapshot);
@@ -1108,7 +1091,7 @@ export class Container extends EventEmitterWithErrorHandling {
1108
1091
  }
1109
1092
  initializeProtocolState(attributes, quorumSnapshot) {
1110
1093
  var _a;
1111
- const protocolHandlerBuilder = (_a = this.protocolHandlerBuilder) !== null && _a !== void 0 ? _a : ((...args) => new ProtocolHandler(...args, new Audience()));
1094
+ const protocolHandlerBuilder = (_a = this.createProps.protocolHandlerBuilder) !== null && _a !== void 0 ? _a : ((...args) => new ProtocolHandler(...args, new Audience()));
1112
1095
  const protocol = protocolHandlerBuilder(attributes, quorumSnapshot, (key, value) => this.submitMessage(MessageType.Propose, JSON.stringify({ key, value })));
1113
1096
  const protocolLogger = ChildLogger.create(this.subLogger, "ProtocolHandler");
1114
1097
  protocol.quorum.on("error", (error) => {
@@ -1129,10 +1112,8 @@ export class Container extends EventEmitterWithErrorHandling {
1129
1112
  });
1130
1113
  }
1131
1114
  this.processCodeProposal().catch((error) => {
1132
- var _a;
1133
1115
  const normalizedError = normalizeError(error);
1134
1116
  this.close(normalizedError);
1135
- (_a = this.dispose) === null || _a === void 0 ? void 0 : _a.call(this, normalizedError);
1136
1117
  throw error;
1137
1118
  });
1138
1119
  }
@@ -1322,7 +1303,6 @@ export class Container extends EventEmitterWithErrorHandling {
1322
1303
  }
1323
1304
  // back-compat: ADO #1385: Remove in the future, summary op should come through submitSummaryMessage()
1324
1305
  submitContainerMessage(type, contents, batch, metadata) {
1325
- var _a;
1326
1306
  switch (type) {
1327
1307
  case MessageType.Operation:
1328
1308
  return this.submitMessage(type, JSON.stringify(contents), batch, metadata);
@@ -1331,7 +1311,6 @@ export class Container extends EventEmitterWithErrorHandling {
1331
1311
  default: {
1332
1312
  const newError = new GenericError("invalidContainerSubmitOpType", undefined /* error */, { messageType: type });
1333
1313
  this.close(newError);
1334
- (_a = this.dispose) === null || _a === void 0 ? void 0 : _a.call(this, newError);
1335
1314
  return -1;
1336
1315
  }
1337
1316
  }
@@ -1440,8 +1419,9 @@ export class Container extends EventEmitterWithErrorHandling {
1440
1419
  assert(((_a = this._context) === null || _a === void 0 ? void 0 : _a.disposed) !== false, 0x0dd /* "Existing context not disposed" */);
1441
1420
  // The relative loader will proxy requests to '/' to the loader itself assuming no non-cache flags
1442
1421
  // are set. Global requests will still go directly to the loader
1443
- const loader = new RelativeLoader(this, this.loader);
1444
- this._context = await ContainerContext.createOrLoad(this, this.scope, this.codeLoader, codeDetails, snapshot, new DeltaManagerProxy(this._deltaManager), new QuorumProxy(this.protocolHandler.quorum), loader, (type, contents, batch, metadata) => this.submitContainerMessage(type, contents, batch, metadata), (summaryOp, referenceSequenceNumber) => this.submitSummaryMessage(summaryOp, referenceSequenceNumber), (batch, referenceSequenceNumber) => this.submitBatch(batch, referenceSequenceNumber), (message) => this.submitSignal(message), (error) => { var _a; return (_a = this.dispose) === null || _a === void 0 ? void 0 : _a.call(this, error); }, (error) => this.close(error), Container.version, (dirty) => this.updateDirtyContainerState(dirty), existing, pendingLocalState);
1422
+ const maybeLoader = this.scope;
1423
+ const loader = new RelativeLoader(this, maybeLoader.ILoader);
1424
+ this._context = await ContainerContext.createOrLoad(this, this.scope, this.codeLoader, codeDetails, snapshot, new DeltaManagerProxy(this._deltaManager), new QuorumProxy(this.protocolHandler.quorum), loader, (type, contents, batch, metadata) => this.submitContainerMessage(type, contents, batch, metadata), (summaryOp, referenceSequenceNumber) => this.submitSummaryMessage(summaryOp, referenceSequenceNumber), (batch, referenceSequenceNumber) => this.submitBatch(batch, referenceSequenceNumber), (message) => this.submitSignal(message), (error) => this.dispose(error), (error) => this.close(error), Container.version, (dirty) => this.updateDirtyContainerState(dirty), existing, pendingLocalState);
1445
1425
  this.emit("contextChanged", codeDetails);
1446
1426
  }
1447
1427
  updateDirtyContainerState(dirty) {