@fluidframework/shared-object-base 2.0.0-rc.1.0.3 → 2.0.0-rc.2.0.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.
Files changed (125) hide show
  1. package/{.eslintrc.js → .eslintrc.cjs} +4 -1
  2. package/{.mocharc.js → .mocharc.cjs} +1 -1
  3. package/CHANGELOG.md +10 -0
  4. package/{api-extractor-esm.json → api-extractor-cjs.json} +5 -1
  5. package/api-extractor-lint.json +1 -1
  6. package/api-extractor.json +1 -1
  7. package/api-report/shared-object-base.api.md +7 -9
  8. package/dist/handle.d.ts +1 -1
  9. package/dist/handle.d.ts.map +1 -1
  10. package/dist/handle.js.map +1 -1
  11. package/dist/index.d.ts +6 -6
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +16 -15
  14. package/dist/index.js.map +1 -1
  15. package/dist/package.json +3 -0
  16. package/dist/packageVersion.d.ts +1 -1
  17. package/dist/packageVersion.js +1 -1
  18. package/dist/packageVersion.js.map +1 -1
  19. package/dist/serializer.js +2 -2
  20. package/dist/serializer.js.map +1 -1
  21. package/dist/shared-object-base-alpha.d.ts +26 -10
  22. package/dist/shared-object-base-beta.d.ts +6 -277
  23. package/dist/shared-object-base-public.d.ts +6 -277
  24. package/dist/shared-object-base-untrimmed.d.ts +31 -10
  25. package/dist/sharedObject.d.ts +26 -12
  26. package/dist/sharedObject.d.ts.map +1 -1
  27. package/dist/sharedObject.js +56 -41
  28. package/dist/sharedObject.js.map +1 -1
  29. package/dist/summarySerializer.d.ts +1 -1
  30. package/dist/summarySerializer.d.ts.map +1 -1
  31. package/dist/summarySerializer.js +2 -2
  32. package/dist/summarySerializer.js.map +1 -1
  33. package/dist/tsdoc-metadata.json +1 -1
  34. package/dist/utils.d.ts +7 -1
  35. package/dist/utils.d.ts.map +1 -1
  36. package/dist/utils.js +14 -1
  37. package/dist/utils.js.map +1 -1
  38. package/lib/{handle.d.mts → handle.d.ts} +2 -2
  39. package/lib/handle.d.ts.map +1 -0
  40. package/lib/{handle.mjs → handle.js} +1 -1
  41. package/lib/handle.js.map +1 -0
  42. package/lib/index.d.ts +11 -0
  43. package/lib/index.d.ts.map +1 -0
  44. package/lib/index.js +10 -0
  45. package/lib/index.js.map +1 -0
  46. package/lib/{packageVersion.d.mts → packageVersion.d.ts} +2 -2
  47. package/lib/packageVersion.d.ts.map +1 -0
  48. package/lib/{packageVersion.mjs → packageVersion.js} +2 -2
  49. package/lib/packageVersion.js.map +1 -0
  50. package/lib/{remoteObjectHandle.d.mts → remoteObjectHandle.d.ts} +1 -1
  51. package/lib/remoteObjectHandle.d.ts.map +1 -0
  52. package/lib/{remoteObjectHandle.mjs → remoteObjectHandle.js} +1 -1
  53. package/lib/remoteObjectHandle.js.map +1 -0
  54. package/lib/{serializer.d.mts → serializer.d.ts} +1 -1
  55. package/lib/serializer.d.ts.map +1 -0
  56. package/lib/{serializer.mjs → serializer.js} +4 -2
  57. package/lib/serializer.js.map +1 -0
  58. package/lib/{shared-object-base-alpha.d.mts → shared-object-base-alpha.d.ts} +26 -10
  59. package/lib/shared-object-base-beta.d.ts +118 -0
  60. package/lib/shared-object-base-public.d.ts +118 -0
  61. package/lib/{shared-object-base-untrimmed.d.mts → shared-object-base-untrimmed.d.ts} +31 -10
  62. package/lib/{sharedObject.d.mts → sharedObject.d.ts} +27 -13
  63. package/lib/sharedObject.d.ts.map +1 -0
  64. package/lib/{sharedObject.mjs → sharedObject.js} +54 -39
  65. package/lib/sharedObject.js.map +1 -0
  66. package/lib/{summarySerializer.d.mts → summarySerializer.d.ts} +2 -2
  67. package/lib/summarySerializer.d.ts.map +1 -0
  68. package/lib/{summarySerializer.mjs → summarySerializer.js} +2 -2
  69. package/lib/summarySerializer.js.map +1 -0
  70. package/lib/test/attachingBindingAndConnecting.spec.js +334 -0
  71. package/lib/test/attachingBindingAndConnecting.spec.js.map +1 -0
  72. package/lib/test/serializer.spec.js +166 -0
  73. package/lib/test/serializer.spec.js.map +1 -0
  74. package/lib/test/sharedObject.spec.js +72 -0
  75. package/lib/test/sharedObject.spec.js.map +1 -0
  76. package/lib/test/types/validateSharedObjectBasePrevious.generated.js +26 -0
  77. package/lib/test/types/validateSharedObjectBasePrevious.generated.js.map +1 -0
  78. package/lib/test/utils.js +37 -0
  79. package/lib/test/utils.js.map +1 -0
  80. package/lib/{types.d.mts → types.d.ts} +1 -1
  81. package/lib/types.d.ts.map +1 -0
  82. package/lib/{types.mjs → types.js} +1 -1
  83. package/lib/types.js.map +1 -0
  84. package/lib/{utils.d.mts → utils.d.ts} +8 -2
  85. package/lib/utils.d.ts.map +1 -0
  86. package/lib/{utils.mjs → utils.js} +13 -1
  87. package/lib/utils.js.map +1 -0
  88. package/lib/{valueType.d.mts → valueType.d.ts} +1 -1
  89. package/lib/valueType.d.ts.map +1 -0
  90. package/lib/{valueType.mjs → valueType.js} +1 -1
  91. package/lib/valueType.js.map +1 -0
  92. package/package.json +44 -49
  93. package/src/handle.ts +1 -1
  94. package/src/index.ts +7 -6
  95. package/src/packageVersion.ts +1 -1
  96. package/src/serializer.ts +1 -1
  97. package/src/sharedObject.ts +84 -53
  98. package/src/summarySerializer.ts +1 -1
  99. package/src/utils.ts +14 -1
  100. package/tsconfig.cjs.json +7 -0
  101. package/tsconfig.json +2 -5
  102. package/lib/handle.d.mts.map +0 -1
  103. package/lib/handle.mjs.map +0 -1
  104. package/lib/index.d.mts +0 -11
  105. package/lib/index.d.mts.map +0 -1
  106. package/lib/index.mjs +0 -10
  107. package/lib/index.mjs.map +0 -1
  108. package/lib/packageVersion.d.mts.map +0 -1
  109. package/lib/packageVersion.mjs.map +0 -1
  110. package/lib/remoteObjectHandle.d.mts.map +0 -1
  111. package/lib/remoteObjectHandle.mjs.map +0 -1
  112. package/lib/serializer.d.mts.map +0 -1
  113. package/lib/serializer.mjs.map +0 -1
  114. package/lib/shared-object-base-beta.d.mts +0 -389
  115. package/lib/shared-object-base-public.d.mts +0 -389
  116. package/lib/sharedObject.d.mts.map +0 -1
  117. package/lib/sharedObject.mjs.map +0 -1
  118. package/lib/summarySerializer.d.mts.map +0 -1
  119. package/lib/summarySerializer.mjs.map +0 -1
  120. package/lib/types.d.mts.map +0 -1
  121. package/lib/types.mjs.map +0 -1
  122. package/lib/utils.d.mts.map +0 -1
  123. package/lib/utils.mjs.map +0 -1
  124. package/lib/valueType.d.mts.map +0 -1
  125. package/lib/valueType.mjs.map +0 -1
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { v4 as uuid } from "uuid";
7
- import { IFluidHandle, ITelemetryProperties } from "@fluidframework/core-interfaces";
7
+ import { IFluidHandle, ITelemetryBaseProperties } from "@fluidframework/core-interfaces";
8
8
  import {
9
9
  ITelemetryLoggerExt,
10
10
  createChildLogger,
@@ -33,14 +33,15 @@ import {
33
33
  totalBlobSizePropertyName,
34
34
  IExperimentalIncrementalSummaryContext,
35
35
  } from "@fluidframework/runtime-definitions";
36
- import { FluidSerializer, IFluidSerializer } from "./serializer";
37
- import { SharedObjectHandle } from "./handle";
38
- import { SummarySerializer } from "./summarySerializer";
39
- import { ISharedObject, ISharedObjectEvents } from "./types";
36
+ import { FluidSerializer, IFluidSerializer } from "./serializer.js";
37
+ import { SharedObjectHandle } from "./handle.js";
38
+ import { SummarySerializer } from "./summarySerializer.js";
39
+ import { ISharedObject, ISharedObjectEvents } from "./types.js";
40
+ import { makeHandlesSerializable, parseHandles } from "./utils.js";
40
41
 
41
42
  /**
42
43
  * Base class from which all shared objects derive.
43
- * @public
44
+ * @alpha
44
45
  */
45
46
  export abstract class SharedObjectCore<TEvent extends ISharedObjectEvents = ISharedObjectEvents>
46
47
  extends EventEmitterWithErrorHandling<TEvent>
@@ -122,8 +123,6 @@ export abstract class SharedObjectCore<TEvent extends ISharedObjectEvents = ISha
122
123
  this.mc = loggerToMonitoringContext(this.logger);
123
124
 
124
125
  [this.opProcessingHelper, this.callbacksHelper] = this.setUpSampledTelemetryHelpers();
125
-
126
- this.attachListeners();
127
126
  }
