@drip-apex/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +46 -0
  3. package/dist/_headers +3 -0
  4. package/dist/bundle-report.json +564 -0
  5. package/dist/drip.debug.js +2 -0
  6. package/dist/drip.debug.js.map +1 -0
  7. package/dist/drip.heatmap.js +2 -0
  8. package/dist/drip.heatmap.js.map +1 -0
  9. package/dist/drip.js +2 -0
  10. package/dist/drip.js.map +1 -0
  11. package/dist/drip.live.js +2 -0
  12. package/dist/drip.live.js.map +1 -0
  13. package/dist/editor.js +480 -0
  14. package/dist/editor.js.map +7 -0
  15. package/dist/index.mjs +645 -0
  16. package/dist/index.mjs.map +7 -0
  17. package/dist/metafiles/drip.debug.meta.json +973 -0
  18. package/dist/metafiles/drip.heatmap.meta.json +918 -0
  19. package/dist/metafiles/drip.live.meta.json +918 -0
  20. package/dist/metafiles/drip.meta.json +973 -0
  21. package/dist/metafiles/editor.meta.json +321 -0
  22. package/dist/metafiles/index.meta.json +1039 -0
  23. package/dist/metafiles/index.mjs.meta.json +78 -0
  24. package/dist/react/index.js +16973 -0
  25. package/dist/react/index.js.map +7 -0
  26. package/dist/sri.json +27 -0
  27. package/dist/types/analytics.d.ts +15 -0
  28. package/dist/types/antiflicker.d.ts +14 -0
  29. package/dist/types/assignment-store.d.ts +30 -0
  30. package/dist/types/audit.d.ts +9 -0
  31. package/dist/types/bucket.d.ts +2 -0
  32. package/dist/types/bucketing-cleanup.d.ts +5 -0
  33. package/dist/types/commerce-gift.d.ts +41 -0
  34. package/dist/types/commerce-price.d.ts +22 -0
  35. package/dist/types/commerce-shipping.d.ts +28 -0
  36. package/dist/types/css.d.ts +5 -0
  37. package/dist/types/cwv.d.ts +10 -0
  38. package/dist/types/data-layer-normalize.d.ts +1 -0
  39. package/dist/types/debug.d.ts +23 -0
  40. package/dist/types/define.d.ts +87 -0
  41. package/dist/types/devtools.d.ts +32 -0
  42. package/dist/types/dom-trigger.d.ts +3 -0
  43. package/dist/types/editor/api.d.ts +37 -0
  44. package/dist/types/editor/artifacts.d.ts +15 -0
  45. package/dist/types/editor/command-runtime.d.ts +48 -0
  46. package/dist/types/editor/controller.d.ts +97 -0
  47. package/dist/types/editor/device-preview.d.ts +23 -0
  48. package/dist/types/editor/index.d.ts +9 -0
  49. package/dist/types/editor/operator.d.ts +39 -0
  50. package/dist/types/editor/picker.d.ts +23 -0
  51. package/dist/types/editor/selector.d.ts +2 -0
  52. package/dist/types/editor/types.d.ts +55 -0
  53. package/dist/types/editor/view-kit.d.ts +33 -0
  54. package/dist/types/editor/view.d.ts +5 -0
  55. package/dist/types/editor-bootstrap.d.ts +37 -0
  56. package/dist/types/exclusion-groups.d.ts +59 -0
  57. package/dist/types/exposure-signals.d.ts +7 -0
  58. package/dist/types/flags.d.ts +65 -0
  59. package/dist/types/goals.d.ts +16 -0
  60. package/dist/types/guards.d.ts +39 -0
  61. package/dist/types/handover.d.ts +10 -0
  62. package/dist/types/hash.d.ts +19 -0
  63. package/dist/types/heatmap.d.ts +8 -0
  64. package/dist/types/hideflicker.d.ts +15 -0
  65. package/dist/types/hydration.d.ts +11 -0
  66. package/dist/types/index.d.ts +144 -0
  67. package/dist/types/js.d.ts +6 -0
  68. package/dist/types/module.d.ts +4 -0
  69. package/dist/types/money.d.ts +14 -0
  70. package/dist/types/mutate.d.ts +34 -0
  71. package/dist/types/observer-mute.d.ts +3 -0
  72. package/dist/types/pii-keys.d.ts +1 -0
  73. package/dist/types/prerequisites.d.ts +12 -0
  74. package/dist/types/qa-assistant-state.d.ts +68 -0
  75. package/dist/types/qa-assistant-view.d.ts +6 -0
  76. package/dist/types/qa-assistant.d.ts +9 -0
  77. package/dist/types/qa-toolbar.d.ts +19 -0
  78. package/dist/types/react/index.d.ts +84 -0
  79. package/dist/types/reassert-sentinel.d.ts +6 -0
  80. package/dist/types/router.d.ts +9 -0
  81. package/dist/types/runtime-tools.d.ts +50 -0
  82. package/dist/types/runtime.d.ts +22 -0
  83. package/dist/types/safe-regex.d.ts +6 -0
  84. package/dist/types/sanitize.d.ts +5 -0
  85. package/dist/types/semantic.d.ts +7 -0
  86. package/dist/types/shopify-cart-events.d.ts +7 -0
  87. package/dist/types/shopify-cart.d.ts +62 -0
  88. package/dist/types/signals.d.ts +31 -0
  89. package/dist/types/surface-signals.d.ts +6 -0
  90. package/dist/types/targeting-diagnostics.d.ts +5 -0
  91. package/dist/types/targeting.d.ts +50 -0
  92. package/dist/types/test-fixtures/commerce.d.ts +12 -0
  93. package/dist/types/track.d.ts +79 -0
  94. package/dist/types/types.d.ts +859 -0
  95. package/dist/types/wait.d.ts +7 -0
  96. package/package.json +74 -0
  97. package/src/analytics.ts +146 -0
  98. package/src/antiflicker.test.ts +127 -0
  99. package/src/antiflicker.ts +147 -0
  100. package/src/assignment-store.test.ts +171 -0
  101. package/src/assignment-store.ts +208 -0
  102. package/src/audit.test.ts +17 -0
  103. package/src/audit.ts +362 -0
  104. package/src/bucket.test.ts +65 -0
  105. package/src/bucket.ts +18 -0
  106. package/src/bucketing-cleanup.test.ts +30 -0
  107. package/src/bucketing-cleanup.ts +72 -0
  108. package/src/bucketing-parity.test.ts +41 -0
  109. package/src/commerce-analytics-lifecycle.test.ts +1416 -0
  110. package/src/commerce-config-lifecycle.test.ts +274 -0
  111. package/src/commerce-epoch-lifecycle.test.ts +62 -0
  112. package/src/commerce-gift.test.ts +1293 -0
  113. package/src/commerce-gift.ts +979 -0
  114. package/src/commerce-offers-display.test.ts +154 -0
  115. package/src/commerce-price.test.ts +1145 -0
  116. package/src/commerce-price.ts +941 -0
  117. package/src/commerce-revocation-lifecycle.test.ts +78 -0
  118. package/src/commerce-shipping.test.ts +630 -0
  119. package/src/commerce-shipping.ts +447 -0
  120. package/src/config-fetch.test.ts +325 -0
  121. package/src/css.ts +54 -0
  122. package/src/cwv.test.ts +95 -0
  123. package/src/cwv.ts +129 -0
  124. package/src/data-layer-normalize.ts +21 -0
  125. package/src/debug.test.ts +83 -0
  126. package/src/debug.ts +138 -0
  127. package/src/define.test.ts +327 -0
  128. package/src/define.ts +208 -0
  129. package/src/devtools.ts +582 -0
  130. package/src/dom-trigger.test.ts +70 -0
  131. package/src/dom-trigger.ts +55 -0
  132. package/src/editor/api.test.ts +154 -0
  133. package/src/editor/api.ts +185 -0
  134. package/src/editor/artifacts.test.ts +57 -0
  135. package/src/editor/artifacts.ts +115 -0
  136. package/src/editor/command-runtime.test.ts +225 -0
  137. package/src/editor/command-runtime.ts +572 -0
  138. package/src/editor/controller.test.ts +371 -0
  139. package/src/editor/controller.ts +596 -0
  140. package/src/editor/device-preview.test.ts +60 -0
  141. package/src/editor/device-preview.ts +120 -0
  142. package/src/editor/index.test.ts +161 -0
  143. package/src/editor/index.ts +169 -0
  144. package/src/editor/operator.test.ts +148 -0
  145. package/src/editor/operator.ts +256 -0
  146. package/src/editor/picker.test.ts +58 -0
  147. package/src/editor/picker.ts +152 -0
  148. package/src/editor/selector.test.ts +44 -0
  149. package/src/editor/selector.ts +110 -0
  150. package/src/editor/types.ts +92 -0
  151. package/src/editor/view-kit.ts +162 -0
  152. package/src/editor/view.test.ts +535 -0
  153. package/src/editor/view.ts +1395 -0
  154. package/src/editor-bootstrap.test.ts +116 -0
  155. package/src/editor-bootstrap.ts +213 -0
  156. package/src/event-schema-contract.test.ts +35 -0
  157. package/src/exclusion-groups.test.ts +383 -0
  158. package/src/exclusion-groups.ts +270 -0
  159. package/src/exposure-signals.test.ts +182 -0
  160. package/src/exposure-signals.ts +110 -0
  161. package/src/flags.test.ts +322 -0
  162. package/src/flags.ts +201 -0
  163. package/src/goals.test.ts +42 -0
  164. package/src/goals.ts +200 -0
  165. package/src/guards.test.ts +249 -0
  166. package/src/guards.ts +250 -0
  167. package/src/handover-cache-order.test.ts +32 -0
  168. package/src/handover.test.ts +349 -0
  169. package/src/handover.ts +309 -0
  170. package/src/hash.ts +214 -0
  171. package/src/heatmap.test.ts +305 -0
  172. package/src/heatmap.ts +373 -0
  173. package/src/hideflicker.ts +21 -0
  174. package/src/hydration.test.ts +252 -0
  175. package/src/hydration.ts +203 -0
  176. package/src/index.ts +7513 -0
  177. package/src/init-empty.test.ts +5572 -0
  178. package/src/js.test.ts +26 -0
  179. package/src/js.ts +61 -0
  180. package/src/module.ts +50 -0
  181. package/src/money.test.ts +35 -0
  182. package/src/money.ts +53 -0
  183. package/src/mutate.test.ts +304 -0
  184. package/src/mutate.ts +469 -0
  185. package/src/observer-mute.test.ts +88 -0
  186. package/src/observer-mute.ts +45 -0
  187. package/src/page-trigger.test.ts +84 -0
  188. package/src/personalization.test.ts +68 -0
  189. package/src/pii-keys.ts +17 -0
  190. package/src/prerequisites.test.ts +39 -0
  191. package/src/prerequisites.ts +94 -0
  192. package/src/qa-assistant-state.test.ts +471 -0
  193. package/src/qa-assistant-state.ts +505 -0
  194. package/src/qa-assistant-view.test.ts +185 -0
  195. package/src/qa-assistant-view.ts +768 -0
  196. package/src/qa-assistant.ts +40 -0
  197. package/src/qa-toolbar.ts +444 -0
  198. package/src/react/index.test.tsx +177 -0
  199. package/src/react/index.tsx +252 -0
  200. package/src/reassert-sentinel.test.ts +314 -0
  201. package/src/reassert-sentinel.ts +191 -0
  202. package/src/router.test.ts +78 -0
  203. package/src/router.ts +92 -0
  204. package/src/runtime-tools.test.ts +112 -0
  205. package/src/runtime-tools.ts +403 -0
  206. package/src/runtime.test.ts +217 -0
  207. package/src/runtime.ts +268 -0
  208. package/src/safe-regex.ts +35 -0
  209. package/src/sanitize.ts +34 -0
  210. package/src/semantic.ts +245 -0
  211. package/src/shopify-cart-events.test.ts +76 -0
  212. package/src/shopify-cart-events.ts +115 -0
  213. package/src/shopify-cart.test.ts +2823 -0
  214. package/src/shopify-cart.ts +1256 -0
  215. package/src/signals.ts +226 -0
  216. package/src/surface-signals.test.ts +83 -0
  217. package/src/surface-signals.ts +165 -0
  218. package/src/targeting-diagnostics.ts +560 -0
  219. package/src/targeting.detailed.test.ts +443 -0
  220. package/src/targeting.test.ts +1054 -0
  221. package/src/targeting.ts +1024 -0
  222. package/src/test-fixtures/commerce.ts +65 -0
  223. package/src/track.test.ts +817 -0
  224. package/src/track.ts +519 -0
  225. package/src/types.ts +991 -0
  226. package/src/wait.test.ts +96 -0
  227. package/src/wait.ts +238 -0
