bippy 0.0.10 → 0.0.13

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.
package/dist/index.mjs CHANGED
@@ -1 +1,416 @@
1
- var e=1,t=1,o=0,n=9,r=11,a=14,i=15,l=5,c=26,m=27,u=18,s=6,f=7,d=23,p=22,b=3,y=60111,h="Symbol(react.concurrent_mode)",g="Symbol(react.async_mode)",C=e=>5===e.tag||26===e.tag||27===e.tag,_=e=>0===e.tag||1===e.tag||15===e.tag||14===e.tag||11===e.tag,F=(e,t)=>{try{const o=e.dependencies,n=e.alternate?.dependencies;if(!o||!n)return!1;if("object"!=typeof o||!("firstContext"in o)||"object"!=typeof n||!("firstContext"in n))return!1;let r=o.firstContext,a=n.firstContext;for(;r&&"object"==typeof r&&"memoizedValue"in r&&a&&"object"==typeof a&&"memoizedValue"in a;){if(!0===t(r,a))return!0;r=r.next,a=a.next}}catch{}return!1},z=(e,t)=>{try{let o=e.memoizedState,n=e.alternate?.memoizedState;for(;o&&n;){if(!0===t(o,n))return!0;o=o.next,n=n.next}}catch{}return!1},S=(e,t)=>{try{const o=e.memoizedProps,n=e.alternate?.memoizedProps||{};for(const e in{...n,...o}){const r=n?.[e],a=o?.[e];if(!0===t(r,a))return!0}}catch{}return!1},R=e=>{const t=e.memoizedProps,o=e.alternate?.memoizedProps||{},n=e.flags??e.effectTag??0;switch(e.tag){case 1:case 0:case 9:case 11:case 14:case 15:return!(1&~n);default:return!e.alternate||(o!==t||e.alternate.memoizedState!==e.memoizedState||e.alternate.ref!==e.ref)}},O=e=>{switch(e.tag){case 18:case 6:case 7:case 23:case 22:return!0;case 3:return!1;default:{const t="object"==typeof e.type&&null!==e.type?e.type.$$typeof:e.type;switch("symbol"==typeof t?t.toString():t){case 60111:case h:case g:return!0;default:return!1}}}},x=e=>{let t=T(e,C);return t||(t=T(e,C,!0)),t},T=(e,t,o=!1)=>{if(!e)return null;if(!0===t(e))return e;let n=o?e.return:e.child;for(;n;){const e=T(n,t,o);if(e)return e;n=o?null:n.sibling}return null},j=e=>{const t=e?.actualDuration??0;let o=t,n=e?.child??null;for(;t>0&&null!=n;)o-=n.actualDuration??0,n=n.sibling;return{selfTime:o,totalTime:t}},P=e=>Boolean(e.updateQueue?.memoCache),w=e=>"function"==typeof e?e:"object"==typeof e&&e?w(e.type||e.render):null,D=e=>{if("function"!=typeof e&&("object"!=typeof e||!e))return null;const t=e.displayName||e.name||null;return t||((e=w(e))&&(e.displayName||e.name)||null)},E=()=>{},L=()=>{let e=globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;const t=new Map;let o=0;e??={checkDCE:E,supportsFiber:!0,supportsFlight:!0,renderers:t,onCommitFiberRoot:E,onCommitFiberUnmount:E,onPostCommitFiberRoot:E,inject(e){const n=++o;return t.set(n,e),n}};try{globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__=e}catch{}return e};"undefined"!=typeof window&&L();var B=({onRender:e,onError:t})=>(o,n)=>{try{const t=n.current,o=null!==t.alternate&&Boolean(t.alternate.memoizedState?.element)&&!0!==t.alternate.memoizedState.isDehydrated,r=Boolean(t.memoizedState?.element),a=(t,o)=>{let n=t;for(;null!=n;){!O(n)&&R(n)&&e(n,"mount"),null!=n.child&&a(n.child,!0),n=o?n.sibling:null}},i=(t,o)=>{if(!o)return;if(!O(t)&&R(t)&&e(t,"update"),t.child!==o.child){let e=t.child;for(;e;){const t=e.alternate;t?i(e,t):a(e,!1),e=e.sibling}}},l=t=>{!(3===t.tag)&&O(t)||e(t,"unmount")};!o&&r?a(t,!1):o&&r?i(t,t.alternate):o&&!r&&l(t)}catch(e){if(!t)throw e;t(e)}},A=({onCommitFiberRoot:e,onCommitFiberUnmount:t,onPostCommitFiberRoot:o})=>{const n=L(),r=n.onCommitFiberRoot;e&&(n.onCommitFiberRoot=(t,o)=>{r&&r(t,o),e(t,o)});const a=n.onCommitFiberUnmount;t&&(n.onCommitFiberUnmount=(e,o)=>{a&&a(e,o),t(e,o)});const i=n.onPostCommitFiberRoot;return o&&(n.onPostCommitFiberRoot=(e,t)=>{i&&i(e,t)}),n};export{y as CONCURRENT_MODE_NUMBER,h as CONCURRENT_MODE_SYMBOL_STRING,t as ClassComponentTag,n as ContextConsumerTag,g as DEPRECATED_ASYNC_MODE_SYMBOL_STRING,u as DehydratedSuspenseComponent,r as ForwardRefTag,f as Fragment,o as FunctionComponentTag,l as HostComponentTag,c as HostHoistableTag,b as HostRoot,m as HostSingletonTag,s as HostText,d as LegacyHiddenComponent,a as MemoComponentTag,p as OffscreenComponent,e as PerformedWorkFlag,i as SimpleMemoComponentTag,B as createFiberVisitor,R as didFiberRender,D as getDisplayName,x as getNearestHostFiber,L as getRDTHook,j as getTimings,w as getType,P as hasMemoCache,A as instrument,_ as isCompositeFiber,C as isHostFiber,O as shouldFilterFiber,F as traverseContexts,T as traverseFiber,S as traverseProps,z as traverseState};
1
+ // src/index.ts
2
+ var ClassComponentTag = 1;
3
+ var FunctionComponentTag = 0;
4
+ var ContextConsumerTag = 9;
5
+ var SuspenseComponentTag = 13;
6
+ var OffscreenComponentTag = 22;
7
+ var ForwardRefTag = 11;
8
+ var MemoComponentTag = 14;
9
+ var SimpleMemoComponentTag = 15;
10
+ var HostComponentTag = 5;
11
+ var HostHoistableTag = 26;
12
+ var HostSingletonTag = 27;
13
+ var DehydratedSuspenseComponent = 18;
14
+ var HostText = 6;
15
+ var Fragment = 7;
16
+ var LegacyHiddenComponent = 23;
17
+ var OffscreenComponent = 22;
18
+ var HostRoot = 3;
19
+ var CONCURRENT_MODE_NUMBER = 60111;
20
+ var CONCURRENT_MODE_SYMBOL_STRING = "Symbol(react.concurrent_mode)";
21
+ var DEPRECATED_ASYNC_MODE_SYMBOL_STRING = "Symbol(react.async_mode)";
22
+ var PerformedWork = 1;
23
+ var Placement = 2;
24
+ var DidCapture = 128;
25
+ var Hydrating = 4096;
26
+ var Update = 4;
27
+ var Cloned = 8;
28
+ var ChildDeletion = 16;
29
+ var ContentReset = 32;
30
+ var Ref = 512;
31
+ var Snapshot = 1024;
32
+ var Visibility = 8192;
33
+ var MutationMask = Placement | Update | ChildDeletion | ContentReset | Hydrating | Visibility | Snapshot;
34
+ var isValidElement = (element) => typeof element === "object" && element !== null && "$$typeof" in element && String(element.$$typeof) === "Symbol(react.element)";
35
+ var isHostFiber = (fiber) => fiber.tag === HostComponentTag || // @ts-expect-error: it exists
36
+ fiber.tag === HostHoistableTag || // @ts-expect-error: it exists
37
+ fiber.tag === HostSingletonTag;
38
+ var isCompositeFiber = (fiber) => fiber.tag === FunctionComponentTag || fiber.tag === ClassComponentTag || fiber.tag === SimpleMemoComponentTag || fiber.tag === MemoComponentTag || fiber.tag === ForwardRefTag;
39
+ var traverseContexts = (fiber, selector) => {
40
+ try {
41
+ const nextDependencies = fiber.dependencies;
42
+ const prevDependencies = fiber.alternate?.dependencies;
43
+ if (!nextDependencies || !prevDependencies) return false;
44
+ if (typeof nextDependencies !== "object" || !("firstContext" in nextDependencies) || typeof prevDependencies !== "object" || !("firstContext" in prevDependencies)) {
45
+ return false;
46
+ }
47
+ let nextContext = nextDependencies.firstContext;
48
+ let prevContext = prevDependencies.firstContext;
49
+ while (nextContext && typeof nextContext === "object" && "memoizedValue" in nextContext && prevContext && typeof prevContext === "object" && "memoizedValue" in prevContext) {
50
+ if (selector(nextContext, prevContext) === true)
51
+ return true;
52
+ nextContext = nextContext.next;
53
+ prevContext = prevContext.next;
54
+ }
55
+ } catch {
56
+ }
57
+ return false;
58
+ };
59
+ var traverseState = (fiber, selector) => {
60
+ try {
61
+ let prevState = fiber.memoizedState;
62
+ let nextState = fiber.alternate?.memoizedState;
63
+ while (prevState && nextState) {
64
+ if (selector(prevState, nextState) === true) return true;
65
+ prevState = prevState.next;
66
+ nextState = nextState.next;
67
+ }
68
+ } catch {
69
+ }
70
+ return false;
71
+ };
72
+ var traverseProps = (fiber, selector) => {
73
+ try {
74
+ const nextProps = fiber.memoizedProps;
75
+ const prevProps = fiber.alternate?.memoizedProps || {};
76
+ for (const propName in { ...prevProps, ...nextProps }) {
77
+ const prevValue = prevProps?.[propName];
78
+ const nextValue = nextProps?.[propName];
79
+ if (selector(prevValue, nextValue) === true) return true;
80
+ }
81
+ } catch {
82
+ }
83
+ return false;
84
+ };
85
+ var didFiberRender = (fiber) => {
86
+ const nextProps = fiber.memoizedProps;
87
+ const prevProps = fiber.alternate?.memoizedProps || {};
88
+ const flags = fiber.flags ?? fiber.effectTag ?? 0;
89
+ switch (fiber.tag) {
90
+ case ClassComponentTag:
91
+ case FunctionComponentTag:
92
+ case ContextConsumerTag:
93
+ case ForwardRefTag:
94
+ case MemoComponentTag:
95
+ case SimpleMemoComponentTag: {
96
+ return (flags & PerformedWork) === PerformedWork;
97
+ }
98
+ default:
99
+ if (!fiber.alternate) return true;
100
+ return prevProps !== nextProps || fiber.alternate.memoizedState !== fiber.memoizedState || fiber.alternate.ref !== fiber.ref;
101
+ }
102
+ };
103
+ var didFiberCommit = (fiber) => {
104
+ return Boolean(
105
+ fiber.subtreeFlags & (MutationMask | Cloned) || fiber.deletions
106
+ );
107
+ };
108
+ var getMutatedHostFibers = (fiber) => {
109
+ const mutations = [];
110
+ const visited = /* @__PURE__ */ new WeakSet();
111
+ const traverse = (node) => {
112
+ if (!node || visited.has(node)) return;
113
+ visited.add(node);
114
+ if (isHostFiber(node) && didFiberCommit(node.return ?? node) && didFiberRender(node)) {
115
+ mutations.push(node);
116
+ }
117
+ if (node.child) {
118
+ traverse(node.child);
119
+ }
120
+ if (node.sibling) {
121
+ traverse(node.sibling);
122
+ }
123
+ };
124
+ traverse(fiber);
125
+ return mutations;
126
+ };
127
+ var getFiberStack = (fiber) => {
128
+ const stack = [];
129
+ while (fiber.return) {
130
+ stack.unshift(fiber);
131
+ fiber = fiber.return;
132
+ }
133
+ return stack;
134
+ };
135
+ var shouldFilterFiber = (fiber) => {
136
+ switch (fiber.tag) {
137
+ case DehydratedSuspenseComponent:
138
+ return true;
139
+ case HostText:
140
+ case Fragment:
141
+ case LegacyHiddenComponent:
142
+ case OffscreenComponent:
143
+ return true;
144
+ case HostRoot:
145
+ return false;
146
+ default: {
147
+ const symbolOrNumber = typeof fiber.type === "object" && fiber.type !== null ? fiber.type.$$typeof : fiber.type;
148
+ const typeSymbol = typeof symbolOrNumber === "symbol" ? symbolOrNumber.toString() : symbolOrNumber;
149
+ switch (typeSymbol) {
150
+ case CONCURRENT_MODE_NUMBER:
151
+ case CONCURRENT_MODE_SYMBOL_STRING:
152
+ case DEPRECATED_ASYNC_MODE_SYMBOL_STRING:
153
+ return true;
154
+ default:
155
+ return false;
156
+ }
157
+ }
158
+ }
159
+ };
160
+ var getNearestHostFiber = (fiber) => {
161
+ let hostFiber = traverseFiber(fiber, isHostFiber);
162
+ if (!hostFiber) {
163
+ hostFiber = traverseFiber(fiber, isHostFiber, true);
164
+ }
165
+ return hostFiber;
166
+ };
167
+ var traverseFiber = (fiber, selector, ascending = false) => {
168
+ if (!fiber) return null;
169
+ if (selector(fiber) === true) return fiber;
170
+ let child = ascending ? fiber.return : fiber.child;
171
+ while (child) {
172
+ const match = traverseFiber(child, selector, ascending);
173
+ if (match) return match;
174
+ child = ascending ? null : child.sibling;
175
+ }
176
+ return null;
177
+ };
178
+ var getTimings = (fiber) => {
179
+ const totalTime = fiber?.actualDuration ?? 0;
180
+ let selfTime = totalTime;
181
+ let child = fiber?.child ?? null;
182
+ while (totalTime > 0 && child != null) {
183
+ selfTime -= child.actualDuration ?? 0;
184
+ child = child.sibling;
185
+ }
186
+ return { selfTime, totalTime };
187
+ };
188
+ var hasMemoCache = (fiber) => {
189
+ return Boolean(fiber.updateQueue?.memoCache);
190
+ };
191
+ var getType = (type) => {
192
+ if (typeof type === "function") {
193
+ return type;
194
+ }
195
+ if (typeof type === "object" && type) {
196
+ return getType(type.type || type.render);
197
+ }
198
+ return null;
199
+ };
200
+ var getDisplayName = (type) => {
201
+ if (typeof type !== "function" && !(typeof type === "object" && type)) {
202
+ return null;
203
+ }
204
+ const name = type.displayName || type.name || null;
205
+ if (name) return name;
206
+ type = getType(type);
207
+ if (!type) return null;
208
+ return type.displayName || type.name || null;
209
+ };
210
+ var NO_OP = () => {
211
+ };
212
+ var getRDTHook = () => {
213
+ let rdtHook = globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;
214
+ const renderers = /* @__PURE__ */ new Map();
215
+ let i = 0;
216
+ rdtHook ??= {
217
+ checkDCE: NO_OP,
218
+ supportsFiber: true,
219
+ supportsFlight: true,
220
+ renderers,
221
+ onCommitFiberRoot: NO_OP,
222
+ onCommitFiberUnmount: NO_OP,
223
+ onPostCommitFiberRoot: NO_OP,
224
+ inject(renderer) {
225
+ const nextID = ++i;
226
+ renderers.set(nextID, renderer);
227
+ return nextID;
228
+ }
229
+ };
230
+ try {
231
+ globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__ = rdtHook;
232
+ } catch {
233
+ }
234
+ return rdtHook;
235
+ };
236
+ if (typeof window !== "undefined") {
237
+ getRDTHook();
238
+ }
239
+ var mountFiberRecursively = (onRender, firstChild, traverseSiblings) => {
240
+ let fiber = firstChild;
241
+ while (fiber != null) {
242
+ const shouldIncludeInTree = !shouldFilterFiber(fiber);
243
+ if (shouldIncludeInTree && didFiberRender(fiber)) {
244
+ onRender(fiber, "mount");
245
+ }
246
+ if (fiber.tag === SuspenseComponentTag) {
247
+ const isTimedOut = fiber.memoizedState !== null;
248
+ if (isTimedOut) {
249
+ const primaryChildFragment = fiber.child;
250
+ const fallbackChildFragment = primaryChildFragment ? primaryChildFragment.sibling : null;
251
+ if (fallbackChildFragment) {
252
+ const fallbackChild = fallbackChildFragment.child;
253
+ if (fallbackChild !== null) {
254
+ mountFiberRecursively(onRender, fallbackChild, false);
255
+ }
256
+ }
257
+ } else {
258
+ let primaryChild = null;
259
+ if (fiber.child !== null) {
260
+ primaryChild = fiber.child.child;
261
+ }
262
+ if (primaryChild !== null) {
263
+ mountFiberRecursively(onRender, primaryChild, false);
264
+ }
265
+ }
266
+ } else if (fiber.child != null) {
267
+ mountFiberRecursively(onRender, fiber.child, true);
268
+ }
269
+ fiber = traverseSiblings ? fiber.sibling : null;
270
+ }
271
+ };
272
+ var updateFiberRecursively = (onRender, nextFiber, prevFiber, parentFiber) => {
273
+ if (!prevFiber) return;
274
+ const isSuspense = nextFiber.tag === SuspenseComponentTag;
275
+ const shouldIncludeInTree = !shouldFilterFiber(nextFiber);
276
+ if (shouldIncludeInTree && didFiberRender(nextFiber)) {
277
+ onRender(nextFiber, "update");
278
+ }
279
+ const prevDidTimeout = isSuspense && prevFiber.memoizedState !== null;
280
+ const nextDidTimeOut = isSuspense && nextFiber.memoizedState !== null;
281
+ if (prevDidTimeout && nextDidTimeOut) {
282
+ const nextFallbackChildSet = nextFiber.child?.sibling ?? null;
283
+ const prevFallbackChildSet = prevFiber.child?.sibling ?? null;
284
+ if (nextFallbackChildSet !== null && prevFallbackChildSet !== null) {
285
+ updateFiberRecursively(
286
+ onRender,
287
+ nextFallbackChildSet,
288
+ prevFallbackChildSet);
289
+ }
290
+ } else if (prevDidTimeout && !nextDidTimeOut) {
291
+ const nextPrimaryChildSet = nextFiber.child;
292
+ if (nextPrimaryChildSet !== null) {
293
+ mountFiberRecursively(onRender, nextPrimaryChildSet, true);
294
+ }
295
+ } else if (!prevDidTimeout && nextDidTimeOut) {
296
+ unmountFiberChildrenRecursively(onRender, prevFiber);
297
+ const nextFallbackChildSet = nextFiber.child?.sibling ?? null;
298
+ if (nextFallbackChildSet !== null) {
299
+ mountFiberRecursively(onRender, nextFallbackChildSet, true);
300
+ }
301
+ } else if (nextFiber.child !== prevFiber.child) {
302
+ let nextChild = nextFiber.child;
303
+ while (nextChild) {
304
+ if (nextChild.alternate) {
305
+ const prevChild = nextChild.alternate;
306
+ updateFiberRecursively(
307
+ onRender,
308
+ nextChild,
309
+ prevChild);
310
+ } else {
311
+ mountFiberRecursively(onRender, nextChild, false);
312
+ }
313
+ nextChild = nextChild.sibling;
314
+ }
315
+ }
316
+ };
317
+ var unmountFiber = (onRender, fiber) => {
318
+ const isRoot = fiber.tag === HostRoot;
319
+ if (isRoot || !shouldFilterFiber(fiber)) {
320
+ onRender(fiber, "unmount");
321
+ }
322
+ };
323
+ var unmountFiberChildrenRecursively = (onRender, fiber) => {
324
+ const isTimedOutSuspense = fiber.tag === SuspenseComponentTag && fiber.memoizedState !== null;
325
+ let child = fiber.child;
326
+ if (isTimedOutSuspense) {
327
+ const primaryChildFragment = fiber.child;
328
+ const fallbackChildFragment = primaryChildFragment?.sibling ?? null;
329
+ child = fallbackChildFragment?.child ?? null;
330
+ }
331
+ while (child !== null) {
332
+ if (child.return !== null) {
333
+ unmountFiber(onRender, child);
334
+ unmountFiberChildrenRecursively(onRender, child);
335
+ }
336
+ child = child.sibling;
337
+ }
338
+ };
339
+ var commitId = 0;
340
+ var rootInstanceMap = /* @__PURE__ */ new WeakMap();
341
+ var createFiberVisitor = ({
342
+ onRender: onRenderWithoutState,
343
+ onError
344
+ }) => {
345
+ return (_rendererID, root, state) => {
346
+ const rootFiber = root.current;
347
+ const onRender = (fiber, phase) => onRenderWithoutState(fiber, phase, state);
348
+ let rootInstance = rootInstanceMap.get(root);
349
+ if (!rootInstance) {
350
+ rootInstance = { prevFiber: null, id: commitId++ };
351
+ rootInstanceMap.set(root, rootInstance);
352
+ }
353
+ const { prevFiber } = rootInstance;
354
+ try {
355
+ if (prevFiber !== null) {
356
+ const wasMounted = prevFiber && prevFiber.memoizedState != null && prevFiber.memoizedState.element != null && // A dehydrated root is not considered mounted
357
+ prevFiber.memoizedState.isDehydrated !== true;
358
+ const isMounted = rootFiber.memoizedState != null && rootFiber.memoizedState.element != null && // A dehydrated root is not considered mounted
359
+ rootFiber.memoizedState.isDehydrated !== true;
360
+ if (!wasMounted && isMounted) {
361
+ mountFiberRecursively(onRender, rootFiber, false);
362
+ } else if (wasMounted && isMounted) {
363
+ updateFiberRecursively(
364
+ onRender,
365
+ rootFiber,
366
+ rootFiber.alternate,
367
+ null
368
+ );
369
+ } else if (wasMounted && !isMounted) {
370
+ unmountFiber(onRender, rootFiber);
371
+ }
372
+ } else {
373
+ mountFiberRecursively(onRender, rootFiber, false);
374
+ }
375
+ } catch (err) {
376
+ if (onError) {
377
+ onError(err);
378
+ } else {
379
+ throw err;
380
+ }
381
+ }
382
+ rootInstance.prevFiber = rootFiber;
383
+ };
384
+ };
385
+ var instrument = ({
386
+ onCommitFiberRoot,
387
+ onCommitFiberUnmount,
388
+ onPostCommitFiberRoot
389
+ }) => {
390
+ const devtoolsHook = getRDTHook();
391
+ const prevOnCommitFiberRoot = devtoolsHook.onCommitFiberRoot;
392
+ if (onCommitFiberRoot) {
393
+ devtoolsHook.onCommitFiberRoot = (rendererID, root) => {
394
+ if (prevOnCommitFiberRoot) prevOnCommitFiberRoot(rendererID, root);
395
+ onCommitFiberRoot(rendererID, root);
396
+ };
397
+ }
398
+ const prevOnCommitFiberUnmount = devtoolsHook.onCommitFiberUnmount;
399
+ if (onCommitFiberUnmount) {
400
+ devtoolsHook.onCommitFiberUnmount = (rendererID, root) => {
401
+ if (prevOnCommitFiberUnmount) prevOnCommitFiberUnmount(rendererID, root);
402
+ onCommitFiberUnmount(rendererID, root);
403
+ };
404
+ }
405
+ const prevOnPostCommitFiberRoot = devtoolsHook.onPostCommitFiberRoot;
406
+ if (onPostCommitFiberRoot) {
407
+ devtoolsHook.onPostCommitFiberRoot = (rendererID, root) => {
408
+ if (prevOnPostCommitFiberRoot) {
409
+ prevOnPostCommitFiberRoot(rendererID, root);
410
+ }
411
+ };
412
+ }
413
+ return devtoolsHook;
414
+ };
415
+
416
+ export { CONCURRENT_MODE_NUMBER, CONCURRENT_MODE_SYMBOL_STRING, ChildDeletion, ClassComponentTag, Cloned, ContentReset, ContextConsumerTag, DEPRECATED_ASYNC_MODE_SYMBOL_STRING, DehydratedSuspenseComponent, DidCapture, ForwardRefTag, Fragment, FunctionComponentTag, HostComponentTag, HostHoistableTag, HostRoot, HostSingletonTag, HostText, Hydrating, LegacyHiddenComponent, MemoComponentTag, MutationMask, OffscreenComponent, OffscreenComponentTag, PerformedWork, Placement, Ref, SimpleMemoComponentTag, Snapshot, SuspenseComponentTag, Update, Visibility, createFiberVisitor, didFiberCommit, didFiberRender, getDisplayName, getFiberStack, getMutatedHostFibers, getNearestHostFiber, getRDTHook, getTimings, getType, hasMemoCache, instrument, isCompositeFiber, isHostFiber, isValidElement, mountFiberRecursively, shouldFilterFiber, traverseContexts, traverseFiber, traverseProps, traverseState, unmountFiber, unmountFiberChildrenRecursively, updateFiberRecursively };
@@ -0,0 +1,17 @@
1
+ import { Fiber } from 'react-reconciler';
2
+
3
+ declare const getFPS: () => number;
4
+ declare const getFiberRenderScore: (fiber: Fiber) => {
5
+ unnecessary: number;
6
+ slow: number;
7
+ };
8
+ declare const isElementVisible: (el: HTMLElement) => boolean;
9
+ declare const getWindowDimensions: () => {
10
+ top: number;
11
+ left: number;
12
+ right: number;
13
+ bottom: number;
14
+ };
15
+ declare const isElementInViewport: (el: HTMLElement) => boolean;
16
+
17
+ export { getFPS, getFiberRenderScore, getWindowDimensions, isElementInViewport, isElementVisible };
@@ -0,0 +1,17 @@
1
+ import { Fiber } from 'react-reconciler';
2
+
3
+ declare const getFPS: () => number;
4
+ declare const getFiberRenderScore: (fiber: Fiber) => {
5
+ unnecessary: number;
6
+ slow: number;
7
+ };
8
+ declare const isElementVisible: (el: HTMLElement) => boolean;
9
+ declare const getWindowDimensions: () => {
10
+ top: number;
11
+ left: number;
12
+ right: number;
13
+ bottom: number;
14
+ };
15
+ declare const isElementInViewport: (el: HTMLElement) => boolean;
16
+
17
+ export { getFPS, getFiberRenderScore, getWindowDimensions, isElementInViewport, isElementVisible };
package/dist/score.js ADDED
@@ -0,0 +1,211 @@
1
+ 'use strict';
2
+
3
+ // src/index.ts
4
+ var ClassComponentTag = 1;
5
+ var FunctionComponentTag = 0;
6
+ var ContextConsumerTag = 9;
7
+ var ForwardRefTag = 11;
8
+ var MemoComponentTag = 14;
9
+ var SimpleMemoComponentTag = 15;
10
+ var HostComponentTag = 5;
11
+ var HostHoistableTag = 26;
12
+ var HostSingletonTag = 27;
13
+ var PerformedWork = 1;
14
+ var Placement = 2;
15
+ var Hydrating = 4096;
16
+ var Update = 4;
17
+ var Cloned = 8;
18
+ var ChildDeletion = 16;
19
+ var ContentReset = 32;
20
+ var Snapshot = 1024;
21
+ var Visibility = 8192;
22
+ var MutationMask = Placement | Update | ChildDeletion | ContentReset | Hydrating | Visibility | Snapshot;
23
+ var isHostFiber = (fiber) => fiber.tag === HostComponentTag || // @ts-expect-error: it exists
24
+ fiber.tag === HostHoistableTag || // @ts-expect-error: it exists
25
+ fiber.tag === HostSingletonTag;
26
+ var didFiberRender = (fiber) => {
27
+ const nextProps = fiber.memoizedProps;
28
+ const prevProps = fiber.alternate?.memoizedProps || {};
29
+ const flags = fiber.flags ?? fiber.effectTag ?? 0;
30
+ switch (fiber.tag) {
31
+ case ClassComponentTag:
32
+ case FunctionComponentTag:
33
+ case ContextConsumerTag:
34
+ case ForwardRefTag:
35
+ case MemoComponentTag:
36
+ case SimpleMemoComponentTag: {
37
+ return (flags & PerformedWork) === PerformedWork;
38
+ }
39
+ default:
40
+ if (!fiber.alternate) return true;
41
+ return prevProps !== nextProps || fiber.alternate.memoizedState !== fiber.memoizedState || fiber.alternate.ref !== fiber.ref;
42
+ }
43
+ };
44
+ var didFiberCommit = (fiber) => {
45
+ return Boolean(
46
+ fiber.subtreeFlags & (MutationMask | Cloned) || fiber.deletions
47
+ );
48
+ };
49
+ var getMutatedHostFibers = (fiber) => {
50
+ const mutations = [];
51
+ const visited = /* @__PURE__ */ new WeakSet();
52
+ const traverse = (node) => {
53
+ if (!node || visited.has(node)) return;
54
+ visited.add(node);
55
+ if (isHostFiber(node) && didFiberCommit(node.return ?? node) && didFiberRender(node)) {
56
+ mutations.push(node);
57
+ }
58
+ if (node.child) {
59
+ traverse(node.child);
60
+ }
61
+ if (node.sibling) {
62
+ traverse(node.sibling);
63
+ }
64
+ };
65
+ traverse(fiber);
66
+ return mutations;
67
+ };
68
+ var getNearestHostFiber = (fiber) => {
69
+ let hostFiber = traverseFiber(fiber, isHostFiber);
70
+ if (!hostFiber) {
71
+ hostFiber = traverseFiber(fiber, isHostFiber, true);
72
+ }
73
+ return hostFiber;
74
+ };
75
+ var traverseFiber = (fiber, selector, ascending = false) => {
76
+ if (!fiber) return null;
77
+ if (selector(fiber) === true) return fiber;
78
+ let child = ascending ? fiber.return : fiber.child;
79
+ while (child) {
80
+ const match = traverseFiber(child, selector, ascending);
81
+ if (match) return match;
82
+ child = ascending ? null : child.sibling;
83
+ }
84
+ return null;
85
+ };
86
+ var NO_OP = () => {
87
+ };
88
+ var getRDTHook = () => {
89
+ let rdtHook = globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;
90
+ const renderers = /* @__PURE__ */ new Map();
91
+ let i = 0;
92
+ rdtHook ??= {
93
+ checkDCE: NO_OP,
94
+ supportsFiber: true,
95
+ supportsFlight: true,
96
+ renderers,
97
+ onCommitFiberRoot: NO_OP,
98
+ onCommitFiberUnmount: NO_OP,
99
+ onPostCommitFiberRoot: NO_OP,
100
+ inject(renderer) {
101
+ const nextID = ++i;
102
+ renderers.set(nextID, renderer);
103
+ return nextID;
104
+ }
105
+ };
106
+ try {
107
+ globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__ = rdtHook;
108
+ } catch {
109
+ }
110
+ return rdtHook;
111
+ };
112
+ if (typeof window !== "undefined") {
113
+ getRDTHook();
114
+ }
115
+
116
+ // src/score.ts
117
+ var fps = 0;
118
+ var lastTime = performance.now();
119
+ var frameCount = 0;
120
+ var inited = false;
121
+ var getFPS = () => {
122
+ const updateFPS = () => {
123
+ frameCount++;
124
+ const now = performance.now();
125
+ if (now - lastTime >= 1e3) {
126
+ fps = frameCount;
127
+ frameCount = 0;
128
+ lastTime = now;
129
+ }
130
+ requestAnimationFrame(updateFPS);
131
+ };
132
+ if (!inited) {
133
+ inited = true;
134
+ updateFPS();
135
+ }
136
+ return fps;
137
+ };
138
+ var truncateFloat = (value, maxLen = 1e4) => {
139
+ if (typeof value === "number" && parseInt(value) !== value) {
140
+ value = ~~(value * maxLen) / maxLen;
141
+ }
142
+ return value;
143
+ };
144
+ var THRESHOLD_FPS = 60;
145
+ var getFiberRenderScore = (fiber) => {
146
+ const hostFiber = getNearestHostFiber(fiber);
147
+ const hasMutation = didFiberCommit(fiber);
148
+ const mutatedHostFibers = getMutatedHostFibers(fiber);
149
+ const isVisible = hostFiber && isElementVisible(hostFiber.stateNode) && isElementInViewport(hostFiber.stateNode);
150
+ const fps2 = getFPS();
151
+ let unnecessaryScore = (
152
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
153
+ isVisible || mutatedHostFibers.length || hasMutation ? 0 : 1
154
+ );
155
+ for (const mutatedHostFiber of mutatedHostFibers) {
156
+ const node = mutatedHostFiber.stateNode;
157
+ if (!isElementVisible(node) || !isElementInViewport(node)) {
158
+ unnecessaryScore += 1 / mutatedHostFibers.length;
159
+ }
160
+ }
161
+ return {
162
+ unnecessary: truncateFloat(unnecessaryScore),
163
+ slow: fps2 < THRESHOLD_FPS ? truncateFloat((THRESHOLD_FPS - fps2) / THRESHOLD_FPS) : 0
164
+ };
165
+ };
166
+ var isElementVisible = (el) => {
167
+ const style = window.getComputedStyle(el);
168
+ return style.display !== "none" && style.visibility !== "hidden" && style.contentVisibility !== "hidden" && style.opacity !== "0";
169
+ };
170
+ var initedEventListeners = false;
171
+ var scrollX = null;
172
+ var scrollY = null;
173
+ var innerWidth = null;
174
+ var innerHeight = null;
175
+ var getWindowDimensions = () => {
176
+ if (scrollX === null) scrollX = window.scrollX;
177
+ if (scrollY === null) scrollY = window.scrollY;
178
+ if (innerWidth === null) innerWidth = window.innerWidth;
179
+ if (innerHeight === null) innerHeight = window.innerHeight;
180
+ if (!initedEventListeners) {
181
+ initedEventListeners = true;
182
+ const handleResize = () => {
183
+ scrollX = null;
184
+ scrollY = null;
185
+ innerWidth = null;
186
+ innerHeight = null;
187
+ };
188
+ window.addEventListener("resize", handleResize);
189
+ window.addEventListener("scroll", handleResize);
190
+ }
191
+ return {
192
+ top: scrollY,
193
+ left: scrollX,
194
+ right: scrollX + innerWidth,
195
+ bottom: scrollY + innerHeight
196
+ };
197
+ };
198
+ var isElementInViewport = (el) => {
199
+ const elTop = el.offsetTop;
200
+ const elLeft = el.offsetLeft;
201
+ const elWidth = el.offsetWidth;
202
+ const elHeight = el.offsetHeight;
203
+ const { top, left, right, bottom } = getWindowDimensions();
204
+ return elTop + elHeight > top && elLeft + elWidth > left && elTop < bottom && elLeft < right;
205
+ };
206
+
207
+ exports.getFPS = getFPS;
208
+ exports.getFiberRenderScore = getFiberRenderScore;
209
+ exports.getWindowDimensions = getWindowDimensions;
210
+ exports.isElementInViewport = isElementInViewport;
211
+ exports.isElementVisible = isElementVisible;