128
127
 
129
128
  /**
@@ -145,7 +144,7 @@ export abstract class SharedObjectCore<TEvent extends ISharedObjectEvents = ISha
145
144
  this.logger,
146
145
  this.mc.config.getNumber("Fluid.SharedObject.OpProcessingTelemetrySampling") ?? 1000,
147
146
  true,
148
- new Map<string, ITelemetryProperties>([
147
+ new Map<string, ITelemetryBaseProperties>([
149
148
  ["local", { localOp: true }],
150
149
  ["remote", { localOp: false }],
151
150
  ]),
@@ -209,14 +208,21 @@ export abstract class SharedObjectCore<TEvent extends ISharedObjectEvents = ISha
209
208
  throw error;
210
209
  }
211
210
 
212
- private attachListeners() {
213
- // Only listen to these events if not attached.
214
- if (!this.isAttached()) {
215
- this.runtime.once("attaching", () => {
216
- // Calling this will let the dds to do any custom processing based on attached
217
- // like starting generating ops.
218
- this.didAttach();
219
- });
211
+ private setBoundAndHandleAttach() {
212
+ // Ensure didAttach is only called once, and we only register a single event
213
+ // but we still call setConnectionState as our existing mocks don't
214
+ // always propagate connection state
215
+ this.setBoundAndHandleAttach = () => this.setConnectionState(this.runtime.connected);
216
+ this._isBoundToContext = true;
217
+ const runDidAttach = () => {
218
+ // Allows objects to do any custom processing if it is attached.
219
+ this.didAttach();
220
+ this.setConnectionState(this.runtime.connected);
221
+ };
222
+ if (this.isAttached()) {
223
+ runDidAttach();
224
+ } else {
225
+ this.runtime.once("attaching", runDidAttach);
220
226
  }
221
227
  }
222
228
 
@@ -226,13 +232,13 @@ export abstract class SharedObjectCore<TEvent extends ISharedObjectEvents = ISha
226
232
  * @param services - Services used by the shared object
227
233
  */