@@ -0,0 +1,96 @@
1
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
2
+
3
+ describe("waitForElement", () => {
4
+ const originalDocument = (globalThis as any).document;
5
+ const originalMutationObserver = (globalThis as any).MutationObserver;
6
+ const originalNode = (globalThis as any).Node;
7
+ let observerCallback: MutationCallback | null = null;
8
+ let disconnect: ReturnType<typeof vi.fn>;
9
+
10
+ beforeEach(() => {
11
+ vi.resetModules();
12
+ vi.useFakeTimers();
13
+ disconnect = vi.fn();
14
+ observerCallback = null;
15
+ (globalThis as any).Node = {
16
+ ELEMENT_NODE: 1,
17
+ DOCUMENT_FRAGMENT_NODE: 11,
18
+ };
19
+ (globalThis as any).document = {
20
+ documentElement: {},
21
+ querySelectorAll: vi.fn(() => []),
22
+ };
23
+ (globalThis as any).MutationObserver = class MutationObserver {
24
+ constructor(callback: MutationCallback) {
25
+ observerCallback = callback;
26
+ }
27
+ observe = vi.fn();
28
+ disconnect = disconnect;
29
+ };
30
+ });
31
+
32
+ afterEach(() => {
33
+ vi.useRealTimers();
34
+ (globalThis as any).document = originalDocument;
35
+ (globalThis as any).MutationObserver = originalMutationObserver;
36
+ (globalThis as any).Node = originalNode;
37
+ });
38
+
39
+ it("ignores invalid selectors instead of leaving a broken observer behind", async () => {
40
+ (globalThis as any).document.querySelectorAll = vi.fn(() => {
41
+ throw new Error("invalid selector");
42
+ });
43
+ const { waitForElement } = await import("./wait");
44
+ const callback = vi.fn();
45
+ const onMiss = vi.fn();
46
+
47
+ expect(() => waitForElement("[", callback, { onMiss })).not.toThrow();
48
+ expect(callback).not.toHaveBeenCalled();
49
+ expect(onMiss).toHaveBeenCalledTimes(1);
50
+ expect(observerCallback).toBeNull();
51
+ });
52
+
53
+ it("expires unresolved selector waits", async () => {
54
+ const { waitForElement } = await import("./wait");
55
+ const callback = vi.fn();
56
+ const onMiss = vi.fn();
57
+ waitForElement(".late-node", callback, { ttlMs: 1000, onMiss });
58
+
59
+ vi.advanceTimersByTime(1001);
60
+ const node = {
61
+ nodeType: 1,
62
+ matches: vi.fn(() => true),
63
+ querySelectorAll: vi.fn(() => []),
64
+ };
65
+ observerCallback?.([{ addedNodes: [node] } as unknown as MutationRecord], {} as MutationObserver);
66
+
67
+ await Promise.resolve();
68
+ expect(callback).not.toHaveBeenCalled();
69
+ expect(onMiss).toHaveBeenCalledTimes(1);
70
+ expect(disconnect).toHaveBeenCalled();
71
+ });
72
+
73
+ it("rechecks existing SPA nodes when attributes make a delayed selector match", async () => {
74
+ const { waitForElement } = await import("./wait");
75
+ const callback = vi.fn();
76
+ const onMiss = vi.fn();
77
+ const node = {
78
+ nodeType: 1,
79
+ matches: vi.fn((selector: string) => selector === "[data-route='pdp']"),
80
+ querySelectorAll: vi.fn(() => []),
81
+ } as unknown as Element;
82
+
83
+ waitForElement("[data-route='pdp']", callback, { ttlMs: 1000, onMiss });
84
+ observerCallback?.(
85
+ [{ type: "attributes", target: node } as unknown as MutationRecord],
86
+ {} as MutationObserver,
87
+ );
88
+
89
+ await Promise.resolve();
90
+ expect(callback).toHaveBeenCalledWith(node);
91
+ expect(onMiss).not.toHaveBeenCalled();
92
+
93
+ vi.advanceTimersByTime(1001);
94
+ expect(onMiss).not.toHaveBeenCalled();
95
+ });
96
+ });
package/src/wait.ts ADDED
@@ -0,0 +1,238 @@
1
+ import { Mutation } from "./types";
2
+ import { applyTrackedMutation, isInsertAction, isInsertDuplicate, getMutationKey } from "./mutate";
3
+
4
+ type WaitEntry = {
5
+ selector: string;
6
+ callback: (el: Element) => void;
7
+ handled: WeakSet<Element>;
8
+ matched: boolean;
9
+ expiresAt: number;
10
+ onMiss?: () => void;
11
+ };
12
+
13
+ const entries: WaitEntry[] = [];
14
+ let observer: MutationObserver | null = null;
15
+ let pending = false;
16
+ const pendingRoots = new Set<ParentNode>();
17
+ const DEFAULT_WAIT_TTL_MS = 30_000;
18
+ let expiryTimer: ReturnType<typeof setTimeout> | null = null;
19
+
20
+ function isElement(node: Node): node is Element {
21
+ return node.nodeType === Node.ELEMENT_NODE;
22
+ }
23
+
24
+ function hasQuerySelectorAll(node: ParentNode): node is ParentNode & { querySelectorAll: (selectors: string) => NodeListOf<Element> } {
25
+ return typeof (node as ParentNode & { querySelectorAll?: unknown }).querySelectorAll === "function";
26
+ }
27
+
28
+ function applyToEntry(entry: WaitEntry, element: Element): void {
29
+ if (entry.expiresAt <= Date.now()) return;
30
+ if (entry.handled.has(element)) return;
31
+ entry.handled.add(element);
32
+ entry.matched = true;
33
+ entry.callback(element);
34
+ }
35
+
36
+ function clearExpiryTimer(): void {
37
+ if (expiryTimer !== null) {
38
+ clearTimeout(expiryTimer);
39
+ expiryTimer = null;
40
+ }
41
+ }
42
+
43
+ function scheduleExpiryPrune(): void {
44
+ clearExpiryTimer();
45
+ if (entries.length === 0) return;
46
+ const nextExpiry = Math.min(...entries.map((entry) => entry.expiresAt));
47
+ const delay = Math.max(1, nextExpiry - Date.now() + 1);
48
+ expiryTimer = setTimeout(() => {
49
+ expiryTimer = null;
50
+ pruneExpiredEntries();
51
+ }, delay);
52
+ }
53
+
54
+ function pruneExpiredEntries(): void {
55
+ const ts = Date.now();
56
+ for (let i = entries.length - 1; i >= 0; i -= 1) {
57
+ if (entries[i].expiresAt <= ts) {
58
+ const [expired] = entries.splice(i, 1);
59
+ if (!expired.matched) {
60
+ try {
61
+ expired.onMiss?.();
62
+ } catch {}
63
+ }
64
+ }
65
+ }
66
+ if (entries.length === 0 && observer) {
67
+ observer.disconnect();
68
+ observer = null;
69
+ pending = false;
70
+ pendingRoots.clear();
71
+ clearExpiryTimer();
72
+ } else {
73
+ scheduleExpiryPrune();
74
+ }
75
+ }
76
+
77
+ function buildSelectorMap(): Map<string, WaitEntry[]> {
78
+ pruneExpiredEntries();
79
+ const selectorMap = new Map<string, WaitEntry[]>();
80
+ for (const entry of entries) {
81
+ const group = selectorMap.get(entry.selector);
82
+ if (group) {
83
+ group.push(entry);
84
+ } else {
85
+ selectorMap.set(entry.selector, [entry]);
86
+ }
87
+ }
88
+ return selectorMap;
89
+ }
90
+
91
+ function runSelectorOnRoot(selector: string, root: ParentNode): Element[] {
92
+ const matched: Element[] = [];
93
+ try {
94
+ if (isElement(root) && root.matches(selector)) {
95
+ matched.push(root);
96
+ }
97
+ if (hasQuerySelectorAll(root)) {
98
+ root.querySelectorAll(selector).forEach((el) => matched.push(el));
99
+ }
100
+ } catch {
101
+ return [];
102
+ }
103
+ return matched;
104
+ }
105
+
106
+ const debouncedCheck = () => {
107
+ if (pending) return;
108
+ pending = true;
109
+ queueMicrotask(() => {
110
+ pending = false;
111
+ flushChecks();
112
+ });
113
+ };
114
+
115
+ function checkAllEntries(): void {
116
+ const selectorMap = buildSelectorMap();
117
+ for (const [selector, selectorEntries] of selectorMap) {
118
+ try {
119
+ const elements = document.querySelectorAll(selector);
120
+ elements.forEach((el) => {
121
+ selectorEntries.forEach((entry) => applyToEntry(entry, el));
122
+ });
123
+ } catch {}
124
+ }
125
+ pruneExpiredEntries();
126
+ }
127
+
128
+ function checkPendingRoots(): void {
129
+ if (pendingRoots.size === 0) return;
130
+ const roots = Array.from(pendingRoots);
131
+ pendingRoots.clear();
132
+
133
+ const selectorMap = buildSelectorMap();
134
+ for (const [selector, selectorEntries] of selectorMap) {
135
+ for (const root of roots) {
136
+ const matches = runSelectorOnRoot(selector, root);
137
+ for (const element of matches) {
138
+ selectorEntries.forEach((entry) => applyToEntry(entry, element));
139
+ }
140
+ }
141
+ }
142
+ pruneExpiredEntries();
143
+ }
144
+
145
+ function flushChecks(): void {
146
+ if (entries.length === 0) return;
147
+ if (pendingRoots.size > 0) {
148
+ checkPendingRoots();
149
+ return;
150
+ }
151
+ checkAllEntries();
152
+ }
153
+
154
+ function ensureObserver(): void {
155
+ if (observer) return;
156
+ observer = new MutationObserver((records) => {
157
+ for (const record of records) {
158
+ if (record.type === "childList") {
159
+ record.addedNodes.forEach((node) => {
160
+ if (isElement(node)) {
161
+ pendingRoots.add(node);
162
+ } else if (node.nodeType === Node.DOCUMENT_FRAGMENT_NODE) {
163
+ pendingRoots.add(node as DocumentFragment);
164
+ }
165
+ });
166
+ } else if (record.type === "attributes" && isElement(record.target)) {
167
+ pendingRoots.add(record.target);
168
+ } else if (record.type === "characterData" && record.target.parentElement) {
169
+ pendingRoots.add(record.target.parentElement);
170
+ }
171
+ }
172
+ if (pendingRoots.size > 0) debouncedCheck();
173
+ });
174
+ observer.observe(document.documentElement, {
175
+ attributes: true,
176
+ characterData: true,
177
+ childList: true,
178
+ subtree: true,
179
+ });
180
+ }
181
+
182
+ export function waitForElement(
183
+ selector: string,
184
+ callback: (el: Element) => void,
185
+ options: { ttlMs?: number; onMiss?: () => void } = {},
186
+ ): void {
187
+ const handled = new WeakSet<Element>();
188
+ let matched = false;
189
+ try {
190
+ const existing = document.querySelectorAll(selector);
191
+ existing.forEach((el) => {
192
+ handled.add(el);
193
+ matched = true;
194
+ callback(el);
195
+ });
196
+ } catch {
197
+ options.onMiss?.();
198
+ return;
199
+ }
200
+ const ttlMs = Math.max(1_000, Math.min(options.ttlMs ?? DEFAULT_WAIT_TTL_MS, 120_000));
201
+ entries.push({ selector, callback, handled, matched, expiresAt: Date.now() + ttlMs, onMiss: options.onMiss });
202
+ scheduleExpiryPrune();
203
+ ensureObserver();
204
+ }
205
+
206
+ export function applyMutationWithWait(
207
+ mutation: Mutation,
208
+ index: number,
209
+ onApplied?: ((mutation: Mutation, element: Element, index: number) => void) | null,
210
+ onMiss?: ((mutation: Mutation, index: number) => void) | null,
211
+ ): void {
212
+ const key = getMutationKey(mutation, index);
213
+ waitForElement(mutation.selector, (element) => {
214
+ if (isInsertAction(mutation.action)) {
215
+ if (isInsertDuplicate(element, key)) {
216
+ onApplied?.(mutation, element, index);
217
+ return;
218
+ }
219
+ applyTrackedMutation(mutation, element, key);
220
+ } else {
221
+ applyTrackedMutation(mutation, element, key);
222
+ }
223
+ onApplied?.(mutation, element, index);
224
+ }, {
225
+ onMiss: () => onMiss?.(mutation, index),
226
+ });
227
+ }
228
+
229
+ export function resetWaitEntries(): void {
230
+ entries.length = 0;
231
+ pending = false;
232
+ pendingRoots.clear();
233
+ if (observer) {
234
+ observer.disconnect();
235
+ observer = null;
236
+ }
237
+ clearExpiryTimer();
238
+ }