@fluidframework/merge-tree 2.0.0-internal.3.2.2 → 2.0.0-internal.3.3.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.
@@ -1 +1 @@
1
- {"version":3,"file":"attributionCollection.d.ts","sourceRoot":"","sources":["../src/attributionCollection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACN,cAAc,EAGd,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAQhD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAG5C;;GAEG;AACH,MAAM,WAAW,+BAA+B;IAC/C;;;;;OAKG;IACH,IAAI,EAAE,CAAC,MAAM,GAAG,cAAc,CAAC,EAAE,CAAC;IAClC,cAAc,EAAE,MAAM,EAAE,CAAC;IAEzB,MAAM,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,gCAAgC;IAChD;;OAEG;IACH,+BAA+B,CAC9B,QAAQ,EAAE,QAAQ,CAAC;QAClB,WAAW,CAAC,EAAE,sBAAsB,CAAC,cAAc,CAAC,CAAC;QACrD,YAAY,EAAE,MAAM,CAAC;KACrB,CAAC,GACA,+BAA+B,CAAC;IAEnC;;;OAGG;IACH,8BAA8B,CAC7B,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAC5B,OAAO,EAAE,+BAA+B,GACtC,IAAI,CAAC;CACR;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB,CAAC,CAAC;IACxC;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC;IAE/B;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB;;;;;;OAMG;IACH,MAAM,IAAI,QAAQ,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,CAAC,CAAA;KAAE,CAAC,CAAC;IAE/C,gBAAgB;IAChB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAEhD,gBAAgB;IAChB,MAAM,CAAC,KAAK,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAE/C,gBAAgB;IAChB,KAAK,IAAI,sBAAsB,CAAC,CAAC,CAAC,CAAC;CACnC;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,cAAc,GAAG,OAAO,CAcrF;AAED,qBAAa,qBAAsB,YAAW,sBAAsB,CAAC,cAAc,CAAC;IAIrC,OAAO,CAAC,OAAO;IAH7D,OAAO,CAAC,OAAO,CAAW;IAC1B,OAAO,CAAC,IAAI,CAAmB;gBAEZ,SAAS,EAAE,cAAc,EAAU,OAAO,EAAE,MAAM;IAK9D,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc;IAKlD,OAAO,CAAC,SAAS;IAWjB,IAAW,MAAM,IAAI,MAAM,CAE1B;IAED;;OAEG;IACI,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,qBAAqB;IAgB3C,MAAM,CAAC,KAAK,EAAE,qBAAqB,GAAG,IAAI;IAW1C,MAAM,IAAI;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,cAAc,CAAA;KAAE,EAAE;IAQnD,KAAK,IAAI,qBAAqB;IAOrC;;OAEG;WACW,8BAA8B,CAC3C,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAC5B,OAAO,EAAE,+BAA+B,GACtC,IAAI;IAsCP;;OAEG;WACW,+BAA+B,CAC5C,QAAQ,EAAE,QAAQ,CAAC;QAClB,WAAW,CAAC,EAAE,sBAAsB,CAAC,cAAc,CAAC,CAAC;QACrD,YAAY,EAAE,MAAM,CAAC;KACrB,CAAC,GACA,+BAA+B;CAwClC;AAED;;;;;GAKG;AACH,wBAAgB,iCAAiC,IAAI,iBAAiB,CAsErE"}
1
+ {"version":3,"file":"attributionCollection.d.ts","sourceRoot":"","sources":["../src/attributionCollection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACN,cAAc,EAGd,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAQhD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAG5C;;GAEG;AACH,MAAM,WAAW,+BAA+B;IAC/C;;;;;OAKG;IACH,IAAI,EAAE,CAAC,MAAM,GAAG,cAAc,CAAC,EAAE,CAAC;IAClC,cAAc,EAAE,MAAM,EAAE,CAAC;IAEzB,MAAM,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,gCAAgC;IAChD;;OAEG;IACH,+BAA+B,CAC9B,QAAQ,EAAE,QAAQ,CAAC;QAClB,WAAW,CAAC,EAAE,sBAAsB,CAAC,cAAc,CAAC,CAAC;QACrD,YAAY,EAAE,MAAM,CAAC;KACrB,CAAC,GACA,+BAA+B,CAAC;IAEnC;;;OAGG;IACH,8BAA8B,CAC7B,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAC5B,OAAO,EAAE,+BAA+B,GACtC,IAAI,CAAC;CACR;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB,CAAC,CAAC;IACxC;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC;IAE/B;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB;;;;;;OAMG;IACH,MAAM,IAAI,QAAQ,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,CAAC,CAAA;KAAE,CAAC,CAAC;IAE/C,gBAAgB;IAChB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAEhD,gBAAgB;IAChB,MAAM,CAAC,KAAK,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAE/C,gBAAgB;IAChB,KAAK,IAAI,sBAAsB,CAAC,CAAC,CAAC,CAAC;CACnC;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,cAAc,GAAG,OAAO,CAgBrF;AAED,qBAAa,qBAAsB,YAAW,sBAAsB,CAAC,cAAc,CAAC;IAIrC,OAAO,CAAC,OAAO;IAH7D,OAAO,CAAC,OAAO,CAAW;IAC1B,OAAO,CAAC,IAAI,CAAmB;gBAEZ,SAAS,EAAE,cAAc,EAAU,OAAO,EAAE,MAAM;IAK9D,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc;IAKlD,OAAO,CAAC,SAAS;IAWjB,IAAW,MAAM,IAAI,MAAM,CAE1B;IAED;;OAEG;IACI,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,qBAAqB;IAgB3C,MAAM,CAAC,KAAK,EAAE,qBAAqB,GAAG,IAAI;IAW1C,MAAM,IAAI;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,cAAc,CAAA;KAAE,EAAE;IAQnD,KAAK,IAAI,qBAAqB;IAOrC;;OAEG;WACW,8BAA8B,CAC3C,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAC5B,OAAO,EAAE,+BAA+B,GACtC,IAAI;IAsCP;;OAEG;WACW,+BAA+B,CAC5C,QAAQ,EAAE,QAAQ,CAAC;QAClB,WAAW,CAAC,EAAE,sBAAsB,CAAC,cAAc,CAAC,CAAC;QACrD,YAAY,EAAE,MAAM,CAAC;KACrB,CAAC,GACA,+BAA+B;CAwClC;AAED;;;;;GAKG;AACH,wBAAgB,iCAAiC,IAAI,iBAAiB,CAsErE"}
@@ -19,6 +19,8 @@ function areEqualAttributionKeys(a, b) {
19
19
  return a.seq === b.seq;
20
20
  case "detached":
21
21
  return a.id === b.id;
22
+ case "local":
23
+ return true;
22
24
  default:
23
25
  (0, common_utils_1.unreachableCase)(a, "Unhandled AttributionKey type");
24
26
  }
@@ -1 +1 @@
1
- {"version":3,"file":"attributionCollection.js","sourceRoot":"","sources":["../src/attributionCollection.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;AAEH,+DAAuE;AAQvE,2CAAgF;AAChF,qEAIkC;AAElC,+BAA2C;AA4E3C,SAAgB,uBAAuB,CAAC,CAAiB,EAAE,CAAiB;IAC3E,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,EAAE;QACtB,OAAO,KAAK,CAAC;KACb;IAED,gGAAgG;IAChG,QAAQ,CAAC,CAAC,IAAI,EAAE;QACf,KAAK,IAAI;YACR,OAAO,CAAC,CAAC,GAAG,KAAM,CAAsB,CAAC,GAAG,CAAC;QAC9C,KAAK,UAAU;YACd,OAAO,CAAC,CAAC,EAAE,KAAM,CAA4B,CAAC,EAAE,CAAC;QAClD;YACC,IAAA,8BAAe,EAAC,CAAC,EAAE,+BAA+B,CAAC,CAAC;KACrD;AACF,CAAC;AAdD,0DAcC;AAED,MAAa,qBAAqB;IAIjC,YAAmB,SAAyB,EAAU,OAAe;QAAf,YAAO,GAAP,OAAO,CAAQ;QACpE,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;QACnB,IAAI,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;IACzB,CAAC;IAEM,WAAW,CAAC,MAAc;QAChC,IAAA,qBAAM,EAAC,MAAM,IAAI,CAAC,IAAI,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC3F,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1C,CAAC;IAEO,SAAS,CAAC,MAAc;QAC/B,8GAA8G;QAC9G,8GAA8G;QAC9G,wGAAwG;QACxG,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;YAC3D,CAAC,EAAE,CAAC;SACJ;QACD,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC/C,CAAC;IAED,IAAW,MAAM;QAChB,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED;;OAEG;IACI,OAAO,CAAC,GAAW;QACzB,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACvC,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7C,MAAM,eAAe,GAAG,IAAI,qBAAqB,CAAC,cAAc,EAAE,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;QACrF,KAAK,IAAI,CAAC,GAAG,UAAU,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACvD,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;YACpD,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;SACxC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC;QACnF,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAC9B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACjC,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC;QACnB,OAAO,eAAe,CAAC;IACxB,CAAC;IAEM,MAAM,CAAC,KAA4B;QACzC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAClD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YAC3C,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE;gBAClE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;gBAClD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;aAC9B;SACD;QACD,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC;IAC9B,CAAC;IAEM,MAAM;QACZ,MAAM,OAAO,GAA8C,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YAC1C,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5D;QACD,OAAO,OAAO,CAAC;IAChB,CAAC;IAEM,KAAK;QACX,MAAM,IAAI,GAAG,IAAI,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAClE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAC9B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC;IACb,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,8BAA8B,CAC3C,QAA4B,EAC5B,OAAwC;QAExC,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;QACzC,IAAA,qBAAM,EACL,IAAI,CAAC,MAAM,KAAK,cAAc,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EACxD,KAAK,CAAC,+CAA+C,CACrD,CAAC;QACF,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,IAAI,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QACjC,IAAI,gBAAgB,GAAG,CAAC,CAAC;QAEzB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;YAC/B,MAAM,WAAW,GAAG,IAAI,qBAAqB,CAC5C,OAAO,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE,EAChF,OAAO,CAAC,YAAY,CACpB,CAAC;YACF,OAAO,cAAc,CAAC,QAAQ,CAAC,GAAG,gBAAgB,GAAG,OAAO,CAAC,YAAY,EAAE;gBAC1E,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC7B,MAAM,UAAU,GAAG,cAAc,CAAC,QAAQ,CAAC,GAAG,gBAAgB,CAAC;gBAC/D,IAAI,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,UAAU,EAAE;oBACvE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;oBACrC,WAAW,CAAC,IAAI,CAAC,IAAI,CACpB,OAAO,WAAW,KAAK,QAAQ;wBAC9B,CAAC,CAAC,WAAW;wBACb,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE,CACnC,CAAC;iBACF;gBACD,QAAQ,EAAE,CAAC;aACX;YAED,IAAI,cAAc,CAAC,QAAQ,CAAC,KAAK,gBAAgB,GAAG,OAAO,CAAC,YAAY,EAAE;gBACzE,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;aAC7B;YAED,OAAO,CAAC,WAAW,GAAG,WAAW,CAAC;YAClC,gBAAgB,IAAI,OAAO,CAAC,YAAY,CAAC;SACzC;IACF,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,+BAA+B,CAC5C,QAGE;;QAEF,MAAM,cAAc,GAAa,EAAE,CAAC;QACpC,MAAM,IAAI,GAAgC,EAAE,CAAC;QAC7C,IAAI,wBAAoD,CAAC;QACzD,IAAI,aAAa,GAAG,CAAC,CAAC;QAEtB,IAAI,uBAAuB,GAAG,CAAC,CAAC;QAChC,IAAI,0BAA0B,GAAG,CAAC,CAAC;QACnC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;YAC/B,IAAI,OAAO,CAAC,WAAW,EAAE;gBACxB,uBAAuB,EAAE,CAAC;gBAC1B,KAAK,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,MAAA,MAAA,OAAO,CAAC,WAAW,0CAAE,MAAM,EAAE,mCAAI,EAAE,EAAE;oBAClE,IACC,CAAC,wBAAwB;wBACzB,CAAC,uBAAuB,CAAC,GAAG,EAAE,wBAAwB,CAAC,EACtD;wBACD,cAAc,CAAC,IAAI,CAAC,MAAM,GAAG,aAAa,CAAC,CAAC;wBAC5C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;qBAC7C;oBACD,wBAAwB,GAAG,GAAG,CAAC;iBAC/B;aACD;iBAAM;gBACN,0BAA0B,EAAE,CAAC;aAC7B;YAED,aAAa,IAAI,OAAO,CAAC,YAAY,CAAC;SACtC;QAED,IAAA,qBAAM,EACL,uBAAuB,KAAK,CAAC,IAAI,0BAA0B,KAAK,CAAC,EACjE,KAAK,CAAC,kFAAkF,CACxF,CAAC;QAEF,MAAM,YAAY,GAAoC;YACrD,IAAI;YACJ,cAAc;YACd,MAAM,EAAE,aAAa;SACrB,CAAC;QACF,OAAO,YAAY,CAAC;IACrB,CAAC;CACD;AAtKD,sDAsKC;AAED;;;;;GAKG;AACH,SAAgB,iCAAiC;IAChD,IAAI,WAAqC,CAAC;IAC1C,OAAO;QACN,MAAM,EAAE,CAAC,MAAc,EAAE,EAAE;YAC1B,IAAA,qBAAM,EACL,WAAW,KAAK,SAAS,EACzB,KAAK,CAAC,+CAA+C,CACrD,CAAC;YACF,MAAM,aAAa,GAA2B,CAC7C,MAAM,EACN,EAAE,aAAa,EAAE,SAAS,EAAE,EAC3B,EAAE;;gBACH,IAAI,SAAS,KAAK,wBAAkB,CAAC,MAAM,EAAE;oBAC5C,OAAO;iBACP;gBAED,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,aAAa,EAAE;oBACxC,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,IAAI,OAAO,CAAC,GAAG,KAAK,oCAAwB,EAAE;wBAC1E,MAAM,GAAG,GACR,OAAO,CAAC,GAAG,KAAK,mCAAuB;4BACtC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,EAAE;4BAC7B,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;wBACrC,MAAA,OAAO,CAAC,WAAW,oCAAnB,OAAO,CAAC,WAAW,GAAK,IAAI,qBAAqB,CAChD,GAAG,EACH,OAAO,CAAC,YAAY,CACpB,EAAC;qBACF;iBACD;YACF,CAAC,CAAC;YAEF,MAAM,mBAAmB,GAAiC,CACzD,EAAE,aAAa,EAAE,SAAS,EAAE,EAC5B,MAAM,EACL,EAAE;gBACH,IACC,SAAS,KAAK,iDAAwB,CAAC,YAAY;oBACnD,MAAM,KAAK,SAAS;oBACpB,MAAM,CAAC,EAAE,CAAC,IAAI,KAAK,wBAAkB,CAAC,MAAM,EAC3C;oBACD,OAAO;iBACP;gBACD,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,aAAa,EAAE;oBACxC,IAAA,qBAAM,EACL,OAAO,CAAC,GAAG,KAAK,SAAS,EACzB,KAAK,CAAC,0CAA0C,CAChD,CAAC;oBACF,OAAO,CAAC,WAAW,GAAG,IAAI,qBAAqB,CAC9C,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAChC,OAAO,CAAC,YAAY,CACpB,CAAC;iBACF;YACF,CAAC,CAAC;YAEF,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;YAClC,MAAM,CAAC,EAAE,CAAC,aAAa,EAAE,mBAAmB,CAAC,CAAC;YAE9C,WAAW,GAAG,GAAG,EAAE;gBAClB,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;gBACnC,MAAM,CAAC,GAAG,CAAC,aAAa,EAAE,mBAAmB,CAAC,CAAC;YAChD,CAAC,CAAC;QACH,CAAC;QACD,MAAM,EAAE,GAAG,EAAE;YACZ,WAAW,aAAX,WAAW,uBAAX,WAAW,EAAI,CAAC;YAChB,WAAW,GAAG,SAAS,CAAC;QACzB,CAAC;QACD,IAAI,UAAU;YACb,OAAO,WAAW,KAAK,SAAS,CAAC;QAClC,CAAC;QACD,UAAU,EAAE,qBAAqB;KACjC,CAAC;AACH,CAAC;AAtED,8EAsEC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert, unreachableCase } from \"@fluidframework/common-utils\";\nimport {\n\tAttributionKey,\n\tOpAttributionKey,\n\tDetachedAttributionKey,\n} from \"@fluidframework/runtime-definitions\";\nimport { AttributionPolicy } from \"./mergeTree\";\nimport { Client } from \"./client\";\nimport { UnassignedSequenceNumber, UniversalSequenceNumber } from \"./constants\";\nimport {\n\tMergeTreeDeltaCallback,\n\tMergeTreeMaintenanceCallback,\n\tMergeTreeMaintenanceType,\n} from \"./mergeTreeDeltaCallback\";\nimport { ISegment } from \"./mergeTreeNodes\";\nimport { MergeTreeDeltaType } from \"./ops\";\n\n/**\n * @internal\n */\nexport interface SerializedAttributionCollection {\n\t/**\n\t * Parallel array with posBreakpoints which tracks the seq of insertion.\n\t * Ex: if seqs is [45, 46] and posBreakpoints is [0, 3], the section of the string\n\t * between offsets 0 and 3 was inserted at seq 45 and the section of the string between\n\t * 3 and the length of the string was inserted at seq 46.\n\t */\n\tseqs: (number | AttributionKey)[];\n\tposBreakpoints: number[];\n\t/* Total length; only necessary for validation */\n\tlength: number;\n}\n\n/**\n * @internal\n * @sealed\n */\nexport interface IAttributionCollectionSerializer {\n\t/**\n\t * @internal\n\t */\n\tserializeAttributionCollections(\n\t\tsegments: Iterable<{\n\t\t\tattribution?: IAttributionCollection<AttributionKey>;\n\t\t\tcachedLength: number;\n\t\t}>,\n\t): SerializedAttributionCollection;\n\n\t/**\n\t * Populates attribution information on segments using the provided summary.\n\t * @internal\n\t */\n\tpopulateAttributionCollections(\n\t\tsegments: Iterable<ISegment>,\n\t\tsummary: SerializedAttributionCollection,\n\t): void;\n}\n\n/**\n * @alpha\n */\nexport interface IAttributionCollection<T> {\n\t/**\n\t * Retrieves the attribution key associated with the provided offset.\n\t */\n\tgetAtOffset(offset: number): T;\n\n\t/**\n\t * Total length of all attribution keys in this collection.\n\t */\n\treadonly length: number;\n\n\t/**\n\t * Retrieve all key/offset pairs stored on this segment. Entries should be ordered by offset, such that\n\t * the `i`th result's attribution key applies to offsets in the open range between the `i`th offset and the\n\t * `i+1`th offset.\n\t * The last entry's key applies to the open interval from the last entry's offset to this collection's length.\n\t * @internal\n\t */\n\tgetAll(): Iterable<{ offset: number; key: T }>;\n\n\t/** @internal */\n\tsplitAt(pos: number): IAttributionCollection<T>;\n\n\t/** @internal */\n\tappend(other: IAttributionCollection<T>): void;\n\n\t/** @internal */\n\tclone(): IAttributionCollection<T>;\n}\n\nexport function areEqualAttributionKeys(a: AttributionKey, b: AttributionKey): boolean {\n\tif (a.type !== b.type) {\n\t\treturn false;\n\t}\n\n\t// Note: TS can't narrow the type of b inside this switch statement, hence the need for casting.\n\tswitch (a.type) {\n\t\tcase \"op\":\n\t\t\treturn a.seq === (b as OpAttributionKey).seq;\n\t\tcase \"detached\":\n\t\t\treturn a.id === (b as DetachedAttributionKey).id;\n\t\tdefault:\n\t\t\tunreachableCase(a, \"Unhandled AttributionKey type\");\n\t}\n}\n\nexport class AttributionCollection implements IAttributionCollection<AttributionKey> {\n\tprivate offsets: number[];\n\tprivate keys: AttributionKey[];\n\n\tpublic constructor(baseEntry: AttributionKey, private _length: number) {\n\t\tthis.offsets = [0];\n\t\tthis.keys = [baseEntry];\n\t}\n\n\tpublic getAtOffset(offset: number): AttributionKey {\n\t\tassert(offset >= 0 && offset < this._length, 0x443 /* Requested offset should be valid */);\n\t\treturn this.keys[this.findIndex(offset)];\n\t}\n\n\tprivate findIndex(offset: number): number {\n\t\t// Note: maximum length here is 256 for text segments. Perf testing shows that linear scan beats binary search\n\t\t// for attribution collections with under ~64 entries, and even at maximum size (which would require a maximum\n\t\t// length segment with every offset having different attribution), getAtOffset is on the order of 100ns.\n\t\tlet i = 0;\n\t\twhile (i < this.offsets.length && offset > this.offsets[i]) {\n\t\t\ti++;\n\t\t}\n\t\treturn this.offsets[i] === offset ? i : i - 1;\n\t}\n\n\tpublic get length(): number {\n\t\treturn this._length;\n\t}\n\n\t/**\n\t * Splits this attribution collection into two with entries for [0, pos) and [pos, length).\n\t */\n\tpublic splitAt(pos: number): AttributionCollection {\n\t\tconst splitIndex = this.findIndex(pos);\n\t\tconst splitBaseEntry = this.keys[splitIndex];\n\t\tconst splitCollection = new AttributionCollection(splitBaseEntry, this.length - pos);\n\t\tfor (let i = splitIndex + 1; i < this.keys.length; i++) {\n\t\t\tsplitCollection.offsets.push(this.offsets[i] - pos);\n\t\t\tsplitCollection.keys.push(this.keys[i]);\n\t\t}\n\n\t\tconst spliceIndex = this.offsets[splitIndex] === pos ? splitIndex : splitIndex + 1;\n\t\tthis.keys.splice(spliceIndex);\n\t\tthis.offsets.splice(spliceIndex);\n\t\tthis._length = pos;\n\t\treturn splitCollection;\n\t}\n\n\tpublic append(other: AttributionCollection): void {\n\t\tconst lastEntry = this.keys[this.keys.length - 1];\n\t\tfor (let i = 0; i < other.keys.length; i++) {\n\t\t\tif (i !== 0 || !areEqualAttributionKeys(lastEntry, other.keys[i])) {\n\t\t\t\tthis.offsets.push(other.offsets[i] + this.length);\n\t\t\t\tthis.keys.push(other.keys[i]);\n\t\t\t}\n\t\t}\n\t\tthis._length += other.length;\n\t}\n\n\tpublic getAll(): { offset: number; key: AttributionKey }[] {\n\t\tconst results: { offset: number; key: AttributionKey }[] = new Array(this.keys.length);\n\t\tfor (let i = 0; i < this.keys.length; i++) {\n\t\t\tresults[i] = { offset: this.offsets[i], key: this.keys[i] };\n\t\t}\n\t\treturn results;\n\t}\n\n\tpublic clone(): AttributionCollection {\n\t\tconst copy = new AttributionCollection(this.keys[0], this.length);\n\t\tcopy.keys = this.keys.slice();\n\t\tcopy.offsets = this.offsets.slice();\n\t\treturn copy;\n\t}\n\n\t/**\n\t * Rehydrates attribution information from its serialized form into the provided iterable of consecutive segments.\n\t */\n\tpublic static populateAttributionCollections(\n\t\tsegments: Iterable<ISegment>,\n\t\tsummary: SerializedAttributionCollection,\n\t): void {\n\t\tconst { seqs, posBreakpoints } = summary;\n\t\tassert(\n\t\t\tseqs.length === posBreakpoints.length && seqs.length > 0,\n\t\t\t0x445 /* Invalid attribution summary blob provided */,\n\t\t);\n\t\tlet curIndex = 0;\n\t\tlet currentInfo = seqs[curIndex];\n\t\tlet cumulativeSegPos = 0;\n\n\t\tfor (const segment of segments) {\n\t\t\tconst attribution = new AttributionCollection(\n\t\t\t\ttypeof currentInfo === \"object\" ? currentInfo : { type: \"op\", seq: currentInfo },\n\t\t\t\tsegment.cachedLength,\n\t\t\t);\n\t\t\twhile (posBreakpoints[curIndex] < cumulativeSegPos + segment.cachedLength) {\n\t\t\t\tcurrentInfo = seqs[curIndex];\n\t\t\t\tconst nextOffset = posBreakpoints[curIndex] - cumulativeSegPos;\n\t\t\t\tif (attribution.offsets[attribution.offsets.length - 1] !== nextOffset) {\n\t\t\t\t\tattribution.offsets.push(nextOffset);\n\t\t\t\t\tattribution.keys.push(\n\t\t\t\t\t\ttypeof currentInfo === \"object\"\n\t\t\t\t\t\t\t? currentInfo\n\t\t\t\t\t\t\t: { type: \"op\", seq: currentInfo },\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tcurIndex++;\n\t\t\t}\n\n\t\t\tif (posBreakpoints[curIndex] === cumulativeSegPos + segment.cachedLength) {\n\t\t\t\tcurrentInfo = seqs[curIndex];\n\t\t\t}\n\n\t\t\tsegment.attribution = attribution;\n\t\t\tcumulativeSegPos += segment.cachedLength;\n\t\t}\n\t}\n\n\t/**\n\t * Condenses attribution information on consecutive segments into a `SerializedAttributionCollection`\n\t */\n\tpublic static serializeAttributionCollections(\n\t\tsegments: Iterable<{\n\t\t\tattribution?: IAttributionCollection<AttributionKey>;\n\t\t\tcachedLength: number;\n\t\t}>,\n\t): SerializedAttributionCollection {\n\t\tconst posBreakpoints: number[] = [];\n\t\tconst seqs: (number | AttributionKey)[] = [];\n\t\tlet mostRecentAttributionKey: AttributionKey | undefined;\n\t\tlet cumulativePos = 0;\n\n\t\tlet segmentsWithAttribution = 0;\n\t\tlet segmentsWithoutAttribution = 0;\n\t\tfor (const segment of segments) {\n\t\t\tif (segment.attribution) {\n\t\t\t\tsegmentsWithAttribution++;\n\t\t\t\tfor (const { offset, key } of segment.attribution?.getAll() ?? []) {\n\t\t\t\t\tif (\n\t\t\t\t\t\t!mostRecentAttributionKey ||\n\t\t\t\t\t\t!areEqualAttributionKeys(key, mostRecentAttributionKey)\n\t\t\t\t\t) {\n\t\t\t\t\t\tposBreakpoints.push(offset + cumulativePos);\n\t\t\t\t\t\tseqs.push(key.type === \"op\" ? key.seq : key);\n\t\t\t\t\t}\n\t\t\t\t\tmostRecentAttributionKey = key;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsegmentsWithoutAttribution++;\n\t\t\t}\n\n\t\t\tcumulativePos += segment.cachedLength;\n\t\t}\n\n\t\tassert(\n\t\t\tsegmentsWithAttribution === 0 || segmentsWithoutAttribution === 0,\n\t\t\t0x446 /* Expected either all segments or no segments to have attribution information. */,\n\t\t);\n\n\t\tconst blobContents: SerializedAttributionCollection = {\n\t\t\tseqs,\n\t\t\tposBreakpoints,\n\t\t\tlength: cumulativePos,\n\t\t};\n\t\treturn blobContents;\n\t}\n}\n\n/**\n * @alpha\n * @returns - An {@link AttributionPolicy} which tracks only insertion of content.\n * Content is only attributed at ack time, unless the container is in a detached state.\n * Detached content is attributed with a {@link @fluidframework/runtime-definitions#DetachedAttributionKey}.\n */\nexport function createInsertOnlyAttributionPolicy(): AttributionPolicy {\n\tlet unsubscribe: undefined | (() => void);\n\treturn {\n\t\tattach: (client: Client) => {\n\t\t\tassert(\n\t\t\t\tunsubscribe === undefined,\n\t\t\t\t0x557 /* cannot attach to multiple clients at once */,\n\t\t\t);\n\t\t\tconst deltaCallback: MergeTreeDeltaCallback = (\n\t\t\t\topArgs,\n\t\t\t\t{ deltaSegments, operation },\n\t\t\t) => {\n\t\t\t\tif (operation !== MergeTreeDeltaType.INSERT) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tfor (const { segment } of deltaSegments) {\n\t\t\t\t\tif (segment.seq !== undefined && segment.seq !== UnassignedSequenceNumber) {\n\t\t\t\t\t\tconst key: AttributionKey =\n\t\t\t\t\t\t\tsegment.seq === UniversalSequenceNumber\n\t\t\t\t\t\t\t\t? { type: \"detached\", id: 0 }\n\t\t\t\t\t\t\t\t: { type: \"op\", seq: segment.seq };\n\t\t\t\t\t\tsegment.attribution ??= new AttributionCollection(\n\t\t\t\t\t\t\tkey,\n\t\t\t\t\t\t\tsegment.cachedLength,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst maintenanceCallback: MergeTreeMaintenanceCallback = (\n\t\t\t\t{ deltaSegments, operation },\n\t\t\t\topArgs,\n\t\t\t) => {\n\t\t\t\tif (\n\t\t\t\t\toperation !== MergeTreeMaintenanceType.ACKNOWLEDGED ||\n\t\t\t\t\topArgs === undefined ||\n\t\t\t\t\topArgs.op.type !== MergeTreeDeltaType.INSERT\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (const { segment } of deltaSegments) {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tsegment.seq !== undefined,\n\t\t\t\t\t\t0x558 /* segment.seq should be set after ack. */,\n\t\t\t\t\t);\n\t\t\t\t\tsegment.attribution = new AttributionCollection(\n\t\t\t\t\t\t{ type: \"op\", seq: segment.seq },\n\t\t\t\t\t\tsegment.cachedLength,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tclient.on(\"delta\", deltaCallback);\n\t\t\tclient.on(\"maintenance\", maintenanceCallback);\n\n\t\t\tunsubscribe = () => {\n\t\t\t\tclient.off(\"delta\", deltaCallback);\n\t\t\t\tclient.off(\"maintenance\", maintenanceCallback);\n\t\t\t};\n\t\t},\n\t\tdetach: () => {\n\t\t\tunsubscribe?.();\n\t\t\tunsubscribe = undefined;\n\t\t},\n\t\tget isAttached() {\n\t\t\treturn unsubscribe !== undefined;\n\t\t},\n\t\tserializer: AttributionCollection,\n\t};\n}\n"]}
1
+ {"version":3,"file":"attributionCollection.js","sourceRoot":"","sources":["../src/attributionCollection.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\nimport { assert, unreachableCase } from \"@fluidframework/common-utils\";\nimport {\n\tAttributionKey,\n\tOpAttributionKey,\n\tDetachedAttributionKey,\n} from \"@fluidframework/runtime-definitions\";\nimport { AttributionPolicy } from \"./mergeTree\";\nimport { Client } from \"./client\";\nimport { UnassignedSequenceNumber, UniversalSequenceNumber } from \"./constants\";\nimport {\n\tMergeTreeDeltaCallback,\n\tMergeTreeMaintenanceCallback,\n\tMergeTreeMaintenanceType,\n} from \"./mergeTreeDeltaCallback\";\nimport { ISegment } from \"./mergeTreeNodes\";\nimport { MergeTreeDeltaType } from \"./ops\";\n\n/**\n * @internal\n */\nexport interface SerializedAttributionCollection {\n\t/**\n\t * Parallel array with posBreakpoints which tracks the seq of insertion.\n\t * Ex: if seqs is [45, 46] and posBreakpoints is [0, 3], the section of the string\n\t * between offsets 0 and 3 was inserted at seq 45 and the section of the string between\n\t * 3 and the length of the string was inserted at seq 46.\n\t */\n\tseqs: (number | AttributionKey)[];\n\tposBreakpoints: number[];\n\t/* Total length; only necessary for validation */\n\tlength: number;\n}\n\n/**\n * @internal\n * @sealed\n */\nexport interface IAttributionCollectionSerializer {\n\t/**\n\t * @internal\n\t */\n\tserializeAttributionCollections(\n\t\tsegments: Iterable<{\n\t\t\tattribution?: IAttributionCollection<AttributionKey>;\n\t\t\tcachedLength: number;\n\t\t}>,\n\t): SerializedAttributionCollection;\n\n\t/**\n\t * Populates attribution information on segments using the provided summary.\n\t * @internal\n\t */\n\tpopulateAttributionCollections(\n\t\tsegments: Iterable<ISegment>,\n\t\tsummary: SerializedAttributionCollection,\n\t): void;\n}\n\n/**\n * @alpha\n */\nexport interface IAttributionCollection<T> {\n\t/**\n\t * Retrieves the attribution key associated with the provided offset.\n\t */\n\tgetAtOffset(offset: number): T;\n\n\t/**\n\t * Total length of all attribution keys in this collection.\n\t */\n\treadonly length: number;\n\n\t/**\n\t * Retrieve all key/offset pairs stored on this segment. Entries should be ordered by offset, such that\n\t * the `i`th result's attribution key applies to offsets in the open range between the `i`th offset and the\n\t * `i+1`th offset.\n\t * The last entry's key applies to the open interval from the last entry's offset to this collection's length.\n\t * @internal\n\t */\n\tgetAll(): Iterable<{ offset: number; key: T }>;\n\n\t/** @internal */\n\tsplitAt(pos: number): IAttributionCollection<T>;\n\n\t/** @internal */\n\tappend(other: IAttributionCollection<T>): void;\n\n\t/** @internal */\n\tclone(): IAttributionCollection<T>;\n}\n\nexport function areEqualAttributionKeys(a: AttributionKey, b: AttributionKey): boolean {\n\tif (a.type !== b.type) {\n\t\treturn false;\n\t}\n\n\t// Note: TS can't narrow the type of b inside this switch statement, hence the need for casting.\n\tswitch (a.type) {\n\t\tcase \"op\":\n\t\t\treturn a.seq === (b as OpAttributionKey).seq;\n\t\tcase \"detached\":\n\t\t\treturn a.id === (b as DetachedAttributionKey).id;\n\t\tcase \"local\":\n\t\t\treturn true;\n\t\tdefault:\n\t\t\tunreachableCase(a, \"Unhandled AttributionKey type\");\n\t}\n}\n\nexport class AttributionCollection implements IAttributionCollection<AttributionKey> {\n\tprivate offsets: number[];\n\tprivate keys: AttributionKey[];\n\n\tpublic constructor(baseEntry: AttributionKey, private _length: number) {\n\t\tthis.offsets = [0];\n\t\tthis.keys = [baseEntry];\n\t}\n\n\tpublic getAtOffset(offset: number): AttributionKey {\n\t\tassert(offset >= 0 && offset < this._length, 0x443 /* Requested offset should be valid */);\n\t\treturn this.keys[this.findIndex(offset)];\n\t}\n\n\tprivate findIndex(offset: number): number {\n\t\t// Note: maximum length here is 256 for text segments. Perf testing shows that linear scan beats binary search\n\t\t// for attribution collections with under ~64 entries, and even at maximum size (which would require a maximum\n\t\t// length segment with every offset having different attribution), getAtOffset is on the order of 100ns.\n\t\tlet i = 0;\n\t\twhile (i < this.offsets.length && offset > this.offsets[i]) {\n\t\t\ti++;\n\t\t}\n\t\treturn this.offsets[i] === offset ? i : i - 1;\n\t}\n\n\tpublic get length(): number {\n\t\treturn this._length;\n\t}\n\n\t/**\n\t * Splits this attribution collection into two with entries for [0, pos) and [pos, length).\n\t */\n\tpublic splitAt(pos: number): AttributionCollection {\n\t\tconst splitIndex = this.findIndex(pos);\n\t\tconst splitBaseEntry = this.keys[splitIndex];\n\t\tconst splitCollection = new AttributionCollection(splitBaseEntry, this.length - pos);\n\t\tfor (let i = splitIndex + 1; i < this.keys.length; i++) {\n\t\t\tsplitCollection.offsets.push(this.offsets[i] - pos);\n\t\t\tsplitCollection.keys.push(this.keys[i]);\n\t\t}\n\n\t\tconst spliceIndex = this.offsets[splitIndex] === pos ? splitIndex : splitIndex + 1;\n\t\tthis.keys.splice(spliceIndex);\n\t\tthis.offsets.splice(spliceIndex);\n\t\tthis._length = pos;\n\t\treturn splitCollection;\n\t}\n\n\tpublic append(other: AttributionCollection): void {\n\t\tconst lastEntry = this.keys[this.keys.length - 1];\n\t\tfor (let i = 0; i < other.keys.length; i++) {\n\t\t\tif (i !== 0 || !areEqualAttributionKeys(lastEntry, other.keys[i])) {\n\t\t\t\tthis.offsets.push(other.offsets[i] + this.length);\n\t\t\t\tthis.keys.push(other.keys[i]);\n\t\t\t}\n\t\t}\n\t\tthis._length += other.length;\n\t}\n\n\tpublic getAll(): { offset: number; key: AttributionKey }[] {\n\t\tconst results: { offset: number; key: AttributionKey }[] = new Array(this.keys.length);\n\t\tfor (let i = 0; i < this.keys.length; i++) {\n\t\t\tresults[i] = { offset: this.offsets[i], key: this.keys[i] };\n\t\t}\n\t\treturn results;\n\t}\n\n\tpublic clone(): AttributionCollection {\n\t\tconst copy = new AttributionCollection(this.keys[0], this.length);\n\t\tcopy.keys = this.keys.slice();\n\t\tcopy.offsets = this.offsets.slice();\n\t\treturn copy;\n\t}\n\n\t/**\n\t * Rehydrates attribution information from its serialized form into the provided iterable of consecutive segments.\n\t */\n\tpublic static populateAttributionCollections(\n\t\tsegments: Iterable<ISegment>,\n\t\tsummary: SerializedAttributionCollection,\n\t): void {\n\t\tconst { seqs, posBreakpoints } = summary;\n\t\tassert(\n\t\t\tseqs.length === posBreakpoints.length && seqs.length > 0,\n\t\t\t0x445 /* Invalid attribution summary blob provided */,\n\t\t);\n\t\tlet curIndex = 0;\n\t\tlet currentInfo = seqs[curIndex];\n\t\tlet cumulativeSegPos = 0;\n\n\t\tfor (const segment of segments) {\n\t\t\tconst attribution = new AttributionCollection(\n\t\t\t\ttypeof currentInfo === \"object\" ? currentInfo : { type: \"op\", seq: currentInfo },\n\t\t\t\tsegment.cachedLength,\n\t\t\t);\n\t\t\twhile (posBreakpoints[curIndex] < cumulativeSegPos + segment.cachedLength) {\n\t\t\t\tcurrentInfo = seqs[curIndex];\n\t\t\t\tconst nextOffset = posBreakpoints[curIndex] - cumulativeSegPos;\n\t\t\t\tif (attribution.offsets[attribution.offsets.length - 1] !== nextOffset) {\n\t\t\t\t\tattribution.offsets.push(nextOffset);\n\t\t\t\t\tattribution.keys.push(\n\t\t\t\t\t\ttypeof currentInfo === \"object\"\n\t\t\t\t\t\t\t? currentInfo\n\t\t\t\t\t\t\t: { type: \"op\", seq: currentInfo },\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tcurIndex++;\n\t\t\t}\n\n\t\t\tif (posBreakpoints[curIndex] === cumulativeSegPos + segment.cachedLength) {\n\t\t\t\tcurrentInfo = seqs[curIndex];\n\t\t\t}\n\n\t\t\tsegment.attribution = attribution;\n\t\t\tcumulativeSegPos += segment.cachedLength;\n\t\t}\n\t}\n\n\t/**\n\t * Condenses attribution information on consecutive segments into a `SerializedAttributionCollection`\n\t */\n\tpublic static serializeAttributionCollections(\n\t\tsegments: Iterable<{\n\t\t\tattribution?: IAttributionCollection<AttributionKey>;\n\t\t\tcachedLength: number;\n\t\t}>,\n\t): SerializedAttributionCollection {\n\t\tconst posBreakpoints: number[] = [];\n\t\tconst seqs: (number | AttributionKey)[] = [];\n\t\tlet mostRecentAttributionKey: AttributionKey | undefined;\n\t\tlet cumulativePos = 0;\n\n\t\tlet segmentsWithAttribution = 0;\n\t\tlet segmentsWithoutAttribution = 0;\n\t\tfor (const segment of segments) {\n\t\t\tif (segment.attribution) {\n\t\t\t\tsegmentsWithAttribution++;\n\t\t\t\tfor (const { offset, key } of segment.attribution?.getAll() ?? []) {\n\t\t\t\t\tif (\n\t\t\t\t\t\t!mostRecentAttributionKey ||\n\t\t\t\t\t\t!areEqualAttributionKeys(key, mostRecentAttributionKey)\n\t\t\t\t\t) {\n\t\t\t\t\t\tposBreakpoints.push(offset + cumulativePos);\n\t\t\t\t\t\tseqs.push(key.type === \"op\" ? key.seq : key);\n\t\t\t\t\t}\n\t\t\t\t\tmostRecentAttributionKey = key;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsegmentsWithoutAttribution++;\n\t\t\t}\n\n\t\t\tcumulativePos += segment.cachedLength;\n\t\t}\n\n\t\tassert(\n\t\t\tsegmentsWithAttribution === 0 || segmentsWithoutAttribution === 0,\n\t\t\t0x446 /* Expected either all segments or no segments to have attribution information. */,\n\t\t);\n\n\t\tconst blobContents: SerializedAttributionCollection = {\n\t\t\tseqs,\n\t\t\tposBreakpoints,\n\t\t\tlength: cumulativePos,\n\t\t};\n\t\treturn blobContents;\n\t}\n}\n\n/**\n * @alpha\n * @returns - An {@link AttributionPolicy} which tracks only insertion of content.\n * Content is only attributed at ack time, unless the container is in a detached state.\n * Detached content is attributed with a {@link @fluidframework/runtime-definitions#DetachedAttributionKey}.\n */\nexport function createInsertOnlyAttributionPolicy(): AttributionPolicy {\n\tlet unsubscribe: undefined | (() => void);\n\treturn {\n\t\tattach: (client: Client) => {\n\t\t\tassert(\n\t\t\t\tunsubscribe === undefined,\n\t\t\t\t0x557 /* cannot attach to multiple clients at once */,\n\t\t\t);\n\t\t\tconst deltaCallback: MergeTreeDeltaCallback = (\n\t\t\t\topArgs,\n\t\t\t\t{ deltaSegments, operation },\n\t\t\t) => {\n\t\t\t\tif (operation !== MergeTreeDeltaType.INSERT) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tfor (const { segment } of deltaSegments) {\n\t\t\t\t\tif (segment.seq !== undefined && segment.seq !== UnassignedSequenceNumber) {\n\t\t\t\t\t\tconst key: AttributionKey =\n\t\t\t\t\t\t\tsegment.seq === UniversalSequenceNumber\n\t\t\t\t\t\t\t\t? { type: \"detached\", id: 0 }\n\t\t\t\t\t\t\t\t: { type: \"op\", seq: segment.seq };\n\t\t\t\t\t\tsegment.attribution ??= new AttributionCollection(\n\t\t\t\t\t\t\tkey,\n\t\t\t\t\t\t\tsegment.cachedLength,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst maintenanceCallback: MergeTreeMaintenanceCallback = (\n\t\t\t\t{ deltaSegments, operation },\n\t\t\t\topArgs,\n\t\t\t) => {\n\t\t\t\tif (\n\t\t\t\t\toperation !== MergeTreeMaintenanceType.ACKNOWLEDGED ||\n\t\t\t\t\topArgs === undefined ||\n\t\t\t\t\topArgs.op.type !== MergeTreeDeltaType.INSERT\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (const { segment } of deltaSegments) {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tsegment.seq !== undefined,\n\t\t\t\t\t\t0x558 /* segment.seq should be set after ack. */,\n\t\t\t\t\t);\n\t\t\t\t\tsegment.attribution = new AttributionCollection(\n\t\t\t\t\t\t{ type: \"op\", seq: segment.seq },\n\t\t\t\t\t\tsegment.cachedLength,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tclient.on(\"delta\", deltaCallback);\n\t\t\tclient.on(\"maintenance\", maintenanceCallback);\n\n\t\t\tunsubscribe = () => {\n\t\t\t\tclient.off(\"delta\", deltaCallback);\n\t\t\t\tclient.off(\"maintenance\", maintenanceCallback);\n\t\t\t};\n\t\t},\n\t\tdetach: () => {\n\t\t\tunsubscribe?.();\n\t\t\tunsubscribe = undefined;\n\t\t},\n\t\tget isAttached() {\n\t\t\treturn unsubscribe !== undefined;\n\t\t},\n\t\tserializer: AttributionCollection,\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"properties.d.ts","sourceRoot":"","sources":["../src/properties.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAErC,MAAM,WAAW,OAAO,CAAC,CAAC;IACzB,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,CAAC;CACnB;AAKD,oBAAY,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;AAIvC,MAAM,WAAW,eAAe;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,GAAG,CAAC;CACX;AAED,wBAAgB,OAAO,CACtB,aAAa,EAAE,YAAY,EAC3B,YAAY,EAAE,GAAG,EACjB,QAAQ,EAAE,GAAG,EACb,GAAG,CAAC,EAAE,MAAM,OAyCZ;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,WAAW,GAAG,SAAS,EAAE,CAAC,EAAE,WAAW,GAAG,SAAS,WAkCrF;AAED,wBAAgB,MAAM,CAAC,CAAC,EACvB,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAChB,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,EACjC,WAAW,CAAC,EAAE,YAAY,EAC1B,GAAG,CAAC,EAAE,MAAM,cAmBZ;AAED,wBAAgB,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,0BAazD;AAED,wBAAgB,aAAa,CAC5B,QAAQ,EAAE,WAAW,GAAG,SAAS,EACjC,QAAQ,EAAE,WAAW,EACrB,EAAE,CAAC,EAAE,YAAY,EACjB,GAAG,CAAC,EAAE,MAAM,eAQZ;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,cAUvF;AAGD,wBAAgB,SAAS,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAEzC"}
1
+ {"version":3,"file":"properties.d.ts","sourceRoot":"","sources":["../src/properties.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAErC,MAAM,WAAW,OAAO,CAAC,CAAC;IACzB,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,CAAC;CACnB;AAKD,oBAAY,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;AAIvC,MAAM,WAAW,eAAe;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,GAAG,CAAC;CACX;AAED,wBAAgB,OAAO,CACtB,aAAa,EAAE,YAAY,EAC3B,YAAY,EAAE,GAAG,EACjB,QAAQ,EAAE,GAAG,EACb,GAAG,CAAC,EAAE,MAAM,OAyCZ;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,WAAW,GAAG,SAAS,EAAE,CAAC,EAAE,WAAW,GAAG,SAAS,WAyBrF;AAED,wBAAgB,MAAM,CAAC,CAAC,EACvB,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAChB,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,EACjC,WAAW,CAAC,EAAE,YAAY,EAC1B,GAAG,CAAC,EAAE,MAAM,cAmBZ;AAED,wBAAgB,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,0BAazD;AAED,wBAAgB,aAAa,CAC5B,QAAQ,EAAE,WAAW,GAAG,SAAS,EACjC,QAAQ,EAAE,WAAW,EACrB,EAAE,CAAC,EAAE,YAAY,EACjB,GAAG,CAAC,EAAE,MAAM,eAQZ;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,cAUvF;AAGD,wBAAgB,SAAS,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAEzC"}
@@ -45,36 +45,24 @@ function combine(combiningInfo, currentValue, newValue, seq) {
45
45
  }
46
46
  exports.combine = combine;
47
47
  function matchProperties(a, b) {
48
- if (a) {
49
- if (!b) {
48
+ if (!a && !b) {
49
+ return true;
50
+ }
51
+ const keysA = a ? Object.keys(a) : [];
52
+ const keysB = b ? Object.keys(b) : [];
53
+ if (keysA.length !== keysB.length) {
54
+ return false;
55
+ }
56
+ for (const key of keysA) {
57
+ if ((b === null || b === void 0 ? void 0 : b[key]) === undefined) {
50
58
  return false;
51
59
  }
52
- else {
53
- // For now, straightforward; later use hashing
54
- // eslint-disable-next-line no-restricted-syntax
55
- for (const key in a) {
56
- if (b[key] === undefined) {
57
- return false;
58
- }
59
- else if (typeof b[key] === "object") {
60
- if (!matchProperties(a[key], b[key])) {
61
- return false;
62
- }
63
- }
64
- else if (b[key] !== a[key]) {
65
- return false;
66
- }
67
- }
68
- // eslint-disable-next-line no-restricted-syntax
69
- for (const key in b) {
70
- if (a[key] === undefined) {
71
- return false;
72
- }
60
+ else if (typeof b[key] === "object") {
61
+ if (!matchProperties(a === null || a === void 0 ? void 0 : a[key], b[key])) {
62
+ return false;
73
63
  }
74
64
  }
75
- }
76
- else {
77
- if (b) {
65
+ else if (b[key] !== (a === null || a === void 0 ? void 0 : a[key])) {
78
66
  return false;
79
67
  }
80
68
  }
@@ -1 +1 @@
1
- {"version":3,"file":"properties.js","sourceRoot":"","sources":["../src/properties.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\nimport { ICombiningOp } from \"./ops\";\n\nexport interface MapLike<T> {\n\t[index: string]: T;\n}\n\n// We use any because when you include custom methods\n// such as toJSON(), JSON.stringify accepts most types other\n// than functions\nexport type PropertySet = MapLike<any>;\n\n// Assume these are created with Object.create(null)\n\nexport interface IConsensusValue {\n\tseq: number;\n\tvalue: any;\n}\n\nexport function combine(\n\tcombiningInfo: ICombiningOp,\n\tcurrentValue: any,\n\tnewValue: any,\n\tseq?: number,\n) {\n\tlet _currentValue = currentValue;\n\n\tif (_currentValue === undefined) {\n\t\t_currentValue = combiningInfo.defaultValue;\n\t}\n\t// Fixed set of operations for now\n\n\tswitch (combiningInfo.name) {\n\t\tcase \"incr\":\n\t\t\t_currentValue += newValue as number;\n\t\t\tif (combiningInfo.minValue) {\n\t\t\t\tif (_currentValue < combiningInfo.minValue) {\n\t\t\t\t\t_currentValue = combiningInfo.minValue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase \"consensus\":\n\t\t\tif (_currentValue === undefined) {\n\t\t\t\tconst cv: IConsensusValue = {\n\t\t\t\t\tvalue: newValue,\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\tseq: seq!,\n\t\t\t\t};\n\n\t\t\t\t_currentValue = cv;\n\t\t\t} else {\n\t\t\t\tconst cv = _currentValue as IConsensusValue;\n\t\t\t\tif (cv.seq === -1) {\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\tcv.seq = seq!;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-return\n\treturn _currentValue;\n}\n\nexport function matchProperties(a: PropertySet | undefined, b: PropertySet | undefined) {\n\tif (a) {\n\t\tif (!b) {\n\t\t\treturn false;\n\t\t} else {\n\t\t\t// For now, straightforward; later use hashing\n\n\t\t\t// eslint-disable-next-line no-restricted-syntax\n\t\t\tfor (const key in a) {\n\t\t\t\tif (b[key] === undefined) {\n\t\t\t\t\treturn false;\n\t\t\t\t} else if (typeof b[key] === \"object\") {\n\t\t\t\t\tif (!matchProperties(a[key], b[key])) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t} else if (b[key] !== a[key]) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// eslint-disable-next-line no-restricted-syntax\n\t\t\tfor (const key in b) {\n\t\t\t\tif (a[key] === undefined) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif (b) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\nexport function extend<T>(\n\tbase: MapLike<T>,\n\textension: MapLike<T> | undefined,\n\tcombiningOp?: ICombiningOp,\n\tseq?: number,\n) {\n\tif (extension !== undefined) {\n\t\t// eslint-disable-next-line guard-for-in, no-restricted-syntax\n\t\tfor (const key in extension) {\n\t\t\tconst v = extension[key];\n\t\t\tif (v === null) {\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n\t\t\t\tdelete base[key];\n\t\t\t} else {\n\t\t\t\tif (combiningOp && combiningOp.name !== \"rewrite\") {\n\t\t\t\t\tbase[key] = combine(combiningOp, base[key], v, seq);\n\t\t\t\t} else {\n\t\t\t\t\tbase[key] = v;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn base;\n}\n\nexport function clone<T>(extension: MapLike<T> | undefined) {\n\tif (extension === undefined) {\n\t\treturn undefined;\n\t}\n\tconst cloneMap = createMap<T>();\n\t// eslint-disable-next-line guard-for-in, no-restricted-syntax\n\tfor (const key in extension) {\n\t\tconst v = extension[key];\n\t\tif (v !== null) {\n\t\t\tcloneMap[key] = v;\n\t\t}\n\t}\n\treturn cloneMap;\n}\n\nexport function addProperties(\n\toldProps: PropertySet | undefined,\n\tnewProps: PropertySet,\n\top?: ICombiningOp,\n\tseq?: number,\n) {\n\tlet _oldProps = oldProps;\n\tif (!_oldProps || (op && op.name === \"rewrite\")) {\n\t\t_oldProps = createMap<any>();\n\t}\n\textend(_oldProps, newProps, op, seq);\n\treturn _oldProps;\n}\n\nexport function extendIfUndefined<T>(base: MapLike<T>, extension: MapLike<T> | undefined) {\n\tif (extension !== undefined) {\n\t\t// eslint-disable-next-line no-restricted-syntax\n\t\tfor (const key in extension) {\n\t\t\tif (base[key] === undefined) {\n\t\t\t\tbase[key] = extension[key];\n\t\t\t}\n\t\t}\n\t}\n\treturn base;\n}\n\n// Create a MapLike with good performance.\nexport function createMap<T>(): MapLike<T> {\n\treturn Object.create(null) as MapLike<T>;\n}\n"]}
1
+ {"version":3,"file":"properties.js","sourceRoot":"","sources":["../src/properties.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\nimport { ICombiningOp } from \"./ops\";\n\nexport interface MapLike<T> {\n\t[index: string]: T;\n}\n\n// We use any because when you include custom methods\n// such as toJSON(), JSON.stringify accepts most types other\n// than functions\nexport type PropertySet = MapLike<any>;\n\n// Assume these are created with Object.create(null)\n\nexport interface IConsensusValue {\n\tseq: number;\n\tvalue: any;\n}\n\nexport function combine(\n\tcombiningInfo: ICombiningOp,\n\tcurrentValue: any,\n\tnewValue: any,\n\tseq?: number,\n) {\n\tlet _currentValue = currentValue;\n\n\tif (_currentValue === undefined) {\n\t\t_currentValue = combiningInfo.defaultValue;\n\t}\n\t// Fixed set of operations for now\n\n\tswitch (combiningInfo.name) {\n\t\tcase \"incr\":\n\t\t\t_currentValue += newValue as number;\n\t\t\tif (combiningInfo.minValue) {\n\t\t\t\tif (_currentValue < combiningInfo.minValue) {\n\t\t\t\t\t_currentValue = combiningInfo.minValue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase \"consensus\":\n\t\t\tif (_currentValue === undefined) {\n\t\t\t\tconst cv: IConsensusValue = {\n\t\t\t\t\tvalue: newValue,\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\tseq: seq!,\n\t\t\t\t};\n\n\t\t\t\t_currentValue = cv;\n\t\t\t} else {\n\t\t\t\tconst cv = _currentValue as IConsensusValue;\n\t\t\t\tif (cv.seq === -1) {\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\tcv.seq = seq!;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-return\n\treturn _currentValue;\n}\n\nexport function matchProperties(a: PropertySet | undefined, b: PropertySet | undefined) {\n\tif (!a && !b) {\n\t\treturn true;\n\t}\n\n\tconst keysA = a ? Object.keys(a) : [];\n\tconst keysB = b ? Object.keys(b) : [];\n\n\tif (keysA.length !== keysB.length) {\n\t\treturn false;\n\t}\n\n\tfor (const key of keysA) {\n\t\tif (b?.[key] === undefined) {\n\t\t\treturn false;\n\t\t} else if (typeof b[key] === \"object\") {\n\t\t\tif (!matchProperties(a?.[key], b[key])) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} else if (b[key] !== a?.[key]) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\nexport function extend<T>(\n\tbase: MapLike<T>,\n\textension: MapLike<T> | undefined,\n\tcombiningOp?: ICombiningOp,\n\tseq?: number,\n) {\n\tif (extension !== undefined) {\n\t\t// eslint-disable-next-line guard-for-in, no-restricted-syntax\n\t\tfor (const key in extension) {\n\t\t\tconst v = extension[key];\n\t\t\tif (v === null) {\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n\t\t\t\tdelete base[key];\n\t\t\t} else {\n\t\t\t\tif (combiningOp && combiningOp.name !== \"rewrite\") {\n\t\t\t\t\tbase[key] = combine(combiningOp, base[key], v, seq);\n\t\t\t\t} else {\n\t\t\t\t\tbase[key] = v;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn base;\n}\n\nexport function clone<T>(extension: MapLike<T> | undefined) {\n\tif (extension === undefined) {\n\t\treturn undefined;\n\t}\n\tconst cloneMap = createMap<T>();\n\t// eslint-disable-next-line guard-for-in, no-restricted-syntax\n\tfor (const key in extension) {\n\t\tconst v = extension[key];\n\t\tif (v !== null) {\n\t\t\tcloneMap[key] = v;\n\t\t}\n\t}\n\treturn cloneMap;\n}\n\nexport function addProperties(\n\toldProps: PropertySet | undefined,\n\tnewProps: PropertySet,\n\top?: ICombiningOp,\n\tseq?: number,\n) {\n\tlet _oldProps = oldProps;\n\tif (!_oldProps || (op && op.name === \"rewrite\")) {\n\t\t_oldProps = createMap<any>();\n\t}\n\textend(_oldProps, newProps, op, seq);\n\treturn _oldProps;\n}\n\nexport function extendIfUndefined<T>(base: MapLike<T>, extension: MapLike<T> | undefined) {\n\tif (extension !== undefined) {\n\t\t// eslint-disable-next-line no-restricted-syntax\n\t\tfor (const key in extension) {\n\t\t\tif (base[key] === undefined) {\n\t\t\t\tbase[key] = extension[key];\n\t\t\t}\n\t\t}\n\t}\n\treturn base;\n}\n\n// Create a MapLike with good performance.\nexport function createMap<T>(): MapLike<T> {\n\treturn Object.create(null) as MapLike<T>;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"snapshotV1.d.ts","sourceRoot":"","sources":["../src/snapshotV1.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAGtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,EAAkB,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAI5F,OAAO,EAAmB,WAAW,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAEN,gBAAgB,EAEhB,gBAAgB,EAGhB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAIxC,qBAAa,UAAU;IAiBd,SAAS,EAAE,SAAS;IAE3B,OAAO,CAAC,QAAQ,CAAC,eAAe;IACzB,QAAQ,CAAC;IACT,YAAY,CAAC,SAAQ,IAAI;IAdjC,gBAAuB,SAAS,EAAE,MAAM,CAAS;IAEjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAW;IAC1C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAA2C;IAClF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAG3B,SAAS,EAAE,SAAS,EAC3B,MAAM,EAAE,gBAAgB,EACP,eAAe,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,EACjD,QAAQ,CAAC,oBAAQ,EACjB,YAAY,CAAC,SAAQ,IAAI,aAAA;IAmBjC,OAAO,CAAC,gBAAgB;IAgDxB;;;OAGG;IACH,IAAI,CAAC,UAAU,EAAE,gBAAgB,EAAE,IAAI,EAAE,YAAY,GAAG,qBAAqB;IA0D7E,WAAW;WAwHS,SAAS,CAC5B,OAAO,EAAE,sBAAsB,EAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,WAAW,GAAG,SAAS,EAChC,UAAU,CAAC,EAAE,gBAAgB,GAC3B,OAAO,CAAC,gBAAgB,CAAC;WAMd,YAAY,CACzB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,WAAW,GAAG,SAAS,EAChC,UAAU,CAAC,EAAE,gBAAgB,GAC3B,gBAAgB;CAInB"}
1
+ {"version":3,"file":"snapshotV1.d.ts","sourceRoot":"","sources":["../src/snapshotV1.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAGtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,EAAkB,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAI5F,OAAO,EAAmB,WAAW,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAEN,gBAAgB,EAEhB,gBAAgB,EAGhB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAIxC,qBAAa,UAAU;IAiBd,SAAS,EAAE,SAAS;IAE3B,OAAO,CAAC,QAAQ,CAAC,eAAe;IACzB,QAAQ,CAAC;IACT,YAAY,CAAC,SAAQ,IAAI;IAdjC,gBAAuB,SAAS,EAAE,MAAM,CAAS;IAEjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAW;IAC1C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAA2C;IAClF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAG3B,SAAS,EAAE,SAAS,EAC3B,MAAM,EAAE,gBAAgB,EACP,eAAe,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,EACjD,QAAQ,CAAC,oBAAQ,EACjB,YAAY,CAAC,SAAQ,IAAI,aAAA;IAmBjC,OAAO,CAAC,gBAAgB;IAgDxB;;;OAGG;IACH,IAAI,CAAC,UAAU,EAAE,gBAAgB,EAAE,IAAI,EAAE,YAAY,GAAG,qBAAqB;IA0D7E,WAAW;WAsIS,SAAS,CAC5B,OAAO,EAAE,sBAAsB,EAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,WAAW,GAAG,SAAS,EAChC,UAAU,CAAC,EAAE,gBAAgB,GAC3B,OAAO,CAAC,gBAAgB,CAAC;WAMd,YAAY,CACzB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,WAAW,GAAG,SAAS,EAChC,UAAU,CAAC,EAAE,gBAAgB,GAC3B,gBAAgB;CAInB"}
@@ -117,6 +117,11 @@ class SnapshotV1 {
117
117
  // Helper to serialize the given `segment` and add it to the snapshot (if a segment is provided).
118
118
  const pushSeg = (segment) => {
119
119
  if (segment) {
120
+ if (segment.properties !== undefined &&
121
+ Object.keys(segment.properties).length === 0) {
122
+ segment.properties = undefined;
123
+ segment.propertyManager = undefined;
124
+ }
120
125
  pushSegRaw(segment.toJSONObject(), segment.cachedLength, segment.attribution);
121
126
  }
122
127
  };
@@ -167,6 +172,11 @@ class SnapshotV1 {
167
172
  // for coalescing, so emit the 'prev' segment now (if any).
168
173
  pushSeg(prev);
169
174
  prev = undefined;
175
+ if (segment.properties !== undefined &&
176
+ Object.keys(segment.properties).length === 0) {
177
+ segment.properties = undefined;
178
+ segment.propertyManager = undefined;
179
+ }
170
180
  const raw = { json: segment.toJSONObject() };
171
181
  // If the segment insertion is above the MSN, record the insertion merge info.
172
182
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -1 +1 @@
1
- {"version":3,"file":"snapshotV1.js","sourceRoot":"","sources":["../src/snapshotV1.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\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { IFluidSerializer } from \"@fluidframework/shared-object-base\";\nimport { assert, bufferToString } from \"@fluidframework/common-utils\";\nimport { ChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { IChannelStorageService } from \"@fluidframework/datastore-definitions\";\nimport { AttributionKey, ISummaryTreeWithStats } from \"@fluidframework/runtime-definitions\";\nimport { SummaryTreeBuilder } from \"@fluidframework/runtime-utils\";\nimport { UnassignedSequenceNumber } from \"./constants\";\nimport { ISegment } from \"./mergeTreeNodes\";\nimport { matchProperties, PropertySet } from \"./properties\";\nimport {\n\tIJSONSegmentWithMergeInfo,\n\tJsonSegmentSpecs,\n\tMergeTreeHeaderMetadata,\n\tMergeTreeChunkV1,\n\ttoLatestVersion,\n\tserializeAsMaxSupportedVersion,\n} from \"./snapshotChunks\";\nimport { SnapshotLegacy } from \"./snapshotlegacy\";\nimport { MergeTree } from \"./mergeTree\";\nimport { walkAllChildSegments } from \"./mergeTreeNodeWalk\";\nimport { IAttributionCollection } from \"./attributionCollection\";\n\nexport class SnapshotV1 {\n\t// Split snapshot into two entries - headers (small) and body (overflow) for faster loading initial content\n\t// Please note that this number has no direct relationship to anything other than size of raw text (characters).\n\t// As we produce json for the blob (and then send over the wire compressed), this number\n\t// is really hard to correlate with any actual metric that matters (like bytes over the wire).\n\t// For test with small number of chunks it would be closer to blob size,\n\t// for very chunky text, blob size can easily be 4x-8x of that number.\n\tpublic static readonly chunkSize: number = 10000;\n\n\tprivate readonly header: MergeTreeHeaderMetadata;\n\tprivate readonly segments: JsonSegmentSpecs[];\n\tprivate readonly segmentLengths: number[];\n\tprivate readonly attributionCollections: IAttributionCollection<AttributionKey>[];\n\tprivate readonly logger: ITelemetryLogger;\n\tprivate readonly chunkSize: number;\n\n\tconstructor(\n\t\tpublic mergeTree: MergeTree,\n\t\tlogger: ITelemetryLogger,\n\t\tprivate readonly getLongClientId: (id: number) => string,\n\t\tpublic filename?: string,\n\t\tpublic onCompletion?: () => void,\n\t) {\n\t\tthis.logger = ChildLogger.create(logger, \"Snapshot\");\n\t\tthis.chunkSize = mergeTree?.options?.mergeTreeSnapshotChunkSize ?? SnapshotV1.chunkSize;\n\n\t\tconst { currentSeq, minSeq } = mergeTree.collabWindow;\n\t\tthis.header = {\n\t\t\tminSequenceNumber: minSeq,\n\t\t\tsequenceNumber: currentSeq,\n\t\t\torderedChunkMetadata: [],\n\t\t\ttotalLength: 0,\n\t\t\ttotalSegmentCount: 0,\n\t\t};\n\n\t\tthis.segments = [];\n\t\tthis.segmentLengths = [];\n\t\tthis.attributionCollections = [];\n\t}\n\n\tprivate getSeqLengthSegs(\n\t\tallSegments: JsonSegmentSpecs[],\n\t\tallLengths: number[],\n\t\tattributionCollections: IAttributionCollection<AttributionKey>[],\n\t\tapproxSequenceLength: number,\n\t\tstartIndex = 0,\n\t): MergeTreeChunkV1 {\n\t\tconst segments: JsonSegmentSpecs[] = [];\n\t\tconst collections: {\n\t\t\tattribution: IAttributionCollection<AttributionKey>;\n\t\t\tcachedLength: number;\n\t\t}[] = [];\n\t\tlet length = 0;\n\t\tlet segmentCount = 0;\n\t\tlet hasAttribution = false;\n\t\twhile (length < approxSequenceLength && startIndex + segmentCount < allSegments.length) {\n\t\t\tconst pseg = allSegments[startIndex + segmentCount];\n\t\t\tsegments.push(pseg);\n\t\t\tlength += allLengths[startIndex + segmentCount];\n\t\t\tif (attributionCollections[startIndex + segmentCount]) {\n\t\t\t\thasAttribution = true;\n\t\t\t\tcollections.push({\n\t\t\t\t\tattribution: attributionCollections[startIndex + segmentCount],\n\t\t\t\t\tcachedLength: allLengths[startIndex + segmentCount],\n\t\t\t\t});\n\t\t\t}\n\t\t\tsegmentCount++;\n\t\t}\n\n\t\tconst attributionSerializer = this.mergeTree.attributionPolicy?.serializer;\n\t\tassert(\n\t\t\t!hasAttribution || attributionSerializer !== undefined,\n\t\t\t0x55a /* attribution serializer must be provided when there are segments with attribution. */,\n\t\t);\n\n\t\treturn {\n\t\t\tversion: \"1\",\n\t\t\tsegmentCount,\n\t\t\tlength,\n\t\t\tsegments,\n\t\t\tstartIndex,\n\t\t\theaderMetadata: undefined,\n\t\t\tattribution: hasAttribution\n\t\t\t\t? attributionSerializer?.serializeAttributionCollections(collections)\n\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\t/**\n\t * Emits the snapshot to an ISummarizeResult. If provided the optional IFluidSerializer will be used when\n\t * serializing the summary data rather than JSON.stringify.\n\t */\n\temit(serializer: IFluidSerializer, bind: IFluidHandle): ISummaryTreeWithStats {\n\t\tconst chunks: MergeTreeChunkV1[] = [];\n\t\tthis.header.totalSegmentCount = 0;\n\t\tthis.header.totalLength = 0;\n\t\tdo {\n\t\t\tconst chunk = this.getSeqLengthSegs(\n\t\t\t\tthis.segments,\n\t\t\t\tthis.segmentLengths,\n\t\t\t\tthis.attributionCollections,\n\t\t\t\tthis.chunkSize,\n\t\t\t\tthis.header.totalSegmentCount,\n\t\t\t);\n\t\t\tchunks.push(chunk);\n\t\t\tthis.header.totalSegmentCount += chunk.segmentCount;\n\t\t\tthis.header.totalLength += chunk.length;\n\t\t} while (this.header.totalSegmentCount < this.segments.length);\n\n\t\t// The do while loop should have added at least one chunk\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst headerChunk = chunks.shift()!;\n\t\theaderChunk.headerMetadata = this.header;\n\t\theaderChunk.headerMetadata.orderedChunkMetadata = [{ id: SnapshotLegacy.header }];\n\t\tconst blobs: [key: string, content: string][] = [];\n\t\tchunks.forEach((chunk, index) => {\n\t\t\tconst id = `${SnapshotLegacy.body}_${index}`;\n\t\t\tthis.header.orderedChunkMetadata.push({ id });\n\t\t\tblobs.push([\n\t\t\t\tid,\n\t\t\t\tserializeAsMaxSupportedVersion(\n\t\t\t\t\tid,\n\t\t\t\t\tchunk,\n\t\t\t\t\tthis.logger,\n\t\t\t\t\tthis.mergeTree.options,\n\t\t\t\t\tserializer,\n\t\t\t\t\tbind,\n\t\t\t\t),\n\t\t\t]);\n\t\t});\n\n\t\tconst builder = new SummaryTreeBuilder();\n\t\tbuilder.addBlob(\n\t\t\tSnapshotLegacy.header,\n\t\t\tserializeAsMaxSupportedVersion(\n\t\t\t\tSnapshotLegacy.header,\n\t\t\t\theaderChunk,\n\t\t\t\tthis.logger,\n\t\t\t\tthis.mergeTree.options,\n\t\t\t\tserializer,\n\t\t\t\tbind,\n\t\t\t),\n\t\t);\n\t\tblobs.forEach((value) => {\n\t\t\tbuilder.addBlob(value[0], value[1]);\n\t\t});\n\n\t\treturn builder.getSummaryTree();\n\t}\n\n\textractSync() {\n\t\tconst mergeTree = this.mergeTree;\n\t\tconst minSeq = this.header.minSequenceNumber;\n\n\t\t// Helper to add the given `MergeTreeChunkV0SegmentSpec` to the snapshot.\n\t\tconst pushSegRaw = (\n\t\t\tjson: JsonSegmentSpecs,\n\t\t\tlength: number,\n\t\t\tattribution: IAttributionCollection<AttributionKey> | undefined,\n\t\t) => {\n\t\t\tthis.segments.push(json);\n\t\t\tthis.segmentLengths.push(length);\n\t\t\tif (attribution) {\n\t\t\t\tthis.attributionCollections.push(attribution);\n\t\t\t}\n\t\t};\n\n\t\t// Helper to serialize the given `segment` and add it to the snapshot (if a segment is provided).\n\t\tconst pushSeg = (segment?: ISegment) => {\n\t\t\tif (segment) {\n\t\t\t\tpushSegRaw(segment.toJSONObject(), segment.cachedLength, segment.attribution);\n\t\t\t}\n\t\t};\n\n\t\tlet prev: ISegment | undefined;\n\t\tconst extractSegment = (segment: ISegment) => {\n\t\t\t// Elide segments that do not need to be included in the snapshot. A segment may be elided if\n\t\t\t// either condition is true:\n\t\t\t// a) The segment has not yet been ACKed. We do not need to snapshot unACKed segments because\n\t\t\t// there is a pending insert op that will deliver the segment on reconnection.\n\t\t\t// b) The segment was removed at or below the MSN. Pending ops can no longer reference this\n\t\t\t// segment, and therefore we can discard it.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tif (segment.seq === UnassignedSequenceNumber || segment.removedSeq! <= minSeq) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// Next determine if the snapshot needs to preserve information required for merging the segment\n\t\t\t// (seq, client, etc.) This information is only needed if the segment is above the MSN (and doesn't\n\t\t\t// have a pending remove.)\n\t\t\tif (\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\tsegment.seq! <= minSeq && // Segment is below the MSN, and...\n\t\t\t\t(segment.removedSeq === undefined || // .. Segment has not been removed, or...\n\t\t\t\t\tsegment.removedSeq === UnassignedSequenceNumber) // .. Removal op to be delivered on reconnect\n\t\t\t) {\n\t\t\t\t// This segment is below the MSN, which means that future ops will not reference it. Attempt to\n\t\t\t\t// coalesce the new segment with the previous (if any).\n\t\t\t\tif (!prev) {\n\t\t\t\t\t// We do not have a previous candidate for coalescing. Make the current segment the new candidate.\n\t\t\t\t\tprev = segment;\n\t\t\t\t} else if (\n\t\t\t\t\tprev.canAppend(segment) &&\n\t\t\t\t\tmatchProperties(prev.properties, segment.properties)\n\t\t\t\t) {\n\t\t\t\t\t// We have a compatible pair. Replace `prev` with the coalesced segment. Clone to avoid\n\t\t\t\t\t// modifying the segment instances currently in the MergeTree.\n\t\t\t\t\tprev = prev.clone();\n\t\t\t\t\tprev.append(segment.clone());\n\t\t\t\t} else {\n\t\t\t\t\t// The segment pair could not be coalesced. Record the `prev` segment in the snapshot\n\t\t\t\t\t// and make the current segment the new candidate for coalescing.\n\t\t\t\t\tpushSeg(prev);\n\t\t\t\t\tprev = segment;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// This segment needs to preserve its metadata as it may be referenced by future ops. It's ineligible\n\t\t\t\t// for coalescing, so emit the 'prev' segment now (if any).\n\t\t\t\tpushSeg(prev);\n\t\t\t\tprev = undefined;\n\n\t\t\t\tconst raw: IJSONSegmentWithMergeInfo = { json: segment.toJSONObject() };\n\t\t\t\t// If the segment insertion is above the MSN, record the insertion merge info.\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\tif (segment.seq! > minSeq) {\n\t\t\t\t\traw.seq = segment.seq;\n\t\t\t\t\traw.client = this.getLongClientId(segment.clientId);\n\t\t\t\t}\n\t\t\t\t// We have already dispensed with removed segments below the MSN and removed segments with unassigned\n\t\t\t\t// sequence numbers. Any remaining removal info should be preserved.\n\t\t\t\tif (segment.removedSeq !== undefined) {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tsegment.removedSeq !== UnassignedSequenceNumber &&\n\t\t\t\t\t\t\tsegment.removedSeq > minSeq,\n\t\t\t\t\t\t0x065 /* \"On removal info preservation, segment has invalid removed sequence number!\" */,\n\t\t\t\t\t);\n\t\t\t\t\traw.removedSeq = segment.removedSeq;\n\n\t\t\t\t\t// back compat for when we split overlap and removed client\n\t\t\t\t\traw.removedClient =\n\t\t\t\t\t\tsegment.removedClientIds !== undefined\n\t\t\t\t\t\t\t? this.getLongClientId(segment.removedClientIds[0])\n\t\t\t\t\t\t\t: undefined;\n\n\t\t\t\t\traw.removedClientIds = segment.removedClientIds?.map((id) =>\n\t\t\t\t\t\tthis.getLongClientId(id),\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Sanity check that we are preserving either the seq < minSeq or a removed segment's info.\n\t\t\t\tassert(\n\t\t\t\t\t(raw.seq !== undefined && raw.client !== undefined) ||\n\t\t\t\t\t\t(raw.removedSeq !== undefined && raw.removedClient !== undefined),\n\t\t\t\t\t0x066 /* \"Corrupted preservation of segment metadata!\" */,\n\t\t\t\t);\n\n\t\t\t\t// Record the segment with it's required metadata.\n\t\t\t\tpushSegRaw(raw, segment.cachedLength, segment.attribution);\n\t\t\t}\n\t\t\treturn true;\n\t\t};\n\n\t\twalkAllChildSegments(mergeTree.root, extractSegment);\n\n\t\t// If the last segment in the walk was coalescable, push it now.\n\t\tpushSeg(prev);\n\n\t\treturn this.segments;\n\t}\n\n\tpublic static async loadChunk(\n\t\tstorage: IChannelStorageService,\n\t\tpath: string,\n\t\tlogger: ITelemetryLogger,\n\t\toptions: PropertySet | undefined,\n\t\tserializer?: IFluidSerializer,\n\t): Promise<MergeTreeChunkV1> {\n\t\tconst blob = await storage.readBlob(path);\n\t\tconst chunkAsString = bufferToString(blob, \"utf8\");\n\t\treturn SnapshotV1.processChunk(path, chunkAsString, logger, options, serializer);\n\t}\n\n\tpublic static processChunk(\n\t\tpath: string,\n\t\tchunk: string,\n\t\tlogger: ITelemetryLogger,\n\t\toptions: PropertySet | undefined,\n\t\tserializer?: IFluidSerializer,\n\t): MergeTreeChunkV1 {\n\t\tconst chunkObj = serializer ? serializer.parse(chunk) : JSON.parse(chunk);\n\t\treturn toLatestVersion(path, chunkObj, logger, options);\n\t}\n}\n"]}
1
+ {"version":3,"file":"snapshotV1.js","sourceRoot":"","sources":["../src/snapshotV1.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\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { IFluidSerializer } from \"@fluidframework/shared-object-base\";\nimport { assert, bufferToString } from \"@fluidframework/common-utils\";\nimport { ChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { IChannelStorageService } from \"@fluidframework/datastore-definitions\";\nimport { AttributionKey, ISummaryTreeWithStats } from \"@fluidframework/runtime-definitions\";\nimport { SummaryTreeBuilder } from \"@fluidframework/runtime-utils\";\nimport { UnassignedSequenceNumber } from \"./constants\";\nimport { ISegment } from \"./mergeTreeNodes\";\nimport { matchProperties, PropertySet } from \"./properties\";\nimport {\n\tIJSONSegmentWithMergeInfo,\n\tJsonSegmentSpecs,\n\tMergeTreeHeaderMetadata,\n\tMergeTreeChunkV1,\n\ttoLatestVersion,\n\tserializeAsMaxSupportedVersion,\n} from \"./snapshotChunks\";\nimport { SnapshotLegacy } from \"./snapshotlegacy\";\nimport { MergeTree } from \"./mergeTree\";\nimport { walkAllChildSegments } from \"./mergeTreeNodeWalk\";\nimport { IAttributionCollection } from \"./attributionCollection\";\n\nexport class SnapshotV1 {\n\t// Split snapshot into two entries - headers (small) and body (overflow) for faster loading initial content\n\t// Please note that this number has no direct relationship to anything other than size of raw text (characters).\n\t// As we produce json for the blob (and then send over the wire compressed), this number\n\t// is really hard to correlate with any actual metric that matters (like bytes over the wire).\n\t// For test with small number of chunks it would be closer to blob size,\n\t// for very chunky text, blob size can easily be 4x-8x of that number.\n\tpublic static readonly chunkSize: number = 10000;\n\n\tprivate readonly header: MergeTreeHeaderMetadata;\n\tprivate readonly segments: JsonSegmentSpecs[];\n\tprivate readonly segmentLengths: number[];\n\tprivate readonly attributionCollections: IAttributionCollection<AttributionKey>[];\n\tprivate readonly logger: ITelemetryLogger;\n\tprivate readonly chunkSize: number;\n\n\tconstructor(\n\t\tpublic mergeTree: MergeTree,\n\t\tlogger: ITelemetryLogger,\n\t\tprivate readonly getLongClientId: (id: number) => string,\n\t\tpublic filename?: string,\n\t\tpublic onCompletion?: () => void,\n\t) {\n\t\tthis.logger = ChildLogger.create(logger, \"Snapshot\");\n\t\tthis.chunkSize = mergeTree?.options?.mergeTreeSnapshotChunkSize ?? SnapshotV1.chunkSize;\n\n\t\tconst { currentSeq, minSeq } = mergeTree.collabWindow;\n\t\tthis.header = {\n\t\t\tminSequenceNumber: minSeq,\n\t\t\tsequenceNumber: currentSeq,\n\t\t\torderedChunkMetadata: [],\n\t\t\ttotalLength: 0,\n\t\t\ttotalSegmentCount: 0,\n\t\t};\n\n\t\tthis.segments = [];\n\t\tthis.segmentLengths = [];\n\t\tthis.attributionCollections = [];\n\t}\n\n\tprivate getSeqLengthSegs(\n\t\tallSegments: JsonSegmentSpecs[],\n\t\tallLengths: number[],\n\t\tattributionCollections: IAttributionCollection<AttributionKey>[],\n\t\tapproxSequenceLength: number,\n\t\tstartIndex = 0,\n\t): MergeTreeChunkV1 {\n\t\tconst segments: JsonSegmentSpecs[] = [];\n\t\tconst collections: {\n\t\t\tattribution: IAttributionCollection<AttributionKey>;\n\t\t\tcachedLength: number;\n\t\t}[] = [];\n\t\tlet length = 0;\n\t\tlet segmentCount = 0;\n\t\tlet hasAttribution = false;\n\t\twhile (length < approxSequenceLength && startIndex + segmentCount < allSegments.length) {\n\t\t\tconst pseg = allSegments[startIndex + segmentCount];\n\t\t\tsegments.push(pseg);\n\t\t\tlength += allLengths[startIndex + segmentCount];\n\t\t\tif (attributionCollections[startIndex + segmentCount]) {\n\t\t\t\thasAttribution = true;\n\t\t\t\tcollections.push({\n\t\t\t\t\tattribution: attributionCollections[startIndex + segmentCount],\n\t\t\t\t\tcachedLength: allLengths[startIndex + segmentCount],\n\t\t\t\t});\n\t\t\t}\n\t\t\tsegmentCount++;\n\t\t}\n\n\t\tconst attributionSerializer = this.mergeTree.attributionPolicy?.serializer;\n\t\tassert(\n\t\t\t!hasAttribution || attributionSerializer !== undefined,\n\t\t\t0x55a /* attribution serializer must be provided when there are segments with attribution. */,\n\t\t);\n\n\t\treturn {\n\t\t\tversion: \"1\",\n\t\t\tsegmentCount,\n\t\t\tlength,\n\t\t\tsegments,\n\t\t\tstartIndex,\n\t\t\theaderMetadata: undefined,\n\t\t\tattribution: hasAttribution\n\t\t\t\t? attributionSerializer?.serializeAttributionCollections(collections)\n\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\t/**\n\t * Emits the snapshot to an ISummarizeResult. If provided the optional IFluidSerializer will be used when\n\t * serializing the summary data rather than JSON.stringify.\n\t */\n\temit(serializer: IFluidSerializer, bind: IFluidHandle): ISummaryTreeWithStats {\n\t\tconst chunks: MergeTreeChunkV1[] = [];\n\t\tthis.header.totalSegmentCount = 0;\n\t\tthis.header.totalLength = 0;\n\t\tdo {\n\t\t\tconst chunk = this.getSeqLengthSegs(\n\t\t\t\tthis.segments,\n\t\t\t\tthis.segmentLengths,\n\t\t\t\tthis.attributionCollections,\n\t\t\t\tthis.chunkSize,\n\t\t\t\tthis.header.totalSegmentCount,\n\t\t\t);\n\t\t\tchunks.push(chunk);\n\t\t\tthis.header.totalSegmentCount += chunk.segmentCount;\n\t\t\tthis.header.totalLength += chunk.length;\n\t\t} while (this.header.totalSegmentCount < this.segments.length);\n\n\t\t// The do while loop should have added at least one chunk\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst headerChunk = chunks.shift()!;\n\t\theaderChunk.headerMetadata = this.header;\n\t\theaderChunk.headerMetadata.orderedChunkMetadata = [{ id: SnapshotLegacy.header }];\n\t\tconst blobs: [key: string, content: string][] = [];\n\t\tchunks.forEach((chunk, index) => {\n\t\t\tconst id = `${SnapshotLegacy.body}_${index}`;\n\t\t\tthis.header.orderedChunkMetadata.push({ id });\n\t\t\tblobs.push([\n\t\t\t\tid,\n\t\t\t\tserializeAsMaxSupportedVersion(\n\t\t\t\t\tid,\n\t\t\t\t\tchunk,\n\t\t\t\t\tthis.logger,\n\t\t\t\t\tthis.mergeTree.options,\n\t\t\t\t\tserializer,\n\t\t\t\t\tbind,\n\t\t\t\t),\n\t\t\t]);\n\t\t});\n\n\t\tconst builder = new SummaryTreeBuilder();\n\t\tbuilder.addBlob(\n\t\t\tSnapshotLegacy.header,\n\t\t\tserializeAsMaxSupportedVersion(\n\t\t\t\tSnapshotLegacy.header,\n\t\t\t\theaderChunk,\n\t\t\t\tthis.logger,\n\t\t\t\tthis.mergeTree.options,\n\t\t\t\tserializer,\n\t\t\t\tbind,\n\t\t\t),\n\t\t);\n\t\tblobs.forEach((value) => {\n\t\t\tbuilder.addBlob(value[0], value[1]);\n\t\t});\n\n\t\treturn builder.getSummaryTree();\n\t}\n\n\textractSync() {\n\t\tconst mergeTree = this.mergeTree;\n\t\tconst minSeq = this.header.minSequenceNumber;\n\n\t\t// Helper to add the given `MergeTreeChunkV0SegmentSpec` to the snapshot.\n\t\tconst pushSegRaw = (\n\t\t\tjson: JsonSegmentSpecs,\n\t\t\tlength: number,\n\t\t\tattribution: IAttributionCollection<AttributionKey> | undefined,\n\t\t) => {\n\t\t\tthis.segments.push(json);\n\t\t\tthis.segmentLengths.push(length);\n\t\t\tif (attribution) {\n\t\t\t\tthis.attributionCollections.push(attribution);\n\t\t\t}\n\t\t};\n\n\t\t// Helper to serialize the given `segment` and add it to the snapshot (if a segment is provided).\n\t\tconst pushSeg = (segment?: ISegment) => {\n\t\t\tif (segment) {\n\t\t\t\tif (\n\t\t\t\t\tsegment.properties !== undefined &&\n\t\t\t\t\tObject.keys(segment.properties).length === 0\n\t\t\t\t) {\n\t\t\t\t\tsegment.properties = undefined;\n\t\t\t\t\tsegment.propertyManager = undefined;\n\t\t\t\t}\n\t\t\t\tpushSegRaw(segment.toJSONObject(), segment.cachedLength, segment.attribution);\n\t\t\t}\n\t\t};\n\n\t\tlet prev: ISegment | undefined;\n\t\tconst extractSegment = (segment: ISegment) => {\n\t\t\t// Elide segments that do not need to be included in the snapshot. A segment may be elided if\n\t\t\t// either condition is true:\n\t\t\t// a) The segment has not yet been ACKed. We do not need to snapshot unACKed segments because\n\t\t\t// there is a pending insert op that will deliver the segment on reconnection.\n\t\t\t// b) The segment was removed at or below the MSN. Pending ops can no longer reference this\n\t\t\t// segment, and therefore we can discard it.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tif (segment.seq === UnassignedSequenceNumber || segment.removedSeq! <= minSeq) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// Next determine if the snapshot needs to preserve information required for merging the segment\n\t\t\t// (seq, client, etc.) This information is only needed if the segment is above the MSN (and doesn't\n\t\t\t// have a pending remove.)\n\t\t\tif (\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\tsegment.seq! <= minSeq && // Segment is below the MSN, and...\n\t\t\t\t(segment.removedSeq === undefined || // .. Segment has not been removed, or...\n\t\t\t\t\tsegment.removedSeq === UnassignedSequenceNumber) // .. Removal op to be delivered on reconnect\n\t\t\t) {\n\t\t\t\t// This segment is below the MSN, which means that future ops will not reference it. Attempt to\n\t\t\t\t// coalesce the new segment with the previous (if any).\n\t\t\t\tif (!prev) {\n\t\t\t\t\t// We do not have a previous candidate for coalescing. Make the current segment the new candidate.\n\t\t\t\t\tprev = segment;\n\t\t\t\t} else if (\n\t\t\t\t\tprev.canAppend(segment) &&\n\t\t\t\t\tmatchProperties(prev.properties, segment.properties)\n\t\t\t\t) {\n\t\t\t\t\t// We have a compatible pair. Replace `prev` with the coalesced segment. Clone to avoid\n\t\t\t\t\t// modifying the segment instances currently in the MergeTree.\n\t\t\t\t\tprev = prev.clone();\n\t\t\t\t\tprev.append(segment.clone());\n\t\t\t\t} else {\n\t\t\t\t\t// The segment pair could not be coalesced. Record the `prev` segment in the snapshot\n\t\t\t\t\t// and make the current segment the new candidate for coalescing.\n\t\t\t\t\tpushSeg(prev);\n\t\t\t\t\tprev = segment;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// This segment needs to preserve its metadata as it may be referenced by future ops. It's ineligible\n\t\t\t\t// for coalescing, so emit the 'prev' segment now (if any).\n\t\t\t\tpushSeg(prev);\n\t\t\t\tprev = undefined;\n\n\t\t\t\tif (\n\t\t\t\t\tsegment.properties !== undefined &&\n\t\t\t\t\tObject.keys(segment.properties).length === 0\n\t\t\t\t) {\n\t\t\t\t\tsegment.properties = undefined;\n\t\t\t\t\tsegment.propertyManager = undefined;\n\t\t\t\t}\n\t\t\t\tconst raw: IJSONSegmentWithMergeInfo = { json: segment.toJSONObject() };\n\t\t\t\t// If the segment insertion is above the MSN, record the insertion merge info.\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\tif (segment.seq! > minSeq) {\n\t\t\t\t\traw.seq = segment.seq;\n\t\t\t\t\traw.client = this.getLongClientId(segment.clientId);\n\t\t\t\t}\n\t\t\t\t// We have already dispensed with removed segments below the MSN and removed segments with unassigned\n\t\t\t\t// sequence numbers. Any remaining removal info should be preserved.\n\t\t\t\tif (segment.removedSeq !== undefined) {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tsegment.removedSeq !== UnassignedSequenceNumber &&\n\t\t\t\t\t\t\tsegment.removedSeq > minSeq,\n\t\t\t\t\t\t0x065 /* \"On removal info preservation, segment has invalid removed sequence number!\" */,\n\t\t\t\t\t);\n\t\t\t\t\traw.removedSeq = segment.removedSeq;\n\n\t\t\t\t\t// back compat for when we split overlap and removed client\n\t\t\t\t\traw.removedClient =\n\t\t\t\t\t\tsegment.removedClientIds !== undefined\n\t\t\t\t\t\t\t? this.getLongClientId(segment.removedClientIds[0])\n\t\t\t\t\t\t\t: undefined;\n\n\t\t\t\t\traw.removedClientIds = segment.removedClientIds?.map((id) =>\n\t\t\t\t\t\tthis.getLongClientId(id),\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Sanity check that we are preserving either the seq < minSeq or a removed segment's info.\n\t\t\t\tassert(\n\t\t\t\t\t(raw.seq !== undefined && raw.client !== undefined) ||\n\t\t\t\t\t\t(raw.removedSeq !== undefined && raw.removedClient !== undefined),\n\t\t\t\t\t0x066 /* \"Corrupted preservation of segment metadata!\" */,\n\t\t\t\t);\n\n\t\t\t\t// Record the segment with it's required metadata.\n\t\t\t\tpushSegRaw(raw, segment.cachedLength, segment.attribution);\n\t\t\t}\n\t\t\treturn true;\n\t\t};\n\n\t\twalkAllChildSegments(mergeTree.root, extractSegment);\n\n\t\t// If the last segment in the walk was coalescable, push it now.\n\t\tpushSeg(prev);\n\n\t\treturn this.segments;\n\t}\n\n\tpublic static async loadChunk(\n\t\tstorage: IChannelStorageService,\n\t\tpath: string,\n\t\tlogger: ITelemetryLogger,\n\t\toptions: PropertySet | undefined,\n\t\tserializer?: IFluidSerializer,\n\t): Promise<MergeTreeChunkV1> {\n\t\tconst blob = await storage.readBlob(path);\n\t\tconst chunkAsString = bufferToString(blob, \"utf8\");\n\t\treturn SnapshotV1.processChunk(path, chunkAsString, logger, options, serializer);\n\t}\n\n\tpublic static processChunk(\n\t\tpath: string,\n\t\tchunk: string,\n\t\tlogger: ITelemetryLogger,\n\t\toptions: PropertySet | undefined,\n\t\tserializer?: IFluidSerializer,\n\t): MergeTreeChunkV1 {\n\t\tconst chunkObj = serializer ? serializer.parse(chunk) : JSON.parse(chunk);\n\t\treturn toLatestVersion(path, chunkObj, logger, options);\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"snapshotlegacy.d.ts","sourceRoot":"","sources":["../src/snapshotlegacy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAEtE,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAE5E,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAGjF,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAO5C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAaxC;;GAEG;AACH,qBAAa,cAAc;IAoBlB,SAAS,EAAE,SAAS;IAEpB,QAAQ,CAAC;IACT,YAAY,CAAC,SAAQ,IAAI;IAtBjC,gBAAuB,MAAM,YAAY;IACzC,gBAAuB,IAAI,UAAU;IACrC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAQlD,gBAAuB,gBAAgB,EAAE,MAAM,CAAS;IAExD,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,GAAG,CAAqB;IAChC,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAG3B,SAAS,EAAE,SAAS,EAC3B,MAAM,EAAE,gBAAgB,EACjB,QAAQ,CAAC,oBAAQ,EACjB,YAAY,CAAC,SAAQ,IAAI,aAAA;IAOjC,OAAO,CAAC,gBAAgB;IAgDxB;;;OAGG;IACH,IAAI,CACH,WAAW,EAAE,yBAAyB,EAAE,EACxC,UAAU,EAAE,gBAAgB,EAC5B,IAAI,EAAE,YAAY,GAChB,qBAAqB;IA0DxB,WAAW;CAwEX"}
1
+ {"version":3,"file":"snapshotlegacy.d.ts","sourceRoot":"","sources":["../src/snapshotlegacy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAEtE,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAE5E,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAGjF,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAO5C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAaxC;;GAEG;AACH,qBAAa,cAAc;IAoBlB,SAAS,EAAE,SAAS;IAEpB,QAAQ,CAAC;IACT,YAAY,CAAC,SAAQ,IAAI;IAtBjC,gBAAuB,MAAM,YAAY;IACzC,gBAAuB,IAAI,UAAU;IACrC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAQlD,gBAAuB,gBAAgB,EAAE,MAAM,CAAS;IAExD,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,GAAG,CAAqB;IAChC,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAG3B,SAAS,EAAE,SAAS,EAC3B,MAAM,EAAE,gBAAgB,EACjB,QAAQ,CAAC,oBAAQ,EACjB,YAAY,CAAC,SAAQ,IAAI,aAAA;IAOjC,OAAO,CAAC,gBAAgB;IAgDxB;;;OAGG;IACH,IAAI,CACH,WAAW,EAAE,yBAAyB,EAAE,EACxC,UAAU,EAAE,gBAAgB,EAC5B,IAAI,EAAE,YAAY,GAChB,qBAAqB;IA0DxB,WAAW;CA4EX"}
@@ -118,6 +118,10 @@ class SnapshotLegacy {
118
118
  let totalLength = 0;
119
119
  segs.map((segment) => {
120
120
  totalLength += segment.cachedLength;
121
+ if (segment.properties !== undefined && Object.keys(segment.properties).length === 0) {
122
+ segment.properties = undefined;
123
+ segment.propertyManager = undefined;
124
+ }
121
125
  this.segments.push(segment);
122
126
  });
123
127
  // We observed this.header.segmentsTotalLength < totalLength to happen in some cases
@@ -1 +1 @@
1
- {"version":3,"file":"snapshotlegacy.js","sourceRoot":"","sources":["../src/snapshotlegacy.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/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { IFluidSerializer } from \"@fluidframework/shared-object-base\";\nimport { ISummaryTreeWithStats } from \"@fluidframework/runtime-definitions\";\nimport { ChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { SummaryTreeBuilder } from \"@fluidframework/runtime-utils\";\nimport { NonCollabClient, UnassignedSequenceNumber } from \"./constants\";\nimport { ISegment } from \"./mergeTreeNodes\";\nimport { matchProperties } from \"./properties\";\nimport {\n\tJsonSegmentSpecs,\n\tMergeTreeChunkLegacy,\n\tserializeAsMinSupportedVersion,\n} from \"./snapshotChunks\";\nimport { MergeTree } from \"./mergeTree\";\n\ninterface SnapshotHeader {\n\tchunkCount?: number;\n\tsegmentsTotalLength: number;\n\tindexOffset?: number;\n\tsegmentsOffset?: number;\n\tseq: number;\n\t// TODO: Make 'minSeq' non-optional once the new snapshot format becomes the default?\n\t// (See https://github.com/microsoft/FluidFramework/issues/84)\n\tminSeq?: number;\n}\n\n/**\n * @internal\n */\nexport class SnapshotLegacy {\n\tpublic static readonly header = \"header\";\n\tpublic static readonly body = \"body\";\n\tprivate static readonly catchupOps = \"catchupOps\";\n\n\t// Split snapshot into two entries - headers (small) and body (overflow) for faster loading initial content\n\t// Please note that this number has no direct relationship to anything other than size of raw text (characters).\n\t// As we produce json for the blob (and then send over the wire compressed), this number\n\t// is really hard to correlate with any actual metric that matters (like bytes over the wire).\n\t// For test with small number of chunks it would be closer to blob size,\n\t// for very chunky text, blob size can easily be 4x-8x of that number.\n\tpublic static readonly sizeOfFirstChunk: number = 10000;\n\n\tprivate header: SnapshotHeader | undefined;\n\tprivate seq: number | undefined;\n\tprivate segments: ISegment[] | undefined;\n\tprivate readonly logger: ITelemetryLogger;\n\tprivate readonly chunkSize: number;\n\n\tconstructor(\n\t\tpublic mergeTree: MergeTree,\n\t\tlogger: ITelemetryLogger,\n\t\tpublic filename?: string,\n\t\tpublic onCompletion?: () => void,\n\t) {\n\t\tthis.logger = ChildLogger.create(logger, \"Snapshot\");\n\t\tthis.chunkSize =\n\t\t\tmergeTree?.options?.mergeTreeSnapshotChunkSize ?? SnapshotLegacy.sizeOfFirstChunk;\n\t}\n\n\tprivate getSeqLengthSegs(\n\t\tallSegments: ISegment[],\n\t\tapproxSequenceLength: number,\n\t\tstartIndex = 0,\n\t): MergeTreeChunkLegacy {\n\t\tconst segs: ISegment[] = [];\n\t\tlet sequenceLength = 0;\n\t\tlet segCount = 0;\n\t\tlet segsWithAttribution = 0;\n\t\twhile (\n\t\t\tsequenceLength < approxSequenceLength &&\n\t\t\tstartIndex + segCount < allSegments.length\n\t\t) {\n\t\t\tconst pseg = allSegments[startIndex + segCount];\n\t\t\tsegs.push(pseg);\n\t\t\tif (pseg.attribution) {\n\t\t\t\tsegsWithAttribution++;\n\t\t\t}\n\t\t\tsequenceLength += pseg.cachedLength;\n\t\t\tsegCount++;\n\t\t}\n\n\t\tassert(\n\t\t\tsegsWithAttribution === 0 || segsWithAttribution === segCount,\n\t\t\t0x4bf /* all or no segments should have attribution */,\n\t\t);\n\n\t\tconst attributionSerializer = this.mergeTree.attributionPolicy?.serializer;\n\t\tassert(\n\t\t\tsegsWithAttribution === 0 || attributionSerializer !== undefined,\n\t\t\t0x559 /* attribution serializer must be provided when there are segments with attribution. */,\n\t\t);\n\t\treturn {\n\t\t\tversion: undefined,\n\t\t\tchunkStartSegmentIndex: startIndex,\n\t\t\tchunkSegmentCount: segCount,\n\t\t\tchunkLengthChars: sequenceLength,\n\t\t\ttotalLengthChars: this.header!.segmentsTotalLength,\n\t\t\ttotalSegmentCount: allSegments.length,\n\t\t\tchunkSequenceNumber: this.header!.seq,\n\t\t\tsegmentTexts: segs.map((seg) => seg.toJSONObject() as JsonSegmentSpecs),\n\t\t\tattribution:\n\t\t\t\tsegsWithAttribution > 0\n\t\t\t\t\t? attributionSerializer?.serializeAttributionCollections(segs)\n\t\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\t/**\n\t * Emits the snapshot to an ISummarizeResult. If provided the optional IFluidSerializer will be used when\n\t * serializing the summary data rather than JSON.stringify.\n\t */\n\temit(\n\t\tcatchUpMsgs: ISequencedDocumentMessage[],\n\t\tserializer: IFluidSerializer,\n\t\tbind: IFluidHandle,\n\t): ISummaryTreeWithStats {\n\t\tconst chunk1 = this.getSeqLengthSegs(this.segments!, this.chunkSize);\n\t\tlet length: number = chunk1.chunkLengthChars;\n\t\tlet segments: number = chunk1.chunkSegmentCount;\n\t\tconst builder = new SummaryTreeBuilder();\n\t\tbuilder.addBlob(\n\t\t\tSnapshotLegacy.header,\n\t\t\tserializeAsMinSupportedVersion(\n\t\t\t\tSnapshotLegacy.header,\n\t\t\t\tchunk1,\n\t\t\t\tthis.logger,\n\t\t\t\tthis.mergeTree.options,\n\t\t\t\tserializer,\n\t\t\t\tbind,\n\t\t\t),\n\t\t);\n\n\t\tif (chunk1.chunkSegmentCount < chunk1.totalSegmentCount!) {\n\t\t\tconst chunk2 = this.getSeqLengthSegs(\n\t\t\t\tthis.segments!,\n\t\t\t\tthis.header!.segmentsTotalLength,\n\t\t\t\tchunk1.chunkSegmentCount,\n\t\t\t);\n\t\t\tlength += chunk2.chunkLengthChars;\n\t\t\tsegments += chunk2.chunkSegmentCount;\n\t\t\tbuilder.addBlob(\n\t\t\t\tSnapshotLegacy.body,\n\t\t\t\tserializeAsMinSupportedVersion(\n\t\t\t\t\tSnapshotLegacy.body,\n\t\t\t\t\tchunk2,\n\t\t\t\t\tthis.logger,\n\t\t\t\t\tthis.mergeTree.options,\n\t\t\t\t\tserializer,\n\t\t\t\t\tbind,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tassert(\n\t\t\tlength === this.header!.segmentsTotalLength,\n\t\t\t0x05d /* \"emit: mismatch in segmentsTotalLength\" */,\n\t\t);\n\n\t\tassert(\n\t\t\tsegments === chunk1.totalSegmentCount,\n\t\t\t0x05e /* \"emit: mismatch in totalSegmentCount\" */,\n\t\t);\n\n\t\tif (catchUpMsgs !== undefined && catchUpMsgs.length > 0) {\n\t\t\tbuilder.addBlob(\n\t\t\t\tthis.mergeTree.options?.catchUpBlobName ?? SnapshotLegacy.catchupOps,\n\t\t\t\tserializer ? serializer.stringify(catchUpMsgs, bind) : JSON.stringify(catchUpMsgs),\n\t\t\t);\n\t\t}\n\n\t\treturn builder.getSummaryTree();\n\t}\n\n\textractSync() {\n\t\tconst collabWindow = this.mergeTree.collabWindow;\n\t\tthis.seq = collabWindow.minSeq;\n\t\tthis.header = {\n\t\t\tsegmentsTotalLength: this.mergeTree.getLength(\n\t\t\t\tthis.mergeTree.collabWindow.minSeq,\n\t\t\t\tNonCollabClient,\n\t\t\t),\n\t\t\tseq: this.mergeTree.collabWindow.minSeq,\n\t\t};\n\n\t\tconst segs: ISegment[] = [];\n\t\tlet prev: ISegment | undefined;\n\t\tconst extractSegment = (\n\t\t\tsegment: ISegment,\n\t\t\tpos: number,\n\t\t\trefSeq: number,\n\t\t\tclientId: number,\n\t\t\tstart: number | undefined,\n\t\t\tend: number | undefined,\n\t\t) => {\n\t\t\tif (\n\t\t\t\tsegment.seq !== UnassignedSequenceNumber &&\n\t\t\t\tsegment.seq! <= this.seq! &&\n\t\t\t\t(segment.removedSeq === undefined ||\n\t\t\t\t\tsegment.removedSeq === UnassignedSequenceNumber ||\n\t\t\t\t\tsegment.removedSeq > this.seq!)\n\t\t\t) {\n\t\t\t\tif (\n\t\t\t\t\tprev?.canAppend(segment) &&\n\t\t\t\t\tmatchProperties(prev.properties, segment.properties)\n\t\t\t\t) {\n\t\t\t\t\tprev = prev.clone();\n\t\t\t\t\tprev.append(segment.clone());\n\t\t\t\t} else {\n\t\t\t\t\tif (prev) {\n\t\t\t\t\t\tsegs.push(prev);\n\t\t\t\t\t}\n\t\t\t\t\tprev = segment;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t};\n\n\t\tthis.mergeTree.mapRange(extractSegment, this.seq, NonCollabClient, undefined);\n\t\tif (prev) {\n\t\t\tsegs.push(prev);\n\t\t}\n\n\t\tthis.segments = [];\n\t\tlet totalLength: number = 0;\n\t\tsegs.map((segment) => {\n\t\t\ttotalLength += segment.cachedLength;\n\t\t\tthis.segments!.push(segment);\n\t\t});\n\n\t\t// We observed this.header.segmentsTotalLength < totalLength to happen in some cases\n\t\t// When this condition happens, we might not write out all segments in getSeqLengthSegs()\n\t\t// when writing out \"body\". Issue #1995 tracks following up on the core of the problem.\n\t\t// In the meantime, this code makes sure we will write out all segments properly\n\n\t\tif (this.header.segmentsTotalLength !== totalLength) {\n\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\teventName: \"SegmentsTotalLengthMismatch\",\n\t\t\t\ttotalLength,\n\t\t\t\tsegmentsTotalLength: this.header.segmentsTotalLength,\n\t\t\t});\n\t\t\tthis.header.segmentsTotalLength = totalLength;\n\t\t}\n\n\t\treturn this.segments;\n\t}\n}\n"]}
1
+ {"version":3,"file":"snapshotlegacy.js","sourceRoot":"","sources":["../src/snapshotlegacy.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/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { IFluidSerializer } from \"@fluidframework/shared-object-base\";\nimport { ISummaryTreeWithStats } from \"@fluidframework/runtime-definitions\";\nimport { ChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { SummaryTreeBuilder } from \"@fluidframework/runtime-utils\";\nimport { NonCollabClient, UnassignedSequenceNumber } from \"./constants\";\nimport { ISegment } from \"./mergeTreeNodes\";\nimport { matchProperties } from \"./properties\";\nimport {\n\tJsonSegmentSpecs,\n\tMergeTreeChunkLegacy,\n\tserializeAsMinSupportedVersion,\n} from \"./snapshotChunks\";\nimport { MergeTree } from \"./mergeTree\";\n\ninterface SnapshotHeader {\n\tchunkCount?: number;\n\tsegmentsTotalLength: number;\n\tindexOffset?: number;\n\tsegmentsOffset?: number;\n\tseq: number;\n\t// TODO: Make 'minSeq' non-optional once the new snapshot format becomes the default?\n\t// (See https://github.com/microsoft/FluidFramework/issues/84)\n\tminSeq?: number;\n}\n\n/**\n * @internal\n */\nexport class SnapshotLegacy {\n\tpublic static readonly header = \"header\";\n\tpublic static readonly body = \"body\";\n\tprivate static readonly catchupOps = \"catchupOps\";\n\n\t// Split snapshot into two entries - headers (small) and body (overflow) for faster loading initial content\n\t// Please note that this number has no direct relationship to anything other than size of raw text (characters).\n\t// As we produce json for the blob (and then send over the wire compressed), this number\n\t// is really hard to correlate with any actual metric that matters (like bytes over the wire).\n\t// For test with small number of chunks it would be closer to blob size,\n\t// for very chunky text, blob size can easily be 4x-8x of that number.\n\tpublic static readonly sizeOfFirstChunk: number = 10000;\n\n\tprivate header: SnapshotHeader | undefined;\n\tprivate seq: number | undefined;\n\tprivate segments: ISegment[] | undefined;\n\tprivate readonly logger: ITelemetryLogger;\n\tprivate readonly chunkSize: number;\n\n\tconstructor(\n\t\tpublic mergeTree: MergeTree,\n\t\tlogger: ITelemetryLogger,\n\t\tpublic filename?: string,\n\t\tpublic onCompletion?: () => void,\n\t) {\n\t\tthis.logger = ChildLogger.create(logger, \"Snapshot\");\n\t\tthis.chunkSize =\n\t\t\tmergeTree?.options?.mergeTreeSnapshotChunkSize ?? SnapshotLegacy.sizeOfFirstChunk;\n\t}\n\n\tprivate getSeqLengthSegs(\n\t\tallSegments: ISegment[],\n\t\tapproxSequenceLength: number,\n\t\tstartIndex = 0,\n\t): MergeTreeChunkLegacy {\n\t\tconst segs: ISegment[] = [];\n\t\tlet sequenceLength = 0;\n\t\tlet segCount = 0;\n\t\tlet segsWithAttribution = 0;\n\t\twhile (\n\t\t\tsequenceLength < approxSequenceLength &&\n\t\t\tstartIndex + segCount < allSegments.length\n\t\t) {\n\t\t\tconst pseg = allSegments[startIndex + segCount];\n\t\t\tsegs.push(pseg);\n\t\t\tif (pseg.attribution) {\n\t\t\t\tsegsWithAttribution++;\n\t\t\t}\n\t\t\tsequenceLength += pseg.cachedLength;\n\t\t\tsegCount++;\n\t\t}\n\n\t\tassert(\n\t\t\tsegsWithAttribution === 0 || segsWithAttribution === segCount,\n\t\t\t0x4bf /* all or no segments should have attribution */,\n\t\t);\n\n\t\tconst attributionSerializer = this.mergeTree.attributionPolicy?.serializer;\n\t\tassert(\n\t\t\tsegsWithAttribution === 0 || attributionSerializer !== undefined,\n\t\t\t0x559 /* attribution serializer must be provided when there are segments with attribution. */,\n\t\t);\n\t\treturn {\n\t\t\tversion: undefined,\n\t\t\tchunkStartSegmentIndex: startIndex,\n\t\t\tchunkSegmentCount: segCount,\n\t\t\tchunkLengthChars: sequenceLength,\n\t\t\ttotalLengthChars: this.header!.segmentsTotalLength,\n\t\t\ttotalSegmentCount: allSegments.length,\n\t\t\tchunkSequenceNumber: this.header!.seq,\n\t\t\tsegmentTexts: segs.map((seg) => seg.toJSONObject() as JsonSegmentSpecs),\n\t\t\tattribution:\n\t\t\t\tsegsWithAttribution > 0\n\t\t\t\t\t? attributionSerializer?.serializeAttributionCollections(segs)\n\t\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\t/**\n\t * Emits the snapshot to an ISummarizeResult. If provided the optional IFluidSerializer will be used when\n\t * serializing the summary data rather than JSON.stringify.\n\t */\n\temit(\n\t\tcatchUpMsgs: ISequencedDocumentMessage[],\n\t\tserializer: IFluidSerializer,\n\t\tbind: IFluidHandle,\n\t): ISummaryTreeWithStats {\n\t\tconst chunk1 = this.getSeqLengthSegs(this.segments!, this.chunkSize);\n\t\tlet length: number = chunk1.chunkLengthChars;\n\t\tlet segments: number = chunk1.chunkSegmentCount;\n\t\tconst builder = new SummaryTreeBuilder();\n\t\tbuilder.addBlob(\n\t\t\tSnapshotLegacy.header,\n\t\t\tserializeAsMinSupportedVersion(\n\t\t\t\tSnapshotLegacy.header,\n\t\t\t\tchunk1,\n\t\t\t\tthis.logger,\n\t\t\t\tthis.mergeTree.options,\n\t\t\t\tserializer,\n\t\t\t\tbind,\n\t\t\t),\n\t\t);\n\n\t\tif (chunk1.chunkSegmentCount < chunk1.totalSegmentCount!) {\n\t\t\tconst chunk2 = this.getSeqLengthSegs(\n\t\t\t\tthis.segments!,\n\t\t\t\tthis.header!.segmentsTotalLength,\n\t\t\t\tchunk1.chunkSegmentCount,\n\t\t\t);\n\t\t\tlength += chunk2.chunkLengthChars;\n\t\t\tsegments += chunk2.chunkSegmentCount;\n\t\t\tbuilder.addBlob(\n\t\t\t\tSnapshotLegacy.body,\n\t\t\t\tserializeAsMinSupportedVersion(\n\t\t\t\t\tSnapshotLegacy.body,\n\t\t\t\t\tchunk2,\n\t\t\t\t\tthis.logger,\n\t\t\t\t\tthis.mergeTree.options,\n\t\t\t\t\tserializer,\n\t\t\t\t\tbind,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tassert(\n\t\t\tlength === this.header!.segmentsTotalLength,\n\t\t\t0x05d /* \"emit: mismatch in segmentsTotalLength\" */,\n\t\t);\n\n\t\tassert(\n\t\t\tsegments === chunk1.totalSegmentCount,\n\t\t\t0x05e /* \"emit: mismatch in totalSegmentCount\" */,\n\t\t);\n\n\t\tif (catchUpMsgs !== undefined && catchUpMsgs.length > 0) {\n\t\t\tbuilder.addBlob(\n\t\t\t\tthis.mergeTree.options?.catchUpBlobName ?? SnapshotLegacy.catchupOps,\n\t\t\t\tserializer ? serializer.stringify(catchUpMsgs, bind) : JSON.stringify(catchUpMsgs),\n\t\t\t);\n\t\t}\n\n\t\treturn builder.getSummaryTree();\n\t}\n\n\textractSync() {\n\t\tconst collabWindow = this.mergeTree.collabWindow;\n\t\tthis.seq = collabWindow.minSeq;\n\t\tthis.header = {\n\t\t\tsegmentsTotalLength: this.mergeTree.getLength(\n\t\t\t\tthis.mergeTree.collabWindow.minSeq,\n\t\t\t\tNonCollabClient,\n\t\t\t),\n\t\t\tseq: this.mergeTree.collabWindow.minSeq,\n\t\t};\n\n\t\tconst segs: ISegment[] = [];\n\t\tlet prev: ISegment | undefined;\n\t\tconst extractSegment = (\n\t\t\tsegment: ISegment,\n\t\t\tpos: number,\n\t\t\trefSeq: number,\n\t\t\tclientId: number,\n\t\t\tstart: number | undefined,\n\t\t\tend: number | undefined,\n\t\t) => {\n\t\t\tif (\n\t\t\t\tsegment.seq !== UnassignedSequenceNumber &&\n\t\t\t\tsegment.seq! <= this.seq! &&\n\t\t\t\t(segment.removedSeq === undefined ||\n\t\t\t\t\tsegment.removedSeq === UnassignedSequenceNumber ||\n\t\t\t\t\tsegment.removedSeq > this.seq!)\n\t\t\t) {\n\t\t\t\tif (\n\t\t\t\t\tprev?.canAppend(segment) &&\n\t\t\t\t\tmatchProperties(prev.properties, segment.properties)\n\t\t\t\t) {\n\t\t\t\t\tprev = prev.clone();\n\t\t\t\t\tprev.append(segment.clone());\n\t\t\t\t} else {\n\t\t\t\t\tif (prev) {\n\t\t\t\t\t\tsegs.push(prev);\n\t\t\t\t\t}\n\t\t\t\t\tprev = segment;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t};\n\n\t\tthis.mergeTree.mapRange(extractSegment, this.seq, NonCollabClient, undefined);\n\t\tif (prev) {\n\t\t\tsegs.push(prev);\n\t\t}\n\n\t\tthis.segments = [];\n\t\tlet totalLength: number = 0;\n\t\tsegs.map((segment) => {\n\t\t\ttotalLength += segment.cachedLength;\n\t\t\tif (segment.properties !== undefined && Object.keys(segment.properties).length === 0) {\n\t\t\t\tsegment.properties = undefined;\n\t\t\t\tsegment.propertyManager = undefined;\n\t\t\t}\n\t\t\tthis.segments!.push(segment);\n\t\t});\n\n\t\t// We observed this.header.segmentsTotalLength < totalLength to happen in some cases\n\t\t// When this condition happens, we might not write out all segments in getSeqLengthSegs()\n\t\t// when writing out \"body\". Issue #1995 tracks following up on the core of the problem.\n\t\t// In the meantime, this code makes sure we will write out all segments properly\n\n\t\tif (this.header.segmentsTotalLength !== totalLength) {\n\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\teventName: \"SegmentsTotalLengthMismatch\",\n\t\t\t\ttotalLength,\n\t\t\t\tsegmentsTotalLength: this.header.segmentsTotalLength,\n\t\t\t});\n\t\t\tthis.header.segmentsTotalLength = totalLength;\n\t\t}\n\n\t\treturn this.segments;\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"attributionCollection.d.ts","sourceRoot":"","sources":["../src/attributionCollection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACN,cAAc,EAGd,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAQhD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAG5C;;GAEG;AACH,MAAM,WAAW,+BAA+B;IAC/C;;;;;OAKG;IACH,IAAI,EAAE,CAAC,MAAM,GAAG,cAAc,CAAC,EAAE,CAAC;IAClC,cAAc,EAAE,MAAM,EAAE,CAAC;IAEzB,MAAM,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,gCAAgC;IAChD;;OAEG;IACH,+BAA+B,CAC9B,QAAQ,EAAE,QAAQ,CAAC;QAClB,WAAW,CAAC,EAAE,sBAAsB,CAAC,cAAc,CAAC,CAAC;QACrD,YAAY,EAAE,MAAM,CAAC;KACrB,CAAC,GACA,+BAA+B,CAAC;IAEnC;;;OAGG;IACH,8BAA8B,CAC7B,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAC5B,OAAO,EAAE,+BAA+B,GACtC,IAAI,CAAC;CACR;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB,CAAC,CAAC;IACxC;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC;IAE/B;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB;;;;;;OAMG;IACH,MAAM,IAAI,QAAQ,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,CAAC,CAAA;KAAE,CAAC,CAAC;IAE/C,gBAAgB;IAChB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAEhD,gBAAgB;IAChB,MAAM,CAAC,KAAK,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAE/C,gBAAgB;IAChB,KAAK,IAAI,sBAAsB,CAAC,CAAC,CAAC,CAAC;CACnC;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,cAAc,GAAG,OAAO,CAcrF;AAED,qBAAa,qBAAsB,YAAW,sBAAsB,CAAC,cAAc,CAAC;IAIrC,OAAO,CAAC,OAAO;IAH7D,OAAO,CAAC,OAAO,CAAW;IAC1B,OAAO,CAAC,IAAI,CAAmB;gBAEZ,SAAS,EAAE,cAAc,EAAU,OAAO,EAAE,MAAM;IAK9D,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc;IAKlD,OAAO,CAAC,SAAS;IAWjB,IAAW,MAAM,IAAI,MAAM,CAE1B;IAED;;OAEG;IACI,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,qBAAqB;IAgB3C,MAAM,CAAC,KAAK,EAAE,qBAAqB,GAAG,IAAI;IAW1C,MAAM,IAAI;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,cAAc,CAAA;KAAE,EAAE;IAQnD,KAAK,IAAI,qBAAqB;IAOrC;;OAEG;WACW,8BAA8B,CAC3C,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAC5B,OAAO,EAAE,+BAA+B,GACtC,IAAI;IAsCP;;OAEG;WACW,+BAA+B,CAC5C,QAAQ,EAAE,QAAQ,CAAC;QAClB,WAAW,CAAC,EAAE,sBAAsB,CAAC,cAAc,CAAC,CAAC;QACrD,YAAY,EAAE,MAAM,CAAC;KACrB,CAAC,GACA,+BAA+B;CAwClC;AAED;;;;;GAKG;AACH,wBAAgB,iCAAiC,IAAI,iBAAiB,CAsErE"}
1
+ {"version":3,"file":"attributionCollection.d.ts","sourceRoot":"","sources":["../src/attributionCollection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACN,cAAc,EAGd,MAAM,qCAAqC,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAQhD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAG5C;;GAEG;AACH,MAAM,WAAW,+BAA+B;IAC/C;;;;;OAKG;IACH,IAAI,EAAE,CAAC,MAAM,GAAG,cAAc,CAAC,EAAE,CAAC;IAClC,cAAc,EAAE,MAAM,EAAE,CAAC;IAEzB,MAAM,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,MAAM,WAAW,gCAAgC;IAChD;;OAEG;IACH,+BAA+B,CAC9B,QAAQ,EAAE,QAAQ,CAAC;QAClB,WAAW,CAAC,EAAE,sBAAsB,CAAC,cAAc,CAAC,CAAC;QACrD,YAAY,EAAE,MAAM,CAAC;KACrB,CAAC,GACA,+BAA+B,CAAC;IAEnC;;;OAGG;IACH,8BAA8B,CAC7B,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAC5B,OAAO,EAAE,+BAA+B,GACtC,IAAI,CAAC;CACR;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB,CAAC,CAAC;IACxC;;OAEG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,CAAC;IAE/B;;OAEG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB;;;;;;OAMG;IACH,MAAM,IAAI,QAAQ,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,CAAC,CAAA;KAAE,CAAC,CAAC;IAE/C,gBAAgB;IAChB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAEhD,gBAAgB;IAChB,MAAM,CAAC,KAAK,EAAE,sBAAsB,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;IAE/C,gBAAgB;IAChB,KAAK,IAAI,sBAAsB,CAAC,CAAC,CAAC,CAAC;CACnC;AAED,wBAAgB,uBAAuB,CAAC,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,cAAc,GAAG,OAAO,CAgBrF;AAED,qBAAa,qBAAsB,YAAW,sBAAsB,CAAC,cAAc,CAAC;IAIrC,OAAO,CAAC,OAAO;IAH7D,OAAO,CAAC,OAAO,CAAW;IAC1B,OAAO,CAAC,IAAI,CAAmB;gBAEZ,SAAS,EAAE,cAAc,EAAU,OAAO,EAAE,MAAM;IAK9D,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,cAAc;IAKlD,OAAO,CAAC,SAAS;IAWjB,IAAW,MAAM,IAAI,MAAM,CAE1B;IAED;;OAEG;IACI,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,qBAAqB;IAgB3C,MAAM,CAAC,KAAK,EAAE,qBAAqB,GAAG,IAAI;IAW1C,MAAM,IAAI;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,cAAc,CAAA;KAAE,EAAE;IAQnD,KAAK,IAAI,qBAAqB;IAOrC;;OAEG;WACW,8BAA8B,CAC3C,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAC5B,OAAO,EAAE,+BAA+B,GACtC,IAAI;IAsCP;;OAEG;WACW,+BAA+B,CAC5C,QAAQ,EAAE,QAAQ,CAAC;QAClB,WAAW,CAAC,EAAE,sBAAsB,CAAC,cAAc,CAAC,CAAC;QACrD,YAAY,EAAE,MAAM,CAAC;KACrB,CAAC,GACA,+BAA+B;CAwClC;AAED;;;;;GAKG;AACH,wBAAgB,iCAAiC,IAAI,iBAAiB,CAsErE"}
@@ -16,6 +16,8 @@ export function areEqualAttributionKeys(a, b) {
16
16
  return a.seq === b.seq;
17
17
  case "detached":
18
18
  return a.id === b.id;
19
+ case "local":
20
+ return true;
19
21
  default:
20
22
  unreachableCase(a, "Unhandled AttributionKey type");
21
23
  }
@@ -1 +1 @@
1
- {"version":3,"file":"attributionCollection.js","sourceRoot":"","sources":["../src/attributionCollection.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\nimport { assert, unreachableCase } from \"@fluidframework/common-utils\";\nimport {\n\tAttributionKey,\n\tOpAttributionKey,\n\tDetachedAttributionKey,\n} from \"@fluidframework/runtime-definitions\";\nimport { AttributionPolicy } from \"./mergeTree\";\nimport { Client } from \"./client\";\nimport { UnassignedSequenceNumber, UniversalSequenceNumber } from \"./constants\";\nimport {\n\tMergeTreeDeltaCallback,\n\tMergeTreeMaintenanceCallback,\n\tMergeTreeMaintenanceType,\n} from \"./mergeTreeDeltaCallback\";\nimport { ISegment } from \"./mergeTreeNodes\";\nimport { MergeTreeDeltaType } from \"./ops\";\n\n/**\n * @internal\n */\nexport interface SerializedAttributionCollection {\n\t/**\n\t * Parallel array with posBreakpoints which tracks the seq of insertion.\n\t * Ex: if seqs is [45, 46] and posBreakpoints is [0, 3], the section of the string\n\t * between offsets 0 and 3 was inserted at seq 45 and the section of the string between\n\t * 3 and the length of the string was inserted at seq 46.\n\t */\n\tseqs: (number | AttributionKey)[];\n\tposBreakpoints: number[];\n\t/* Total length; only necessary for validation */\n\tlength: number;\n}\n\n/**\n * @internal\n * @sealed\n */\nexport interface IAttributionCollectionSerializer {\n\t/**\n\t * @internal\n\t */\n\tserializeAttributionCollections(\n\t\tsegments: Iterable<{\n\t\t\tattribution?: IAttributionCollection<AttributionKey>;\n\t\t\tcachedLength: number;\n\t\t}>,\n\t): SerializedAttributionCollection;\n\n\t/**\n\t * Populates attribution information on segments using the provided summary.\n\t * @internal\n\t */\n\tpopulateAttributionCollections(\n\t\tsegments: Iterable<ISegment>,\n\t\tsummary: SerializedAttributionCollection,\n\t): void;\n}\n\n/**\n * @alpha\n */\nexport interface IAttributionCollection<T> {\n\t/**\n\t * Retrieves the attribution key associated with the provided offset.\n\t */\n\tgetAtOffset(offset: number): T;\n\n\t/**\n\t * Total length of all attribution keys in this collection.\n\t */\n\treadonly length: number;\n\n\t/**\n\t * Retrieve all key/offset pairs stored on this segment. Entries should be ordered by offset, such that\n\t * the `i`th result's attribution key applies to offsets in the open range between the `i`th offset and the\n\t * `i+1`th offset.\n\t * The last entry's key applies to the open interval from the last entry's offset to this collection's length.\n\t * @internal\n\t */\n\tgetAll(): Iterable<{ offset: number; key: T }>;\n\n\t/** @internal */\n\tsplitAt(pos: number): IAttributionCollection<T>;\n\n\t/** @internal */\n\tappend(other: IAttributionCollection<T>): void;\n\n\t/** @internal */\n\tclone(): IAttributionCollection<T>;\n}\n\nexport function areEqualAttributionKeys(a: AttributionKey, b: AttributionKey): boolean {\n\tif (a.type !== b.type) {\n\t\treturn false;\n\t}\n\n\t// Note: TS can't narrow the type of b inside this switch statement, hence the need for casting.\n\tswitch (a.type) {\n\t\tcase \"op\":\n\t\t\treturn a.seq === (b as OpAttributionKey).seq;\n\t\tcase \"detached\":\n\t\t\treturn a.id === (b as DetachedAttributionKey).id;\n\t\tdefault:\n\t\t\tunreachableCase(a, \"Unhandled AttributionKey type\");\n\t}\n}\n\nexport class AttributionCollection implements IAttributionCollection<AttributionKey> {\n\tprivate offsets: number[];\n\tprivate keys: AttributionKey[];\n\n\tpublic constructor(baseEntry: AttributionKey, private _length: number) {\n\t\tthis.offsets = [0];\n\t\tthis.keys = [baseEntry];\n\t}\n\n\tpublic getAtOffset(offset: number): AttributionKey {\n\t\tassert(offset >= 0 && offset < this._length, 0x443 /* Requested offset should be valid */);\n\t\treturn this.keys[this.findIndex(offset)];\n\t}\n\n\tprivate findIndex(offset: number): number {\n\t\t// Note: maximum length here is 256 for text segments. Perf testing shows that linear scan beats binary search\n\t\t// for attribution collections with under ~64 entries, and even at maximum size (which would require a maximum\n\t\t// length segment with every offset having different attribution), getAtOffset is on the order of 100ns.\n\t\tlet i = 0;\n\t\twhile (i < this.offsets.length && offset > this.offsets[i]) {\n\t\t\ti++;\n\t\t}\n\t\treturn this.offsets[i] === offset ? i : i - 1;\n\t}\n\n\tpublic get length(): number {\n\t\treturn this._length;\n\t}\n\n\t/**\n\t * Splits this attribution collection into two with entries for [0, pos) and [pos, length).\n\t */\n\tpublic splitAt(pos: number): AttributionCollection {\n\t\tconst splitIndex = this.findIndex(pos);\n\t\tconst splitBaseEntry = this.keys[splitIndex];\n\t\tconst splitCollection = new AttributionCollection(splitBaseEntry, this.length - pos);\n\t\tfor (let i = splitIndex + 1; i < this.keys.length; i++) {\n\t\t\tsplitCollection.offsets.push(this.offsets[i] - pos);\n\t\t\tsplitCollection.keys.push(this.keys[i]);\n\t\t}\n\n\t\tconst spliceIndex = this.offsets[splitIndex] === pos ? splitIndex : splitIndex + 1;\n\t\tthis.keys.splice(spliceIndex);\n\t\tthis.offsets.splice(spliceIndex);\n\t\tthis._length = pos;\n\t\treturn splitCollection;\n\t}\n\n\tpublic append(other: AttributionCollection): void {\n\t\tconst lastEntry = this.keys[this.keys.length - 1];\n\t\tfor (let i = 0; i < other.keys.length; i++) {\n\t\t\tif (i !== 0 || !areEqualAttributionKeys(lastEntry, other.keys[i])) {\n\t\t\t\tthis.offsets.push(other.offsets[i] + this.length);\n\t\t\t\tthis.keys.push(other.keys[i]);\n\t\t\t}\n\t\t}\n\t\tthis._length += other.length;\n\t}\n\n\tpublic getAll(): { offset: number; key: AttributionKey }[] {\n\t\tconst results: { offset: number; key: AttributionKey }[] = new Array(this.keys.length);\n\t\tfor (let i = 0; i < this.keys.length; i++) {\n\t\t\tresults[i] = { offset: this.offsets[i], key: this.keys[i] };\n\t\t}\n\t\treturn results;\n\t}\n\n\tpublic clone(): AttributionCollection {\n\t\tconst copy = new AttributionCollection(this.keys[0], this.length);\n\t\tcopy.keys = this.keys.slice();\n\t\tcopy.offsets = this.offsets.slice();\n\t\treturn copy;\n\t}\n\n\t/**\n\t * Rehydrates attribution information from its serialized form into the provided iterable of consecutive segments.\n\t */\n\tpublic static populateAttributionCollections(\n\t\tsegments: Iterable<ISegment>,\n\t\tsummary: SerializedAttributionCollection,\n\t): void {\n\t\tconst { seqs, posBreakpoints } = summary;\n\t\tassert(\n\t\t\tseqs.length === posBreakpoints.length && seqs.length > 0,\n\t\t\t0x445 /* Invalid attribution summary blob provided */,\n\t\t);\n\t\tlet curIndex = 0;\n\t\tlet currentInfo = seqs[curIndex];\n\t\tlet cumulativeSegPos = 0;\n\n\t\tfor (const segment of segments) {\n\t\t\tconst attribution = new AttributionCollection(\n\t\t\t\ttypeof currentInfo === \"object\" ? currentInfo : { type: \"op\", seq: currentInfo },\n\t\t\t\tsegment.cachedLength,\n\t\t\t);\n\t\t\twhile (posBreakpoints[curIndex] < cumulativeSegPos + segment.cachedLength) {\n\t\t\t\tcurrentInfo = seqs[curIndex];\n\t\t\t\tconst nextOffset = posBreakpoints[curIndex] - cumulativeSegPos;\n\t\t\t\tif (attribution.offsets[attribution.offsets.length - 1] !== nextOffset) {\n\t\t\t\t\tattribution.offsets.push(nextOffset);\n\t\t\t\t\tattribution.keys.push(\n\t\t\t\t\t\ttypeof currentInfo === \"object\"\n\t\t\t\t\t\t\t? currentInfo\n\t\t\t\t\t\t\t: { type: \"op\", seq: currentInfo },\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tcurIndex++;\n\t\t\t}\n\n\t\t\tif (posBreakpoints[curIndex] === cumulativeSegPos + segment.cachedLength) {\n\t\t\t\tcurrentInfo = seqs[curIndex];\n\t\t\t}\n\n\t\t\tsegment.attribution = attribution;\n\t\t\tcumulativeSegPos += segment.cachedLength;\n\t\t}\n\t}\n\n\t/**\n\t * Condenses attribution information on consecutive segments into a `SerializedAttributionCollection`\n\t */\n\tpublic static serializeAttributionCollections(\n\t\tsegments: Iterable<{\n\t\t\tattribution?: IAttributionCollection<AttributionKey>;\n\t\t\tcachedLength: number;\n\t\t}>,\n\t): SerializedAttributionCollection {\n\t\tconst posBreakpoints: number[] = [];\n\t\tconst seqs: (number | AttributionKey)[] = [];\n\t\tlet mostRecentAttributionKey: AttributionKey | undefined;\n\t\tlet cumulativePos = 0;\n\n\t\tlet segmentsWithAttribution = 0;\n\t\tlet segmentsWithoutAttribution = 0;\n\t\tfor (const segment of segments) {\n\t\t\tif (segment.attribution) {\n\t\t\t\tsegmentsWithAttribution++;\n\t\t\t\tfor (const { offset, key } of segment.attribution?.getAll() ?? []) {\n\t\t\t\t\tif (\n\t\t\t\t\t\t!mostRecentAttributionKey ||\n\t\t\t\t\t\t!areEqualAttributionKeys(key, mostRecentAttributionKey)\n\t\t\t\t\t) {\n\t\t\t\t\t\tposBreakpoints.push(offset + cumulativePos);\n\t\t\t\t\t\tseqs.push(key.type === \"op\" ? key.seq : key);\n\t\t\t\t\t}\n\t\t\t\t\tmostRecentAttributionKey = key;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsegmentsWithoutAttribution++;\n\t\t\t}\n\n\t\t\tcumulativePos += segment.cachedLength;\n\t\t}\n\n\t\tassert(\n\t\t\tsegmentsWithAttribution === 0 || segmentsWithoutAttribution === 0,\n\t\t\t0x446 /* Expected either all segments or no segments to have attribution information. */,\n\t\t);\n\n\t\tconst blobContents: SerializedAttributionCollection = {\n\t\t\tseqs,\n\t\t\tposBreakpoints,\n\t\t\tlength: cumulativePos,\n\t\t};\n\t\treturn blobContents;\n\t}\n}\n\n/**\n * @alpha\n * @returns - An {@link AttributionPolicy} which tracks only insertion of content.\n * Content is only attributed at ack time, unless the container is in a detached state.\n * Detached content is attributed with a {@link @fluidframework/runtime-definitions#DetachedAttributionKey}.\n */\nexport function createInsertOnlyAttributionPolicy(): AttributionPolicy {\n\tlet unsubscribe: undefined | (() => void);\n\treturn {\n\t\tattach: (client: Client) => {\n\t\t\tassert(\n\t\t\t\tunsubscribe === undefined,\n\t\t\t\t0x557 /* cannot attach to multiple clients at once */,\n\t\t\t);\n\t\t\tconst deltaCallback: MergeTreeDeltaCallback = (\n\t\t\t\topArgs,\n\t\t\t\t{ deltaSegments, operation },\n\t\t\t) => {\n\t\t\t\tif (operation !== MergeTreeDeltaType.INSERT) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tfor (const { segment } of deltaSegments) {\n\t\t\t\t\tif (segment.seq !== undefined && segment.seq !== UnassignedSequenceNumber) {\n\t\t\t\t\t\tconst key: AttributionKey =\n\t\t\t\t\t\t\tsegment.seq === UniversalSequenceNumber\n\t\t\t\t\t\t\t\t? { type: \"detached\", id: 0 }\n\t\t\t\t\t\t\t\t: { type: \"op\", seq: segment.seq };\n\t\t\t\t\t\tsegment.attribution ??= new AttributionCollection(\n\t\t\t\t\t\t\tkey,\n\t\t\t\t\t\t\tsegment.cachedLength,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst maintenanceCallback: MergeTreeMaintenanceCallback = (\n\t\t\t\t{ deltaSegments, operation },\n\t\t\t\topArgs,\n\t\t\t) => {\n\t\t\t\tif (\n\t\t\t\t\toperation !== MergeTreeMaintenanceType.ACKNOWLEDGED ||\n\t\t\t\t\topArgs === undefined ||\n\t\t\t\t\topArgs.op.type !== MergeTreeDeltaType.INSERT\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (const { segment } of deltaSegments) {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tsegment.seq !== undefined,\n\t\t\t\t\t\t0x558 /* segment.seq should be set after ack. */,\n\t\t\t\t\t);\n\t\t\t\t\tsegment.attribution = new AttributionCollection(\n\t\t\t\t\t\t{ type: \"op\", seq: segment.seq },\n\t\t\t\t\t\tsegment.cachedLength,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tclient.on(\"delta\", deltaCallback);\n\t\t\tclient.on(\"maintenance\", maintenanceCallback);\n\n\t\t\tunsubscribe = () => {\n\t\t\t\tclient.off(\"delta\", deltaCallback);\n\t\t\t\tclient.off(\"maintenance\", maintenanceCallback);\n\t\t\t};\n\t\t},\n\t\tdetach: () => {\n\t\t\tunsubscribe?.();\n\t\t\tunsubscribe = undefined;\n\t\t},\n\t\tget isAttached() {\n\t\t\treturn unsubscribe !== undefined;\n\t\t},\n\t\tserializer: AttributionCollection,\n\t};\n}\n"]}
1
+ {"version":3,"file":"attributionCollection.js","sourceRoot":"","sources":["../src/attributionCollection.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAQvE,OAAO,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,EAGN,wBAAwB,GACxB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AA4E3C,MAAM,UAAU,uBAAuB,CAAC,CAAiB,EAAE,CAAiB;IAC3E,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,EAAE;QACtB,OAAO,KAAK,CAAC;KACb;IAED,gGAAgG;IAChG,QAAQ,CAAC,CAAC,IAAI,EAAE;QACf,KAAK,IAAI;YACR,OAAO,CAAC,CAAC,GAAG,KAAM,CAAsB,CAAC,GAAG,CAAC;QAC9C,KAAK,UAAU;YACd,OAAO,CAAC,CAAC,EAAE,KAAM,CAA4B,CAAC,EAAE,CAAC;QAClD,KAAK,OAAO;YACX,OAAO,IAAI,CAAC;QACb;YACC,eAAe,CAAC,CAAC,EAAE,+BAA+B,CAAC,CAAC;KACrD;AACF,CAAC;AAED,MAAM,OAAO,qBAAqB;IAIjC,YAAmB,SAAyB,EAAU,OAAe;QAAf,YAAO,GAAP,OAAO,CAAQ;QACpE,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;QACnB,IAAI,CAAC,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;IACzB,CAAC;IAEM,WAAW,CAAC,MAAc;QAChC,MAAM,CAAC,MAAM,IAAI,CAAC,IAAI,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC3F,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAC1C,CAAC;IAEO,SAAS,CAAC,MAAc;QAC/B,8GAA8G;QAC9G,8GAA8G;QAC9G,wGAAwG;QACxG,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;YAC3D,CAAC,EAAE,CAAC;SACJ;QACD,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IAC/C,CAAC;IAED,IAAW,MAAM;QAChB,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED;;OAEG;IACI,OAAO,CAAC,GAAW;QACzB,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACvC,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC7C,MAAM,eAAe,GAAG,IAAI,qBAAqB,CAAC,cAAc,EAAE,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC;QACrF,KAAK,IAAI,CAAC,GAAG,UAAU,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACvD,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;YACpD,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;SACxC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,GAAG,CAAC,CAAC;QACnF,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAC9B,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QACjC,IAAI,CAAC,OAAO,GAAG,GAAG,CAAC;QACnB,OAAO,eAAe,CAAC;IACxB,CAAC;IAEM,MAAM,CAAC,KAA4B;QACzC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAClD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YAC3C,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE;gBAClE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;gBAClD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;aAC9B;SACD;QACD,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,MAAM,CAAC;IAC9B,CAAC;IAEM,MAAM;QACZ,MAAM,OAAO,GAA8C,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YAC1C,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5D;QACD,OAAO,OAAO,CAAC;IAChB,CAAC;IAEM,KAAK;QACX,MAAM,IAAI,GAAG,IAAI,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;QAClE,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAC9B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACpC,OAAO,IAAI,CAAC;IACb,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,8BAA8B,CAC3C,QAA4B,EAC5B,OAAwC;QAExC,MAAM,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,OAAO,CAAC;QACzC,MAAM,CACL,IAAI,CAAC,MAAM,KAAK,cAAc,CAAC,MAAM,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EACxD,KAAK,CAAC,+CAA+C,CACrD,CAAC;QACF,IAAI,QAAQ,GAAG,CAAC,CAAC;QACjB,IAAI,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;QACjC,IAAI,gBAAgB,GAAG,CAAC,CAAC;QAEzB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;YAC/B,MAAM,WAAW,GAAG,IAAI,qBAAqB,CAC5C,OAAO,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE,EAChF,OAAO,CAAC,YAAY,CACpB,CAAC;YACF,OAAO,cAAc,CAAC,QAAQ,CAAC,GAAG,gBAAgB,GAAG,OAAO,CAAC,YAAY,EAAE;gBAC1E,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC7B,MAAM,UAAU,GAAG,cAAc,CAAC,QAAQ,CAAC,GAAG,gBAAgB,CAAC;gBAC/D,IAAI,WAAW,CAAC,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,UAAU,EAAE;oBACvE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;oBACrC,WAAW,CAAC,IAAI,CAAC,IAAI,CACpB,OAAO,WAAW,KAAK,QAAQ;wBAC9B,CAAC,CAAC,WAAW;wBACb,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,EAAE,CACnC,CAAC;iBACF;gBACD,QAAQ,EAAE,CAAC;aACX;YAED,IAAI,cAAc,CAAC,QAAQ,CAAC,KAAK,gBAAgB,GAAG,OAAO,CAAC,YAAY,EAAE;gBACzE,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC;aAC7B;YAED,OAAO,CAAC,WAAW,GAAG,WAAW,CAAC;YAClC,gBAAgB,IAAI,OAAO,CAAC,YAAY,CAAC;SACzC;IACF,CAAC;IAED;;OAEG;IACI,MAAM,CAAC,+BAA+B,CAC5C,QAGE;;QAEF,MAAM,cAAc,GAAa,EAAE,CAAC;QACpC,MAAM,IAAI,GAAgC,EAAE,CAAC;QAC7C,IAAI,wBAAoD,CAAC;QACzD,IAAI,aAAa,GAAG,CAAC,CAAC;QAEtB,IAAI,uBAAuB,GAAG,CAAC,CAAC;QAChC,IAAI,0BAA0B,GAAG,CAAC,CAAC;QACnC,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE;YAC/B,IAAI,OAAO,CAAC,WAAW,EAAE;gBACxB,uBAAuB,EAAE,CAAC;gBAC1B,KAAK,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,MAAA,MAAA,OAAO,CAAC,WAAW,0CAAE,MAAM,EAAE,mCAAI,EAAE,EAAE;oBAClE,IACC,CAAC,wBAAwB;wBACzB,CAAC,uBAAuB,CAAC,GAAG,EAAE,wBAAwB,CAAC,EACtD;wBACD,cAAc,CAAC,IAAI,CAAC,MAAM,GAAG,aAAa,CAAC,CAAC;wBAC5C,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;qBAC7C;oBACD,wBAAwB,GAAG,GAAG,CAAC;iBAC/B;aACD;iBAAM;gBACN,0BAA0B,EAAE,CAAC;aAC7B;YAED,aAAa,IAAI,OAAO,CAAC,YAAY,CAAC;SACtC;QAED,MAAM,CACL,uBAAuB,KAAK,CAAC,IAAI,0BAA0B,KAAK,CAAC,EACjE,KAAK,CAAC,kFAAkF,CACxF,CAAC;QAEF,MAAM,YAAY,GAAoC;YACrD,IAAI;YACJ,cAAc;YACd,MAAM,EAAE,aAAa;SACrB,CAAC;QACF,OAAO,YAAY,CAAC;IACrB,CAAC;CACD;AAED;;;;;GAKG;AACH,MAAM,UAAU,iCAAiC;IAChD,IAAI,WAAqC,CAAC;IAC1C,OAAO;QACN,MAAM,EAAE,CAAC,MAAc,EAAE,EAAE;YAC1B,MAAM,CACL,WAAW,KAAK,SAAS,EACzB,KAAK,CAAC,+CAA+C,CACrD,CAAC;YACF,MAAM,aAAa,GAA2B,CAC7C,MAAM,EACN,EAAE,aAAa,EAAE,SAAS,EAAE,EAC3B,EAAE;;gBACH,IAAI,SAAS,KAAK,kBAAkB,CAAC,MAAM,EAAE;oBAC5C,OAAO;iBACP;gBAED,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,aAAa,EAAE;oBACxC,IAAI,OAAO,CAAC,GAAG,KAAK,SAAS,IAAI,OAAO,CAAC,GAAG,KAAK,wBAAwB,EAAE;wBAC1E,MAAM,GAAG,GACR,OAAO,CAAC,GAAG,KAAK,uBAAuB;4BACtC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,EAAE;4BAC7B,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;wBACrC,MAAA,OAAO,CAAC,WAAW,oCAAnB,OAAO,CAAC,WAAW,GAAK,IAAI,qBAAqB,CAChD,GAAG,EACH,OAAO,CAAC,YAAY,CACpB,EAAC;qBACF;iBACD;YACF,CAAC,CAAC;YAEF,MAAM,mBAAmB,GAAiC,CACzD,EAAE,aAAa,EAAE,SAAS,EAAE,EAC5B,MAAM,EACL,EAAE;gBACH,IACC,SAAS,KAAK,wBAAwB,CAAC,YAAY;oBACnD,MAAM,KAAK,SAAS;oBACpB,MAAM,CAAC,EAAE,CAAC,IAAI,KAAK,kBAAkB,CAAC,MAAM,EAC3C;oBACD,OAAO;iBACP;gBACD,KAAK,MAAM,EAAE,OAAO,EAAE,IAAI,aAAa,EAAE;oBACxC,MAAM,CACL,OAAO,CAAC,GAAG,KAAK,SAAS,EACzB,KAAK,CAAC,0CAA0C,CAChD,CAAC;oBACF,OAAO,CAAC,WAAW,GAAG,IAAI,qBAAqB,CAC9C,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,EAChC,OAAO,CAAC,YAAY,CACpB,CAAC;iBACF;YACF,CAAC,CAAC;YAEF,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;YAClC,MAAM,CAAC,EAAE,CAAC,aAAa,EAAE,mBAAmB,CAAC,CAAC;YAE9C,WAAW,GAAG,GAAG,EAAE;gBAClB,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;gBACnC,MAAM,CAAC,GAAG,CAAC,aAAa,EAAE,mBAAmB,CAAC,CAAC;YAChD,CAAC,CAAC;QACH,CAAC;QACD,MAAM,EAAE,GAAG,EAAE;YACZ,WAAW,aAAX,WAAW,uBAAX,WAAW,EAAI,CAAC;YAChB,WAAW,GAAG,SAAS,CAAC;QACzB,CAAC;QACD,IAAI,UAAU;YACb,OAAO,WAAW,KAAK,SAAS,CAAC;QAClC,CAAC;QACD,UAAU,EAAE,qBAAqB;KACjC,CAAC;AACH,CAAC","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\nimport { assert, unreachableCase } from \"@fluidframework/common-utils\";\nimport {\n\tAttributionKey,\n\tOpAttributionKey,\n\tDetachedAttributionKey,\n} from \"@fluidframework/runtime-definitions\";\nimport { AttributionPolicy } from \"./mergeTree\";\nimport { Client } from \"./client\";\nimport { UnassignedSequenceNumber, UniversalSequenceNumber } from \"./constants\";\nimport {\n\tMergeTreeDeltaCallback,\n\tMergeTreeMaintenanceCallback,\n\tMergeTreeMaintenanceType,\n} from \"./mergeTreeDeltaCallback\";\nimport { ISegment } from \"./mergeTreeNodes\";\nimport { MergeTreeDeltaType } from \"./ops\";\n\n/**\n * @internal\n */\nexport interface SerializedAttributionCollection {\n\t/**\n\t * Parallel array with posBreakpoints which tracks the seq of insertion.\n\t * Ex: if seqs is [45, 46] and posBreakpoints is [0, 3], the section of the string\n\t * between offsets 0 and 3 was inserted at seq 45 and the section of the string between\n\t * 3 and the length of the string was inserted at seq 46.\n\t */\n\tseqs: (number | AttributionKey)[];\n\tposBreakpoints: number[];\n\t/* Total length; only necessary for validation */\n\tlength: number;\n}\n\n/**\n * @internal\n * @sealed\n */\nexport interface IAttributionCollectionSerializer {\n\t/**\n\t * @internal\n\t */\n\tserializeAttributionCollections(\n\t\tsegments: Iterable<{\n\t\t\tattribution?: IAttributionCollection<AttributionKey>;\n\t\t\tcachedLength: number;\n\t\t}>,\n\t): SerializedAttributionCollection;\n\n\t/**\n\t * Populates attribution information on segments using the provided summary.\n\t * @internal\n\t */\n\tpopulateAttributionCollections(\n\t\tsegments: Iterable<ISegment>,\n\t\tsummary: SerializedAttributionCollection,\n\t): void;\n}\n\n/**\n * @alpha\n */\nexport interface IAttributionCollection<T> {\n\t/**\n\t * Retrieves the attribution key associated with the provided offset.\n\t */\n\tgetAtOffset(offset: number): T;\n\n\t/**\n\t * Total length of all attribution keys in this collection.\n\t */\n\treadonly length: number;\n\n\t/**\n\t * Retrieve all key/offset pairs stored on this segment. Entries should be ordered by offset, such that\n\t * the `i`th result's attribution key applies to offsets in the open range between the `i`th offset and the\n\t * `i+1`th offset.\n\t * The last entry's key applies to the open interval from the last entry's offset to this collection's length.\n\t * @internal\n\t */\n\tgetAll(): Iterable<{ offset: number; key: T }>;\n\n\t/** @internal */\n\tsplitAt(pos: number): IAttributionCollection<T>;\n\n\t/** @internal */\n\tappend(other: IAttributionCollection<T>): void;\n\n\t/** @internal */\n\tclone(): IAttributionCollection<T>;\n}\n\nexport function areEqualAttributionKeys(a: AttributionKey, b: AttributionKey): boolean {\n\tif (a.type !== b.type) {\n\t\treturn false;\n\t}\n\n\t// Note: TS can't narrow the type of b inside this switch statement, hence the need for casting.\n\tswitch (a.type) {\n\t\tcase \"op\":\n\t\t\treturn a.seq === (b as OpAttributionKey).seq;\n\t\tcase \"detached\":\n\t\t\treturn a.id === (b as DetachedAttributionKey).id;\n\t\tcase \"local\":\n\t\t\treturn true;\n\t\tdefault:\n\t\t\tunreachableCase(a, \"Unhandled AttributionKey type\");\n\t}\n}\n\nexport class AttributionCollection implements IAttributionCollection<AttributionKey> {\n\tprivate offsets: number[];\n\tprivate keys: AttributionKey[];\n\n\tpublic constructor(baseEntry: AttributionKey, private _length: number) {\n\t\tthis.offsets = [0];\n\t\tthis.keys = [baseEntry];\n\t}\n\n\tpublic getAtOffset(offset: number): AttributionKey {\n\t\tassert(offset >= 0 && offset < this._length, 0x443 /* Requested offset should be valid */);\n\t\treturn this.keys[this.findIndex(offset)];\n\t}\n\n\tprivate findIndex(offset: number): number {\n\t\t// Note: maximum length here is 256 for text segments. Perf testing shows that linear scan beats binary search\n\t\t// for attribution collections with under ~64 entries, and even at maximum size (which would require a maximum\n\t\t// length segment with every offset having different attribution), getAtOffset is on the order of 100ns.\n\t\tlet i = 0;\n\t\twhile (i < this.offsets.length && offset > this.offsets[i]) {\n\t\t\ti++;\n\t\t}\n\t\treturn this.offsets[i] === offset ? i : i - 1;\n\t}\n\n\tpublic get length(): number {\n\t\treturn this._length;\n\t}\n\n\t/**\n\t * Splits this attribution collection into two with entries for [0, pos) and [pos, length).\n\t */\n\tpublic splitAt(pos: number): AttributionCollection {\n\t\tconst splitIndex = this.findIndex(pos);\n\t\tconst splitBaseEntry = this.keys[splitIndex];\n\t\tconst splitCollection = new AttributionCollection(splitBaseEntry, this.length - pos);\n\t\tfor (let i = splitIndex + 1; i < this.keys.length; i++) {\n\t\t\tsplitCollection.offsets.push(this.offsets[i] - pos);\n\t\t\tsplitCollection.keys.push(this.keys[i]);\n\t\t}\n\n\t\tconst spliceIndex = this.offsets[splitIndex] === pos ? splitIndex : splitIndex + 1;\n\t\tthis.keys.splice(spliceIndex);\n\t\tthis.offsets.splice(spliceIndex);\n\t\tthis._length = pos;\n\t\treturn splitCollection;\n\t}\n\n\tpublic append(other: AttributionCollection): void {\n\t\tconst lastEntry = this.keys[this.keys.length - 1];\n\t\tfor (let i = 0; i < other.keys.length; i++) {\n\t\t\tif (i !== 0 || !areEqualAttributionKeys(lastEntry, other.keys[i])) {\n\t\t\t\tthis.offsets.push(other.offsets[i] + this.length);\n\t\t\t\tthis.keys.push(other.keys[i]);\n\t\t\t}\n\t\t}\n\t\tthis._length += other.length;\n\t}\n\n\tpublic getAll(): { offset: number; key: AttributionKey }[] {\n\t\tconst results: { offset: number; key: AttributionKey }[] = new Array(this.keys.length);\n\t\tfor (let i = 0; i < this.keys.length; i++) {\n\t\t\tresults[i] = { offset: this.offsets[i], key: this.keys[i] };\n\t\t}\n\t\treturn results;\n\t}\n\n\tpublic clone(): AttributionCollection {\n\t\tconst copy = new AttributionCollection(this.keys[0], this.length);\n\t\tcopy.keys = this.keys.slice();\n\t\tcopy.offsets = this.offsets.slice();\n\t\treturn copy;\n\t}\n\n\t/**\n\t * Rehydrates attribution information from its serialized form into the provided iterable of consecutive segments.\n\t */\n\tpublic static populateAttributionCollections(\n\t\tsegments: Iterable<ISegment>,\n\t\tsummary: SerializedAttributionCollection,\n\t): void {\n\t\tconst { seqs, posBreakpoints } = summary;\n\t\tassert(\n\t\t\tseqs.length === posBreakpoints.length && seqs.length > 0,\n\t\t\t0x445 /* Invalid attribution summary blob provided */,\n\t\t);\n\t\tlet curIndex = 0;\n\t\tlet currentInfo = seqs[curIndex];\n\t\tlet cumulativeSegPos = 0;\n\n\t\tfor (const segment of segments) {\n\t\t\tconst attribution = new AttributionCollection(\n\t\t\t\ttypeof currentInfo === \"object\" ? currentInfo : { type: \"op\", seq: currentInfo },\n\t\t\t\tsegment.cachedLength,\n\t\t\t);\n\t\t\twhile (posBreakpoints[curIndex] < cumulativeSegPos + segment.cachedLength) {\n\t\t\t\tcurrentInfo = seqs[curIndex];\n\t\t\t\tconst nextOffset = posBreakpoints[curIndex] - cumulativeSegPos;\n\t\t\t\tif (attribution.offsets[attribution.offsets.length - 1] !== nextOffset) {\n\t\t\t\t\tattribution.offsets.push(nextOffset);\n\t\t\t\t\tattribution.keys.push(\n\t\t\t\t\t\ttypeof currentInfo === \"object\"\n\t\t\t\t\t\t\t? currentInfo\n\t\t\t\t\t\t\t: { type: \"op\", seq: currentInfo },\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tcurIndex++;\n\t\t\t}\n\n\t\t\tif (posBreakpoints[curIndex] === cumulativeSegPos + segment.cachedLength) {\n\t\t\t\tcurrentInfo = seqs[curIndex];\n\t\t\t}\n\n\t\t\tsegment.attribution = attribution;\n\t\t\tcumulativeSegPos += segment.cachedLength;\n\t\t}\n\t}\n\n\t/**\n\t * Condenses attribution information on consecutive segments into a `SerializedAttributionCollection`\n\t */\n\tpublic static serializeAttributionCollections(\n\t\tsegments: Iterable<{\n\t\t\tattribution?: IAttributionCollection<AttributionKey>;\n\t\t\tcachedLength: number;\n\t\t}>,\n\t): SerializedAttributionCollection {\n\t\tconst posBreakpoints: number[] = [];\n\t\tconst seqs: (number | AttributionKey)[] = [];\n\t\tlet mostRecentAttributionKey: AttributionKey | undefined;\n\t\tlet cumulativePos = 0;\n\n\t\tlet segmentsWithAttribution = 0;\n\t\tlet segmentsWithoutAttribution = 0;\n\t\tfor (const segment of segments) {\n\t\t\tif (segment.attribution) {\n\t\t\t\tsegmentsWithAttribution++;\n\t\t\t\tfor (const { offset, key } of segment.attribution?.getAll() ?? []) {\n\t\t\t\t\tif (\n\t\t\t\t\t\t!mostRecentAttributionKey ||\n\t\t\t\t\t\t!areEqualAttributionKeys(key, mostRecentAttributionKey)\n\t\t\t\t\t) {\n\t\t\t\t\t\tposBreakpoints.push(offset + cumulativePos);\n\t\t\t\t\t\tseqs.push(key.type === \"op\" ? key.seq : key);\n\t\t\t\t\t}\n\t\t\t\t\tmostRecentAttributionKey = key;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsegmentsWithoutAttribution++;\n\t\t\t}\n\n\t\t\tcumulativePos += segment.cachedLength;\n\t\t}\n\n\t\tassert(\n\t\t\tsegmentsWithAttribution === 0 || segmentsWithoutAttribution === 0,\n\t\t\t0x446 /* Expected either all segments or no segments to have attribution information. */,\n\t\t);\n\n\t\tconst blobContents: SerializedAttributionCollection = {\n\t\t\tseqs,\n\t\t\tposBreakpoints,\n\t\t\tlength: cumulativePos,\n\t\t};\n\t\treturn blobContents;\n\t}\n}\n\n/**\n * @alpha\n * @returns - An {@link AttributionPolicy} which tracks only insertion of content.\n * Content is only attributed at ack time, unless the container is in a detached state.\n * Detached content is attributed with a {@link @fluidframework/runtime-definitions#DetachedAttributionKey}.\n */\nexport function createInsertOnlyAttributionPolicy(): AttributionPolicy {\n\tlet unsubscribe: undefined | (() => void);\n\treturn {\n\t\tattach: (client: Client) => {\n\t\t\tassert(\n\t\t\t\tunsubscribe === undefined,\n\t\t\t\t0x557 /* cannot attach to multiple clients at once */,\n\t\t\t);\n\t\t\tconst deltaCallback: MergeTreeDeltaCallback = (\n\t\t\t\topArgs,\n\t\t\t\t{ deltaSegments, operation },\n\t\t\t) => {\n\t\t\t\tif (operation !== MergeTreeDeltaType.INSERT) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tfor (const { segment } of deltaSegments) {\n\t\t\t\t\tif (segment.seq !== undefined && segment.seq !== UnassignedSequenceNumber) {\n\t\t\t\t\t\tconst key: AttributionKey =\n\t\t\t\t\t\t\tsegment.seq === UniversalSequenceNumber\n\t\t\t\t\t\t\t\t? { type: \"detached\", id: 0 }\n\t\t\t\t\t\t\t\t: { type: \"op\", seq: segment.seq };\n\t\t\t\t\t\tsegment.attribution ??= new AttributionCollection(\n\t\t\t\t\t\t\tkey,\n\t\t\t\t\t\t\tsegment.cachedLength,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tconst maintenanceCallback: MergeTreeMaintenanceCallback = (\n\t\t\t\t{ deltaSegments, operation },\n\t\t\t\topArgs,\n\t\t\t) => {\n\t\t\t\tif (\n\t\t\t\t\toperation !== MergeTreeMaintenanceType.ACKNOWLEDGED ||\n\t\t\t\t\topArgs === undefined ||\n\t\t\t\t\topArgs.op.type !== MergeTreeDeltaType.INSERT\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tfor (const { segment } of deltaSegments) {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tsegment.seq !== undefined,\n\t\t\t\t\t\t0x558 /* segment.seq should be set after ack. */,\n\t\t\t\t\t);\n\t\t\t\t\tsegment.attribution = new AttributionCollection(\n\t\t\t\t\t\t{ type: \"op\", seq: segment.seq },\n\t\t\t\t\t\tsegment.cachedLength,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tclient.on(\"delta\", deltaCallback);\n\t\t\tclient.on(\"maintenance\", maintenanceCallback);\n\n\t\t\tunsubscribe = () => {\n\t\t\t\tclient.off(\"delta\", deltaCallback);\n\t\t\t\tclient.off(\"maintenance\", maintenanceCallback);\n\t\t\t};\n\t\t},\n\t\tdetach: () => {\n\t\t\tunsubscribe?.();\n\t\t\tunsubscribe = undefined;\n\t\t},\n\t\tget isAttached() {\n\t\t\treturn unsubscribe !== undefined;\n\t\t},\n\t\tserializer: AttributionCollection,\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"properties.d.ts","sourceRoot":"","sources":["../src/properties.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAErC,MAAM,WAAW,OAAO,CAAC,CAAC;IACzB,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,CAAC;CACnB;AAKD,oBAAY,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;AAIvC,MAAM,WAAW,eAAe;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,GAAG,CAAC;CACX;AAED,wBAAgB,OAAO,CACtB,aAAa,EAAE,YAAY,EAC3B,YAAY,EAAE,GAAG,EACjB,QAAQ,EAAE,GAAG,EACb,GAAG,CAAC,EAAE,MAAM,OAyCZ;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,WAAW,GAAG,SAAS,EAAE,CAAC,EAAE,WAAW,GAAG,SAAS,WAkCrF;AAED,wBAAgB,MAAM,CAAC,CAAC,EACvB,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAChB,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,EACjC,WAAW,CAAC,EAAE,YAAY,EAC1B,GAAG,CAAC,EAAE,MAAM,cAmBZ;AAED,wBAAgB,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,0BAazD;AAED,wBAAgB,aAAa,CAC5B,QAAQ,EAAE,WAAW,GAAG,SAAS,EACjC,QAAQ,EAAE,WAAW,EACrB,EAAE,CAAC,EAAE,YAAY,EACjB,GAAG,CAAC,EAAE,MAAM,eAQZ;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,cAUvF;AAGD,wBAAgB,SAAS,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAEzC"}
1
+ {"version":3,"file":"properties.d.ts","sourceRoot":"","sources":["../src/properties.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAErC,MAAM,WAAW,OAAO,CAAC,CAAC;IACzB,CAAC,KAAK,EAAE,MAAM,GAAG,CAAC,CAAC;CACnB;AAKD,oBAAY,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;AAIvC,MAAM,WAAW,eAAe;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,GAAG,CAAC;CACX;AAED,wBAAgB,OAAO,CACtB,aAAa,EAAE,YAAY,EAC3B,YAAY,EAAE,GAAG,EACjB,QAAQ,EAAE,GAAG,EACb,GAAG,CAAC,EAAE,MAAM,OAyCZ;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,WAAW,GAAG,SAAS,EAAE,CAAC,EAAE,WAAW,GAAG,SAAS,WAyBrF;AAED,wBAAgB,MAAM,CAAC,CAAC,EACvB,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAChB,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,EACjC,WAAW,CAAC,EAAE,YAAY,EAC1B,GAAG,CAAC,EAAE,MAAM,cAmBZ;AAED,wBAAgB,KAAK,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,0BAazD;AAED,wBAAgB,aAAa,CAC5B,QAAQ,EAAE,WAAW,GAAG,SAAS,EACjC,QAAQ,EAAE,WAAW,EACrB,EAAE,CAAC,EAAE,YAAY,EACjB,GAAG,CAAC,EAAE,MAAM,eAQZ;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,SAAS,cAUvF;AAGD,wBAAgB,SAAS,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAEzC"}
package/lib/properties.js CHANGED
@@ -41,36 +41,24 @@ export function combine(combiningInfo, currentValue, newValue, seq) {
41
41
  return _currentValue;
42
42
  }
43
43
  export function matchProperties(a, b) {
44
- if (a) {
45
- if (!b) {
44
+ if (!a && !b) {
45
+ return true;
46
+ }
47
+ const keysA = a ? Object.keys(a) : [];
48
+ const keysB = b ? Object.keys(b) : [];
49
+ if (keysA.length !== keysB.length) {
50
+ return false;
51
+ }
52
+ for (const key of keysA) {
53
+ if ((b === null || b === void 0 ? void 0 : b[key]) === undefined) {
46
54
  return false;
47
55
  }
48
- else {
49
- // For now, straightforward; later use hashing
50
- // eslint-disable-next-line no-restricted-syntax
51
- for (const key in a) {
52
- if (b[key] === undefined) {
53
- return false;
54
- }
55
- else if (typeof b[key] === "object") {
56
- if (!matchProperties(a[key], b[key])) {
57
- return false;
58
- }
59
- }
60
- else if (b[key] !== a[key]) {
61
- return false;
62
- }
63
- }
64
- // eslint-disable-next-line no-restricted-syntax
65
- for (const key in b) {
66
- if (a[key] === undefined) {
67
- return false;
68
- }
56
+ else if (typeof b[key] === "object") {
57
+ if (!matchProperties(a === null || a === void 0 ? void 0 : a[key], b[key])) {
58
+ return false;
69
59
  }
70
60
  }
71
- }
72
- else {
73
- if (b) {
61
+ else if (b[key] !== (a === null || a === void 0 ? void 0 : a[key])) {
74
62
  return false;
75
63
  }
76
64
  }
@@ -1 +1 @@
1
- {"version":3,"file":"properties.js","sourceRoot":"","sources":["../src/properties.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\nimport { ICombiningOp } from \"./ops\";\n\nexport interface MapLike<T> {\n\t[index: string]: T;\n}\n\n// We use any because when you include custom methods\n// such as toJSON(), JSON.stringify accepts most types other\n// than functions\nexport type PropertySet = MapLike<any>;\n\n// Assume these are created with Object.create(null)\n\nexport interface IConsensusValue {\n\tseq: number;\n\tvalue: any;\n}\n\nexport function combine(\n\tcombiningInfo: ICombiningOp,\n\tcurrentValue: any,\n\tnewValue: any,\n\tseq?: number,\n) {\n\tlet _currentValue = currentValue;\n\n\tif (_currentValue === undefined) {\n\t\t_currentValue = combiningInfo.defaultValue;\n\t}\n\t// Fixed set of operations for now\n\n\tswitch (combiningInfo.name) {\n\t\tcase \"incr\":\n\t\t\t_currentValue += newValue as number;\n\t\t\tif (combiningInfo.minValue) {\n\t\t\t\tif (_currentValue < combiningInfo.minValue) {\n\t\t\t\t\t_currentValue = combiningInfo.minValue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase \"consensus\":\n\t\t\tif (_currentValue === undefined) {\n\t\t\t\tconst cv: IConsensusValue = {\n\t\t\t\t\tvalue: newValue,\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\tseq: seq!,\n\t\t\t\t};\n\n\t\t\t\t_currentValue = cv;\n\t\t\t} else {\n\t\t\t\tconst cv = _currentValue as IConsensusValue;\n\t\t\t\tif (cv.seq === -1) {\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\tcv.seq = seq!;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-return\n\treturn _currentValue;\n}\n\nexport function matchProperties(a: PropertySet | undefined, b: PropertySet | undefined) {\n\tif (a) {\n\t\tif (!b) {\n\t\t\treturn false;\n\t\t} else {\n\t\t\t// For now, straightforward; later use hashing\n\n\t\t\t// eslint-disable-next-line no-restricted-syntax\n\t\t\tfor (const key in a) {\n\t\t\t\tif (b[key] === undefined) {\n\t\t\t\t\treturn false;\n\t\t\t\t} else if (typeof b[key] === \"object\") {\n\t\t\t\t\tif (!matchProperties(a[key], b[key])) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t} else if (b[key] !== a[key]) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// eslint-disable-next-line no-restricted-syntax\n\t\t\tfor (const key in b) {\n\t\t\t\tif (a[key] === undefined) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t} else {\n\t\tif (b) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\nexport function extend<T>(\n\tbase: MapLike<T>,\n\textension: MapLike<T> | undefined,\n\tcombiningOp?: ICombiningOp,\n\tseq?: number,\n) {\n\tif (extension !== undefined) {\n\t\t// eslint-disable-next-line guard-for-in, no-restricted-syntax\n\t\tfor (const key in extension) {\n\t\t\tconst v = extension[key];\n\t\t\tif (v === null) {\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n\t\t\t\tdelete base[key];\n\t\t\t} else {\n\t\t\t\tif (combiningOp && combiningOp.name !== \"rewrite\") {\n\t\t\t\t\tbase[key] = combine(combiningOp, base[key], v, seq);\n\t\t\t\t} else {\n\t\t\t\t\tbase[key] = v;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn base;\n}\n\nexport function clone<T>(extension: MapLike<T> | undefined) {\n\tif (extension === undefined) {\n\t\treturn undefined;\n\t}\n\tconst cloneMap = createMap<T>();\n\t// eslint-disable-next-line guard-for-in, no-restricted-syntax\n\tfor (const key in extension) {\n\t\tconst v = extension[key];\n\t\tif (v !== null) {\n\t\t\tcloneMap[key] = v;\n\t\t}\n\t}\n\treturn cloneMap;\n}\n\nexport function addProperties(\n\toldProps: PropertySet | undefined,\n\tnewProps: PropertySet,\n\top?: ICombiningOp,\n\tseq?: number,\n) {\n\tlet _oldProps = oldProps;\n\tif (!_oldProps || (op && op.name === \"rewrite\")) {\n\t\t_oldProps = createMap<any>();\n\t}\n\textend(_oldProps, newProps, op, seq);\n\treturn _oldProps;\n}\n\nexport function extendIfUndefined<T>(base: MapLike<T>, extension: MapLike<T> | undefined) {\n\tif (extension !== undefined) {\n\t\t// eslint-disable-next-line no-restricted-syntax\n\t\tfor (const key in extension) {\n\t\t\tif (base[key] === undefined) {\n\t\t\t\tbase[key] = extension[key];\n\t\t\t}\n\t\t}\n\t}\n\treturn base;\n}\n\n// Create a MapLike with good performance.\nexport function createMap<T>(): MapLike<T> {\n\treturn Object.create(null) as MapLike<T>;\n}\n"]}
1
+ {"version":3,"file":"properties.js","sourceRoot":"","sources":["../src/properties.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\nimport { ICombiningOp } from \"./ops\";\n\nexport interface MapLike<T> {\n\t[index: string]: T;\n}\n\n// We use any because when you include custom methods\n// such as toJSON(), JSON.stringify accepts most types other\n// than functions\nexport type PropertySet = MapLike<any>;\n\n// Assume these are created with Object.create(null)\n\nexport interface IConsensusValue {\n\tseq: number;\n\tvalue: any;\n}\n\nexport function combine(\n\tcombiningInfo: ICombiningOp,\n\tcurrentValue: any,\n\tnewValue: any,\n\tseq?: number,\n) {\n\tlet _currentValue = currentValue;\n\n\tif (_currentValue === undefined) {\n\t\t_currentValue = combiningInfo.defaultValue;\n\t}\n\t// Fixed set of operations for now\n\n\tswitch (combiningInfo.name) {\n\t\tcase \"incr\":\n\t\t\t_currentValue += newValue as number;\n\t\t\tif (combiningInfo.minValue) {\n\t\t\t\tif (_currentValue < combiningInfo.minValue) {\n\t\t\t\t\t_currentValue = combiningInfo.minValue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tcase \"consensus\":\n\t\t\tif (_currentValue === undefined) {\n\t\t\t\tconst cv: IConsensusValue = {\n\t\t\t\t\tvalue: newValue,\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\tseq: seq!,\n\t\t\t\t};\n\n\t\t\t\t_currentValue = cv;\n\t\t\t} else {\n\t\t\t\tconst cv = _currentValue as IConsensusValue;\n\t\t\t\tif (cv.seq === -1) {\n\t\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\t\tcv.seq = seq!;\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\t\tdefault:\n\t\t\tbreak;\n\t}\n\n\t// eslint-disable-next-line @typescript-eslint/no-unsafe-return\n\treturn _currentValue;\n}\n\nexport function matchProperties(a: PropertySet | undefined, b: PropertySet | undefined) {\n\tif (!a && !b) {\n\t\treturn true;\n\t}\n\n\tconst keysA = a ? Object.keys(a) : [];\n\tconst keysB = b ? Object.keys(b) : [];\n\n\tif (keysA.length !== keysB.length) {\n\t\treturn false;\n\t}\n\n\tfor (const key of keysA) {\n\t\tif (b?.[key] === undefined) {\n\t\t\treturn false;\n\t\t} else if (typeof b[key] === \"object\") {\n\t\t\tif (!matchProperties(a?.[key], b[key])) {\n\t\t\t\treturn false;\n\t\t\t}\n\t\t} else if (b[key] !== a?.[key]) {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\treturn true;\n}\n\nexport function extend<T>(\n\tbase: MapLike<T>,\n\textension: MapLike<T> | undefined,\n\tcombiningOp?: ICombiningOp,\n\tseq?: number,\n) {\n\tif (extension !== undefined) {\n\t\t// eslint-disable-next-line guard-for-in, no-restricted-syntax\n\t\tfor (const key in extension) {\n\t\t\tconst v = extension[key];\n\t\t\tif (v === null) {\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n\t\t\t\tdelete base[key];\n\t\t\t} else {\n\t\t\t\tif (combiningOp && combiningOp.name !== \"rewrite\") {\n\t\t\t\t\tbase[key] = combine(combiningOp, base[key], v, seq);\n\t\t\t\t} else {\n\t\t\t\t\tbase[key] = v;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn base;\n}\n\nexport function clone<T>(extension: MapLike<T> | undefined) {\n\tif (extension === undefined) {\n\t\treturn undefined;\n\t}\n\tconst cloneMap = createMap<T>();\n\t// eslint-disable-next-line guard-for-in, no-restricted-syntax\n\tfor (const key in extension) {\n\t\tconst v = extension[key];\n\t\tif (v !== null) {\n\t\t\tcloneMap[key] = v;\n\t\t}\n\t}\n\treturn cloneMap;\n}\n\nexport function addProperties(\n\toldProps: PropertySet | undefined,\n\tnewProps: PropertySet,\n\top?: ICombiningOp,\n\tseq?: number,\n) {\n\tlet _oldProps = oldProps;\n\tif (!_oldProps || (op && op.name === \"rewrite\")) {\n\t\t_oldProps = createMap<any>();\n\t}\n\textend(_oldProps, newProps, op, seq);\n\treturn _oldProps;\n}\n\nexport function extendIfUndefined<T>(base: MapLike<T>, extension: MapLike<T> | undefined) {\n\tif (extension !== undefined) {\n\t\t// eslint-disable-next-line no-restricted-syntax\n\t\tfor (const key in extension) {\n\t\t\tif (base[key] === undefined) {\n\t\t\t\tbase[key] = extension[key];\n\t\t\t}\n\t\t}\n\t}\n\treturn base;\n}\n\n// Create a MapLike with good performance.\nexport function createMap<T>(): MapLike<T> {\n\treturn Object.create(null) as MapLike<T>;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"snapshotV1.d.ts","sourceRoot":"","sources":["../src/snapshotV1.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAGtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,EAAkB,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAI5F,OAAO,EAAmB,WAAW,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAEN,gBAAgB,EAEhB,gBAAgB,EAGhB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAIxC,qBAAa,UAAU;IAiBd,SAAS,EAAE,SAAS;IAE3B,OAAO,CAAC,QAAQ,CAAC,eAAe;IACzB,QAAQ,CAAC;IACT,YAAY,CAAC,SAAQ,IAAI;IAdjC,gBAAuB,SAAS,EAAE,MAAM,CAAS;IAEjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAW;IAC1C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAA2C;IAClF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAG3B,SAAS,EAAE,SAAS,EAC3B,MAAM,EAAE,gBAAgB,EACP,eAAe,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,EACjD,QAAQ,CAAC,oBAAQ,EACjB,YAAY,CAAC,SAAQ,IAAI,aAAA;IAmBjC,OAAO,CAAC,gBAAgB;IAgDxB;;;OAGG;IACH,IAAI,CAAC,UAAU,EAAE,gBAAgB,EAAE,IAAI,EAAE,YAAY,GAAG,qBAAqB;IA0D7E,WAAW;WAwHS,SAAS,CAC5B,OAAO,EAAE,sBAAsB,EAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,WAAW,GAAG,SAAS,EAChC,UAAU,CAAC,EAAE,gBAAgB,GAC3B,OAAO,CAAC,gBAAgB,CAAC;WAMd,YAAY,CACzB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,WAAW,GAAG,SAAS,EAChC,UAAU,CAAC,EAAE,gBAAgB,GAC3B,gBAAgB;CAInB"}
1
+ {"version":3,"file":"snapshotV1.d.ts","sourceRoot":"","sources":["../src/snapshotV1.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAGtE,OAAO,EAAE,sBAAsB,EAAE,MAAM,uCAAuC,CAAC;AAC/E,OAAO,EAAkB,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAI5F,OAAO,EAAmB,WAAW,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,EAEN,gBAAgB,EAEhB,gBAAgB,EAGhB,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAIxC,qBAAa,UAAU;IAiBd,SAAS,EAAE,SAAS;IAE3B,OAAO,CAAC,QAAQ,CAAC,eAAe;IACzB,QAAQ,CAAC;IACT,YAAY,CAAC,SAAQ,IAAI;IAdjC,gBAAuB,SAAS,EAAE,MAAM,CAAS;IAEjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAC9C,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAW;IAC1C,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAA2C;IAClF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAG3B,SAAS,EAAE,SAAS,EAC3B,MAAM,EAAE,gBAAgB,EACP,eAAe,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,EACjD,QAAQ,CAAC,oBAAQ,EACjB,YAAY,CAAC,SAAQ,IAAI,aAAA;IAmBjC,OAAO,CAAC,gBAAgB;IAgDxB;;;OAGG;IACH,IAAI,CAAC,UAAU,EAAE,gBAAgB,EAAE,IAAI,EAAE,YAAY,GAAG,qBAAqB;IA0D7E,WAAW;WAsIS,SAAS,CAC5B,OAAO,EAAE,sBAAsB,EAC/B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,WAAW,GAAG,SAAS,EAChC,UAAU,CAAC,EAAE,gBAAgB,GAC3B,OAAO,CAAC,gBAAgB,CAAC;WAMd,YAAY,CACzB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,WAAW,GAAG,SAAS,EAChC,UAAU,CAAC,EAAE,gBAAgB,GAC3B,gBAAgB;CAInB"}
package/lib/snapshotV1.js CHANGED
@@ -114,6 +114,11 @@ export class SnapshotV1 {
114
114
  // Helper to serialize the given `segment` and add it to the snapshot (if a segment is provided).
115
115
  const pushSeg = (segment) => {
116
116
  if (segment) {
117
+ if (segment.properties !== undefined &&
118
+ Object.keys(segment.properties).length === 0) {
119
+ segment.properties = undefined;
120
+ segment.propertyManager = undefined;
121
+ }
117
122
  pushSegRaw(segment.toJSONObject(), segment.cachedLength, segment.attribution);
118
123
  }
119
124
  };
@@ -164,6 +169,11 @@ export class SnapshotV1 {
164
169
  // for coalescing, so emit the 'prev' segment now (if any).
165
170
  pushSeg(prev);
166
171
  prev = undefined;
172
+ if (segment.properties !== undefined &&
173
+ Object.keys(segment.properties).length === 0) {
174
+ segment.properties = undefined;
175
+ segment.propertyManager = undefined;
176
+ }
167
177
  const raw = { json: segment.toJSONObject() };
168
178
  // If the segment insertion is above the MSN, record the insertion merge info.
169
179
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -1 +1 @@
1
- {"version":3,"file":"snapshotV1.js","sourceRoot":"","sources":["../src/snapshotV1.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\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { IFluidSerializer } from \"@fluidframework/shared-object-base\";\nimport { assert, bufferToString } from \"@fluidframework/common-utils\";\nimport { ChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { IChannelStorageService } from \"@fluidframework/datastore-definitions\";\nimport { AttributionKey, ISummaryTreeWithStats } from \"@fluidframework/runtime-definitions\";\nimport { SummaryTreeBuilder } from \"@fluidframework/runtime-utils\";\nimport { UnassignedSequenceNumber } from \"./constants\";\nimport { ISegment } from \"./mergeTreeNodes\";\nimport { matchProperties, PropertySet } from \"./properties\";\nimport {\n\tIJSONSegmentWithMergeInfo,\n\tJsonSegmentSpecs,\n\tMergeTreeHeaderMetadata,\n\tMergeTreeChunkV1,\n\ttoLatestVersion,\n\tserializeAsMaxSupportedVersion,\n} from \"./snapshotChunks\";\nimport { SnapshotLegacy } from \"./snapshotlegacy\";\nimport { MergeTree } from \"./mergeTree\";\nimport { walkAllChildSegments } from \"./mergeTreeNodeWalk\";\nimport { IAttributionCollection } from \"./attributionCollection\";\n\nexport class SnapshotV1 {\n\t// Split snapshot into two entries - headers (small) and body (overflow) for faster loading initial content\n\t// Please note that this number has no direct relationship to anything other than size of raw text (characters).\n\t// As we produce json for the blob (and then send over the wire compressed), this number\n\t// is really hard to correlate with any actual metric that matters (like bytes over the wire).\n\t// For test with small number of chunks it would be closer to blob size,\n\t// for very chunky text, blob size can easily be 4x-8x of that number.\n\tpublic static readonly chunkSize: number = 10000;\n\n\tprivate readonly header: MergeTreeHeaderMetadata;\n\tprivate readonly segments: JsonSegmentSpecs[];\n\tprivate readonly segmentLengths: number[];\n\tprivate readonly attributionCollections: IAttributionCollection<AttributionKey>[];\n\tprivate readonly logger: ITelemetryLogger;\n\tprivate readonly chunkSize: number;\n\n\tconstructor(\n\t\tpublic mergeTree: MergeTree,\n\t\tlogger: ITelemetryLogger,\n\t\tprivate readonly getLongClientId: (id: number) => string,\n\t\tpublic filename?: string,\n\t\tpublic onCompletion?: () => void,\n\t) {\n\t\tthis.logger = ChildLogger.create(logger, \"Snapshot\");\n\t\tthis.chunkSize = mergeTree?.options?.mergeTreeSnapshotChunkSize ?? SnapshotV1.chunkSize;\n\n\t\tconst { currentSeq, minSeq } = mergeTree.collabWindow;\n\t\tthis.header = {\n\t\t\tminSequenceNumber: minSeq,\n\t\t\tsequenceNumber: currentSeq,\n\t\t\torderedChunkMetadata: [],\n\t\t\ttotalLength: 0,\n\t\t\ttotalSegmentCount: 0,\n\t\t};\n\n\t\tthis.segments = [];\n\t\tthis.segmentLengths = [];\n\t\tthis.attributionCollections = [];\n\t}\n\n\tprivate getSeqLengthSegs(\n\t\tallSegments: JsonSegmentSpecs[],\n\t\tallLengths: number[],\n\t\tattributionCollections: IAttributionCollection<AttributionKey>[],\n\t\tapproxSequenceLength: number,\n\t\tstartIndex = 0,\n\t): MergeTreeChunkV1 {\n\t\tconst segments: JsonSegmentSpecs[] = [];\n\t\tconst collections: {\n\t\t\tattribution: IAttributionCollection<AttributionKey>;\n\t\t\tcachedLength: number;\n\t\t}[] = [];\n\t\tlet length = 0;\n\t\tlet segmentCount = 0;\n\t\tlet hasAttribution = false;\n\t\twhile (length < approxSequenceLength && startIndex + segmentCount < allSegments.length) {\n\t\t\tconst pseg = allSegments[startIndex + segmentCount];\n\t\t\tsegments.push(pseg);\n\t\t\tlength += allLengths[startIndex + segmentCount];\n\t\t\tif (attributionCollections[startIndex + segmentCount]) {\n\t\t\t\thasAttribution = true;\n\t\t\t\tcollections.push({\n\t\t\t\t\tattribution: attributionCollections[startIndex + segmentCount],\n\t\t\t\t\tcachedLength: allLengths[startIndex + segmentCount],\n\t\t\t\t});\n\t\t\t}\n\t\t\tsegmentCount++;\n\t\t}\n\n\t\tconst attributionSerializer = this.mergeTree.attributionPolicy?.serializer;\n\t\tassert(\n\t\t\t!hasAttribution || attributionSerializer !== undefined,\n\t\t\t0x55a /* attribution serializer must be provided when there are segments with attribution. */,\n\t\t);\n\n\t\treturn {\n\t\t\tversion: \"1\",\n\t\t\tsegmentCount,\n\t\t\tlength,\n\t\t\tsegments,\n\t\t\tstartIndex,\n\t\t\theaderMetadata: undefined,\n\t\t\tattribution: hasAttribution\n\t\t\t\t? attributionSerializer?.serializeAttributionCollections(collections)\n\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\t/**\n\t * Emits the snapshot to an ISummarizeResult. If provided the optional IFluidSerializer will be used when\n\t * serializing the summary data rather than JSON.stringify.\n\t */\n\temit(serializer: IFluidSerializer, bind: IFluidHandle): ISummaryTreeWithStats {\n\t\tconst chunks: MergeTreeChunkV1[] = [];\n\t\tthis.header.totalSegmentCount = 0;\n\t\tthis.header.totalLength = 0;\n\t\tdo {\n\t\t\tconst chunk = this.getSeqLengthSegs(\n\t\t\t\tthis.segments,\n\t\t\t\tthis.segmentLengths,\n\t\t\t\tthis.attributionCollections,\n\t\t\t\tthis.chunkSize,\n\t\t\t\tthis.header.totalSegmentCount,\n\t\t\t);\n\t\t\tchunks.push(chunk);\n\t\t\tthis.header.totalSegmentCount += chunk.segmentCount;\n\t\t\tthis.header.totalLength += chunk.length;\n\t\t} while (this.header.totalSegmentCount < this.segments.length);\n\n\t\t// The do while loop should have added at least one chunk\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst headerChunk = chunks.shift()!;\n\t\theaderChunk.headerMetadata = this.header;\n\t\theaderChunk.headerMetadata.orderedChunkMetadata = [{ id: SnapshotLegacy.header }];\n\t\tconst blobs: [key: string, content: string][] = [];\n\t\tchunks.forEach((chunk, index) => {\n\t\t\tconst id = `${SnapshotLegacy.body}_${index}`;\n\t\t\tthis.header.orderedChunkMetadata.push({ id });\n\t\t\tblobs.push([\n\t\t\t\tid,\n\t\t\t\tserializeAsMaxSupportedVersion(\n\t\t\t\t\tid,\n\t\t\t\t\tchunk,\n\t\t\t\t\tthis.logger,\n\t\t\t\t\tthis.mergeTree.options,\n\t\t\t\t\tserializer,\n\t\t\t\t\tbind,\n\t\t\t\t),\n\t\t\t]);\n\t\t});\n\n\t\tconst builder = new SummaryTreeBuilder();\n\t\tbuilder.addBlob(\n\t\t\tSnapshotLegacy.header,\n\t\t\tserializeAsMaxSupportedVersion(\n\t\t\t\tSnapshotLegacy.header,\n\t\t\t\theaderChunk,\n\t\t\t\tthis.logger,\n\t\t\t\tthis.mergeTree.options,\n\t\t\t\tserializer,\n\t\t\t\tbind,\n\t\t\t),\n\t\t);\n\t\tblobs.forEach((value) => {\n\t\t\tbuilder.addBlob(value[0], value[1]);\n\t\t});\n\n\t\treturn builder.getSummaryTree();\n\t}\n\n\textractSync() {\n\t\tconst mergeTree = this.mergeTree;\n\t\tconst minSeq = this.header.minSequenceNumber;\n\n\t\t// Helper to add the given `MergeTreeChunkV0SegmentSpec` to the snapshot.\n\t\tconst pushSegRaw = (\n\t\t\tjson: JsonSegmentSpecs,\n\t\t\tlength: number,\n\t\t\tattribution: IAttributionCollection<AttributionKey> | undefined,\n\t\t) => {\n\t\t\tthis.segments.push(json);\n\t\t\tthis.segmentLengths.push(length);\n\t\t\tif (attribution) {\n\t\t\t\tthis.attributionCollections.push(attribution);\n\t\t\t}\n\t\t};\n\n\t\t// Helper to serialize the given `segment` and add it to the snapshot (if a segment is provided).\n\t\tconst pushSeg = (segment?: ISegment) => {\n\t\t\tif (segment) {\n\t\t\t\tpushSegRaw(segment.toJSONObject(), segment.cachedLength, segment.attribution);\n\t\t\t}\n\t\t};\n\n\t\tlet prev: ISegment | undefined;\n\t\tconst extractSegment = (segment: ISegment) => {\n\t\t\t// Elide segments that do not need to be included in the snapshot. A segment may be elided if\n\t\t\t// either condition is true:\n\t\t\t// a) The segment has not yet been ACKed. We do not need to snapshot unACKed segments because\n\t\t\t// there is a pending insert op that will deliver the segment on reconnection.\n\t\t\t// b) The segment was removed at or below the MSN. Pending ops can no longer reference this\n\t\t\t// segment, and therefore we can discard it.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tif (segment.seq === UnassignedSequenceNumber || segment.removedSeq! <= minSeq) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// Next determine if the snapshot needs to preserve information required for merging the segment\n\t\t\t// (seq, client, etc.) This information is only needed if the segment is above the MSN (and doesn't\n\t\t\t// have a pending remove.)\n\t\t\tif (\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\tsegment.seq! <= minSeq && // Segment is below the MSN, and...\n\t\t\t\t(segment.removedSeq === undefined || // .. Segment has not been removed, or...\n\t\t\t\t\tsegment.removedSeq === UnassignedSequenceNumber) // .. Removal op to be delivered on reconnect\n\t\t\t) {\n\t\t\t\t// This segment is below the MSN, which means that future ops will not reference it. Attempt to\n\t\t\t\t// coalesce the new segment with the previous (if any).\n\t\t\t\tif (!prev) {\n\t\t\t\t\t// We do not have a previous candidate for coalescing. Make the current segment the new candidate.\n\t\t\t\t\tprev = segment;\n\t\t\t\t} else if (\n\t\t\t\t\tprev.canAppend(segment) &&\n\t\t\t\t\tmatchProperties(prev.properties, segment.properties)\n\t\t\t\t) {\n\t\t\t\t\t// We have a compatible pair. Replace `prev` with the coalesced segment. Clone to avoid\n\t\t\t\t\t// modifying the segment instances currently in the MergeTree.\n\t\t\t\t\tprev = prev.clone();\n\t\t\t\t\tprev.append(segment.clone());\n\t\t\t\t} else {\n\t\t\t\t\t// The segment pair could not be coalesced. Record the `prev` segment in the snapshot\n\t\t\t\t\t// and make the current segment the new candidate for coalescing.\n\t\t\t\t\tpushSeg(prev);\n\t\t\t\t\tprev = segment;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// This segment needs to preserve its metadata as it may be referenced by future ops. It's ineligible\n\t\t\t\t// for coalescing, so emit the 'prev' segment now (if any).\n\t\t\t\tpushSeg(prev);\n\t\t\t\tprev = undefined;\n\n\t\t\t\tconst raw: IJSONSegmentWithMergeInfo = { json: segment.toJSONObject() };\n\t\t\t\t// If the segment insertion is above the MSN, record the insertion merge info.\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\tif (segment.seq! > minSeq) {\n\t\t\t\t\traw.seq = segment.seq;\n\t\t\t\t\traw.client = this.getLongClientId(segment.clientId);\n\t\t\t\t}\n\t\t\t\t// We have already dispensed with removed segments below the MSN and removed segments with unassigned\n\t\t\t\t// sequence numbers. Any remaining removal info should be preserved.\n\t\t\t\tif (segment.removedSeq !== undefined) {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tsegment.removedSeq !== UnassignedSequenceNumber &&\n\t\t\t\t\t\t\tsegment.removedSeq > minSeq,\n\t\t\t\t\t\t0x065 /* \"On removal info preservation, segment has invalid removed sequence number!\" */,\n\t\t\t\t\t);\n\t\t\t\t\traw.removedSeq = segment.removedSeq;\n\n\t\t\t\t\t// back compat for when we split overlap and removed client\n\t\t\t\t\traw.removedClient =\n\t\t\t\t\t\tsegment.removedClientIds !== undefined\n\t\t\t\t\t\t\t? this.getLongClientId(segment.removedClientIds[0])\n\t\t\t\t\t\t\t: undefined;\n\n\t\t\t\t\traw.removedClientIds = segment.removedClientIds?.map((id) =>\n\t\t\t\t\t\tthis.getLongClientId(id),\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Sanity check that we are preserving either the seq < minSeq or a removed segment's info.\n\t\t\t\tassert(\n\t\t\t\t\t(raw.seq !== undefined && raw.client !== undefined) ||\n\t\t\t\t\t\t(raw.removedSeq !== undefined && raw.removedClient !== undefined),\n\t\t\t\t\t0x066 /* \"Corrupted preservation of segment metadata!\" */,\n\t\t\t\t);\n\n\t\t\t\t// Record the segment with it's required metadata.\n\t\t\t\tpushSegRaw(raw, segment.cachedLength, segment.attribution);\n\t\t\t}\n\t\t\treturn true;\n\t\t};\n\n\t\twalkAllChildSegments(mergeTree.root, extractSegment);\n\n\t\t// If the last segment in the walk was coalescable, push it now.\n\t\tpushSeg(prev);\n\n\t\treturn this.segments;\n\t}\n\n\tpublic static async loadChunk(\n\t\tstorage: IChannelStorageService,\n\t\tpath: string,\n\t\tlogger: ITelemetryLogger,\n\t\toptions: PropertySet | undefined,\n\t\tserializer?: IFluidSerializer,\n\t): Promise<MergeTreeChunkV1> {\n\t\tconst blob = await storage.readBlob(path);\n\t\tconst chunkAsString = bufferToString(blob, \"utf8\");\n\t\treturn SnapshotV1.processChunk(path, chunkAsString, logger, options, serializer);\n\t}\n\n\tpublic static processChunk(\n\t\tpath: string,\n\t\tchunk: string,\n\t\tlogger: ITelemetryLogger,\n\t\toptions: PropertySet | undefined,\n\t\tserializer?: IFluidSerializer,\n\t): MergeTreeChunkV1 {\n\t\tconst chunkObj = serializer ? serializer.parse(chunk) : JSON.parse(chunk);\n\t\treturn toLatestVersion(path, chunkObj, logger, options);\n\t}\n}\n"]}
1
+ {"version":3,"file":"snapshotV1.js","sourceRoot":"","sources":["../src/snapshotV1.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\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { IFluidSerializer } from \"@fluidframework/shared-object-base\";\nimport { assert, bufferToString } from \"@fluidframework/common-utils\";\nimport { ChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { IChannelStorageService } from \"@fluidframework/datastore-definitions\";\nimport { AttributionKey, ISummaryTreeWithStats } from \"@fluidframework/runtime-definitions\";\nimport { SummaryTreeBuilder } from \"@fluidframework/runtime-utils\";\nimport { UnassignedSequenceNumber } from \"./constants\";\nimport { ISegment } from \"./mergeTreeNodes\";\nimport { matchProperties, PropertySet } from \"./properties\";\nimport {\n\tIJSONSegmentWithMergeInfo,\n\tJsonSegmentSpecs,\n\tMergeTreeHeaderMetadata,\n\tMergeTreeChunkV1,\n\ttoLatestVersion,\n\tserializeAsMaxSupportedVersion,\n} from \"./snapshotChunks\";\nimport { SnapshotLegacy } from \"./snapshotlegacy\";\nimport { MergeTree } from \"./mergeTree\";\nimport { walkAllChildSegments } from \"./mergeTreeNodeWalk\";\nimport { IAttributionCollection } from \"./attributionCollection\";\n\nexport class SnapshotV1 {\n\t// Split snapshot into two entries - headers (small) and body (overflow) for faster loading initial content\n\t// Please note that this number has no direct relationship to anything other than size of raw text (characters).\n\t// As we produce json for the blob (and then send over the wire compressed), this number\n\t// is really hard to correlate with any actual metric that matters (like bytes over the wire).\n\t// For test with small number of chunks it would be closer to blob size,\n\t// for very chunky text, blob size can easily be 4x-8x of that number.\n\tpublic static readonly chunkSize: number = 10000;\n\n\tprivate readonly header: MergeTreeHeaderMetadata;\n\tprivate readonly segments: JsonSegmentSpecs[];\n\tprivate readonly segmentLengths: number[];\n\tprivate readonly attributionCollections: IAttributionCollection<AttributionKey>[];\n\tprivate readonly logger: ITelemetryLogger;\n\tprivate readonly chunkSize: number;\n\n\tconstructor(\n\t\tpublic mergeTree: MergeTree,\n\t\tlogger: ITelemetryLogger,\n\t\tprivate readonly getLongClientId: (id: number) => string,\n\t\tpublic filename?: string,\n\t\tpublic onCompletion?: () => void,\n\t) {\n\t\tthis.logger = ChildLogger.create(logger, \"Snapshot\");\n\t\tthis.chunkSize = mergeTree?.options?.mergeTreeSnapshotChunkSize ?? SnapshotV1.chunkSize;\n\n\t\tconst { currentSeq, minSeq } = mergeTree.collabWindow;\n\t\tthis.header = {\n\t\t\tminSequenceNumber: minSeq,\n\t\t\tsequenceNumber: currentSeq,\n\t\t\torderedChunkMetadata: [],\n\t\t\ttotalLength: 0,\n\t\t\ttotalSegmentCount: 0,\n\t\t};\n\n\t\tthis.segments = [];\n\t\tthis.segmentLengths = [];\n\t\tthis.attributionCollections = [];\n\t}\n\n\tprivate getSeqLengthSegs(\n\t\tallSegments: JsonSegmentSpecs[],\n\t\tallLengths: number[],\n\t\tattributionCollections: IAttributionCollection<AttributionKey>[],\n\t\tapproxSequenceLength: number,\n\t\tstartIndex = 0,\n\t): MergeTreeChunkV1 {\n\t\tconst segments: JsonSegmentSpecs[] = [];\n\t\tconst collections: {\n\t\t\tattribution: IAttributionCollection<AttributionKey>;\n\t\t\tcachedLength: number;\n\t\t}[] = [];\n\t\tlet length = 0;\n\t\tlet segmentCount = 0;\n\t\tlet hasAttribution = false;\n\t\twhile (length < approxSequenceLength && startIndex + segmentCount < allSegments.length) {\n\t\t\tconst pseg = allSegments[startIndex + segmentCount];\n\t\t\tsegments.push(pseg);\n\t\t\tlength += allLengths[startIndex + segmentCount];\n\t\t\tif (attributionCollections[startIndex + segmentCount]) {\n\t\t\t\thasAttribution = true;\n\t\t\t\tcollections.push({\n\t\t\t\t\tattribution: attributionCollections[startIndex + segmentCount],\n\t\t\t\t\tcachedLength: allLengths[startIndex + segmentCount],\n\t\t\t\t});\n\t\t\t}\n\t\t\tsegmentCount++;\n\t\t}\n\n\t\tconst attributionSerializer = this.mergeTree.attributionPolicy?.serializer;\n\t\tassert(\n\t\t\t!hasAttribution || attributionSerializer !== undefined,\n\t\t\t0x55a /* attribution serializer must be provided when there are segments with attribution. */,\n\t\t);\n\n\t\treturn {\n\t\t\tversion: \"1\",\n\t\t\tsegmentCount,\n\t\t\tlength,\n\t\t\tsegments,\n\t\t\tstartIndex,\n\t\t\theaderMetadata: undefined,\n\t\t\tattribution: hasAttribution\n\t\t\t\t? attributionSerializer?.serializeAttributionCollections(collections)\n\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\t/**\n\t * Emits the snapshot to an ISummarizeResult. If provided the optional IFluidSerializer will be used when\n\t * serializing the summary data rather than JSON.stringify.\n\t */\n\temit(serializer: IFluidSerializer, bind: IFluidHandle): ISummaryTreeWithStats {\n\t\tconst chunks: MergeTreeChunkV1[] = [];\n\t\tthis.header.totalSegmentCount = 0;\n\t\tthis.header.totalLength = 0;\n\t\tdo {\n\t\t\tconst chunk = this.getSeqLengthSegs(\n\t\t\t\tthis.segments,\n\t\t\t\tthis.segmentLengths,\n\t\t\t\tthis.attributionCollections,\n\t\t\t\tthis.chunkSize,\n\t\t\t\tthis.header.totalSegmentCount,\n\t\t\t);\n\t\t\tchunks.push(chunk);\n\t\t\tthis.header.totalSegmentCount += chunk.segmentCount;\n\t\t\tthis.header.totalLength += chunk.length;\n\t\t} while (this.header.totalSegmentCount < this.segments.length);\n\n\t\t// The do while loop should have added at least one chunk\n\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\tconst headerChunk = chunks.shift()!;\n\t\theaderChunk.headerMetadata = this.header;\n\t\theaderChunk.headerMetadata.orderedChunkMetadata = [{ id: SnapshotLegacy.header }];\n\t\tconst blobs: [key: string, content: string][] = [];\n\t\tchunks.forEach((chunk, index) => {\n\t\t\tconst id = `${SnapshotLegacy.body}_${index}`;\n\t\t\tthis.header.orderedChunkMetadata.push({ id });\n\t\t\tblobs.push([\n\t\t\t\tid,\n\t\t\t\tserializeAsMaxSupportedVersion(\n\t\t\t\t\tid,\n\t\t\t\t\tchunk,\n\t\t\t\t\tthis.logger,\n\t\t\t\t\tthis.mergeTree.options,\n\t\t\t\t\tserializer,\n\t\t\t\t\tbind,\n\t\t\t\t),\n\t\t\t]);\n\t\t});\n\n\t\tconst builder = new SummaryTreeBuilder();\n\t\tbuilder.addBlob(\n\t\t\tSnapshotLegacy.header,\n\t\t\tserializeAsMaxSupportedVersion(\n\t\t\t\tSnapshotLegacy.header,\n\t\t\t\theaderChunk,\n\t\t\t\tthis.logger,\n\t\t\t\tthis.mergeTree.options,\n\t\t\t\tserializer,\n\t\t\t\tbind,\n\t\t\t),\n\t\t);\n\t\tblobs.forEach((value) => {\n\t\t\tbuilder.addBlob(value[0], value[1]);\n\t\t});\n\n\t\treturn builder.getSummaryTree();\n\t}\n\n\textractSync() {\n\t\tconst mergeTree = this.mergeTree;\n\t\tconst minSeq = this.header.minSequenceNumber;\n\n\t\t// Helper to add the given `MergeTreeChunkV0SegmentSpec` to the snapshot.\n\t\tconst pushSegRaw = (\n\t\t\tjson: JsonSegmentSpecs,\n\t\t\tlength: number,\n\t\t\tattribution: IAttributionCollection<AttributionKey> | undefined,\n\t\t) => {\n\t\t\tthis.segments.push(json);\n\t\t\tthis.segmentLengths.push(length);\n\t\t\tif (attribution) {\n\t\t\t\tthis.attributionCollections.push(attribution);\n\t\t\t}\n\t\t};\n\n\t\t// Helper to serialize the given `segment` and add it to the snapshot (if a segment is provided).\n\t\tconst pushSeg = (segment?: ISegment) => {\n\t\t\tif (segment) {\n\t\t\t\tif (\n\t\t\t\t\tsegment.properties !== undefined &&\n\t\t\t\t\tObject.keys(segment.properties).length === 0\n\t\t\t\t) {\n\t\t\t\t\tsegment.properties = undefined;\n\t\t\t\t\tsegment.propertyManager = undefined;\n\t\t\t\t}\n\t\t\t\tpushSegRaw(segment.toJSONObject(), segment.cachedLength, segment.attribution);\n\t\t\t}\n\t\t};\n\n\t\tlet prev: ISegment | undefined;\n\t\tconst extractSegment = (segment: ISegment) => {\n\t\t\t// Elide segments that do not need to be included in the snapshot. A segment may be elided if\n\t\t\t// either condition is true:\n\t\t\t// a) The segment has not yet been ACKed. We do not need to snapshot unACKed segments because\n\t\t\t// there is a pending insert op that will deliver the segment on reconnection.\n\t\t\t// b) The segment was removed at or below the MSN. Pending ops can no longer reference this\n\t\t\t// segment, and therefore we can discard it.\n\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\tif (segment.seq === UnassignedSequenceNumber || segment.removedSeq! <= minSeq) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\t// Next determine if the snapshot needs to preserve information required for merging the segment\n\t\t\t// (seq, client, etc.) This information is only needed if the segment is above the MSN (and doesn't\n\t\t\t// have a pending remove.)\n\t\t\tif (\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\tsegment.seq! <= minSeq && // Segment is below the MSN, and...\n\t\t\t\t(segment.removedSeq === undefined || // .. Segment has not been removed, or...\n\t\t\t\t\tsegment.removedSeq === UnassignedSequenceNumber) // .. Removal op to be delivered on reconnect\n\t\t\t) {\n\t\t\t\t// This segment is below the MSN, which means that future ops will not reference it. Attempt to\n\t\t\t\t// coalesce the new segment with the previous (if any).\n\t\t\t\tif (!prev) {\n\t\t\t\t\t// We do not have a previous candidate for coalescing. Make the current segment the new candidate.\n\t\t\t\t\tprev = segment;\n\t\t\t\t} else if (\n\t\t\t\t\tprev.canAppend(segment) &&\n\t\t\t\t\tmatchProperties(prev.properties, segment.properties)\n\t\t\t\t) {\n\t\t\t\t\t// We have a compatible pair. Replace `prev` with the coalesced segment. Clone to avoid\n\t\t\t\t\t// modifying the segment instances currently in the MergeTree.\n\t\t\t\t\tprev = prev.clone();\n\t\t\t\t\tprev.append(segment.clone());\n\t\t\t\t} else {\n\t\t\t\t\t// The segment pair could not be coalesced. Record the `prev` segment in the snapshot\n\t\t\t\t\t// and make the current segment the new candidate for coalescing.\n\t\t\t\t\tpushSeg(prev);\n\t\t\t\t\tprev = segment;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// This segment needs to preserve its metadata as it may be referenced by future ops. It's ineligible\n\t\t\t\t// for coalescing, so emit the 'prev' segment now (if any).\n\t\t\t\tpushSeg(prev);\n\t\t\t\tprev = undefined;\n\n\t\t\t\tif (\n\t\t\t\t\tsegment.properties !== undefined &&\n\t\t\t\t\tObject.keys(segment.properties).length === 0\n\t\t\t\t) {\n\t\t\t\t\tsegment.properties = undefined;\n\t\t\t\t\tsegment.propertyManager = undefined;\n\t\t\t\t}\n\t\t\t\tconst raw: IJSONSegmentWithMergeInfo = { json: segment.toJSONObject() };\n\t\t\t\t// If the segment insertion is above the MSN, record the insertion merge info.\n\t\t\t\t// eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n\t\t\t\tif (segment.seq! > minSeq) {\n\t\t\t\t\traw.seq = segment.seq;\n\t\t\t\t\traw.client = this.getLongClientId(segment.clientId);\n\t\t\t\t}\n\t\t\t\t// We have already dispensed with removed segments below the MSN and removed segments with unassigned\n\t\t\t\t// sequence numbers. Any remaining removal info should be preserved.\n\t\t\t\tif (segment.removedSeq !== undefined) {\n\t\t\t\t\tassert(\n\t\t\t\t\t\tsegment.removedSeq !== UnassignedSequenceNumber &&\n\t\t\t\t\t\t\tsegment.removedSeq > minSeq,\n\t\t\t\t\t\t0x065 /* \"On removal info preservation, segment has invalid removed sequence number!\" */,\n\t\t\t\t\t);\n\t\t\t\t\traw.removedSeq = segment.removedSeq;\n\n\t\t\t\t\t// back compat for when we split overlap and removed client\n\t\t\t\t\traw.removedClient =\n\t\t\t\t\t\tsegment.removedClientIds !== undefined\n\t\t\t\t\t\t\t? this.getLongClientId(segment.removedClientIds[0])\n\t\t\t\t\t\t\t: undefined;\n\n\t\t\t\t\traw.removedClientIds = segment.removedClientIds?.map((id) =>\n\t\t\t\t\t\tthis.getLongClientId(id),\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\t// Sanity check that we are preserving either the seq < minSeq or a removed segment's info.\n\t\t\t\tassert(\n\t\t\t\t\t(raw.seq !== undefined && raw.client !== undefined) ||\n\t\t\t\t\t\t(raw.removedSeq !== undefined && raw.removedClient !== undefined),\n\t\t\t\t\t0x066 /* \"Corrupted preservation of segment metadata!\" */,\n\t\t\t\t);\n\n\t\t\t\t// Record the segment with it's required metadata.\n\t\t\t\tpushSegRaw(raw, segment.cachedLength, segment.attribution);\n\t\t\t}\n\t\t\treturn true;\n\t\t};\n\n\t\twalkAllChildSegments(mergeTree.root, extractSegment);\n\n\t\t// If the last segment in the walk was coalescable, push it now.\n\t\tpushSeg(prev);\n\n\t\treturn this.segments;\n\t}\n\n\tpublic static async loadChunk(\n\t\tstorage: IChannelStorageService,\n\t\tpath: string,\n\t\tlogger: ITelemetryLogger,\n\t\toptions: PropertySet | undefined,\n\t\tserializer?: IFluidSerializer,\n\t): Promise<MergeTreeChunkV1> {\n\t\tconst blob = await storage.readBlob(path);\n\t\tconst chunkAsString = bufferToString(blob, \"utf8\");\n\t\treturn SnapshotV1.processChunk(path, chunkAsString, logger, options, serializer);\n\t}\n\n\tpublic static processChunk(\n\t\tpath: string,\n\t\tchunk: string,\n\t\tlogger: ITelemetryLogger,\n\t\toptions: PropertySet | undefined,\n\t\tserializer?: IFluidSerializer,\n\t): MergeTreeChunkV1 {\n\t\tconst chunkObj = serializer ? serializer.parse(chunk) : JSON.parse(chunk);\n\t\treturn toLatestVersion(path, chunkObj, logger, options);\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"snapshotlegacy.d.ts","sourceRoot":"","sources":["../src/snapshotlegacy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAEtE,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAE5E,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAGjF,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAO5C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAaxC;;GAEG;AACH,qBAAa,cAAc;IAoBlB,SAAS,EAAE,SAAS;IAEpB,QAAQ,CAAC;IACT,YAAY,CAAC,SAAQ,IAAI;IAtBjC,gBAAuB,MAAM,YAAY;IACzC,gBAAuB,IAAI,UAAU;IACrC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAQlD,gBAAuB,gBAAgB,EAAE,MAAM,CAAS;IAExD,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,GAAG,CAAqB;IAChC,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAG3B,SAAS,EAAE,SAAS,EAC3B,MAAM,EAAE,gBAAgB,EACjB,QAAQ,CAAC,oBAAQ,EACjB,YAAY,CAAC,SAAQ,IAAI,aAAA;IAOjC,OAAO,CAAC,gBAAgB;IAgDxB;;;OAGG;IACH,IAAI,CACH,WAAW,EAAE,yBAAyB,EAAE,EACxC,UAAU,EAAE,gBAAgB,EAC5B,IAAI,EAAE,YAAY,GAChB,qBAAqB;IA0DxB,WAAW;CAwEX"}
1
+ {"version":3,"file":"snapshotlegacy.d.ts","sourceRoot":"","sources":["../src/snapshotlegacy.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAEtE,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAE5E,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AAGjF,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAO5C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAaxC;;GAEG;AACH,qBAAa,cAAc;IAoBlB,SAAS,EAAE,SAAS;IAEpB,QAAQ,CAAC;IACT,YAAY,CAAC,SAAQ,IAAI;IAtBjC,gBAAuB,MAAM,YAAY;IACzC,gBAAuB,IAAI,UAAU;IACrC,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAgB;IAQlD,gBAAuB,gBAAgB,EAAE,MAAM,CAAS;IAExD,OAAO,CAAC,MAAM,CAA6B;IAC3C,OAAO,CAAC,GAAG,CAAqB;IAChC,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAmB;IAC1C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAG3B,SAAS,EAAE,SAAS,EAC3B,MAAM,EAAE,gBAAgB,EACjB,QAAQ,CAAC,oBAAQ,EACjB,YAAY,CAAC,SAAQ,IAAI,aAAA;IAOjC,OAAO,CAAC,gBAAgB;IAgDxB;;;OAGG;IACH,IAAI,CACH,WAAW,EAAE,yBAAyB,EAAE,EACxC,UAAU,EAAE,gBAAgB,EAC5B,IAAI,EAAE,YAAY,GAChB,qBAAqB;IA0DxB,WAAW;CA4EX"}
@@ -115,6 +115,10 @@ export class SnapshotLegacy {
115
115
  let totalLength = 0;
116
116
  segs.map((segment) => {
117
117
  totalLength += segment.cachedLength;
118
+ if (segment.properties !== undefined && Object.keys(segment.properties).length === 0) {
119
+ segment.properties = undefined;
120
+ segment.propertyManager = undefined;
121
+ }
118
122
  this.segments.push(segment);
119
123
  });
120
124
  // We observed this.header.segmentsTotalLength < totalLength to happen in some cases
@@ -1 +1 @@
1
- {"version":3,"file":"snapshotlegacy.js","sourceRoot":"","sources":["../src/snapshotlegacy.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/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { IFluidSerializer } from \"@fluidframework/shared-object-base\";\nimport { ISummaryTreeWithStats } from \"@fluidframework/runtime-definitions\";\nimport { ChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { SummaryTreeBuilder } from \"@fluidframework/runtime-utils\";\nimport { NonCollabClient, UnassignedSequenceNumber } from \"./constants\";\nimport { ISegment } from \"./mergeTreeNodes\";\nimport { matchProperties } from \"./properties\";\nimport {\n\tJsonSegmentSpecs,\n\tMergeTreeChunkLegacy,\n\tserializeAsMinSupportedVersion,\n} from \"./snapshotChunks\";\nimport { MergeTree } from \"./mergeTree\";\n\ninterface SnapshotHeader {\n\tchunkCount?: number;\n\tsegmentsTotalLength: number;\n\tindexOffset?: number;\n\tsegmentsOffset?: number;\n\tseq: number;\n\t// TODO: Make 'minSeq' non-optional once the new snapshot format becomes the default?\n\t// (See https://github.com/microsoft/FluidFramework/issues/84)\n\tminSeq?: number;\n}\n\n/**\n * @internal\n */\nexport class SnapshotLegacy {\n\tpublic static readonly header = \"header\";\n\tpublic static readonly body = \"body\";\n\tprivate static readonly catchupOps = \"catchupOps\";\n\n\t// Split snapshot into two entries - headers (small) and body (overflow) for faster loading initial content\n\t// Please note that this number has no direct relationship to anything other than size of raw text (characters).\n\t// As we produce json for the blob (and then send over the wire compressed), this number\n\t// is really hard to correlate with any actual metric that matters (like bytes over the wire).\n\t// For test with small number of chunks it would be closer to blob size,\n\t// for very chunky text, blob size can easily be 4x-8x of that number.\n\tpublic static readonly sizeOfFirstChunk: number = 10000;\n\n\tprivate header: SnapshotHeader | undefined;\n\tprivate seq: number | undefined;\n\tprivate segments: ISegment[] | undefined;\n\tprivate readonly logger: ITelemetryLogger;\n\tprivate readonly chunkSize: number;\n\n\tconstructor(\n\t\tpublic mergeTree: MergeTree,\n\t\tlogger: ITelemetryLogger,\n\t\tpublic filename?: string,\n\t\tpublic onCompletion?: () => void,\n\t) {\n\t\tthis.logger = ChildLogger.create(logger, \"Snapshot\");\n\t\tthis.chunkSize =\n\t\t\tmergeTree?.options?.mergeTreeSnapshotChunkSize ?? SnapshotLegacy.sizeOfFirstChunk;\n\t}\n\n\tprivate getSeqLengthSegs(\n\t\tallSegments: ISegment[],\n\t\tapproxSequenceLength: number,\n\t\tstartIndex = 0,\n\t): MergeTreeChunkLegacy {\n\t\tconst segs: ISegment[] = [];\n\t\tlet sequenceLength = 0;\n\t\tlet segCount = 0;\n\t\tlet segsWithAttribution = 0;\n\t\twhile (\n\t\t\tsequenceLength < approxSequenceLength &&\n\t\t\tstartIndex + segCount < allSegments.length\n\t\t) {\n\t\t\tconst pseg = allSegments[startIndex + segCount];\n\t\t\tsegs.push(pseg);\n\t\t\tif (pseg.attribution) {\n\t\t\t\tsegsWithAttribution++;\n\t\t\t}\n\t\t\tsequenceLength += pseg.cachedLength;\n\t\t\tsegCount++;\n\t\t}\n\n\t\tassert(\n\t\t\tsegsWithAttribution === 0 || segsWithAttribution === segCount,\n\t\t\t0x4bf /* all or no segments should have attribution */,\n\t\t);\n\n\t\tconst attributionSerializer = this.mergeTree.attributionPolicy?.serializer;\n\t\tassert(\n\t\t\tsegsWithAttribution === 0 || attributionSerializer !== undefined,\n\t\t\t0x559 /* attribution serializer must be provided when there are segments with attribution. */,\n\t\t);\n\t\treturn {\n\t\t\tversion: undefined,\n\t\t\tchunkStartSegmentIndex: startIndex,\n\t\t\tchunkSegmentCount: segCount,\n\t\t\tchunkLengthChars: sequenceLength,\n\t\t\ttotalLengthChars: this.header!.segmentsTotalLength,\n\t\t\ttotalSegmentCount: allSegments.length,\n\t\t\tchunkSequenceNumber: this.header!.seq,\n\t\t\tsegmentTexts: segs.map((seg) => seg.toJSONObject() as JsonSegmentSpecs),\n\t\t\tattribution:\n\t\t\t\tsegsWithAttribution > 0\n\t\t\t\t\t? attributionSerializer?.serializeAttributionCollections(segs)\n\t\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\t/**\n\t * Emits the snapshot to an ISummarizeResult. If provided the optional IFluidSerializer will be used when\n\t * serializing the summary data rather than JSON.stringify.\n\t */\n\temit(\n\t\tcatchUpMsgs: ISequencedDocumentMessage[],\n\t\tserializer: IFluidSerializer,\n\t\tbind: IFluidHandle,\n\t): ISummaryTreeWithStats {\n\t\tconst chunk1 = this.getSeqLengthSegs(this.segments!, this.chunkSize);\n\t\tlet length: number = chunk1.chunkLengthChars;\n\t\tlet segments: number = chunk1.chunkSegmentCount;\n\t\tconst builder = new SummaryTreeBuilder();\n\t\tbuilder.addBlob(\n\t\t\tSnapshotLegacy.header,\n\t\t\tserializeAsMinSupportedVersion(\n\t\t\t\tSnapshotLegacy.header,\n\t\t\t\tchunk1,\n\t\t\t\tthis.logger,\n\t\t\t\tthis.mergeTree.options,\n\t\t\t\tserializer,\n\t\t\t\tbind,\n\t\t\t),\n\t\t);\n\n\t\tif (chunk1.chunkSegmentCount < chunk1.totalSegmentCount!) {\n\t\t\tconst chunk2 = this.getSeqLengthSegs(\n\t\t\t\tthis.segments!,\n\t\t\t\tthis.header!.segmentsTotalLength,\n\t\t\t\tchunk1.chunkSegmentCount,\n\t\t\t);\n\t\t\tlength += chunk2.chunkLengthChars;\n\t\t\tsegments += chunk2.chunkSegmentCount;\n\t\t\tbuilder.addBlob(\n\t\t\t\tSnapshotLegacy.body,\n\t\t\t\tserializeAsMinSupportedVersion(\n\t\t\t\t\tSnapshotLegacy.body,\n\t\t\t\t\tchunk2,\n\t\t\t\t\tthis.logger,\n\t\t\t\t\tthis.mergeTree.options,\n\t\t\t\t\tserializer,\n\t\t\t\t\tbind,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tassert(\n\t\t\tlength === this.header!.segmentsTotalLength,\n\t\t\t0x05d /* \"emit: mismatch in segmentsTotalLength\" */,\n\t\t);\n\n\t\tassert(\n\t\t\tsegments === chunk1.totalSegmentCount,\n\t\t\t0x05e /* \"emit: mismatch in totalSegmentCount\" */,\n\t\t);\n\n\t\tif (catchUpMsgs !== undefined && catchUpMsgs.length > 0) {\n\t\t\tbuilder.addBlob(\n\t\t\t\tthis.mergeTree.options?.catchUpBlobName ?? SnapshotLegacy.catchupOps,\n\t\t\t\tserializer ? serializer.stringify(catchUpMsgs, bind) : JSON.stringify(catchUpMsgs),\n\t\t\t);\n\t\t}\n\n\t\treturn builder.getSummaryTree();\n\t}\n\n\textractSync() {\n\t\tconst collabWindow = this.mergeTree.collabWindow;\n\t\tthis.seq = collabWindow.minSeq;\n\t\tthis.header = {\n\t\t\tsegmentsTotalLength: this.mergeTree.getLength(\n\t\t\t\tthis.mergeTree.collabWindow.minSeq,\n\t\t\t\tNonCollabClient,\n\t\t\t),\n\t\t\tseq: this.mergeTree.collabWindow.minSeq,\n\t\t};\n\n\t\tconst segs: ISegment[] = [];\n\t\tlet prev: ISegment | undefined;\n\t\tconst extractSegment = (\n\t\t\tsegment: ISegment,\n\t\t\tpos: number,\n\t\t\trefSeq: number,\n\t\t\tclientId: number,\n\t\t\tstart: number | undefined,\n\t\t\tend: number | undefined,\n\t\t) => {\n\t\t\tif (\n\t\t\t\tsegment.seq !== UnassignedSequenceNumber &&\n\t\t\t\tsegment.seq! <= this.seq! &&\n\t\t\t\t(segment.removedSeq === undefined ||\n\t\t\t\t\tsegment.removedSeq === UnassignedSequenceNumber ||\n\t\t\t\t\tsegment.removedSeq > this.seq!)\n\t\t\t) {\n\t\t\t\tif (\n\t\t\t\t\tprev?.canAppend(segment) &&\n\t\t\t\t\tmatchProperties(prev.properties, segment.properties)\n\t\t\t\t) {\n\t\t\t\t\tprev = prev.clone();\n\t\t\t\t\tprev.append(segment.clone());\n\t\t\t\t} else {\n\t\t\t\t\tif (prev) {\n\t\t\t\t\t\tsegs.push(prev);\n\t\t\t\t\t}\n\t\t\t\t\tprev = segment;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t};\n\n\t\tthis.mergeTree.mapRange(extractSegment, this.seq, NonCollabClient, undefined);\n\t\tif (prev) {\n\t\t\tsegs.push(prev);\n\t\t}\n\n\t\tthis.segments = [];\n\t\tlet totalLength: number = 0;\n\t\tsegs.map((segment) => {\n\t\t\ttotalLength += segment.cachedLength;\n\t\t\tthis.segments!.push(segment);\n\t\t});\n\n\t\t// We observed this.header.segmentsTotalLength < totalLength to happen in some cases\n\t\t// When this condition happens, we might not write out all segments in getSeqLengthSegs()\n\t\t// when writing out \"body\". Issue #1995 tracks following up on the core of the problem.\n\t\t// In the meantime, this code makes sure we will write out all segments properly\n\n\t\tif (this.header.segmentsTotalLength !== totalLength) {\n\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\teventName: \"SegmentsTotalLengthMismatch\",\n\t\t\t\ttotalLength,\n\t\t\t\tsegmentsTotalLength: this.header.segmentsTotalLength,\n\t\t\t});\n\t\t\tthis.header.segmentsTotalLength = totalLength;\n\t\t}\n\n\t\treturn this.segments;\n\t}\n}\n"]}
1
+ {"version":3,"file":"snapshotlegacy.js","sourceRoot":"","sources":["../src/snapshotlegacy.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/* eslint-disable @typescript-eslint/no-non-null-assertion */\n\nimport { ITelemetryLogger } from \"@fluidframework/common-definitions\";\nimport { assert } from \"@fluidframework/common-utils\";\nimport { IFluidHandle } from \"@fluidframework/core-interfaces\";\nimport { IFluidSerializer } from \"@fluidframework/shared-object-base\";\nimport { ISummaryTreeWithStats } from \"@fluidframework/runtime-definitions\";\nimport { ChildLogger } from \"@fluidframework/telemetry-utils\";\nimport { ISequencedDocumentMessage } from \"@fluidframework/protocol-definitions\";\nimport { SummaryTreeBuilder } from \"@fluidframework/runtime-utils\";\nimport { NonCollabClient, UnassignedSequenceNumber } from \"./constants\";\nimport { ISegment } from \"./mergeTreeNodes\";\nimport { matchProperties } from \"./properties\";\nimport {\n\tJsonSegmentSpecs,\n\tMergeTreeChunkLegacy,\n\tserializeAsMinSupportedVersion,\n} from \"./snapshotChunks\";\nimport { MergeTree } from \"./mergeTree\";\n\ninterface SnapshotHeader {\n\tchunkCount?: number;\n\tsegmentsTotalLength: number;\n\tindexOffset?: number;\n\tsegmentsOffset?: number;\n\tseq: number;\n\t// TODO: Make 'minSeq' non-optional once the new snapshot format becomes the default?\n\t// (See https://github.com/microsoft/FluidFramework/issues/84)\n\tminSeq?: number;\n}\n\n/**\n * @internal\n */\nexport class SnapshotLegacy {\n\tpublic static readonly header = \"header\";\n\tpublic static readonly body = \"body\";\n\tprivate static readonly catchupOps = \"catchupOps\";\n\n\t// Split snapshot into two entries - headers (small) and body (overflow) for faster loading initial content\n\t// Please note that this number has no direct relationship to anything other than size of raw text (characters).\n\t// As we produce json for the blob (and then send over the wire compressed), this number\n\t// is really hard to correlate with any actual metric that matters (like bytes over the wire).\n\t// For test with small number of chunks it would be closer to blob size,\n\t// for very chunky text, blob size can easily be 4x-8x of that number.\n\tpublic static readonly sizeOfFirstChunk: number = 10000;\n\n\tprivate header: SnapshotHeader | undefined;\n\tprivate seq: number | undefined;\n\tprivate segments: ISegment[] | undefined;\n\tprivate readonly logger: ITelemetryLogger;\n\tprivate readonly chunkSize: number;\n\n\tconstructor(\n\t\tpublic mergeTree: MergeTree,\n\t\tlogger: ITelemetryLogger,\n\t\tpublic filename?: string,\n\t\tpublic onCompletion?: () => void,\n\t) {\n\t\tthis.logger = ChildLogger.create(logger, \"Snapshot\");\n\t\tthis.chunkSize =\n\t\t\tmergeTree?.options?.mergeTreeSnapshotChunkSize ?? SnapshotLegacy.sizeOfFirstChunk;\n\t}\n\n\tprivate getSeqLengthSegs(\n\t\tallSegments: ISegment[],\n\t\tapproxSequenceLength: number,\n\t\tstartIndex = 0,\n\t): MergeTreeChunkLegacy {\n\t\tconst segs: ISegment[] = [];\n\t\tlet sequenceLength = 0;\n\t\tlet segCount = 0;\n\t\tlet segsWithAttribution = 0;\n\t\twhile (\n\t\t\tsequenceLength < approxSequenceLength &&\n\t\t\tstartIndex + segCount < allSegments.length\n\t\t) {\n\t\t\tconst pseg = allSegments[startIndex + segCount];\n\t\t\tsegs.push(pseg);\n\t\t\tif (pseg.attribution) {\n\t\t\t\tsegsWithAttribution++;\n\t\t\t}\n\t\t\tsequenceLength += pseg.cachedLength;\n\t\t\tsegCount++;\n\t\t}\n\n\t\tassert(\n\t\t\tsegsWithAttribution === 0 || segsWithAttribution === segCount,\n\t\t\t0x4bf /* all or no segments should have attribution */,\n\t\t);\n\n\t\tconst attributionSerializer = this.mergeTree.attributionPolicy?.serializer;\n\t\tassert(\n\t\t\tsegsWithAttribution === 0 || attributionSerializer !== undefined,\n\t\t\t0x559 /* attribution serializer must be provided when there are segments with attribution. */,\n\t\t);\n\t\treturn {\n\t\t\tversion: undefined,\n\t\t\tchunkStartSegmentIndex: startIndex,\n\t\t\tchunkSegmentCount: segCount,\n\t\t\tchunkLengthChars: sequenceLength,\n\t\t\ttotalLengthChars: this.header!.segmentsTotalLength,\n\t\t\ttotalSegmentCount: allSegments.length,\n\t\t\tchunkSequenceNumber: this.header!.seq,\n\t\t\tsegmentTexts: segs.map((seg) => seg.toJSONObject() as JsonSegmentSpecs),\n\t\t\tattribution:\n\t\t\t\tsegsWithAttribution > 0\n\t\t\t\t\t? attributionSerializer?.serializeAttributionCollections(segs)\n\t\t\t\t\t: undefined,\n\t\t};\n\t}\n\n\t/**\n\t * Emits the snapshot to an ISummarizeResult. If provided the optional IFluidSerializer will be used when\n\t * serializing the summary data rather than JSON.stringify.\n\t */\n\temit(\n\t\tcatchUpMsgs: ISequencedDocumentMessage[],\n\t\tserializer: IFluidSerializer,\n\t\tbind: IFluidHandle,\n\t): ISummaryTreeWithStats {\n\t\tconst chunk1 = this.getSeqLengthSegs(this.segments!, this.chunkSize);\n\t\tlet length: number = chunk1.chunkLengthChars;\n\t\tlet segments: number = chunk1.chunkSegmentCount;\n\t\tconst builder = new SummaryTreeBuilder();\n\t\tbuilder.addBlob(\n\t\t\tSnapshotLegacy.header,\n\t\t\tserializeAsMinSupportedVersion(\n\t\t\t\tSnapshotLegacy.header,\n\t\t\t\tchunk1,\n\t\t\t\tthis.logger,\n\t\t\t\tthis.mergeTree.options,\n\t\t\t\tserializer,\n\t\t\t\tbind,\n\t\t\t),\n\t\t);\n\n\t\tif (chunk1.chunkSegmentCount < chunk1.totalSegmentCount!) {\n\t\t\tconst chunk2 = this.getSeqLengthSegs(\n\t\t\t\tthis.segments!,\n\t\t\t\tthis.header!.segmentsTotalLength,\n\t\t\t\tchunk1.chunkSegmentCount,\n\t\t\t);\n\t\t\tlength += chunk2.chunkLengthChars;\n\t\t\tsegments += chunk2.chunkSegmentCount;\n\t\t\tbuilder.addBlob(\n\t\t\t\tSnapshotLegacy.body,\n\t\t\t\tserializeAsMinSupportedVersion(\n\t\t\t\t\tSnapshotLegacy.body,\n\t\t\t\t\tchunk2,\n\t\t\t\t\tthis.logger,\n\t\t\t\t\tthis.mergeTree.options,\n\t\t\t\t\tserializer,\n\t\t\t\t\tbind,\n\t\t\t\t),\n\t\t\t);\n\t\t}\n\n\t\tassert(\n\t\t\tlength === this.header!.segmentsTotalLength,\n\t\t\t0x05d /* \"emit: mismatch in segmentsTotalLength\" */,\n\t\t);\n\n\t\tassert(\n\t\t\tsegments === chunk1.totalSegmentCount,\n\t\t\t0x05e /* \"emit: mismatch in totalSegmentCount\" */,\n\t\t);\n\n\t\tif (catchUpMsgs !== undefined && catchUpMsgs.length > 0) {\n\t\t\tbuilder.addBlob(\n\t\t\t\tthis.mergeTree.options?.catchUpBlobName ?? SnapshotLegacy.catchupOps,\n\t\t\t\tserializer ? serializer.stringify(catchUpMsgs, bind) : JSON.stringify(catchUpMsgs),\n\t\t\t);\n\t\t}\n\n\t\treturn builder.getSummaryTree();\n\t}\n\n\textractSync() {\n\t\tconst collabWindow = this.mergeTree.collabWindow;\n\t\tthis.seq = collabWindow.minSeq;\n\t\tthis.header = {\n\t\t\tsegmentsTotalLength: this.mergeTree.getLength(\n\t\t\t\tthis.mergeTree.collabWindow.minSeq,\n\t\t\t\tNonCollabClient,\n\t\t\t),\n\t\t\tseq: this.mergeTree.collabWindow.minSeq,\n\t\t};\n\n\t\tconst segs: ISegment[] = [];\n\t\tlet prev: ISegment | undefined;\n\t\tconst extractSegment = (\n\t\t\tsegment: ISegment,\n\t\t\tpos: number,\n\t\t\trefSeq: number,\n\t\t\tclientId: number,\n\t\t\tstart: number | undefined,\n\t\t\tend: number | undefined,\n\t\t) => {\n\t\t\tif (\n\t\t\t\tsegment.seq !== UnassignedSequenceNumber &&\n\t\t\t\tsegment.seq! <= this.seq! &&\n\t\t\t\t(segment.removedSeq === undefined ||\n\t\t\t\t\tsegment.removedSeq === UnassignedSequenceNumber ||\n\t\t\t\t\tsegment.removedSeq > this.seq!)\n\t\t\t) {\n\t\t\t\tif (\n\t\t\t\t\tprev?.canAppend(segment) &&\n\t\t\t\t\tmatchProperties(prev.properties, segment.properties)\n\t\t\t\t) {\n\t\t\t\t\tprev = prev.clone();\n\t\t\t\t\tprev.append(segment.clone());\n\t\t\t\t} else {\n\t\t\t\t\tif (prev) {\n\t\t\t\t\t\tsegs.push(prev);\n\t\t\t\t\t}\n\t\t\t\t\tprev = segment;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn true;\n\t\t};\n\n\t\tthis.mergeTree.mapRange(extractSegment, this.seq, NonCollabClient, undefined);\n\t\tif (prev) {\n\t\t\tsegs.push(prev);\n\t\t}\n\n\t\tthis.segments = [];\n\t\tlet totalLength: number = 0;\n\t\tsegs.map((segment) => {\n\t\t\ttotalLength += segment.cachedLength;\n\t\t\tif (segment.properties !== undefined && Object.keys(segment.properties).length === 0) {\n\t\t\t\tsegment.properties = undefined;\n\t\t\t\tsegment.propertyManager = undefined;\n\t\t\t}\n\t\t\tthis.segments!.push(segment);\n\t\t});\n\n\t\t// We observed this.header.segmentsTotalLength < totalLength to happen in some cases\n\t\t// When this condition happens, we might not write out all segments in getSeqLengthSegs()\n\t\t// when writing out \"body\". Issue #1995 tracks following up on the core of the problem.\n\t\t// In the meantime, this code makes sure we will write out all segments properly\n\n\t\tif (this.header.segmentsTotalLength !== totalLength) {\n\t\t\tthis.logger.sendErrorEvent({\n\t\t\t\teventName: \"SegmentsTotalLengthMismatch\",\n\t\t\t\ttotalLength,\n\t\t\t\tsegmentsTotalLength: this.header.segmentsTotalLength,\n\t\t\t});\n\t\t\tthis.header.segmentsTotalLength = totalLength;\n\t\t}\n\n\t\treturn this.segments;\n\t}\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fluidframework/merge-tree",
3
- "version": "2.0.0-internal.3.2.2",
3
+ "version": "2.0.0-internal.3.3.0",
4
4
  "description": "Merge tree",
5
5
  "homepage": "https://fluidframework.com",
6
6
  "repository": {
@@ -37,27 +37,27 @@
37
37
  "dependencies": {
38
38
  "@fluidframework/common-definitions": "^0.20.1",
39
39
  "@fluidframework/common-utils": "^1.1.1",
40
- "@fluidframework/container-definitions": ">=2.0.0-internal.3.2.2 <2.0.0-internal.4.0.0",
41
- "@fluidframework/container-utils": ">=2.0.0-internal.3.2.2 <2.0.0-internal.4.0.0",
42
- "@fluidframework/core-interfaces": ">=2.0.0-internal.3.2.2 <2.0.0-internal.4.0.0",
43
- "@fluidframework/datastore-definitions": ">=2.0.0-internal.3.2.2 <2.0.0-internal.4.0.0",
40
+ "@fluidframework/container-definitions": ">=2.0.0-internal.3.3.0 <2.0.0-internal.4.0.0",
41
+ "@fluidframework/container-utils": ">=2.0.0-internal.3.3.0 <2.0.0-internal.4.0.0",
42
+ "@fluidframework/core-interfaces": ">=2.0.0-internal.3.3.0 <2.0.0-internal.4.0.0",
43
+ "@fluidframework/datastore-definitions": ">=2.0.0-internal.3.3.0 <2.0.0-internal.4.0.0",
44
44
  "@fluidframework/protocol-definitions": "^1.1.0",
45
- "@fluidframework/runtime-definitions": ">=2.0.0-internal.3.2.2 <2.0.0-internal.4.0.0",
46
- "@fluidframework/runtime-utils": ">=2.0.0-internal.3.2.2 <2.0.0-internal.4.0.0",
47
- "@fluidframework/shared-object-base": ">=2.0.0-internal.3.2.2 <2.0.0-internal.4.0.0",
48
- "@fluidframework/telemetry-utils": ">=2.0.0-internal.3.2.2 <2.0.0-internal.4.0.0"
45
+ "@fluidframework/runtime-definitions": ">=2.0.0-internal.3.3.0 <2.0.0-internal.4.0.0",
46
+ "@fluidframework/runtime-utils": ">=2.0.0-internal.3.3.0 <2.0.0-internal.4.0.0",
47
+ "@fluidframework/shared-object-base": ">=2.0.0-internal.3.3.0 <2.0.0-internal.4.0.0",
48
+ "@fluidframework/telemetry-utils": ">=2.0.0-internal.3.3.0 <2.0.0-internal.4.0.0"
49
49
  },
50
50
  "devDependencies": {
51
- "@fluid-internal/stochastic-test-utils": ">=2.0.0-internal.3.2.2 <2.0.0-internal.4.0.0",
52
- "@fluid-tools/benchmark": "^0.45.0",
53
- "@fluid-tools/build-cli": "^0.10.0",
51
+ "@fluid-internal/stochastic-test-utils": ">=2.0.0-internal.3.3.0 <2.0.0-internal.4.0.0",
52
+ "@fluid-tools/benchmark": "^0.46.0",
53
+ "@fluid-tools/build-cli": "^0.12.0",
54
54
  "@fluidframework/build-common": "^1.1.0",
55
- "@fluidframework/build-tools": "^0.10.0",
55
+ "@fluidframework/build-tools": "^0.12.0",
56
56
  "@fluidframework/eslint-config-fluid": "^2.0.0",
57
- "@fluidframework/merge-tree-previous": "npm:@fluidframework/merge-tree@2.0.0-internal.3.1.0",
58
- "@fluidframework/mocha-test-setup": ">=2.0.0-internal.3.2.2 <2.0.0-internal.4.0.0",
59
- "@fluidframework/test-pairwise-generator": ">=2.0.0-internal.3.2.2 <2.0.0-internal.4.0.0",
60
- "@fluidframework/test-runtime-utils": ">=2.0.0-internal.3.2.2 <2.0.0-internal.4.0.0",
57
+ "@fluidframework/merge-tree-previous": "npm:@fluidframework/merge-tree@2.0.0-internal.3.2.0",
58
+ "@fluidframework/mocha-test-setup": ">=2.0.0-internal.3.3.0 <2.0.0-internal.4.0.0",
59
+ "@fluidframework/test-pairwise-generator": ">=2.0.0-internal.3.3.0 <2.0.0-internal.4.0.0",
60
+ "@fluidframework/test-runtime-utils": ">=2.0.0-internal.3.3.0 <2.0.0-internal.4.0.0",
61
61
  "@microsoft/api-extractor": "^7.22.2",
62
62
  "@rushstack/eslint-config": "^2.5.1",
63
63
  "@types/diff": "^3.5.1",
@@ -78,11 +78,11 @@
78
78
  "typescript": "~4.5.5"
79
79
  },
80
80
  "typeValidation": {
81
- "version": "2.0.0-internal.3.2.0",
82
- "previousVersionStyle": "~previousMinor",
83
- "baselineRange": ">=2.0.0-internal.3.1.0 <2.0.0-internal.3.2.0",
84
- "baselineVersion": "2.0.0-internal.3.1.0",
85
- "broken": {}
81
+ "broken": {
82
+ "InterfaceDeclaration_SerializedAttributionCollection": {
83
+ "backCompat": false
84
+ }
85
+ }
86
86
  },
87
87
  "scripts": {
88
88
  "build": "concurrently npm:build:compile npm:lint && npm run build:docs",
@@ -105,12 +105,13 @@
105
105
  "prettier": "prettier --check . --ignore-path ../../../.prettierignore",
106
106
  "prettier:fix": "prettier --write . --ignore-path ../../../.prettierignore",
107
107
  "test": "npm run test:mocha",
108
+ "test:benchmark:report": "mocha \"dist/test/*.perf.spec.js\" --node-option unhandled-rejections=strict,expose-gc --exit --perfMode --fgrep @Benchmark -r @fluidframework/mocha-test-setup --reporter @fluid-tools/benchmark/dist/MochaReporter.js --timeout 60000",
108
109
  "test:coverage": "nyc npm test -- --reporter xunit --reporter-option output=nyc/junit-report.xml",
109
110
  "test:mocha": "mocha --ignore 'dist/test/types/*' --recursive dist/test --exit -r node_modules/@fluidframework/mocha-test-setup -r source-map-support/register --unhandled-rejections=strict",
110
111
  "test:mocha:verbose": "cross-env FLUID_TEST_VERBOSE=1 npm run test:mocha",
111
112
  "test:stress": "cross-env FUZZ_STRESS_RUN=1 FUZZ_TEST_COUNT=1 npm run test:mocha",
112
113
  "tsc": "tsc",
113
- "typetests:gen": "flub generate typetests --generate --dir .",
114
+ "typetests:gen": "fluid-type-test-generator",
114
115
  "typetests:prepare": "flub generate typetests --prepare --dir . --pin"
115
116
  }
116
117
  }
@@ -105,6 +105,8 @@ export function areEqualAttributionKeys(a: AttributionKey, b: AttributionKey): b
105
105
  return a.seq === (b as OpAttributionKey).seq;
106
106
  case "detached":
107
107
  return a.id === (b as DetachedAttributionKey).id;
108
+ case "local":
109
+ return true;
108
110
  default:
109
111
  unreachableCase(a, "Unhandled AttributionKey type");
110
112
  }
package/src/properties.ts CHANGED
@@ -69,34 +69,25 @@ export function combine(
69
69
  }
70
70
 
71
71
  export function matchProperties(a: PropertySet | undefined, b: PropertySet | undefined) {
72
- if (a) {
73
- if (!b) {
74
- return false;
75
- } else {
76
- // For now, straightforward; later use hashing
77
-
78
- // eslint-disable-next-line no-restricted-syntax
79
- for (const key in a) {
80
- if (b[key] === undefined) {
81
- return false;
82
- } else if (typeof b[key] === "object") {
83
- if (!matchProperties(a[key], b[key])) {
84
- return false;
85
- }
86
- } else if (b[key] !== a[key]) {
87
- return false;
88
- }
89
- }
72
+ if (!a && !b) {
73
+ return true;
74
+ }
90
75
 
91
- // eslint-disable-next-line no-restricted-syntax
92
- for (const key in b) {
93
- if (a[key] === undefined) {
94
- return false;
95
- }
76
+ const keysA = a ? Object.keys(a) : [];
77
+ const keysB = b ? Object.keys(b) : [];
78
+
79
+ if (keysA.length !== keysB.length) {
80
+ return false;
81
+ }
82
+
83
+ for (const key of keysA) {
84
+ if (b?.[key] === undefined) {
85
+ return false;
86
+ } else if (typeof b[key] === "object") {
87
+ if (!matchProperties(a?.[key], b[key])) {
88
+ return false;
96
89
  }
97
- }
98
- } else {
99
- if (b) {
90
+ } else if (b[key] !== a?.[key]) {
100
91
  return false;
101
92
  }
102
93
  }
package/src/snapshotV1.ts CHANGED
@@ -197,6 +197,13 @@ export class SnapshotV1 {
197
197
  // Helper to serialize the given `segment` and add it to the snapshot (if a segment is provided).
198
198
  const pushSeg = (segment?: ISegment) => {
199
199
  if (segment) {
200
+ if (
201
+ segment.properties !== undefined &&
202
+ Object.keys(segment.properties).length === 0
203
+ ) {
204
+ segment.properties = undefined;
205
+ segment.propertyManager = undefined;
206
+ }
200
207
  pushSegRaw(segment.toJSONObject(), segment.cachedLength, segment.attribution);
201
208
  }
202
209
  };
@@ -248,6 +255,13 @@ export class SnapshotV1 {
248
255
  pushSeg(prev);
249
256
  prev = undefined;
250
257
 
258
+ if (
259
+ segment.properties !== undefined &&
260
+ Object.keys(segment.properties).length === 0
261
+ ) {
262
+ segment.properties = undefined;
263
+ segment.propertyManager = undefined;
264
+ }
251
265
  const raw: IJSONSegmentWithMergeInfo = { json: segment.toJSONObject() };
252
266
  // If the segment insertion is above the MSN, record the insertion merge info.
253
267
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
@@ -234,6 +234,10 @@ export class SnapshotLegacy {
234
234
  let totalLength: number = 0;
235
235
  segs.map((segment) => {
236
236
  totalLength += segment.cachedLength;
237
+ if (segment.properties !== undefined && Object.keys(segment.properties).length === 0) {
238
+ segment.properties = undefined;
239
+ segment.propertyManager = undefined;
240
+ }
237
241
  this.segments!.push(segment);
238
242
  });
239
243