228
234
  public async load(services: IChannelServices): Promise<void> {
229
- if (this.runtime.attachState !== AttachState.Detached) {
230
- this.services = services;
231
- }
235
+ this.services = services;
236
+ // set this before load so that isAttached is true
237
+ // for attached runtimes when load core is running
238
+ this._isBoundToContext = true;
232
239
  await this.loadCore(services.objectStorage);
233
- if (this.runtime.attachState !== AttachState.Detached) {
234
- this.attachDeltaHandler();
235
- }
240
+ this.attachDeltaHandler();
241
+ this.setBoundAndHandleAttach();
236
242
  }
237
243
 
238
244
  /**
@@ -247,28 +253,36 @@ export abstract class SharedObjectCore<TEvent extends ISharedObjectEvents = ISha
247
253
  * {@inheritDoc (ISharedObject:interface).bindToContext}
248
254
  */
249
255
  public bindToContext(): void {
250
- if (this._isBoundToContext) {
251
- return;
256
+ // ensure the method only runs once by removing the implementation
257
+ // without this the method suffers from re-entrancy issues
258
+ this.bindToContext = () => {};
259
+ if (!this._isBoundToContext) {
260
+ this.runtime.bindChannel(this);
261
+ // must set after bind channel so isAttached doesn't report true
262
+ // before binding is complete
263
+ this.setBoundAndHandleAttach();
252
264
  }
253
-
254
- this._isBoundToContext = true;
255
-
256
- this.runtime.bindChannel(this);
257
265
  }
258
266
 
259
267
  /**
260
268
  * {@inheritDoc @fluidframework/datastore-definitions#(IChannel:interface).connect}
261
269
  */
262
270
  public connect(services: IChannelServices) {
263
- this.services = services;
264
- this.attachDeltaHandler();
271
+ // handle the case where load is called
272
+ // before connect; loading detached data stores
273
+ if (this.services === undefined) {
274
+ this.services = services;
275
+ this.attachDeltaHandler();
276
+ }
277
+
278
+ this.setBoundAndHandleAttach();
265
279
  }
266
280
 
267
281
  /**
268
282
  * {@inheritDoc @fluidframework/datastore-definitions#(IChannel:interface).isAttached}
269
283
  */
270
284
  public isAttached(): boolean {
271
- return this.services !== undefined && this.runtime.attachState !== AttachState.Detached;
285
+ return this._isBoundToContext && this.runtime.attachState !== AttachState.Detached;
272
286
  }
273
287
 
274
288
  /**
@@ -345,9 +359,15 @@ export abstract class SharedObjectCore<TEvent extends ISharedObjectEvents = ISha
345
359
  */
346
360
  protected abstract onDisconnect();
347
361
 
362
+ /**
363
+ * The serializer to serialize / parse handles.
364
+ */
365
+ protected abstract get serializer(): IFluidSerializer;
366
+
348
367
  /**
349
368
  * Submits a message by the local client to the runtime.
350
- * @param content - Content of the message
369
+ * @param content - Content of the message. Note: handles contained in the
370
+ * message object should not be encoded in any way
351
371
  * @param localOpMetadata - The local metadata associated with the message. This is kept locally by the runtime
352
372
  * and not sent to the server. This will be sent back when this message is received back from the server. This is
353
373
  * also sent if we are asked to resubmit the message.
@@ -356,7 +376,10 @@ export abstract class SharedObjectCore<TEvent extends ISharedObjectEvents = ISha
356
376
  this.verifyNotClosed();
357
377
  if (this.isAttached()) {
358
378
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
359
- this.services!.deltaConnection.submit(content, localOpMetadata);
379
+ this.services!.deltaConnection.submit(
380
+ makeHandlesSerializable(content, this.serializer, this.handle),
381
+ localOpMetadata,
382
+ );
360
383
  }
361
384
  }
362
385
 
@@ -431,10 +454,6 @@ export abstract class SharedObjectCore<TEvent extends ISharedObjectEvents = ISha
431
454
  this.services !== undefined,
432
455
  0x07a /* "Services should be there to attach delta handler" */,
433
456
  );
434
- this._isBoundToContext = true;
435
- // Allows objects to do any custom processing if it is attached.
436
- this.didAttach();
437
-
438
457
  // attachDeltaHandler is only called after services is assigned
