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 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 { instrument, traverseFiber } from 'bippy';
22
-
23
- instrument({
24
- onCommitFiberRoot(_, root) {
25
- traverseFiber(root.current, (fiber) => {
26
- // will print every fiber in the current React tree
27
- console.log('fiber:', fiber);
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
- - `createFiberVisitor` to detect renders and `traverseFiber` to traverse the overall fiber tree
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
- - `createFiberVisitor` to traverse the fiber tree and determine which fibers have actually rendered
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. must be added before any other scripts run:
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
- ### createFiberVisitor
201
+ ### getRDTHook
181
202
 
182
- not every fiber in the fiber tree renders. `createFiberVisitor` allows you to traverse the fiber tree and determine which fibers have actually rendered.
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 { instrument, secure, createFiberVisitor } from 'bippy'; // must be imported BEFORE react
186
- import * as React from 'react';
206
+ import { getRDTHook } from 'bippy';
187
207
 
188
- const visit = createFiberVisitor({
189
- onRender(fiber) {
190
- console.log('fiber rendered', fiber);
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
- visit(rendererID, root);
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
- createFiberVisitor,
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
- visit(rendererID, root);
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
- createFiberVisitor,
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
- const visit = createFiberVisitor({
506
- onRender(fiber) {
507
- /**
508
- * `isCompositeFiber` is a utility function that checks if a fiber is a composite fiber.
509
- * a composite fiber is a fiber that represents a function or class component.
510
- */
511
- if (!isCompositeFiber(fiber)) return;
512
-
513
- /**
514
- * `getDisplayName` is a utility function that gets the display name of a fiber.
515
- */
516
- const displayName = getDisplayName(fiber);
517
- if (!displayName) return;
518
-
519
- const changes = [];
520
-
521
- /**
522
- * `traverseProps` is a utility function that traverses the props of a fiber.
523
- */
524
- traverseProps(fiber, (propName, next, prev) => {
525
- if (next !== prev) {
526
- changes.push({
527
- name: `prop ${propName}`,
528
- prev,
529
- next,
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
- let contextId = 0;
535
- /**
536
- * `traverseContexts` is a utility function that traverses the contexts of a fiber.
537
- * Contexts don't have a "name" like props, so we use an id to identify them.
538
- */
539
- traverseContexts(fiber, (next, prev) => {
540
- if (next !== prev) {
541
- changes.push({
542
- name: `context ${contextId}`,
543
- prev,
544
- next,
545
- contextId,
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
- let stateId = 0;
552
- /**
553
- * `traverseState` is a utility function that traverses the state of a fiber.
554
- *
555
- * State don't have a "name" like props, so we use an id to identify them.
556
- */
557
- traverseState(fiber, (value, prevValue) => {
558
- if (next !== prev) {
559
- changes.push({
560
- name: `state ${stateId}`,
561
- prev,
562
- next,
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
- instrument(
580
- secure({
581
- onCommitFiberRoot(rendererID, root) {
582
- visit(rendererID, root);
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
+