bippy 0.1.1 → 0.2.1
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/README.md +141 -120
- package/dist/chunk-6TJRMCM3.js +1 -0
- package/dist/chunk-T46XOVG6.js +687 -0
- package/dist/chunk-XX2XAH3Z.cjs +750 -0
- package/dist/chunk-YZYCWAB2.cjs +2 -0
- package/dist/core-DBUthQlD.d.cts +261 -0
- package/dist/core-DBUthQlD.d.ts +261 -0
- package/dist/core.cjs +229 -737
- package/dist/core.d.cts +3 -185
- package/dist/core.d.ts +3 -185
- package/dist/core.js +1 -686
- package/dist/index.cjs +250 -742
- package/dist/index.d.cts +2 -3
- package/dist/index.d.ts +2 -3
- package/dist/index.global.js +1 -1
- package/dist/index.js +2 -686
- package/dist/inspect.cjs +1555 -0
- package/dist/inspect.d.cts +9 -0
- package/dist/inspect.d.ts +9 -0
- package/dist/inspect.js +1546 -0
- package/package.json +22 -6
- package/dist/scan/index.cjs +0 -1087
- package/dist/scan/index.d.cts +0 -24
- package/dist/scan/index.d.ts +0 -24
- package/dist/scan/index.global.js +0 -9
- package/dist/scan/index.js +0 -1079
- package/dist/types-CxxtX49h.d.cts +0 -69
- package/dist/types-CxxtX49h.d.ts +0 -69
package/README.md
CHANGED
|
@@ -18,18 +18,24 @@ by default, you cannot access react internals. bippy bypasses this by "pretendin
|
|
|
18
18
|
- no prior react source code knowledge required
|
|
19
19
|
|
|
20
20
|
```jsx
|
|
21
|
-
import {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
});
|
|
29
|
-
},
|
|
21
|
+
import { onCommitFiberRoot, traverseFiber } from 'bippy';
|
|
22
|
+
|
|
23
|
+
onCommitFiberRoot((root) => {
|
|
24
|
+
traverseFiber(root.current, (fiber) => {
|
|
25
|
+
// prints every fiber in the current React tree
|
|
26
|
+
console.log('fiber:', fiber);
|
|
27
|
+
});
|
|
30
28
|
});
|
|
31
29
|
```
|
|
32
30
|
|
|
31
|
+
or, use the `/inspect` subpackage to graphically visualize the fiber tree:
|
|
32
|
+
|
|
33
|
+
```jsx
|
|
34
|
+
import { Inspector } from 'bippy/inspect';
|
|
35
|
+
|
|
36
|
+
<Inspector enabled={true} />
|
|
37
|
+
```
|
|
38
|
+
|
|
33
39
|
<table>
|
|
34
40
|
<tbody>
|
|
35
41
|
<tr>
|
|
@@ -87,7 +93,7 @@ additionally, `memoizedProps`, `memoizedState`, and `dependencies` are the fiber
|
|
|
87
93
|
|
|
88
94
|
while all of the information is there, it's not super easy to work with, and changes frequently across different versions of react. bippy simplifies this by providing utility functions like:
|
|
89
95
|
|
|
90
|
-
- `
|
|
96
|
+
- `traverseRenderedFibers` to detect renders and `traverseFiber` to traverse the overall fiber tree
|
|
91
97
|
- _(instead of `child`, `sibling`, and `return` pointers)_
|
|
92
98
|
- `traverseProps`, `traverseState`, and `traverseContexts` to traverse the fiber's props, state, and contexts
|
|
93
99
|
- _(instead of `memoizedProps`, `memoizedState`, and `dependencies`)_
|
|
@@ -125,7 +131,7 @@ bippy works by monkey-patching `window.__REACT_DEVTOOLS_GLOBAL_HOOK__` with our
|
|
|
125
131
|
- _(instead of directly mutating `onCommitFiberRoot`, ...)_
|
|
126
132
|
- `secure` to wrap your handlers in a try/catch and determine if handlers are safe to run
|
|
127
133
|
- _(instead of rawdogging `window.__REACT_DEVTOOLS_GLOBAL_HOOK__` handlers, which may crash your app)_
|
|
128
|
-
- `
|
|
134
|
+
- `traverseRenderedFibers` to traverse the fiber tree and determine which fibers have actually rendered
|
|
129
135
|
- _(instead of `child`, `sibling`, and `return` pointers)_
|
|
130
136
|
- `traverseFiber` to traverse the fiber tree, regardless of whether it has rendered
|
|
131
137
|
- _(instead of `child`, `sibling`, and `return` pointers)_
|
|
@@ -142,7 +148,7 @@ this package should be imported before a React app runs. this will add a special
|
|
|
142
148
|
npm install bippy
|
|
143
149
|
```
|
|
144
150
|
|
|
145
|
-
or, use via script tag
|
|
151
|
+
or, use via script tag:
|
|
146
152
|
|
|
147
153
|
```html
|
|
148
154
|
<script src="https://unpkg.com/bippy"></script>
|
|
@@ -152,8 +158,23 @@ or, use via script tag. must be added before any other scripts run:
|
|
|
152
158
|
|
|
153
159
|
next, you can use the api to get data about the fiber tree. below is a (useful) subset of the api. for the full api, read the [source code](https://github.com/aidenybai/bippy/blob/main/src/core.ts).
|
|
154
160
|
|
|
161
|
+
|
|
162
|
+
### onCommitFiberRoot
|
|
163
|
+
|
|
164
|
+
a utility function that wraps the `instrument` function and sets the `onCommitFiberRoot` hook.
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
import { onCommitFiberRoot } from 'bippy';
|
|
168
|
+
|
|
169
|
+
onCommitFiberRoot((root) => {
|
|
170
|
+
console.log('root ready to commit', root);
|
|
171
|
+
});
|
|
172
|
+
```
|
|
173
|
+
|
|
155
174
|
### instrument
|
|
156
175
|
|
|
176
|
+
> the underlying implementation for the `onCommitFiberRoot()` function. this is optional, unless you want to plug into more less common, advanced functionality.
|
|
177
|
+
|
|
157
178
|
patches `window.__REACT_DEVTOOLS_GLOBAL_HOOK__` with your handlers. must be imported before react, and must be initialized to properly run any other methods.
|
|
158
179
|
|
|
159
180
|
> use with the `secure` function to prevent uncaught errors from crashing your app.
|
|
@@ -177,24 +198,31 @@ instrument(
|
|
|
177
198
|
);
|
|
178
199
|
```
|
|
179
200
|
|
|
180
|
-
###
|
|
201
|
+
### getRDTHook
|
|
181
202
|
|
|
182
|
-
|
|
203
|
+
returns the `window.__REACT_DEVTOOLS_GLOBAL_HOOK__` object. great for advanced use cases, such as accessing or modifying the `renderers` property.
|
|
183
204
|
|
|
184
205
|
```typescript
|
|
185
|
-
import {
|
|
186
|
-
import * as React from 'react';
|
|
206
|
+
import { getRDTHook } from 'bippy';
|
|
187
207
|
|
|
188
|
-
const
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
208
|
+
const hook = getRDTHook();
|
|
209
|
+
console.log(hook);
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### traverseRenderedFibers
|
|
213
|
+
|
|
214
|
+
not every fiber in the fiber tree renders. `traverseRenderedFibers` allows you to traverse the fiber tree and determine which fibers have actually rendered.
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
import { instrument, secure, traverseRenderedFibers } from 'bippy'; // must be imported BEFORE react
|
|
218
|
+
import * as React from 'react';
|
|
193
219
|
|
|
194
220
|
instrument(
|
|
195
221
|
secure({
|
|
196
222
|
onCommitFiberRoot(rendererID, root) {
|
|
197
|
-
|
|
223
|
+
traverseRenderedFibers(root, (fiber) => {
|
|
224
|
+
console.log('fiber rendered', fiber);
|
|
225
|
+
});
|
|
198
226
|
},
|
|
199
227
|
})
|
|
200
228
|
);
|
|
@@ -275,6 +303,7 @@ traverseContexts(fiber, (next, prev) => {
|
|
|
275
303
|
});
|
|
276
304
|
```
|
|
277
305
|
|
|
306
|
+
|
|
278
307
|
### setFiberId / getFiberId
|
|
279
308
|
|
|
280
309
|
set and get a persistent identity for a fiber. by default, fibers are anonymous and have no identity.
|
|
@@ -415,7 +444,7 @@ import {
|
|
|
415
444
|
instrument,
|
|
416
445
|
isHostFiber,
|
|
417
446
|
getNearestHostFiber,
|
|
418
|
-
|
|
447
|
+
traverseRenderedFibers,
|
|
419
448
|
} from 'bippy'; // must be imported BEFORE react
|
|
420
449
|
|
|
421
450
|
const highlightFiber = (fiber) => {
|
|
@@ -436,29 +465,6 @@ const highlightFiber = (fiber) => {
|
|
|
436
465
|
}, 100);
|
|
437
466
|
};
|
|
438
467
|
|
|
439
|
-
/**
|
|
440
|
-
* `createFiberVisitor` traverses the fiber tree and determines which
|
|
441
|
-
* fibers have actually rendered.
|
|
442
|
-
*
|
|
443
|
-
* A fiber tree contains many fibers that may have not rendered. this
|
|
444
|
-
* can be because it bailed out (e.g. `useMemo`) or because it wasn't
|
|
445
|
-
* actually rendered (if <Child> re-rendered, then <Parent> didn't
|
|
446
|
-
* actually render, but exists in the fiber tree).
|
|
447
|
-
*/
|
|
448
|
-
const visit = createFiberVisitor({
|
|
449
|
-
onRender(fiber) {
|
|
450
|
-
/**
|
|
451
|
-
* `getNearestHostFiber` is a utility function that finds the
|
|
452
|
-
* nearest host fiber to a given fiber.
|
|
453
|
-
*
|
|
454
|
-
* a host fiber for `react-dom` is a fiber that has a DOM element
|
|
455
|
-
* as its `stateNode`.
|
|
456
|
-
*/
|
|
457
|
-
const hostFiber = getNearestHostFiber(fiber);
|
|
458
|
-
highlightFiber(hostFiber);
|
|
459
|
-
},
|
|
460
|
-
});
|
|
461
|
-
|
|
462
468
|
/**
|
|
463
469
|
* `instrument` is a function that installs the react DevTools global
|
|
464
470
|
* hook and allows you to set up custom handlers for react fiber events.
|
|
@@ -480,7 +486,26 @@ instrument(
|
|
|
480
486
|
* the host tree (e.g. via DOM mutations).
|
|
481
487
|
*/
|
|
482
488
|
onCommitFiberRoot(rendererID, root) {
|
|
483
|
-
|
|
489
|
+
/**
|
|
490
|
+
* `traverseRenderedFibers` traverses the fiber tree and determines which
|
|
491
|
+
* fibers have actually rendered.
|
|
492
|
+
*
|
|
493
|
+
* A fiber tree contains many fibers that may have not rendered. this
|
|
494
|
+
* can be because it bailed out (e.g. `useMemo`) or because it wasn't
|
|
495
|
+
* actually rendered (if <Child> re-rendered, then <Parent> didn't
|
|
496
|
+
* actually render, but exists in the fiber tree).
|
|
497
|
+
*/
|
|
498
|
+
traverseRenderedFibers(root, (fiber) => {
|
|
499
|
+
/**
|
|
500
|
+
* `getNearestHostFiber` is a utility function that finds the
|
|
501
|
+
* nearest host fiber to a given fiber.
|
|
502
|
+
*
|
|
503
|
+
* a host fiber for `react-dom` is a fiber that has a DOM element
|
|
504
|
+
* as its `stateNode`.
|
|
505
|
+
*/
|
|
506
|
+
const hostFiber = getNearestHostFiber(fiber);
|
|
507
|
+
highlightFiber(hostFiber);
|
|
508
|
+
});
|
|
484
509
|
},
|
|
485
510
|
})
|
|
486
511
|
);
|
|
@@ -494,7 +519,7 @@ here's a mini toy version of [`why-did-you-render`](https://github.com/welldone-
|
|
|
494
519
|
import {
|
|
495
520
|
instrument,
|
|
496
521
|
isHostFiber,
|
|
497
|
-
|
|
522
|
+
traverseRenderedFibers,
|
|
498
523
|
isCompositeFiber,
|
|
499
524
|
getDisplayName,
|
|
500
525
|
traverseProps,
|
|
@@ -502,84 +527,80 @@ import {
|
|
|
502
527
|
traverseState,
|
|
503
528
|
} from 'bippy'; // must be imported BEFORE react
|
|
504
529
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
+
instrument(
|
|
531
|
+
secure({
|
|
532
|
+
onCommitFiberRoot(rendererID, root) {
|
|
533
|
+
traverseRenderedFibers(root, (fiber) => {
|
|
534
|
+
/**
|
|
535
|
+
* `isCompositeFiber` is a utility function that checks if a fiber is a composite fiber.
|
|
536
|
+
* a composite fiber is a fiber that represents a function or class component.
|
|
537
|
+
*/
|
|
538
|
+
if (!isCompositeFiber(fiber)) return;
|
|
539
|
+
|
|
540
|
+
/**
|
|
541
|
+
* `getDisplayName` is a utility function that gets the display name of a fiber.
|
|
542
|
+
*/
|
|
543
|
+
const displayName = getDisplayName(fiber);
|
|
544
|
+
if (!displayName) return;
|
|
545
|
+
|
|
546
|
+
const changes = [];
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* `traverseProps` is a utility function that traverses the props of a fiber.
|
|
550
|
+
*/
|
|
551
|
+
traverseProps(fiber, (propName, next, prev) => {
|
|
552
|
+
if (next !== prev) {
|
|
553
|
+
changes.push({
|
|
554
|
+
name: `prop ${propName}`,
|
|
555
|
+
prev,
|
|
556
|
+
next,
|
|
557
|
+
});
|
|
558
|
+
}
|
|
530
559
|
});
|
|
531
|
-
}
|
|
532
|
-
});
|
|
533
560
|
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
561
|
+
let contextId = 0;
|
|
562
|
+
/**
|
|
563
|
+
* `traverseContexts` is a utility function that traverses the contexts of a fiber.
|
|
564
|
+
* Contexts don't have a "name" like props, so we use an id to identify them.
|
|
565
|
+
*/
|
|
566
|
+
traverseContexts(fiber, (next, prev) => {
|
|
567
|
+
if (next !== prev) {
|
|
568
|
+
changes.push({
|
|
569
|
+
name: `context ${contextId}`,
|
|
570
|
+
prev,
|
|
571
|
+
next,
|
|
572
|
+
contextId,
|
|
573
|
+
});
|
|
574
|
+
}
|
|
575
|
+
contextId++;
|
|
546
576
|
});
|
|
547
|
-
}
|
|
548
|
-
contextId++;
|
|
549
|
-
});
|
|
550
577
|
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
578
|
+
let stateId = 0;
|
|
579
|
+
/**
|
|
580
|
+
* `traverseState` is a utility function that traverses the state of a fiber.
|
|
581
|
+
*
|
|
582
|
+
* State don't have a "name" like props, so we use an id to identify them.
|
|
583
|
+
*/
|
|
584
|
+
traverseState(fiber, (value, prevValue) => {
|
|
585
|
+
if (next !== prev) {
|
|
586
|
+
changes.push({
|
|
587
|
+
name: `state ${stateId}`,
|
|
588
|
+
prev,
|
|
589
|
+
next,
|
|
590
|
+
});
|
|
591
|
+
}
|
|
592
|
+
stateId++;
|
|
563
593
|
});
|
|
564
|
-
}
|
|
565
|
-
stateId++;
|
|
566
|
-
});
|
|
567
|
-
|
|
568
|
-
console.group(
|
|
569
|
-
`%c${displayName}`,
|
|
570
|
-
'background: hsla(0,0%,70%,.3); border-radius:3px; padding: 0 2px;'
|
|
571
|
-
);
|
|
572
|
-
for (const { name, prev, next } of changes) {
|
|
573
|
-
console.log(`${name}:`, prev, '!==', next);
|
|
574
|
-
}
|
|
575
|
-
console.groupEnd();
|
|
576
|
-
},
|
|
577
|
-
});
|
|
578
594
|
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
595
|
+
console.group(
|
|
596
|
+
`%c${displayName}`,
|
|
597
|
+
'background: hsla(0,0%,70%,.3); border-radius:3px; padding: 0 2px;'
|
|
598
|
+
);
|
|
599
|
+
for (const { name, prev, next } of changes) {
|
|
600
|
+
console.log(`${name}:`, prev, '!==', next);
|
|
601
|
+
}
|
|
602
|
+
console.groupEnd();
|
|
603
|
+
});
|
|
583
604
|
},
|
|
584
605
|
})
|
|
585
606
|
);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|