439
458
  this.services.deltaConnection.attach({
440
459
  process: (
@@ -442,7 +461,11 @@ export abstract class SharedObjectCore<TEvent extends ISharedObjectEvents = ISha
442
461
  local: boolean,
443
462
  localOpMetadata: unknown,
444
463
  ) => {
445
- this.process(message, local, localOpMetadata);
464
+ this.process(
465
+ { ...message, contents: parseHandles(message.contents, this.serializer) },
466
+ local,
467
+ localOpMetadata,
468
+ );
446
469
  },
447
470
  setConnectionState: (connected: boolean) => {
448
471
  this.setConnectionState(connected);
@@ -450,17 +473,13 @@ export abstract class SharedObjectCore<TEvent extends ISharedObjectEvents = ISha
450
473
  reSubmit: (content: any, localOpMetadata: unknown) => {
451
474
  this.reSubmit(content, localOpMetadata);
452
475
  },
453
- applyStashedOp: (content: any): unknown => {
454
- return this.applyStashedOp(content);
476
+ applyStashedOp: (content: any): void => {
477
+ this.applyStashedOp(parseHandles(content, this.serializer));
455
478
  },
456
479
  rollback: (content: any, localOpMetadata: unknown) => {
457
480
  this.rollback(content, localOpMetadata);
458
481
  },
459
482
  });
460
-
461
- // Trigger initial state
462
- // attachDeltaHandler is only called after services is assigned
463
- this.setConnectionState(this.services.deltaConnection.connected);
464
483
  }
465
484
 
466
485
  /**
@@ -468,7 +487,10 @@ export abstract class SharedObjectCore<TEvent extends ISharedObjectEvents = ISha
468
487
  * @param connected - true if connected, false otherwise.
469
488
  */
470
489
  private setConnectionState(connected: boolean) {
471
- if (this._connected === connected) {
490
+ // only an attached shared object can transition its
491
+ // connected state. This is defensive, as some
492
+ // of our test harnesses don't handle this correctly
493
+ if (!this.isAttached() || this._connected === connected) {
472
494
  // Not changing state, nothing the same.
473
495
  return;
474
496
  }
@@ -529,14 +551,23 @@ export abstract class SharedObjectCore<TEvent extends ISharedObjectEvents = ISha
529
551
  }
530
552
 
531
553
  /**
532
- * Apply changes from an op. Used when rehydrating an attached container
533
- * with pending changes. This prepares the SharedObject for seeing an ACK
534
- * for the op or resubmitting the op upon reconnection.
554
+ * Apply changes from the provided op content just as if a local client has made the change,
555
+ * including submitting the op. Used when rehydrating an attached container
556
+ * with pending changes. The rehydration process replays all remote ops
557
+ * and applies stashed ops after the remote op with a sequence number
558
+ * that matches that of the stashed op is applied. This ensures
559
+ * stashed ops are applied at the same state they were originally created.
560
+ *
561
+ * It is possible that stashed ops have been sent in the past, and will be found when
562
+ * the shared object catches up with remotes ops.
563
+ * So this prepares the SharedObject for seeing potentially seeing the ACK.
564
+ * If no matching remote op is found, all the applied stashed ops will go
565
+ * through the normal resubmit flow upon reconnection, which allows the dds
566
+ * to rebase them to the latest state, and then resubmit them.
567
+ *
535
568
  * @param content - Contents of a stashed op.
536
- * @returns localMetadata of the op, to be passed to process() or resubmit()
537
- * when the op is ACKed or resubmitted, respectively
538
569
  */
539
- protected abstract applyStashedOp(content: any): unknown;
570
+ protected abstract applyStashedOp(content: any): void;
540
571
 
541
572
  /**
542
573
  * Emit an event. This function is only intended for use by DDS classes that extend SharedObject/SharedObjectCore,
@@ -581,7 +612,7 @@ export abstract class SharedObjectCore<TEvent extends ISharedObjectEvents = ISha
581
612
  /**
582
613
  * SharedObject with simplified, synchronous summarization and GC.
583
614
  * DDS implementations with async and incremental summarization should extend SharedObjectCore directly instead.
584
- * @public
615
+ * @alpha
585
616
  */
586
617
  export abstract class SharedObject<
587
618
  TEvent extends ISharedObjectEvents = ISharedObjectEvents,
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  import { IFluidHandle } from "@fluidframework/core-interfaces";
7
- import { FluidSerializer } from "./serializer";
7
+ import { FluidSerializer } from "./serializer.js";
8
8
 
9
9
  /**
10
10
  * Serializer implementation for serializing handles during summary.
package/src/utils.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  import { IFluidHandle } from "@fluidframework/core-interfaces";
7
7
  import { ISummaryTreeWithStats } from "@fluidframework/runtime-definitions";
8
8
  import { SummaryTreeBuilder } from "@fluidframework/runtime-utils";
9
- import { IFluidSerializer } from "./serializer";
9
+ import { IFluidSerializer } from "./serializer.js";
10
10
 
11
11
  /**
12
12
  * Given a mostly-plain object that may have handle objects embedded within, return a string representation of an object
@@ -78,3 +78,16 @@ export function createSingleBlobSummary(
78
78
  builder.addBlob(key, content);
79
79
  return builder.getSummaryTree();
80
80
  }
81
+
82
+ /**
83
+ * Binds all handles found in `value` to `bind`. Does not modify original input.
84
+ *
85
+ * @internal
86
+ */
87
+ export function bindHandles(value: any, serializer: IFluidSerializer, bind: IFluidHandle): void {
88
+ // N.B. AB#7316 this could be made more efficient by writing an ad hoc
89
+ // implementation that doesn't clone at all. Today the distinction between
90
+ // this function and `encode` is purely semantic -- encoding both serializes
91
+ // handles and binds them, but sometimes we only wish to do the latter
92
+ serializer.encode(value, bind);
93
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ // This config must be used in a "type": "commonjs" environment. (Use fluid-tsc commonjs.)
3
+ "extends": "./tsconfig.json",
4
+ "compilerOptions": {
5
+ "outDir": "./dist",
6
+ },
7
+ }
package/tsconfig.json CHANGED
@@ -1,12 +1,9 @@
1
1
  {
2
- "extends": [
3
- "../../../common/build/build-common/tsconfig.base.json",
4
- "../../../common/build/build-common/tsconfig.cjs.json",
5
- ],
2
+ "extends": "../../../common/build/build-common/tsconfig.node16.json",
6
3
  "include": ["src/**/*"],
7
4
  "exclude": ["src/test/**/*"],
8
5
  "compilerOptions": {
9
6
  "rootDir": "./src",
10
- "outDir": "./dist",
7
+ "outDir": "./lib",
11
8
  },
12
9
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"handle.d.mts","sourceRoot":"","sources":["../src/handle.ts"],"names":[],"mappings":"AAAA;;;GAGG;OAEI,EAAE,mBAAmB,EAAE,MAAM,iCAAiC;OAC9D,EAAE,iBAAiB,EAAE,MAAM,2BAA2B;OACtD,EAAE,aAAa,EAAE;AAExB;;;;;;;;;;GAUG;AACH,qBAAa,kBAAmB,SAAQ,iBAAiB,CAAC,aAAa,CAAC;IAgBtE,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,aAAa;IAfxC;;OAEG;IACH,IAAW,UAAU,IAAI,OAAO,CAE/B;IAED;;;;;;OAMG;gBAEiB,KAAK,EAAE,aAAa,EACvC,IAAI,EAAE,MAAM,EACZ,YAAY,EAAE,mBAAmB;IAKlC;;;OAGG;IACI,WAAW,IAAI,IAAI;CAI1B"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"handle.mjs","sourceRoot":"","sources":["../src/handle.ts"],"names":[],"mappings":"AAAA;;;GAGG;OAGI,EAAE,iBAAiB,EAAE,MAAM,2BAA2B;AAG7D;;;;;;;;;;GAUG;AACH,MAAM,OAAO,kBAAmB,SAAQ,iBAAgC;IACvE;;OAEG;IACH,IAAW,UAAU;QACpB,OAAO,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;IAChC,CAAC;IAED;;;;;;OAMG;IACH,YACoB,KAAoB,EACvC,IAAY,EACZ,YAAiC;QAEjC,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC;QAJd,UAAK,GAAL,KAAK,CAAe;IAKxC,CAAC;IAED;;;OAGG;IACI,WAAW;QACjB,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC;QAC3B,KAAK,CAAC,WAAW,EAAE,CAAC;IACrB,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { IFluidHandleContext } from \"@fluidframework/core-interfaces\";\nimport { FluidObjectHandle } from \"@fluidframework/datastore\";\nimport { ISharedObject } from \"./types\";\n\n/**\n * Handle for a shared object.\n *\n * @remarks\n *\n * This object is used for already loaded (in-memory) shared objects and is used only for serialization purposes.\n *\n * De-serialization process goes through {@link @fluidframework/datastore#FluidObjectHandle}, and request flow:\n * {@link @fluidframework/datastore#FluidDataStoreRuntime.request} recognizes requests in the form of\n * '/\\<shared object id\\>' and loads shared object.\n */\nexport class SharedObjectHandle extends FluidObjectHandle<ISharedObject> {\n\t/**\n\t * Whether services have been attached for the associated shared object.\n\t */\n\tpublic get isAttached(): boolean {\n\t\treturn this.value.isAttached();\n\t}\n\n\t/**\n\t * Creates a new SharedObjectHandle.\n\t * @param value - The shared object this handle is for.\n\t * @param path - The id of the shared object. It is also the path to this object relative to the routeContext.\n\t * @param routeContext - The parent {@link @fluidframework/core-interfaces#IFluidHandleContext} that has a route\n\t * to this handle.\n\t */\n\tconstructor(\n\t\tprotected readonly value: ISharedObject,\n\t\tpath: string,\n\t\trouteContext: IFluidHandleContext,\n\t) {\n\t\tsuper(value, path, routeContext);\n\t}\n\n\t/**\n\t * Attaches all bound handles first (which may in turn attach further handles), then attaches this handle.\n\t * When attaching the handle, it registers the associated shared object.\n\t */\n\tpublic attachGraph(): void {\n\t\tthis.value.bindToContext();\n\t\tsuper.attachGraph();\n\t}\n}\n"]}
package/lib/index.d.mts DELETED
@@ -1,11 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
- export { FluidSerializer, IFluidSerializer } from "./serializer.mjs";
6
- export { SharedObject, SharedObjectCore } from "./sharedObject.mjs";
7
- export { SummarySerializer } from "./summarySerializer.mjs";
8
- export { ISharedObject, ISharedObjectEvents } from "./types.mjs";
9
- export { createSingleBlobSummary, makeHandlesSerializable, parseHandles, serializeHandles, } from "./utils.mjs";
10
- export { ValueType } from "./valueType.mjs";
11
- //# sourceMappingURL=index.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;OAEI,EAAE,eAAe,EAAE,gBAAgB,EAAE;OACrC,EAAE,YAAY,EAAE,gBAAgB,EAAE;OAClC,EAAE,iBAAiB,EAAE;OACrB,EAAE,aAAa,EAAE,mBAAmB,EAAE;OACtC,EACN,uBAAuB,EACvB,uBAAuB,EACvB,YAAY,EACZ,gBAAgB,GAChB;OACM,EAAE,SAAS,EAAE"}
package/lib/index.mjs DELETED
@@ -1,10 +0,0 @@
1
- /*!
2
- * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
3
- * Licensed under the MIT License.
4
- */
5
- export { FluidSerializer } from "./serializer.mjs";
6
- export { SharedObject, SharedObjectCore } from "./sharedObject.mjs";
7
- export { SummarySerializer } from "./summarySerializer.mjs";
8
- export { createSingleBlobSummary, makeHandlesSerializable, parseHandles, serializeHandles, } from "./utils.mjs";
9
- export { ValueType } from "./valueType.mjs";
10
- //# sourceMappingURL=index.mjs.map
package/lib/index.mjs.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;OAEI,EAAE,eAAe,EAAoB;OACrC,EAAE,YAAY,EAAE,gBAAgB,EAAE;OAClC,EAAE,iBAAiB,EAAE;OAErB,EACN,uBAAuB,EACvB,uBAAuB,EACvB,YAAY,EACZ,gBAAgB,GAChB;OACM,EAAE,SAAS,EAAE","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nexport { FluidSerializer, IFluidSerializer } from \"./serializer\";\nexport { SharedObject, SharedObjectCore } from \"./sharedObject\";\nexport { SummarySerializer } from \"./summarySerializer\";\nexport { ISharedObject, ISharedObjectEvents } from \"./types\";\nexport {\n\tcreateSingleBlobSummary,\n\tmakeHandlesSerializable,\n\tparseHandles,\n\tserializeHandles,\n} from \"./utils\";\nexport { ValueType } from \"./valueType\";\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"packageVersion.d.mts","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,eAAO,MAAM,OAAO,uCAAuC,CAAC;AAC5D,eAAO,MAAM,UAAU,mBAAmB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"packageVersion.mjs","sourceRoot":"","sources":["../src/packageVersion.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,oCAAoC,CAAC;AAC5D,MAAM,CAAC,MAAM,UAAU,GAAG,gBAAgB,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n *\n * THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY\n */\n\nexport const pkgName = \"@fluidframework/shared-object-base\";\nexport const pkgVersion = \"2.0.0-rc.1.0.3\";\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"remoteObjectHandle.d.mts","sourceRoot":"","sources":["../src/remoteObjectHandle.ts"],"names":[],"mappings":"AAAA;;;GAGG;OAII,EACN,YAAY,EACZ,mBAAmB,EAGnB,MAAM,iCAAiC;AAGxC;;;;;;GAMG;AACH,qBAAa,uBAAwB,YAAW,YAAY;aAiB1C,YAAY,EAAE,MAAM;aACpB,YAAY,EAAE,mBAAmB;IAjBlD,IAAW,mBAAmB,SAE7B;IACD,IAAW,YAAY,SAEtB;IAED,SAAgB,UAAU,QAAQ;IAClC,OAAO,CAAC,OAAO,CAAmC;IAElD;;;;OAIG;gBAEc,YAAY,EAAE,MAAM,EACpB,YAAY,EAAE,mBAAmB;IAQrC,GAAG,IAAI,OAAO,CAAC,GAAG,CAAC;IAoBzB,WAAW,IAAI,IAAI;IAInB,IAAI,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI;CAGvC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"remoteObjectHandle.mjs","sourceRoot":"","sources":["../src/remoteObjectHandle.ts"],"names":[],"mappings":"AAAA;;;GAGG;OAEI,EAAE,MAAM,EAAE,MAAM,4BAA4B;OAC5C,EAAE,cAAc,EAAE,MAAM,mCAAmC;OAO3D,EAAE,mBAAmB,EAAE,MAAM,+BAA+B;AAEnE;;;;;;GAMG;AACH,MAAM,OAAO,uBAAuB;IACnC,IAAW,mBAAmB;QAC7B,OAAO,IAAI,CAAC;IACb,CAAC;IACD,IAAW,YAAY;QACtB,OAAO,IAAI,CAAC;IACb,CAAC;IAKD;;;;OAIG;IACH,YACiB,YAAoB,EACpB,YAAiC;QADjC,iBAAY,GAAZ,YAAY,CAAQ;QACpB,iBAAY,GAAZ,YAAY,CAAqB;QAVlC,eAAU,GAAG,IAAI,CAAC;QAYjC,MAAM,CACL,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,EAC5B,KAAK,CAAC,iDAAiD,CACvD,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,GAAG;QACf,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE;YAC/B,6EAA6E;YAC7E,MAAM,OAAO,GAAa;gBACzB,GAAG,EAAE,IAAI,CAAC,YAAY;gBACtB,OAAO,EAAE,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE;aAC7C,CAAC;YACF,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,YAAY;iBAC9B,aAAa,CAAC,OAAO,CAAC;iBACtB,IAAI,CAAc,CAAC,QAAQ,EAAE,EAAE;gBAC/B,IAAI,QAAQ,CAAC,QAAQ,KAAK,cAAc,EAAE;oBACzC,MAAM,WAAW,GAAgB,QAAQ,CAAC,KAAK,CAAC;oBAChD,OAAO,WAAW,CAAC;iBACnB;gBACD,MAAM,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC9C,CAAC,CAAC,CAAC;SACJ;QACD,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAEM,WAAW;QACjB,OAAO;IACR,CAAC;IAEM,IAAI,CAAC,MAAoB;QAC/B,MAAM,CAAC,WAAW,EAAE,CAAC;IACtB,CAAC;CACD","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert } from \"@fluidframework/core-utils\";\nimport { RuntimeHeaders } from \"@fluidframework/container-runtime\";\nimport {\n\tIFluidHandle,\n\tIFluidHandleContext,\n\tIRequest,\n\tFluidObject,\n} from \"@fluidframework/core-interfaces\";\nimport { responseToException } from \"@fluidframework/runtime-utils\";\n\n/**\n * This handle is used to dynamically load a Fluid object on a remote client and is created on parsing a serialized\n * FluidObjectHandle.\n * This class is used to generate an IFluidHandle when de-serializing any all handles (including handles to DDSes,\n * custom objects) that are stored in SharedObjects. The Data Store or SharedObject corresponding to the\n * IFluidHandle can be retrieved by calling `get` on it.\n */\nexport class RemoteFluidObjectHandle implements IFluidHandle {\n\tpublic get IFluidHandleContext() {\n\t\treturn this;\n\t}\n\tpublic get IFluidHandle() {\n\t\treturn this;\n\t}\n\n\tpublic readonly isAttached = true;\n\tprivate objectP: Promise<FluidObject> | undefined;\n\n\t/**\n\t * Creates a new RemoteFluidObjectHandle when parsing an IFluidHandle.\n\t * @param absolutePath - The absolute path to the handle from the container runtime.\n\t * @param routeContext - The root IFluidHandleContext that has a route to this handle.\n\t */\n\tconstructor(\n\t\tpublic readonly absolutePath: string,\n\t\tpublic readonly routeContext: IFluidHandleContext,\n\t) {\n\t\tassert(\n\t\t\tabsolutePath.startsWith(\"/\"),\n\t\t\t0x19d /* \"Handles should always have absolute paths\" */,\n\t\t);\n\t}\n\n\tpublic async get(): Promise<any> {\n\t\tif (this.objectP === undefined) {\n\t\t\t// Add `viaHandle` header to distinguish from requests from non-handle paths.\n\t\t\tconst request: IRequest = {\n\t\t\t\turl: this.absolutePath,\n\t\t\t\theaders: { [RuntimeHeaders.viaHandle]: true },\n\t\t\t};\n\t\t\tthis.objectP = this.routeContext\n\t\t\t\t.resolveHandle(request)\n\t\t\t\t.then<FluidObject>((response) => {\n\t\t\t\t\tif (response.mimeType === \"fluid/object\") {\n\t\t\t\t\t\tconst fluidObject: FluidObject = response.value;\n\t\t\t\t\t\treturn fluidObject;\n\t\t\t\t\t}\n\t\t\t\t\tthrow responseToException(response, request);\n\t\t\t\t});\n\t\t}\n\t\treturn this.objectP;\n\t}\n\n\tpublic attachGraph(): void {\n\t\treturn;\n\t}\n\n\tpublic bind(handle: IFluidHandle): void {\n\t\thandle.attachGraph();\n\t}\n}\n"]}
@@ -1 +0,0 @@
1
- {"version":3,"file":"serializer.d.mts","sourceRoot":"","sources":["../src/serializer.ts"],"names":[],"mappings":"AAAA;;;GAGG;OAMI,EAAE,YAAY,EAAE,mBAAmB,EAAE,MAAM,iCAAiC;AAGnF;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY,GAAG,GAAG,CAAC;IAE5C;;;;;;;;OAQG;IACH,MAAM,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAAC;IAExB;;OAEG;IACH,SAAS,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY,GAAG,MAAM,CAAC;IAElD;;;OAGG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,GAAG,CAAC;CAC1B;AAED;;;GAGG;AACH,qBAAa,eAAgB,YAAW,gBAAgB;IAItD,OAAO,CAAC,QAAQ,CAAC,OAAO;IAExB,OAAO,CAAC,QAAQ,CAAC,cAAc;IALhC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAsB;gBAGzB,OAAO,EAAE,mBAAmB,EAE5B,cAAc,GAAE,CAAC,MAAM,EAAE,YAAY,KAAK,IAAe;IAQ3E,IAAW,gBAAgB,SAE1B;IAED;;;;;;;;OAQG;IACI,MAAM,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY;IAS5C;;;;;;;;OAQG;IACI,MAAM,CAAC,KAAK,EAAE,GAAG;IASjB,SAAS,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,YAAY;IAKxC,KAAK,CAAC,KAAK,EAAE,MAAM;IAM1B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAM1B;IAIF,OAAO,CAAC,QAAQ,CAAC,WAAW,CAe1B;IAKF,OAAO,CAAC,kBAAkB;IA6C1B,SAAS,CAAC,eAAe,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY;;;;CAOlE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"serializer.mjs","sourceRoot":"","sources":["../src/serializer.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n// RATIONALE: Many methods consume and return 'any' by necessity.\n/* eslint-disable @typescript-eslint/no-unsafe-return */\n\nimport { generateHandleContextPath, isSerializedHandle } from \"@fluidframework/runtime-utils\";\nimport { IFluidHandle, IFluidHandleContext } from \"@fluidframework/core-interfaces\";\nimport { RemoteFluidObjectHandle } from \"./remoteObjectHandle\";\n\n/**\n * @public\n */\nexport interface IFluidSerializer {\n\t/**\n\t * Given a mostly-plain object that may have handle objects embedded within, will return a fully-plain object\n\t * where any embedded IFluidHandles have been replaced with a serializable form.\n\t *\n\t * The original `input` object is not mutated. This method will shallowly clones all objects in the path from\n\t * the root to any replaced handles. (If no handles are found, returns the original object.)\n\t */\n\tencode(value: any, bind: IFluidHandle): any;\n\n\t/**\n\t * Given a fully-jsonable object tree that may have encoded handle objects embedded within, will return an\n\t * equivalent object tree where any encoded IFluidHandles have been replaced with their decoded form.\n\t *\n\t * The original `input` object is not mutated. This method will shallowly clone all objects in the path from\n\t * the root to any replaced handles. (If no handles are found, returns the original object.)\n\t *\n\t * The decoded handles are implicitly bound to the handle context of this serializer.\n\t */\n\tdecode(input: any): any;\n\n\t/**\n\t * Stringifies a given value. Converts any IFluidHandle to its stringified equivalent.\n\t */\n\tstringify(value: any, bind: IFluidHandle): string;\n\n\t/**\n\t * Parses the given JSON input string and returns the JavaScript object defined by it. Any Fluid\n\t * handles will be realized as part of the parse\n\t */\n\tparse(value: string): any;\n}\n\n/**\n * Data Store serializer implementation\n * @internal\n */\nexport class FluidSerializer implements IFluidSerializer {\n\tprivate readonly root: IFluidHandleContext;\n\n\tpublic constructor(\n\t\tprivate readonly context: IFluidHandleContext,\n\t\t// To be called whenever a handle is parsed by this serializer.\n\t\tprivate readonly handleParsedCb: (handle: IFluidHandle) => void = () => {},\n\t) {\n\t\tthis.root = this.context;\n\t\twhile (this.root.routeContext !== undefined) {\n\t\t\tthis.root = this.root.routeContext;\n\t\t}\n\t}\n\n\tpublic get IFluidSerializer() {\n\t\treturn this;\n\t}\n\n\t/**\n\t * Given a mostly-jsonable object tree that may have handle objects embedded within, will return a\n\t * fully-jsonable object tree where any embedded IFluidHandles have been replaced with a serializable form.\n\t *\n\t * The original `input` object is not mutated. This method will shallowly clone all objects in the path from\n\t * the root to any replaced handles. (If no handles are found, returns the original object.)\n\t *\n\t * Any unbound handles encountered are bound to the provided IFluidHandle.\n\t */\n\tpublic encode(input: any, bind: IFluidHandle) {\n\t\t// If the given 'input' cannot contain handles, return it immediately. Otherwise,\n\t\t// return the result of 'recursivelyReplace()'.\n\t\t// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions\n\t\treturn !!input && typeof input === \"object\"\n\t\t\t? this.recursivelyReplace(input, this.encodeValue, bind)\n\t\t\t: input;\n\t}\n\n\t/**\n\t * Given a fully-jsonable object tree that may have encoded handle objects embedded within, will return an\n\t * equivalent object tree where any encoded IFluidHandles have been replaced with their decoded form.\n\t *\n\t * The original `input` object is not mutated. This method will shallowly clone all objects in the path from\n\t * the root to any replaced handles. (If no handles are found, returns the original object.)\n\t *\n\t * The decoded handles are implicitly bound to the handle context of this serializer.\n\t */\n\tpublic decode(input: any) {\n\t\t// If the given 'input' cannot contain handles, return it immediately. Otherwise,\n\t\t// return the result of 'recursivelyReplace()'.\n\t\t// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions\n\t\treturn !!input && typeof input === \"object\"\n\t\t\t? this.recursivelyReplace(input, this.decodeValue)\n\t\t\t: input;\n\t}\n\n\tpublic stringify(input: any, bind: IFluidHandle) {\n\t\treturn JSON.stringify(input, (key, value) => this.encodeValue(value, bind));\n\t}\n\n\t// Parses the serialized data - context must match the context with which the JSON was stringified\n\tpublic parse(input: string) {\n\t\treturn JSON.parse(input, (key, value) => this.decodeValue(value));\n\t}\n\n\t// If the given 'value' is an IFluidHandle, returns the encoded IFluidHandle.\n\t// Otherwise returns the original 'value'. Used by 'encode()' and 'stringify()'.\n\tprivate readonly encodeValue = (value: any, bind: IFluidHandle) => {\n\t\t// Detect if 'value' is an IFluidHandle.\n\t\tconst handle = value?.IFluidHandle;\n\n\t\t// If 'value' is an IFluidHandle return its encoded form.\n\t\treturn handle !== undefined ? this.serializeHandle(handle, bind) : value;\n\t};\n\n\t// If the given 'value' is an encoded IFluidHandle, returns the decoded IFluidHandle.\n\t// Otherwise returns the original 'value'. Used by 'decode()' and 'parse()'.\n\tprivate readonly decodeValue = (value: any) => {\n\t\t// If 'value' is a serialized IFluidHandle return the deserialized result.\n\t\tif (isSerializedHandle(value)) {\n\t\t\t// Old documents may have handles with relative path in their summaries. Convert these to absolute\n\t\t\t// paths. This will ensure that future summaries will have absolute paths for these handles.\n\t\t\tconst absolutePath = value.url.startsWith(\"/\")\n\t\t\t\t? value.url\n\t\t\t\t: generateHandleContextPath(value.url, this.context);\n\n\t\t\tconst parsedHandle = new RemoteFluidObjectHandle(absolutePath, this.root);\n\t\t\tthis.handleParsedCb(parsedHandle);\n\t\t\treturn parsedHandle;\n\t\t} else {\n\t\t\treturn value;\n\t\t}\n\t};\n\n\t// Invoked for non-null objects to recursively replace references to IFluidHandles.\n\t// Clones as-needed to avoid mutating the `input` object. If no IFluidHandes are present,\n\t// returns the original `input`.\n\tprivate recursivelyReplace(\n\t\tinput: any,\n\t\treplacer: (input: any, context: any) => any,\n\t\tcontext?: any,\n\t) {\n\t\t// Note: Caller is responsible for ensuring that `input` is defined / non-null.\n\t\t// (Required for Object.keys() below.)\n\n\t\t// Execute the `replace` on the current input. Note that Caller is responsible for ensuring that `input`\n\t\t// is a non-null object.\n\t\tconst maybeReplaced = replacer(input, context);\n\n\t\t// If the replacer made a substitution there is no need to decscend further. IFluidHandles are always\n\t\t// leaves in the object graph.\n\t\tif (maybeReplaced !== input) {\n\t\t\treturn maybeReplaced;\n\t\t}\n\n\t\t// Otherwise descend into the object graph looking for IFluidHandle instances.\n\t\tlet clone: object | undefined;\n\t\tfor (const key of Object.keys(input)) {\n\t\t\tconst value = input[key];\n\t\t\t// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions\n\t\t\tif (!!value && typeof value === \"object\") {\n\t\t\t\t// Note: Except for IFluidHandle, `input` must not contain circular references (as object must\n\t\t\t\t// be JSON serializable.) Therefore, guarding against infinite recursion here would only\n\t\t\t\t// lead to a later error when attempting to stringify().\n\t\t\t\tconst replaced = this.recursivelyReplace(value, replacer, context);\n\n\t\t\t\t// If the `replaced` object is different than the original `value` then the subgraph contained one\n\t\t\t\t// or more handles. If this happens, we need to return a clone of the `input` object where the\n\t\t\t\t// current property is replaced by the `replaced` value.\n\t\t\t\tif (replaced !== value) {\n\t\t\t\t\t// Lazily create a shallow clone of the `input` object if we haven't done so already.\n\t\t\t\t\tclone = clone ?? (Array.isArray(input) ? [...input] : { ...input });\n\n\t\t\t\t\t// Overwrite the current property `key` in the clone with the `replaced` value.\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\tclone![key] = replaced;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn clone ?? input;\n\t}\n\n\tprotected serializeHandle(handle: IFluidHandle, bind: IFluidHandle) {\n\t\tbind.bind(handle);\n\t\treturn {\n\t\t\ttype: \"__fluid_handle__\",\n\t\t\turl: handle.absolutePath,\n\t\t};\n\t}\n}\n"]}