@atlaskit/react-ufo 3.14.6 → 3.14.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/cjs/vc/index.js +39 -6
  3. package/dist/cjs/vc/vc-observer/index.js +10 -2
  4. package/dist/cjs/vc/vc-observer/observers/index.js +12 -7
  5. package/dist/cjs/vc/vc-observer/observers/ssr-placeholders/index.js +76 -40
  6. package/dist/cjs/vc/vc-observer-new/index.js +84 -0
  7. package/dist/cjs/vc/vc-observer-new/viewport-observer/index.js +214 -71
  8. package/dist/cjs/vc/vc-observer-new/viewport-observer/mutation-observer/index.js +97 -59
  9. package/dist/es2019/vc/index.js +37 -5
  10. package/dist/es2019/vc/vc-observer/index.js +8 -2
  11. package/dist/es2019/vc/vc-observer/observers/index.js +11 -5
  12. package/dist/es2019/vc/vc-observer/observers/ssr-placeholders/index.js +57 -26
  13. package/dist/es2019/vc/vc-observer-new/index.js +67 -1
  14. package/dist/es2019/vc/vc-observer-new/viewport-observer/index.js +87 -22
  15. package/dist/es2019/vc/vc-observer-new/viewport-observer/mutation-observer/index.js +50 -34
  16. package/dist/esm/vc/index.js +39 -6
  17. package/dist/esm/vc/vc-observer/index.js +10 -2
  18. package/dist/esm/vc/vc-observer/observers/index.js +12 -7
  19. package/dist/esm/vc/vc-observer/observers/ssr-placeholders/index.js +76 -40
  20. package/dist/esm/vc/vc-observer-new/index.js +84 -0
  21. package/dist/esm/vc/vc-observer-new/viewport-observer/index.js +214 -71
  22. package/dist/esm/vc/vc-observer-new/viewport-observer/mutation-observer/index.js +97 -59
  23. package/dist/types/vc/index.d.ts +2 -0
  24. package/dist/types/vc/types.d.ts +2 -0
  25. package/dist/types/vc/vc-observer/index.d.ts +1 -0
  26. package/dist/types/vc/vc-observer/observers/index.d.ts +2 -0
  27. package/dist/types/vc/vc-observer/observers/ssr-placeholders/index.d.ts +6 -0
  28. package/dist/types/vc/vc-observer-new/index.d.ts +30 -0
  29. package/dist/types/vc/vc-observer-new/types.d.ts +1 -1
  30. package/dist/types/vc/vc-observer-new/viewport-observer/index.d.ts +5 -1
  31. package/dist/types/vc/vc-observer-new/viewport-observer/mutation-observer/index.d.ts +2 -0
  32. package/dist/types-ts4.5/vc/index.d.ts +2 -0
  33. package/dist/types-ts4.5/vc/types.d.ts +2 -0
  34. package/dist/types-ts4.5/vc/vc-observer/index.d.ts +1 -0
  35. package/dist/types-ts4.5/vc/vc-observer/observers/index.d.ts +2 -0
  36. package/dist/types-ts4.5/vc/vc-observer/observers/ssr-placeholders/index.d.ts +6 -0
  37. package/dist/types-ts4.5/vc/vc-observer-new/index.d.ts +30 -0
  38. package/dist/types-ts4.5/vc/vc-observer-new/types.d.ts +1 -1
  39. package/dist/types-ts4.5/vc/vc-observer-new/viewport-observer/index.d.ts +5 -1
  40. package/dist/types-ts4.5/vc/vc-observer-new/viewport-observer/mutation-observer/index.d.ts +2 -0
  41. package/package.json +5 -3
@@ -5,6 +5,8 @@ Object.defineProperty(exports, "__esModule", {
5
5
  value: true
6
6
  });
7
7
  exports.default = void 0;
8
+ var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator"));
9
+ var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator"));
8
10
  var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck"));
9
11
  var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass"));
10
12
  var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
@@ -26,7 +28,7 @@ function isElementVisible(element) {
26
28
  }
27
29
  try {
28
30
  var visible = element.checkVisibility({
29
- // @ts-expect-error
31
+ // @ts-ignore - visibilityProperty may not exist in all TS environments
30
32
  visibilityProperty: true,
31
33
  contentVisibilityAuto: true,
32
34
  opacityProperty: true
@@ -74,9 +76,13 @@ var createElementMutationsWatcher = function createElementMutationsWatcher(remov
74
76
  };
75
77
  };
76
78
  var ViewportObserver = exports.default = /*#__PURE__*/function () {
79
+ // SSR context functions
80
+
77
81
  function ViewportObserver(_ref2) {
78
82
  var _this = this;
79
- var onChange = _ref2.onChange;
83
+ var onChange = _ref2.onChange,
84
+ getSSRState = _ref2.getSSRState,
85
+ getSSRPlaceholderHandler = _ref2.getSSRPlaceholderHandler;
80
86
  (0, _classCallCheck2.default)(this, ViewportObserver);
81
87
  (0, _defineProperty2.default)(this, "handleIntersectionEntry", function (_ref3) {
82
88
  var target = _ref3.target,
@@ -100,65 +106,198 @@ var ViewportObserver = exports.default = /*#__PURE__*/function () {
100
106
  mutationData: mutationData
101
107
  });
102
108
  });
103
- (0, _defineProperty2.default)(this, "handleChildListMutation", function (_ref4) {
104
- var addedNodes = _ref4.addedNodes,
105
- removedNodes = _ref4.removedNodes;
106
- var removedNodeRects = removedNodes.map(function (ref) {
107
- var n = ref.deref();
108
- if (!n) {
109
- return;
110
- }
111
- return _this.mapVisibleNodeRects.get(n);
112
- });
113
- addedNodes.forEach(function (addedNodeRef) {
114
- var _this$intersectionObs4;
115
- var addedNode = addedNodeRef.deref();
116
- if (!addedNode) {
117
- return;
118
- }
119
- var sameDeletedNode = removedNodes.find(function (ref) {
120
- var n = ref.deref();
121
- if (!n || !addedNode) {
122
- return false;
109
+ (0, _defineProperty2.default)(this, "handleChildListMutation", /*#__PURE__*/function () {
110
+ var _ref5 = (0, _asyncToGenerator2.default)( /*#__PURE__*/_regenerator.default.mark(function _callee(_ref4) {
111
+ var target, addedNodes, removedNodes, timestamp, removedNodeRects, targetNode, _iterator, _step, _loop, _ret;
112
+ return _regenerator.default.wrap(function _callee$(_context2) {
113
+ while (1) switch (_context2.prev = _context2.next) {
114
+ case 0:
115
+ target = _ref4.target, addedNodes = _ref4.addedNodes, removedNodes = _ref4.removedNodes, timestamp = _ref4.timestamp;
116
+ removedNodeRects = removedNodes.map(function (ref) {
117
+ var n = ref.deref();
118
+ if (!n) {
119
+ return;
120
+ }
121
+ return _this.mapVisibleNodeRects.get(n);
122
+ });
123
+ targetNode = target.deref();
124
+ _iterator = _createForOfIteratorHelper(addedNodes);
125
+ _context2.prev = 4;
126
+ _loop = /*#__PURE__*/_regenerator.default.mark(function _loop() {
127
+ var _this$intersectionObs8;
128
+ var addedNodeRef, addedNode, ssrState, SSRStateEnum, _this$intersectionObs, _this$intersectionObs2, ssrPlaceholderHandler, result, _this$intersectionObs3, _result, _this$intersectionObs4, sameDeletedNode, isInIgnoreLsMarker, isNoLsMarkerEnabled, _this$intersectionObs5, _this$intersectionObs6, _checkThirdPartySegme, isWithinThirdPartySegment, ignoredReason, _this$intersectionObs7, assignedReason;
129
+ return _regenerator.default.wrap(function _loop$(_context) {
130
+ while (1) switch (_context.prev = _context.next) {
131
+ case 0:
132
+ addedNodeRef = _step.value;
133
+ addedNode = addedNodeRef.deref();
134
+ if (addedNode) {
135
+ _context.next = 4;
136
+ break;
137
+ }
138
+ return _context.abrupt("return", 0);
139
+ case 4:
140
+ if (!(_this.getSSRState && (0, _platformFeatureFlags.fg)('platform_ufo_vc_v3_ssr_placeholder'))) {
141
+ _context.next = 19;
142
+ break;
143
+ }
144
+ ssrState = _this.getSSRState();
145
+ SSRStateEnum = {
146
+ normal: 1,
147
+ waitingForFirstRender: 2,
148
+ ignoring: 3
149
+ };
150
+ if (!(ssrState.state === SSRStateEnum.waitingForFirstRender && timestamp > ssrState.renderStart && targetNode === ssrState.reactRootElement)) {
151
+ _context.next = 12;
152
+ break;
153
+ }
154
+ ssrState.state = SSRStateEnum.ignoring;
155
+ if (ssrState.renderStop === -1) {
156
+ // arbitrary 500ms DOM update window
157
+ ssrState.renderStop = timestamp + 500;
158
+ }
159
+ (_this$intersectionObs = _this.intersectionObserver) === null || _this$intersectionObs === void 0 || _this$intersectionObs.watchAndTag(addedNode, 'ssr-hydration');
160
+ return _context.abrupt("return", 0);
161
+ case 12:
162
+ if (!(ssrState.state === SSRStateEnum.ignoring && timestamp > ssrState.renderStart && targetNode === ssrState.reactRootElement)) {
163
+ _context.next = 19;
164
+ break;
165
+ }
166
+ if (!(timestamp <= ssrState.renderStop)) {
167
+ _context.next = 18;
168
+ break;
169
+ }
170
+ (_this$intersectionObs2 = _this.intersectionObserver) === null || _this$intersectionObs2 === void 0 || _this$intersectionObs2.watchAndTag(addedNode, 'ssr-hydration');
171
+ return _context.abrupt("return", 0);
172
+ case 18:
173
+ ssrState.state = SSRStateEnum.normal;
174
+ case 19:
175
+ if (!(_this.getSSRPlaceholderHandler && (0, _platformFeatureFlags.fg)('platform_ufo_vc_v3_ssr_placeholder'))) {
176
+ _context.next = 36;
177
+ break;
178
+ }
179
+ ssrPlaceholderHandler = _this.getSSRPlaceholderHandler();
180
+ if (!ssrPlaceholderHandler) {
181
+ _context.next = 36;
182
+ break;
183
+ }
184
+ if (!(ssrPlaceholderHandler.isPlaceholder(addedNode) || ssrPlaceholderHandler.isPlaceholderIgnored(addedNode))) {
185
+ _context.next = 29;
186
+ break;
187
+ }
188
+ _context.next = 25;
189
+ return ssrPlaceholderHandler.checkIfExistedAndSizeMatching(addedNode);
190
+ case 25:
191
+ result = _context.sent;
192
+ if (!(result !== false)) {
193
+ _context.next = 29;
194
+ break;
195
+ }
196
+ (_this$intersectionObs3 = _this.intersectionObserver) === null || _this$intersectionObs3 === void 0 || _this$intersectionObs3.watchAndTag(addedNode, 'mutation:ssr-placeholder');
197
+ return _context.abrupt("return", 0);
198
+ case 29:
199
+ if (!(ssrPlaceholderHandler.isPlaceholderReplacement(addedNode) || ssrPlaceholderHandler.isPlaceholderIgnored(addedNode))) {
200
+ _context.next = 36;
201
+ break;
202
+ }
203
+ _context.next = 32;
204
+ return ssrPlaceholderHandler.validateReactComponentMatchToPlaceholder(addedNode);
205
+ case 32:
206
+ _result = _context.sent;
207
+ if (!(_result !== false)) {
208
+ _context.next = 36;
209
+ break;
210
+ }
211
+ (_this$intersectionObs4 = _this.intersectionObserver) === null || _this$intersectionObs4 === void 0 || _this$intersectionObs4.watchAndTag(addedNode, 'mutation:ssr-placeholder');
212
+ return _context.abrupt("return", 0);
213
+ case 36:
214
+ sameDeletedNode = removedNodes.find(function (ref) {
215
+ var n = ref.deref();
216
+ if (!n || !addedNode) {
217
+ return false;
218
+ }
219
+ return n.isEqualNode(addedNode);
220
+ });
221
+ isInIgnoreLsMarker = (0, _isInVcIgnoreIfNoLayoutShiftMarker.default)(addedNode);
222
+ isNoLsMarkerEnabled = (0, _platformFeatureFlags.fg)('platform_vc_ignore_no_ls_mutation_marker'); // When fg('platform_vc_ignore_no_ls_mutation_marker') is not enabled,
223
+ // no layout shift mutation is excluded as per existing fy25.03 logic
224
+ if (!(sameDeletedNode && (!isNoLsMarkerEnabled || isInIgnoreLsMarker))) {
225
+ _context.next = 42;
226
+ break;
227
+ }
228
+ (_this$intersectionObs5 = _this.intersectionObserver) === null || _this$intersectionObs5 === void 0 || _this$intersectionObs5.watchAndTag(addedNode, 'mutation:remount');
229
+ return _context.abrupt("return", 0);
230
+ case 42:
231
+ if (!(0, _vcUtils.isContainedWithinMediaWrapper)(addedNode)) {
232
+ _context.next = 45;
233
+ break;
234
+ }
235
+ (_this$intersectionObs6 = _this.intersectionObserver) === null || _this$intersectionObs6 === void 0 || _this$intersectionObs6.watchAndTag(addedNode, 'mutation:media');
236
+ return _context.abrupt("return", 0);
237
+ case 45:
238
+ _checkThirdPartySegme = (0, _getComponentNameAndChildProps.checkThirdPartySegmentWithIgnoreReason)(addedNode), isWithinThirdPartySegment = _checkThirdPartySegme.isWithinThirdPartySegment, ignoredReason = _checkThirdPartySegme.ignoredReason;
239
+ if (!isWithinThirdPartySegment) {
240
+ _context.next = 50;
241
+ break;
242
+ }
243
+ assignedReason = (0, _getComponentNameAndChildProps.createMutationTypeWithIgnoredReason)(ignoredReason || 'third-party-element');
244
+ (_this$intersectionObs7 = _this.intersectionObserver) === null || _this$intersectionObs7 === void 0 || _this$intersectionObs7.watchAndTag(addedNode, assignedReason);
245
+ return _context.abrupt("return", 0);
246
+ case 50:
247
+ (_this$intersectionObs8 = _this.intersectionObserver) === null || _this$intersectionObs8 === void 0 || _this$intersectionObs8.watchAndTag(addedNode, createElementMutationsWatcher(removedNodeRects));
248
+ case 51:
249
+ case "end":
250
+ return _context.stop();
251
+ }
252
+ }, _loop);
253
+ });
254
+ _iterator.s();
255
+ case 7:
256
+ if ((_step = _iterator.n()).done) {
257
+ _context2.next = 14;
258
+ break;
259
+ }
260
+ return _context2.delegateYield(_loop(), "t0", 9);
261
+ case 9:
262
+ _ret = _context2.t0;
263
+ if (!(_ret === 0)) {
264
+ _context2.next = 12;
265
+ break;
266
+ }
267
+ return _context2.abrupt("continue", 12);
268
+ case 12:
269
+ _context2.next = 7;
270
+ break;
271
+ case 14:
272
+ _context2.next = 19;
273
+ break;
274
+ case 16:
275
+ _context2.prev = 16;
276
+ _context2.t1 = _context2["catch"](4);
277
+ _iterator.e(_context2.t1);
278
+ case 19:
279
+ _context2.prev = 19;
280
+ _iterator.f();
281
+ return _context2.finish(19);
282
+ case 22:
283
+ case "end":
284
+ return _context2.stop();
123
285
  }
124
- return n.isEqualNode(addedNode);
125
- });
126
- var isInIgnoreLsMarker = (0, _isInVcIgnoreIfNoLayoutShiftMarker.default)(addedNode);
127
- var isNoLsMarkerEnabled = (0, _platformFeatureFlags.fg)('platform_vc_ignore_no_ls_mutation_marker');
128
-
129
- // When fg('platform_vc_ignore_no_ls_mutation_marker') is not enabled,
130
- // no layout shift mutation is excluded as per existing fy25.03 logic
131
- if (sameDeletedNode && (!isNoLsMarkerEnabled || isInIgnoreLsMarker)) {
132
- var _this$intersectionObs;
133
- (_this$intersectionObs = _this.intersectionObserver) === null || _this$intersectionObs === void 0 || _this$intersectionObs.watchAndTag(addedNode, 'mutation:remount');
134
- return;
135
- }
136
- if ((0, _vcUtils.isContainedWithinMediaWrapper)(addedNode)) {
137
- var _this$intersectionObs2;
138
- (_this$intersectionObs2 = _this.intersectionObserver) === null || _this$intersectionObs2 === void 0 || _this$intersectionObs2.watchAndTag(addedNode, 'mutation:media');
139
- return;
140
- }
141
- var _checkThirdPartySegme = (0, _getComponentNameAndChildProps.checkThirdPartySegmentWithIgnoreReason)(addedNode),
142
- isWithinThirdPartySegment = _checkThirdPartySegme.isWithinThirdPartySegment,
143
- ignoredReason = _checkThirdPartySegme.ignoredReason;
144
- if (isWithinThirdPartySegment) {
145
- var _this$intersectionObs3;
146
- var assignedReason = (0, _getComponentNameAndChildProps.createMutationTypeWithIgnoredReason)(ignoredReason || 'third-party-element');
147
- (_this$intersectionObs3 = _this.intersectionObserver) === null || _this$intersectionObs3 === void 0 || _this$intersectionObs3.watchAndTag(addedNode, assignedReason);
148
- return;
149
- }
150
- (_this$intersectionObs4 = _this.intersectionObserver) === null || _this$intersectionObs4 === void 0 || _this$intersectionObs4.watchAndTag(addedNode, createElementMutationsWatcher(removedNodeRects));
151
- });
152
- });
153
- (0, _defineProperty2.default)(this, "handleAttributeMutation", function (_ref5) {
154
- var _this$intersectionObs5;
155
- var target = _ref5.target,
156
- attributeName = _ref5.attributeName,
157
- oldValue = _ref5.oldValue,
158
- newValue = _ref5.newValue;
159
- (_this$intersectionObs5 = _this.intersectionObserver) === null || _this$intersectionObs5 === void 0 || _this$intersectionObs5.watchAndTag(target, function (_ref6) {
160
- var target = _ref6.target,
161
- rect = _ref6.rect;
286
+ }, _callee, null, [[4, 16, 19, 22]]);
287
+ }));
288
+ return function (_x) {
289
+ return _ref5.apply(this, arguments);
290
+ };
291
+ }());
292
+ (0, _defineProperty2.default)(this, "handleAttributeMutation", function (_ref6) {
293
+ var _this$intersectionObs9;
294
+ var target = _ref6.target,
295
+ attributeName = _ref6.attributeName,
296
+ oldValue = _ref6.oldValue,
297
+ newValue = _ref6.newValue;
298
+ (_this$intersectionObs9 = _this.intersectionObserver) === null || _this$intersectionObs9 === void 0 || _this$intersectionObs9.watchAndTag(target, function (_ref7) {
299
+ var target = _ref7.target,
300
+ rect = _ref7.rect;
162
301
  if ((0, _vcUtils.isContainedWithinMediaWrapper)(target)) {
163
302
  return {
164
303
  type: 'mutation:media',
@@ -229,14 +368,14 @@ var ViewportObserver = exports.default = /*#__PURE__*/function () {
229
368
  };
230
369
  });
231
370
  });
232
- (0, _defineProperty2.default)(this, "handleLayoutShift", function (_ref7) {
233
- var time = _ref7.time,
234
- changedRects = _ref7.changedRects;
235
- var _iterator = _createForOfIteratorHelper(changedRects),
236
- _step;
371
+ (0, _defineProperty2.default)(this, "handleLayoutShift", function (_ref8) {
372
+ var time = _ref8.time,
373
+ changedRects = _ref8.changedRects;
374
+ var _iterator2 = _createForOfIteratorHelper(changedRects),
375
+ _step2;
237
376
  try {
238
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
239
- var changedRect = _step.value;
377
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
378
+ var changedRect = _step2.value;
240
379
  var target = changedRect.node;
241
380
  if (target) {
242
381
  _this.onChange({
@@ -250,9 +389,9 @@ var ViewportObserver = exports.default = /*#__PURE__*/function () {
250
389
  }
251
390
  }
252
391
  } catch (err) {
253
- _iterator.e(err);
392
+ _iterator2.e(err);
254
393
  } finally {
255
- _iterator.f();
394
+ _iterator2.f();
256
395
  }
257
396
  });
258
397
  this.mapVisibleNodeRects = new WeakMap();
@@ -261,6 +400,10 @@ var ViewportObserver = exports.default = /*#__PURE__*/function () {
261
400
  this.intersectionObserver = null;
262
401
  this.mutationObserver = null;
263
402
  this.performanceObserver = null;
403
+
404
+ // Initialize SSR context functions
405
+ this.getSSRState = getSSRState;
406
+ this.getSSRPlaceholderHandler = getSSRPlaceholderHandler;
264
407
  }
265
408
  return (0, _createClass2.default)(ViewportObserver, [{
266
409
  key: "initializeObservers",
@@ -304,12 +447,12 @@ var ViewportObserver = exports.default = /*#__PURE__*/function () {
304
447
  }, {
305
448
  key: "stop",
306
449
  value: function stop() {
307
- var _this$mutationObserve2, _this$intersectionObs6, _this$performanceObse2;
450
+ var _this$mutationObserve2, _this$intersectionObs0, _this$performanceObse2;
308
451
  if (!this.isStarted) {
309
452
  return;
310
453
  }
311
454
  (_this$mutationObserve2 = this.mutationObserver) === null || _this$mutationObserve2 === void 0 || _this$mutationObserve2.disconnect();
312
- (_this$intersectionObs6 = this.intersectionObserver) === null || _this$intersectionObs6 === void 0 || _this$intersectionObs6.disconnect();
455
+ (_this$intersectionObs0 = this.intersectionObserver) === null || _this$intersectionObs0 === void 0 || _this$intersectionObs0.disconnect();
313
456
  (_this$performanceObse2 = this.performanceObserver) === null || _this$performanceObse2 === void 0 || _this$performanceObse2.disconnect();
314
457
  this.isStarted = false;
315
458
  }
@@ -4,10 +4,11 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- var _platformFeatureFlags = require("@atlaskit/platform-feature-flags");
8
7
  function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
9
8
  function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
10
9
  function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
10
+ // Batched mutation data for performance optimization
11
+
11
12
  function createMutationObserver(_ref) {
12
13
  var onAttributeMutation = _ref.onAttributeMutation,
13
14
  onChildListMutation = _ref.onChildListMutation,
@@ -16,82 +17,119 @@ function createMutationObserver(_ref) {
16
17
  return null;
17
18
  }
18
19
  var mutationObserverCallback = function mutationObserverCallback(mutations) {
19
- var addedNodes = [];
20
- var removedNodes = [];
21
- var attributeMutations = [];
22
20
  var targets = [];
21
+ // Use nested Maps for O(1) batching performance
22
+ // Short-lived Maps are safe since they're discarded after each callback
23
+ var batchedMutations = new Map();
23
24
  var _iterator = _createForOfIteratorHelper(mutations),
24
25
  _step;
25
26
  try {
26
- for (_iterator.s(); !(_step = _iterator.n()).done;) {
27
- var _mut = _step.value;
28
- if (!(_mut.target instanceof HTMLElement)) {
29
- continue;
30
- }
31
- if (_mut.type === 'attributes') {
32
- var _mut$oldValue;
33
- /*
34
- "MutationObserver was explicitly designed to work that way, but I can't now recall the reasoning.
35
- I think it might have been something along the lines that for consistency every setAttribute call should create a record.
36
- Conceptually there is after all a mutation: there is an old value replaced with a new one,
37
- and whether or not they are the same doesn't really matter.
38
- And Custom elements should work the same way as MutationObserver."
39
- https://github.com/whatwg/dom/issues/520#issuecomment-336574796
40
- */
41
- var oldValue = (_mut$oldValue = _mut.oldValue) !== null && _mut$oldValue !== void 0 ? _mut$oldValue : undefined;
42
- var newValue = _mut.attributeName ? _mut.target.getAttribute(_mut.attributeName) : undefined;
43
- if (oldValue !== newValue) {
44
- if ((0, _platformFeatureFlags.fg)('platform_vc_ignore_no_ls_mutation_marker')) {
27
+ var _loop = function _loop() {
28
+ var mut = _step.value;
29
+ if (!(mut.target instanceof HTMLElement)) {
30
+ return 0; // continue
31
+ }
32
+ if (mut.type === 'attributes') {
33
+ var _mut$oldValue;
34
+ /*
35
+ "MutationObserver was explicitly designed to work that way, but I can't now recall the reasoning.
36
+ I think it might have been something along the lines that for consistency every setAttribute call should create a record.
37
+ Conceptually there is after all a mutation: there is an old value replaced with a new one,
38
+ and whether or not they are the same doesn't really matter.
39
+ And Custom elements should work the same way as MutationObserver."
40
+ https://github.com/whatwg/dom/issues/520#issuecomment-336574796
41
+ */
42
+ var oldValue = (_mut$oldValue = mut.oldValue) !== null && _mut$oldValue !== void 0 ? _mut$oldValue : undefined;
43
+ var newValue = mut.attributeName ? mut.target.getAttribute(mut.attributeName) : undefined;
44
+ if (oldValue !== newValue) {
45
45
  var _mut$attributeName;
46
- attributeMutations.push({
47
- target: new WeakRef(_mut.target),
48
- attributeName: (_mut$attributeName = _mut.attributeName) !== null && _mut$attributeName !== void 0 ? _mut$attributeName : 'unknown',
49
- oldValue: oldValue,
50
- newValue: newValue
51
- });
52
- } else {
53
- var _mut$attributeName2;
54
46
  onAttributeMutation({
55
- target: _mut.target,
56
- attributeName: (_mut$attributeName2 = _mut.attributeName) !== null && _mut$attributeName2 !== void 0 ? _mut$attributeName2 : 'unknown',
47
+ target: mut.target,
48
+ attributeName: (_mut$attributeName = mut.attributeName) !== null && _mut$attributeName !== void 0 ? _mut$attributeName : 'unknown',
57
49
  oldValue: oldValue,
58
50
  newValue: newValue
59
51
  });
60
52
  }
61
- }
62
- continue;
63
- } else if (_mut.type === 'childList') {
64
- var _mut$addedNodes, _mut$removedNodes;
65
- ((_mut$addedNodes = _mut.addedNodes) !== null && _mut$addedNodes !== void 0 ? _mut$addedNodes : []).forEach(function (node) {
66
- if (node instanceof HTMLElement) {
67
- addedNodes.push(new WeakRef(node));
53
+ return 0; // continue
54
+ } else if (mut.type === 'childList') {
55
+ var _mut$addedNodes, _mut$removedNodes;
56
+ // In chromium browser MutationRecord has timestamp field, which we should use.
57
+ var timestamp = Math.round(mut.timestamp || performance.now());
58
+
59
+ // Get or create timestamp bucket
60
+ var timestampBucket = batchedMutations.get(timestamp);
61
+ if (!timestampBucket) {
62
+ timestampBucket = new Map();
63
+ batchedMutations.set(timestamp, timestampBucket);
68
64
  }
69
- });
70
- ((_mut$removedNodes = _mut.removedNodes) !== null && _mut$removedNodes !== void 0 ? _mut$removedNodes : []).forEach(function (node) {
71
- if (node instanceof HTMLElement) {
72
- removedNodes.push(new WeakRef(node));
65
+
66
+ // Get or create target batch within timestamp bucket
67
+ var batch = timestampBucket.get(mut.target);
68
+ if (!batch) {
69
+ batch = {
70
+ target: new WeakRef(mut.target),
71
+ addedNodes: [],
72
+ removedNodes: [],
73
+ timestamp: timestamp
74
+ };
75
+ timestampBucket.set(mut.target, batch);
73
76
  }
74
- });
75
- }
76
- targets.push(_mut.target);
77
+
78
+ // Accumulate added nodes
79
+ ((_mut$addedNodes = mut.addedNodes) !== null && _mut$addedNodes !== void 0 ? _mut$addedNodes : []).forEach(function (node) {
80
+ if (node instanceof HTMLElement) {
81
+ batch.addedNodes.push(new WeakRef(node));
82
+ }
83
+ });
84
+
85
+ // Accumulate removed nodes
86
+ ((_mut$removedNodes = mut.removedNodes) !== null && _mut$removedNodes !== void 0 ? _mut$removedNodes : []).forEach(function (node) {
87
+ if (node instanceof HTMLElement) {
88
+ batch.removedNodes.push(new WeakRef(node));
89
+ }
90
+ });
91
+ }
92
+ targets.push(mut.target);
93
+ },
94
+ _ret;
95
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
96
+ _ret = _loop();
97
+ if (_ret === 0) continue;
77
98
  }
99
+
100
+ // Process all batched childList mutations
78
101
  } catch (err) {
79
102
  _iterator.e(err);
80
103
  } finally {
81
104
  _iterator.f();
82
105
  }
83
- onChildListMutation({
84
- addedNodes: addedNodes,
85
- removedNodes: removedNodes
86
- });
87
- for (var _i = 0, _attributeMutations = attributeMutations; _i < _attributeMutations.length; _i++) {
88
- var mut = _attributeMutations[_i];
89
- onAttributeMutation({
90
- target: mut.target.deref(),
91
- attributeName: mut.attributeName,
92
- oldValue: mut.oldValue,
93
- newValue: mut.newValue
94
- });
106
+ var _iterator2 = _createForOfIteratorHelper(batchedMutations.values()),
107
+ _step2;
108
+ try {
109
+ for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
110
+ var timestampBucket = _step2.value;
111
+ var _iterator3 = _createForOfIteratorHelper(timestampBucket.values()),
112
+ _step3;
113
+ try {
114
+ for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
115
+ var batch = _step3.value;
116
+ onChildListMutation({
117
+ target: batch.target,
118
+ addedNodes: batch.addedNodes,
119
+ removedNodes: batch.removedNodes,
120
+ timestamp: batch.timestamp
121
+ });
122
+ }
123
+ } catch (err) {
124
+ _iterator3.e(err);
125
+ } finally {
126
+ _iterator3.f();
127
+ }
128
+ }
129
+ } catch (err) {
130
+ _iterator2.e(err);
131
+ } finally {
132
+ _iterator2.f();
95
133
  }
96
134
  onMutationFinished === null || onMutationFinished === void 0 || onMutationFinished({
97
135
  targets: targets
@@ -4,17 +4,41 @@ import { VCObserverNOOP } from './no-op-vc-observer';
4
4
  import { VCObserver } from './vc-observer';
5
5
  import VCObserverNew from './vc-observer-new';
6
6
  import { RLLPlaceholderHandlers } from './vc-observer/observers/rll-placeholders';
7
+ import { SSRPlaceholderHandlers } from './vc-observer/observers/ssr-placeholders';
7
8
  export class VCObserverWrapper {
8
9
  constructor(opts = {}) {
10
+ var _opts$ssrEnablePageLa, _opts$disableSizeAndP;
9
11
  this.newVCObserver = null;
10
12
  this.oldVCObserver = null;
13
+
14
+ // Initialize SSR placeholder handler once
15
+ this.ssrPlaceholderHandler = new SSRPlaceholderHandlers({
16
+ enablePageLayoutPlaceholder: (_opts$ssrEnablePageLa = opts.ssrEnablePageLayoutPlaceholder) !== null && _opts$ssrEnablePageLa !== void 0 ? _opts$ssrEnablePageLa : false,
17
+ disableSizeAndPositionCheck: (_opts$disableSizeAndP = opts.disableSizeAndPositionCheck) !== null && _opts$disableSizeAndP !== void 0 ? _opts$disableSizeAndP : {
18
+ v: false,
19
+ h: false
20
+ }
21
+ });
11
22
  if (isVCRevisionEnabled('fy25.03')) {
23
+ var _opts$ssrEnablePageLa2, _opts$disableSizeAndP2;
12
24
  this.newVCObserver = new VCObserverNew({
13
- selectorConfig: opts.selectorConfig
25
+ selectorConfig: opts.selectorConfig,
26
+ isPostInteraction: opts.isPostInteraction,
27
+ SSRConfig: {
28
+ enablePageLayoutPlaceholder: (_opts$ssrEnablePageLa2 = opts.ssrEnablePageLayoutPlaceholder) !== null && _opts$ssrEnablePageLa2 !== void 0 ? _opts$ssrEnablePageLa2 : false,
29
+ disableSizeAndPositionCheck: (_opts$disableSizeAndP2 = opts.disableSizeAndPositionCheck) !== null && _opts$disableSizeAndP2 !== void 0 ? _opts$disableSizeAndP2 : {
30
+ v: false,
31
+ h: false
32
+ }
33
+ },
34
+ ssrPlaceholderHandler: this.ssrPlaceholderHandler
14
35
  });
15
36
  }
16
37
  if (isVCRevisionEnabled('fy25.01') || isVCRevisionEnabled('fy25.02')) {
17
- this.oldVCObserver = new VCObserver(opts);
38
+ this.oldVCObserver = new VCObserver({
39
+ ...opts,
40
+ ssrPlaceholderHandler: this.ssrPlaceholderHandler
41
+ });
18
42
  }
19
43
  }
20
44
 
@@ -68,6 +92,8 @@ export class VCObserverWrapper {
68
92
  (_this$newVCObserver2 = this.newVCObserver) === null || _this$newVCObserver2 === void 0 ? void 0 : _this$newVCObserver2.stop();
69
93
  }
70
94
  RLLPlaceholderHandlers.getInstance().reset();
95
+ // Clear shared SSR placeholder handler
96
+ this.ssrPlaceholderHandler.clear();
71
97
  }
72
98
  getVCRawData() {
73
99
  var _this$oldVCObserver$g, _this$oldVCObserver3;
@@ -94,16 +120,22 @@ export class VCObserverWrapper {
94
120
  };
95
121
  }
96
122
  setSSRElement(element) {
97
- var _this$oldVCObserver5;
123
+ var _this$oldVCObserver5, _this$newVCObserver4;
98
124
  (_this$oldVCObserver5 = this.oldVCObserver) === null || _this$oldVCObserver5 === void 0 ? void 0 : _this$oldVCObserver5.setSSRElement(element);
125
+ (_this$newVCObserver4 = this.newVCObserver) === null || _this$newVCObserver4 === void 0 ? void 0 : _this$newVCObserver4.setReactRootElement(element);
99
126
  }
100
127
  setReactRootRenderStart(startTime) {
101
- var _this$oldVCObserver6;
128
+ var _this$oldVCObserver6, _this$newVCObserver5;
102
129
  (_this$oldVCObserver6 = this.oldVCObserver) === null || _this$oldVCObserver6 === void 0 ? void 0 : _this$oldVCObserver6.setReactRootRenderStart(startTime || performance.now());
130
+ (_this$newVCObserver5 = this.newVCObserver) === null || _this$newVCObserver5 === void 0 ? void 0 : _this$newVCObserver5.setReactRootRenderStart(startTime || performance.now());
103
131
  }
104
132
  setReactRootRenderStop(stopTime) {
105
- var _this$oldVCObserver7;
133
+ var _this$oldVCObserver7, _this$newVCObserver6;
106
134
  (_this$oldVCObserver7 = this.oldVCObserver) === null || _this$oldVCObserver7 === void 0 ? void 0 : _this$oldVCObserver7.setReactRootRenderStop(stopTime || performance.now());
135
+ (_this$newVCObserver6 = this.newVCObserver) === null || _this$newVCObserver6 === void 0 ? void 0 : _this$newVCObserver6.setReactRootRenderStop(stopTime || performance.now());
136
+ }
137
+ collectSSRPlaceholders() {
138
+ this.ssrPlaceholderHandler.collectExistingPlaceholders();
107
139
  }
108
140
  }
109
141
 
@@ -495,7 +495,8 @@ export class VCObserver {
495
495
  this.oldDomUpdatesEnabled = options.oldDomUpdates || false;
496
496
  const {
497
497
  ssrEnablePageLayoutPlaceholder,
498
- disableSizeAndPositionCheck
498
+ disableSizeAndPositionCheck,
499
+ ssrPlaceholderHandler
499
500
  } = options;
500
501
  this.observers = new Observers({
501
502
  selectorConfig: options.selectorConfig || {
@@ -508,7 +509,8 @@ export class VCObserver {
508
509
  SSRConfig: {
509
510
  enablePageLayoutPlaceholder: ssrEnablePageLayoutPlaceholder || false,
510
511
  disableSizeAndPositionCheck: disableSizeAndPositionCheck
511
- }
512
+ },
513
+ ssrPlaceholderHandler: ssrPlaceholderHandler
512
514
  });
513
515
  this.heatmap = !isVCRevisionEnabled('fy25.01') ? [] : this.getCleanHeatmap();
514
516
  this.heatmapNext = this.getCleanHeatmap();
@@ -654,6 +656,10 @@ export class VCObserver {
654
656
  setReactRootRenderStop(stopTime = performance.now()) {
655
657
  this.observers.setReactRootRenderStop(stopTime);
656
658
  }
659
+ collectSSRPlaceholders() {
660
+ // This is handled by the shared SSRPlaceholderHandlers in VCObserverWrapper
661
+ // Individual observers don't need to implement this
662
+ }
657
663
  setAbortReason(abort, timestamp, info = '') {
658
664
  if (this.abortReason.reason === null || this.abortReason.blocking === false) {
659
665
  this.abortReason.reason = abort;