@memlab/lens 1.0.0 → 1.0.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.
Files changed (85) hide show
  1. package/LICENSE +21 -0
  2. package/dist/config/config.d.ts +22 -0
  3. package/dist/core/dom-observer.d.ts +10 -0
  4. package/dist/core/event-listener-tracker.d.ts +33 -0
  5. package/dist/core/react-fiber-analysis.d.ts +4 -0
  6. package/dist/core/react-memory-scan.d.ts +36 -0
  7. package/{src/core/types.ts → dist/core/types.d.ts} +56 -80
  8. package/{src/index.ts → dist/core/valid-component-name.d.ts} +2 -7
  9. package/dist/extensions/basic-extension.d.ts +30 -0
  10. package/dist/extensions/dom-visualization-extension.d.ts +17 -0
  11. package/dist/index.d.ts +1 -0
  12. package/dist/memlens.lib.bundle.js +1695 -0
  13. package/dist/memlens.lib.bundle.min.js +1 -0
  14. package/dist/memlens.lib.d.ts +12 -0
  15. package/dist/memlens.run.bundle.js +2673 -0
  16. package/dist/memlens.run.bundle.min.js +1 -0
  17. package/dist/memlens.run.d.ts +1 -0
  18. package/dist/tests/bundle/lib.bundle.test.d.ts +1 -0
  19. package/dist/tests/bundle/run.bundle.start.head.test.d.ts +1 -0
  20. package/dist/tests/bundle/run.bundle.start.test.d.ts +1 -0
  21. package/dist/tests/bundle/run.bundle.test.d.ts +1 -0
  22. package/dist/tests/fiber/dev.fiber.complex.dev.test.d.ts +1 -0
  23. package/dist/tests/fiber/dev.fiber.complex.list.dev.test.d.ts +1 -0
  24. package/dist/tests/fiber/dev.fiber.complex.prod.test.d.ts +1 -0
  25. package/dist/tests/fiber/dev.fiber.name.dev.test.d.ts +1 -0
  26. package/dist/tests/fiber/dev.fiber.name.prod.test.d.ts +1 -0
  27. package/dist/tests/utils/test-utils.d.ts +11 -0
  28. package/dist/utils/intersection-observer.d.ts +18 -0
  29. package/dist/utils/react-fiber-utils.d.ts +56 -0
  30. package/dist/utils/utils.d.ts +26 -0
  31. package/dist/utils/weak-ref-utils.d.ts +67 -0
  32. package/dist/visual/components/component-stack-panel.d.ts +11 -0
  33. package/dist/visual/components/control-widget.d.ts +13 -0
  34. package/dist/visual/components/overlay-rectangle.d.ts +11 -0
  35. package/dist/visual/components/status-text.d.ts +2 -0
  36. package/dist/visual/components/toggle-button.d.ts +3 -0
  37. package/dist/visual/components/visual-overlay.d.ts +1 -0
  38. package/dist/visual/dom-element-visualizer-interactive.d.ts +26 -0
  39. package/{src/core/valid-component-name.ts → dist/visual/dom-element-visualizer.d.ts} +5 -7
  40. package/dist/visual/visual-utils.d.ts +16 -0
  41. package/package.json +5 -1
  42. package/explainer.md +0 -54
  43. package/playwright.config.ts +0 -21
  44. package/src/config/config.ts +0 -32
  45. package/src/core/dom-observer.ts +0 -189
  46. package/src/core/event-listener-tracker.ts +0 -171
  47. package/src/core/react-fiber-analysis.ts +0 -123
  48. package/src/core/react-memory-scan.ts +0 -366
  49. package/src/extensions/basic-extension.ts +0 -41
  50. package/src/extensions/dom-visualization-extension.ts +0 -42
  51. package/src/memlens.lib.js.flow +0 -75
  52. package/src/memlens.lib.ts +0 -22
  53. package/src/memlens.run.ts +0 -21
  54. package/src/tests/bundle/lib.bundle.test.ts +0 -31
  55. package/src/tests/bundle/run.bundle.start.head.test.ts +0 -48
  56. package/src/tests/bundle/run.bundle.start.test.ts +0 -48
  57. package/src/tests/bundle/run.bundle.test.ts +0 -51
  58. package/src/tests/fiber/dev.fiber.complex.dev.test.ts +0 -92
  59. package/src/tests/fiber/dev.fiber.complex.list.dev.test.ts +0 -118
  60. package/src/tests/fiber/dev.fiber.complex.prod.test.ts +0 -92
  61. package/src/tests/fiber/dev.fiber.name.dev.test.ts +0 -77
  62. package/src/tests/fiber/dev.fiber.name.prod.test.ts +0 -79
  63. package/src/tests/lib/babel.prod.js +0 -4
  64. package/src/tests/lib/react-dom-v18.dev.js +0 -29926
  65. package/src/tests/lib/react-dom-v18.prod.js +0 -269
  66. package/src/tests/lib/react-v18.dev.js +0 -3345
  67. package/src/tests/lib/react-v18.prod.js +0 -33
  68. package/src/tests/manual/playwright-open-manual.js +0 -40
  69. package/src/tests/manual/todo-list/todo-with-run.bundle.html +0 -80
  70. package/src/tests/utils/test-utils.ts +0 -28
  71. package/src/utils/intersection-observer.ts +0 -65
  72. package/src/utils/react-fiber-utils.ts +0 -212
  73. package/src/utils/utils.ts +0 -201
  74. package/src/utils/weak-ref-utils.ts +0 -308
  75. package/src/visual/components/component-stack-panel.ts +0 -85
  76. package/src/visual/components/control-widget.ts +0 -96
  77. package/src/visual/components/overlay-rectangle.ts +0 -167
  78. package/src/visual/components/status-text.ts +0 -53
  79. package/src/visual/components/toggle-button.ts +0 -57
  80. package/src/visual/components/visual-overlay.ts +0 -19
  81. package/src/visual/dom-element-visualizer-interactive.ts +0 -358
  82. package/src/visual/dom-element-visualizer.ts +0 -130
  83. package/src/visual/visual-utils.ts +0 -89
  84. package/tsconfig.json +0 -18
  85. package/webpack.config.js +0 -105
@@ -1,33 +0,0 @@
1
- /* @generated */
2
- /* @nolint */
3
- /**
4
- * @license React
5
- * react.production.min.js
6
- *
7
- * Copyright (c) Facebook, Inc. and its affiliates.
8
- *
9
- * This source code is licensed under the MIT license found in the
10
- * LICENSE file in the root directory of this source tree.
11
- */
12
- (function(){'use strict';(function(c,x){"object"===typeof exports&&"undefined"!==typeof module?x(exports):"function"===typeof define&&define.amd?define(["exports"],x):(c=c||self,x(c.React={}))})(this,function(c){function x(a){if(null===a||"object"!==typeof a)return null;a=V&&a[V]||a["@@iterator"];return"function"===typeof a?a:null}function w(a,b,e){this.props=a;this.context=b;this.refs=W;this.updater=e||X}function Y(){}function K(a,b,e){this.props=a;this.context=b;this.refs=W;this.updater=e||X}function Z(a,b,
13
- e){var m,d={},c=null,h=null;if(null!=b)for(m in void 0!==b.ref&&(h=b.ref),void 0!==b.key&&(c=""+b.key),b)aa.call(b,m)&&!ba.hasOwnProperty(m)&&(d[m]=b[m]);var l=arguments.length-2;if(1===l)d.children=e;else if(1<l){for(var f=Array(l),k=0;k<l;k++)f[k]=arguments[k+2];d.children=f}if(a&&a.defaultProps)for(m in l=a.defaultProps,l)void 0===d[m]&&(d[m]=l[m]);return{$$typeof:y,type:a,key:c,ref:h,props:d,_owner:L.current}}function oa(a,b){return{$$typeof:y,type:a.type,key:b,ref:a.ref,props:a.props,_owner:a._owner}}
14
- function M(a){return"object"===typeof a&&null!==a&&a.$$typeof===y}function pa(a){var b={"=":"=0",":":"=2"};return"$"+a.replace(/[=:]/g,function(a){return b[a]})}function N(a,b){return"object"===typeof a&&null!==a&&null!=a.key?pa(""+a.key):b.toString(36)}function B(a,b,e,m,d){var c=typeof a;if("undefined"===c||"boolean"===c)a=null;var h=!1;if(null===a)h=!0;else switch(c){case "string":case "number":h=!0;break;case "object":switch(a.$$typeof){case y:case qa:h=!0}}if(h)return h=a,d=d(h),a=""===m?"."+
15
- N(h,0):m,ca(d)?(e="",null!=a&&(e=a.replace(da,"$&/")+"/"),B(d,b,e,"",function(a){return a})):null!=d&&(M(d)&&(d=oa(d,e+(!d.key||h&&h.key===d.key?"":(""+d.key).replace(da,"$&/")+"/")+a)),b.push(d)),1;h=0;m=""===m?".":m+":";if(ca(a))for(var l=0;l<a.length;l++){c=a[l];var f=m+N(c,l);h+=B(c,b,e,f,d)}else if(f=x(a),"function"===typeof f)for(a=f.call(a),l=0;!(c=a.next()).done;)c=c.value,f=m+N(c,l++),h+=B(c,b,e,f,d);else if("object"===c)throw b=String(a),Error("Objects are not valid as a React child (found: "+
16
- ("[object Object]"===b?"object with keys {"+Object.keys(a).join(", ")+"}":b)+"). If you meant to render a collection of children, use an array instead.");return h}function C(a,b,e){if(null==a)return a;var c=[],d=0;B(a,c,"","",function(a){return b.call(e,a,d++)});return c}function ra(a){if(-1===a._status){var b=a._result;b=b();b.then(function(b){if(0===a._status||-1===a._status)a._status=1,a._result=b},function(b){if(0===a._status||-1===a._status)a._status=2,a._result=b});-1===a._status&&(a._status=
17
- 0,a._result=b)}if(1===a._status)return a._result.default;throw a._result;}function O(a,b){var e=a.length;a.push(b);a:for(;0<e;){var c=e-1>>>1,d=a[c];if(0<D(d,b))a[c]=b,a[e]=d,e=c;else break a}}function p(a){return 0===a.length?null:a[0]}function E(a){if(0===a.length)return null;var b=a[0],e=a.pop();if(e!==b){a[0]=e;a:for(var c=0,d=a.length,k=d>>>1;c<k;){var h=2*(c+1)-1,l=a[h],f=h+1,g=a[f];if(0>D(l,e))f<d&&0>D(g,l)?(a[c]=g,a[f]=e,c=f):(a[c]=l,a[h]=e,c=h);else if(f<d&&0>D(g,e))a[c]=g,a[f]=e,c=f;else break a}}return b}
18
- function D(a,b){var c=a.sortIndex-b.sortIndex;return 0!==c?c:a.id-b.id}function P(a){for(var b=p(r);null!==b;){if(null===b.callback)E(r);else if(b.startTime<=a)E(r),b.sortIndex=b.expirationTime,O(q,b);else break;b=p(r)}}function Q(a){z=!1;P(a);if(!u)if(null!==p(q))u=!0,R(S);else{var b=p(r);null!==b&&T(Q,b.startTime-a)}}function S(a,b){u=!1;z&&(z=!1,ea(A),A=-1);F=!0;var c=k;try{P(b);for(n=p(q);null!==n&&(!(n.expirationTime>b)||a&&!fa());){var m=n.callback;if("function"===typeof m){n.callback=null;
19
- k=n.priorityLevel;var d=m(n.expirationTime<=b);b=v();"function"===typeof d?n.callback=d:n===p(q)&&E(q);P(b)}else E(q);n=p(q)}if(null!==n)var g=!0;else{var h=p(r);null!==h&&T(Q,h.startTime-b);g=!1}return g}finally{n=null,k=c,F=!1}}function fa(){return v()-ha<ia?!1:!0}function R(a){G=a;H||(H=!0,I())}function T(a,b){A=ja(function(){a(v())},b)}function ka(a){throw Error("act(...) is not supported in production builds of React.");}var y=Symbol.for("react.element"),qa=Symbol.for("react.portal"),sa=Symbol.for("react.fragment"),
20
- ta=Symbol.for("react.strict_mode"),ua=Symbol.for("react.profiler"),va=Symbol.for("react.provider"),wa=Symbol.for("react.context"),xa=Symbol.for("react.forward_ref"),ya=Symbol.for("react.suspense"),za=Symbol.for("react.memo"),Aa=Symbol.for("react.lazy"),V=Symbol.iterator,X={isMounted:function(a){return!1},enqueueForceUpdate:function(a,b,c){},enqueueReplaceState:function(a,b,c,m){},enqueueSetState:function(a,b,c,m){}},la=Object.assign,W={};w.prototype.isReactComponent={};w.prototype.setState=function(a,
21
- b){if("object"!==typeof a&&"function"!==typeof a&&null!=a)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,a,b,"setState")};w.prototype.forceUpdate=function(a){this.updater.enqueueForceUpdate(this,a,"forceUpdate")};Y.prototype=w.prototype;var t=K.prototype=new Y;t.constructor=K;la(t,w.prototype);t.isPureReactComponent=!0;var ca=Array.isArray,aa=Object.prototype.hasOwnProperty,L={current:null},
22
- ba={key:!0,ref:!0,__self:!0,__source:!0},da=/\/+/g,g={current:null},J={transition:null};if("object"===typeof performance&&"function"===typeof performance.now){var Ba=performance;var v=function(){return Ba.now()}}else{var ma=Date,Ca=ma.now();v=function(){return ma.now()-Ca}}var q=[],r=[],Da=1,n=null,k=3,F=!1,u=!1,z=!1,ja="function"===typeof setTimeout?setTimeout:null,ea="function"===typeof clearTimeout?clearTimeout:null,na="undefined"!==typeof setImmediate?setImmediate:null;"undefined"!==typeof navigator&&
23
- void 0!==navigator.scheduling&&void 0!==navigator.scheduling.isInputPending&&navigator.scheduling.isInputPending.bind(navigator.scheduling);var H=!1,G=null,A=-1,ia=5,ha=-1,U=function(){if(null!==G){var a=v();ha=a;var b=!0;try{b=G(!0,a)}finally{b?I():(H=!1,G=null)}}else H=!1};if("function"===typeof na)var I=function(){na(U)};else if("undefined"!==typeof MessageChannel){t=new MessageChannel;var Ea=t.port2;t.port1.onmessage=U;I=function(){Ea.postMessage(null)}}else I=function(){ja(U,0)};t={ReactCurrentDispatcher:g,
24
- ReactCurrentOwner:L,ReactCurrentBatchConfig:J,Scheduler:{__proto__:null,unstable_ImmediatePriority:1,unstable_UserBlockingPriority:2,unstable_NormalPriority:3,unstable_IdlePriority:5,unstable_LowPriority:4,unstable_runWithPriority:function(a,b){switch(a){case 1:case 2:case 3:case 4:case 5:break;default:a=3}var c=k;k=a;try{return b()}finally{k=c}},unstable_next:function(a){switch(k){case 1:case 2:case 3:var b=3;break;default:b=k}var c=k;k=b;try{return a()}finally{k=c}},unstable_scheduleCallback:function(a,
25
- b,c){var e=v();"object"===typeof c&&null!==c?(c=c.delay,c="number"===typeof c&&0<c?e+c:e):c=e;switch(a){case 1:var d=-1;break;case 2:d=250;break;case 5:d=1073741823;break;case 4:d=1E4;break;default:d=5E3}d=c+d;a={id:Da++,callback:b,priorityLevel:a,startTime:c,expirationTime:d,sortIndex:-1};c>e?(a.sortIndex=c,O(r,a),null===p(q)&&a===p(r)&&(z?(ea(A),A=-1):z=!0,T(Q,c-e))):(a.sortIndex=d,O(q,a),u||F||(u=!0,R(S)));return a},unstable_cancelCallback:function(a){a.callback=null},unstable_wrapCallback:function(a){var b=
26
- k;return function(){var c=k;k=b;try{return a.apply(this,arguments)}finally{k=c}}},unstable_getCurrentPriorityLevel:function(){return k},unstable_shouldYield:fa,unstable_requestPaint:function(){},unstable_continueExecution:function(){u||F||(u=!0,R(S))},unstable_pauseExecution:function(){},unstable_getFirstCallbackNode:function(){return p(q)},get unstable_now(){return v},unstable_forceFrameRate:function(a){0>a||125<a?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):
27
- ia=0<a?Math.floor(1E3/a):5},unstable_Profiling:null}};c.Children={map:C,forEach:function(a,b,c){C(a,function(){b.apply(this,arguments)},c)},count:function(a){var b=0;C(a,function(){b++});return b},toArray:function(a){return C(a,function(a){return a})||[]},only:function(a){if(!M(a))throw Error("React.Children.only expected to receive a single React element child.");return a}};c.Component=w;c.Fragment=sa;c.Profiler=ua;c.PureComponent=K;c.StrictMode=ta;c.Suspense=ya;c.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=
28
- t;c.act=ka;c.cloneElement=function(a,b,c){if(null===a||void 0===a)throw Error("React.cloneElement(...): The argument must be a React element, but you passed "+a+".");var e=la({},a.props),d=a.key,k=a.ref,h=a._owner;if(null!=b){void 0!==b.ref&&(k=b.ref,h=L.current);void 0!==b.key&&(d=""+b.key);if(a.type&&a.type.defaultProps)var l=a.type.defaultProps;for(f in b)aa.call(b,f)&&!ba.hasOwnProperty(f)&&(e[f]=void 0===b[f]&&void 0!==l?l[f]:b[f])}var f=arguments.length-2;if(1===f)e.children=c;else if(1<f){l=
29
- Array(f);for(var g=0;g<f;g++)l[g]=arguments[g+2];e.children=l}return{$$typeof:y,type:a.type,key:d,ref:k,props:e,_owner:h}};c.createContext=function(a){a={$$typeof:wa,_currentValue:a,_currentValue2:a,_threadCount:0,Provider:null,Consumer:null,_defaultValue:null,_globalName:null};a.Provider={$$typeof:va,_context:a};return a.Consumer=a};c.createElement=Z;c.createFactory=function(a){var b=Z.bind(null,a);b.type=a;return b};c.createRef=function(){return{current:null}};c.forwardRef=function(a){return{$$typeof:xa,
30
- render:a}};c.isValidElement=M;c.lazy=function(a){return{$$typeof:Aa,_payload:{_status:-1,_result:a},_init:ra}};c.memo=function(a,b){return{$$typeof:za,type:a,compare:void 0===b?null:b}};c.startTransition=function(a,b){b=J.transition;J.transition={};try{a()}finally{J.transition=b}};c.unstable_act=ka;c.useCallback=function(a,b){return g.current.useCallback(a,b)};c.useContext=function(a){return g.current.useContext(a)};c.useDebugValue=function(a,b){};c.useDeferredValue=function(a){return g.current.useDeferredValue(a)};
31
- c.useEffect=function(a,b){return g.current.useEffect(a,b)};c.useId=function(){return g.current.useId()};c.useImperativeHandle=function(a,b,c){return g.current.useImperativeHandle(a,b,c)};c.useInsertionEffect=function(a,b){return g.current.useInsertionEffect(a,b)};c.useLayoutEffect=function(a,b){return g.current.useLayoutEffect(a,b)};c.useMemo=function(a,b){return g.current.useMemo(a,b)};c.useReducer=function(a,b,c){return g.current.useReducer(a,b,c)};c.useRef=function(a){return g.current.useRef(a)};
32
- c.useState=function(a){return g.current.useState(a)};c.useSyncExternalStore=function(a,b,c){return g.current.useSyncExternalStore(a,b,c)};c.useTransition=function(){return g.current.useTransition()};c.version="18.3.1"});
33
- })();
@@ -1,40 +0,0 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @format
8
- * @oncall memory_lab
9
- */
10
- const path = require('path');
11
- const {chromium, devices} = require('playwright');
12
-
13
- // eslint-disable-next-line fb-www/async-iife-termination
14
- (async () => {
15
- const args = process.argv.slice(2);
16
- if (args.length === 0) {
17
- const scriptName = path.basename(__filename);
18
- console.error(`Usage: node ${scriptName} <path-to-html-file>`);
19
- process.exit(1);
20
- }
21
-
22
- let filePath = args[0];
23
- if (!path.isAbsolute(filePath)) {
24
- filePath = path.resolve(__dirname, filePath);
25
- }
26
-
27
- const browser = await chromium.launch({
28
- headless: false,
29
- args: ['--auto-open-devtools-for-tabs'],
30
- });
31
-
32
- const context = await browser.newContext({
33
- ...devices['Desktop Chrome'],
34
- });
35
-
36
- const page = await context.newPage();
37
- await page.goto('file://' + filePath);
38
-
39
- // Don’t close the browser so you can inspect
40
- })();
@@ -1,80 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
-
4
- <head>
5
- <meta charset="UTF-8" />
6
- <title>React To-Do</title>
7
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
- <script src="../../../../dist/run.bundle.js"></script>
9
- <script src="../../lib/react-v18.dev.js"></script>
10
- <script src="../../lib/react-dom-v18.dev.js"></script>
11
- <script src="../../lib/babel.prod.js"></script>
12
- <style>
13
- body {
14
- font-family: sans-serif;
15
- max-width: 600px;
16
- margin: 2rem auto;
17
- }
18
-
19
- input {
20
- padding: 0.5em;
21
- width: 70%;
22
- }
23
-
24
- button {
25
- padding: 0.5em;
26
- }
27
-
28
- li {
29
- margin: 0.5em 0;
30
- }
31
- </style>
32
- </head>
33
-
34
- <body>
35
- <h1>To-Do List</h1>
36
- <div id="root"></div>
37
-
38
- <script type="text/babel">
39
- const { useState } = React;
40
-
41
- function TodoApp() {
42
- const [todos, setTodos] = useState([]);
43
- const [input, setInput] = useState('');
44
-
45
- const handleAdd = () => {
46
- if (input.trim() === '') return;
47
- setTodos([...todos, { id: Date.now(), text: input }]);
48
- setInput('');
49
- };
50
-
51
- const handleDelete = (id) => {
52
- setTodos(todos.filter(todo => todo.id !== id));
53
- };
54
-
55
- return (
56
- <div>
57
- <input
58
- value={input}
59
- onChange={(e) => setInput(e.target.value)}
60
- placeholder="Add a task..."
61
- />
62
- <button onClick={handleAdd}>Add</button>
63
- <ul>
64
- {todos.map(todo => (
65
- <li key={todo.id}>
66
- {todo.text}
67
- <button onClick={() => handleDelete(todo.id)}> ❌ </button>
68
- </li>
69
- ))}
70
- </ul>
71
- </div>
72
- );
73
- }
74
-
75
- const root = ReactDOM.createRoot(document.getElementById('root'));
76
- root.render(<TodoApp />);
77
- </script>
78
- </body>
79
-
80
- </html>
@@ -1,28 +0,0 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @format
8
- * @oncall memory_lab
9
- */
10
- import path from 'path';
11
-
12
- // export a function that returns the absolute path to the dist folder
13
-
14
- export const distPath = path.join(__dirname, '..', '..', '..', 'dist');
15
- export const srcPath = path.join(__dirname, '..', '..', '..', 'src');
16
-
17
- export async function wait(timeoutInMs: number) {
18
- await new Promise(resolve => setTimeout(resolve, timeoutInMs));
19
- }
20
-
21
- export const libBundleFile = 'memlens.lib.bundle.js';
22
- export const libBundleFilePath = path.join(distPath, libBundleFile);
23
- export const libBundleMinFile = 'memlens.lib.bundle.min.js';
24
- export const libBundleMinFilePath = path.join(distPath, libBundleMinFile);
25
- export const runBundleFile = 'memlens.run.bundle.js';
26
- export const runBundleFilePath = path.join(distPath, runBundleFile);
27
- export const runBundleMinFile = 'memlens.run.bundle.min.js';
28
- export const runBundleMinFilePath = path.join(distPath, runBundleMinFile);
@@ -1,65 +0,0 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @format
8
- * @oncall memory_lab
9
- */
10
- export class IntersectionObserverManager {
11
- private static instance: IntersectionObserverManager;
12
- private observer: IntersectionObserver;
13
- private observedElements: Map<
14
- HTMLElement,
15
- (entry: IntersectionObserverEntry) => void
16
- > = new Map();
17
-
18
- private constructor() {
19
- this.observer = new IntersectionObserver(
20
- entries => {
21
- entries.forEach((entry: IntersectionObserverEntry) => {
22
- const element = entry.target as HTMLElement;
23
- const callback = this.observedElements.get(element);
24
- if (callback) {
25
- callback(entry);
26
- }
27
- });
28
- },
29
- {
30
- // Only trigger when element is completely out of viewport
31
- threshold: 0,
32
- // Add some margin to trigger before element is completely out of view
33
- rootMargin: '50px',
34
- },
35
- );
36
- }
37
-
38
- public static getInstance(): IntersectionObserverManager {
39
- if (!IntersectionObserverManager.instance) {
40
- IntersectionObserverManager.instance = new IntersectionObserverManager();
41
- }
42
- return IntersectionObserverManager.instance;
43
- }
44
-
45
- public observe(
46
- elementRef: WeakRef<HTMLElement>,
47
- callback: (entry: IntersectionObserverEntry) => void,
48
- ) {
49
- const element = elementRef.deref();
50
- if (element == null) {
51
- return;
52
- }
53
- this.observedElements.set(element, callback);
54
- this.observer.observe(element);
55
- }
56
-
57
- public unobserve(elementRef: WeakRef<HTMLElement>) {
58
- const element = elementRef.deref();
59
- if (element == null) {
60
- return;
61
- }
62
- this.observedElements.delete(element);
63
- this.observer.unobserve(element);
64
- }
65
- }
@@ -1,212 +0,0 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @format
8
- * @oncall memory_lab
9
- */
10
- import type {Fiber} from 'react-reconciler';
11
- import type {Nullable, Optional, AnyValue} from '../core/types';
12
- import {getMeaningfulName} from './utils';
13
- import {isValidComponentName} from '../core/valid-component-name';
14
-
15
- export const ClassComponentTag = 1;
16
- export const FunctionComponentTag = 0;
17
- export const ContextConsumerTag = 9;
18
- export const SuspenseComponentTag = 13;
19
- export const OffscreenComponentTag = 22;
20
- export const ForwardRefTag = 11;
21
- export const MemoComponentTag = 14;
22
- export const SimpleMemoComponentTag = 15;
23
- export const HostComponentTag = 5;
24
- export const HostHoistableTag = 26;
25
- export const HostSingletonTag = 27;
26
- export const DehydratedSuspenseComponent = 18;
27
- export const HostText = 6;
28
- export const Fragment = 7;
29
- export const LegacyHiddenComponent = 23;
30
- export const OffscreenComponent = 22;
31
- export const HostRoot = 3;
32
- export const CONCURRENT_MODE_NUMBER = 0xeacf;
33
- export const CONCURRENT_MODE_SYMBOL_STRING = 'Symbol(react.concurrent_mode)';
34
- export const DEPRECATED_ASYNC_MODE_SYMBOL_STRING = 'Symbol(react.async_mode)';
35
-
36
- // https://github.com/facebook/react/blob/main/packages/react-reconciler/src/ReactFiberFlags.js
37
- export const PerformedWork = 0b1;
38
- export const Placement = 0b10;
39
- export const DidCapture = 0b10000000;
40
- export const Hydrating = 0b1000000000000;
41
- export const Update = 0b100;
42
- export const Cloned = 0b1000;
43
- export const ChildDeletion = 0b10000;
44
- export const ContentReset = 0b100000;
45
- export const Ref = 0b1000000000;
46
- export const Snapshot = 0b10000000000;
47
- export const Visibility = 0b10000000000000;
48
- export const MutationMask =
49
- Placement |
50
- Update |
51
- ChildDeletion |
52
- ContentReset |
53
- Hydrating |
54
- Visibility |
55
- Snapshot;
56
-
57
- /**
58
- * @see https://reactnative.dev/architecture/glossary#host-view-tree-and-host-view
59
- */
60
- export const isHostFiber = (fiber: Fiber) =>
61
- fiber.tag === HostComponentTag ||
62
- // @ts-expect-error: it exists
63
- fiber.tag === HostHoistableTag ||
64
- // @ts-expect-error: it exists
65
- fiber.tag === HostSingletonTag ||
66
- typeof fiber.type === 'string';
67
-
68
- export const getNearestHostFiber = (fiber: Fiber) => {
69
- let hostFiber = traverseFiber(fiber, isHostFiber);
70
- if (!hostFiber) {
71
- hostFiber = traverseFiber(fiber, isHostFiber, true);
72
- }
73
- return hostFiber;
74
- };
75
-
76
- export const getTopMostHostFiber = (fiber: Fiber): Nullable<Fiber> => {
77
- let topMostHostFiber: Nullable<Fiber> = null;
78
- function checkFiber(fiber: Fiber): void {
79
- if (isHostFiber(fiber)) {
80
- topMostHostFiber = fiber;
81
- }
82
- }
83
- traverseFiber(fiber, checkFiber, true);
84
- return topMostHostFiber;
85
- };
86
-
87
- export const getTopMostFiberWithChild = (fiber: Fiber): Nullable<Fiber> => {
88
- let topMostFiber: Nullable<Fiber> = null;
89
- function checkFiber(fiber: Fiber): void {
90
- if (fiber.child != null) {
91
- topMostFiber = fiber;
92
- }
93
- }
94
- traverseFiber(fiber, checkFiber, true);
95
- return topMostFiber;
96
- };
97
-
98
- export const traverseFiber = (
99
- fiber: Nullable<Fiber>,
100
- selector: (node: Fiber) => boolean | void,
101
- ascending = false,
102
- ): Nullable<Fiber> => {
103
- if (!fiber) {
104
- return null;
105
- }
106
- if (selector(fiber) === true) {
107
- return fiber;
108
- }
109
-
110
- let next = ascending ? fiber.return : fiber.child;
111
- while (next) {
112
- const match = traverseFiber(next, selector, ascending);
113
- if (match) {
114
- return match;
115
- }
116
- next = ascending ? null : next.sibling;
117
- }
118
- return null;
119
- };
120
-
121
- // React internal property keys
122
- const internalKeys = [
123
- '__reactFiber$', // React 17+
124
- '__reactInternalInstance$', // React 16
125
- '_reactRootContainer', // React Root
126
- ];
127
-
128
- const getOwnPropertyNames = Object.getOwnPropertyNames.bind(Object);
129
-
130
- export function getFiberNodeFromElement(element: Element) {
131
- for (const prefix of internalKeys) {
132
- // Use Object.keys only as fallback since it's slower
133
- const key = getOwnPropertyNames(element).find(k => k.startsWith(prefix));
134
-
135
- if (key) {
136
- return (element as AnyValue)[key];
137
- }
138
- }
139
- return null;
140
- }
141
-
142
- export function getReactComponentStack(node: Fiber): Array<string> {
143
- const stack = [];
144
- const visited = new Set<Fiber>();
145
- let fiber: Nullable<Fiber> = node;
146
- while (fiber) {
147
- if (visited.has(fiber)) {
148
- break;
149
- }
150
- visited.add(fiber);
151
- const name = getDisplayNameOfFiberNode(fiber);
152
- if (name) {
153
- stack.push(name);
154
- }
155
- fiber = fiber.return;
156
- }
157
- return stack;
158
- }
159
-
160
- export function getDisplayNameOfFiberNode(node: Fiber) {
161
- const elementType = node.type ?? node.elementType;
162
-
163
- // Try to get name from displayName or name properties
164
- let displayName: Optional<string> =
165
- elementType?.displayName ?? elementType?.name;
166
-
167
- // Handle class components and forwardRef
168
- if (displayName == null) {
169
- if (elementType?.render) {
170
- // Class components
171
- const render = elementType?.render;
172
- displayName = render?.displayName ?? render?.name;
173
- } else if (elementType?.type) {
174
- // ForwardRef components
175
- displayName = elementType.type.displayName ?? elementType.type.name;
176
- }
177
- }
178
-
179
- // Handle anonymous functions
180
- if (!displayName && typeof elementType === 'function') {
181
- displayName = elementType.name;
182
- }
183
- const ret = getMeaningfulName(extractReactComponentName(displayName));
184
- return isValidComponentName(ret) ? ret : null;
185
- }
186
-
187
- export function isFunctionalComponent(node: Fiber) {
188
- const elementType = node?.elementType;
189
- return typeof elementType === 'function';
190
- }
191
-
192
- // dom-element [from component.react] --> component.react
193
- export function extractReactComponentName(
194
- displayName: Optional<string>,
195
- ): Nullable<string> {
196
- if (typeof displayName !== 'string') {
197
- return null;
198
- }
199
- if (!displayName.includes('[') || !displayName.includes(']')) {
200
- return displayName;
201
- }
202
- const startIndex = displayName.indexOf('[');
203
- const endIndex = displayName.indexOf(']');
204
- if (startIndex > endIndex) {
205
- return displayName;
206
- }
207
- const name = displayName.substring(startIndex + 1, endIndex);
208
- if (name.startsWith('from ')) {
209
- return name.substring('from '.length);
210
- }
211
- return name;
212
- }
@@ -1,201 +0,0 @@
1
- /**
2
- * Copyright (c) Meta Platforms, Inc. and affiliates.
3
- *
4
- * This source code is licensed under the MIT license found in the
5
- * LICENSE file in the root directory of this source tree.
6
- *
7
- * @format
8
- * @oncall memory_lab
9
- */
10
- import type {
11
- BoundingRect,
12
- Nullable,
13
- AnyValue,
14
- ObjectValue,
15
- } from '../core/types';
16
- import {isVisualizerElement} from '../visual/visual-utils';
17
-
18
- export function getDOMElements(): Array<WeakRef<Element>> {
19
- const elements = Array.from(document.querySelectorAll('*'));
20
- const ret = [];
21
- for (const element of elements) {
22
- if (isVisualizerElement(element)) {
23
- continue;
24
- }
25
- ret.push(new WeakRef(element));
26
- }
27
- return ret;
28
- }
29
-
30
- export function getDOMElementCount(): number {
31
- const elements = Array.from(document.querySelectorAll('*'));
32
- let ret = 0;
33
- for (const element of elements) {
34
- if (isVisualizerElement(element)) {
35
- continue;
36
- }
37
- ++ret;
38
- }
39
- return ret;
40
- }
41
-
42
- export function getMeaningfulName(name: Nullable<string>) {
43
- if (name == null) {
44
- return null;
45
- }
46
- const isMinified = isMinifiedName(name);
47
- return isMinified ? null : name;
48
- }
49
-
50
- /**
51
- * Determines if a given function or class name is minified.
52
- *
53
- * @param {string} name - The function or class name to check.
54
- * @return {boolean} - Returns true if the name is likely minified, otherwise false.
55
- */
56
- export function isMinifiedName(name: string): boolean {
57
- if (name.length >= 5) {
58
- return false;
59
- }
60
- // Minified names are often very short, e.g., "a", "b", "c"
61
- if (name.length <= 3) {
62
- return true;
63
- }
64
-
65
- // Names with non-alphanumeric characters (except $ and _) are unlikely to be minified
66
- if (/[^a-zA-Z0-9$_]/.test(name)) {
67
- return false;
68
- }
69
-
70
- // Minified names rarely have meaningful words (detect camelCase or PascalCase)
71
- const hasMeaningfulPattern =
72
- /^[A-Z][a-z]+([A-Z][a-z]*)*$|^[a-z]+([A-Z][a-z]*)*$/.test(name);
73
- return !hasMeaningfulPattern;
74
- }
75
-
76
- export function addCountbyKey<K extends ObjectValue>(
77
- map: WeakMap<K, number>,
78
- key: K,
79
- count: number,
80
- ) {
81
- map.set(key, (map.get(key) ?? 0) + count);
82
- }
83
-
84
- export function updateWeakRefList(
85
- weakRefList: Array<WeakRef<Element>>,
86
- elementRefs: Array<WeakRef<Element>>,
87
- ) {
88
- consolidateWeakRefList(weakRefList);
89
- const set = getElementsSet(weakRefList);
90
- for (const elementRef of elementRefs) {
91
- const element = elementRef.deref();
92
- if (element == null || set.has(element)) {
93
- continue;
94
- }
95
- set.add(element);
96
- weakRefList.push(new WeakRef(element));
97
- }
98
- return weakRefList;
99
- }
100
-
101
- function getElementsSet(weakRefList: Array<WeakRef<Element>>) {
102
- const set = new Set();
103
- for (const weakRef of weakRefList) {
104
- set.add(weakRef.deref());
105
- }
106
- return set;
107
- }
108
-
109
- function consolidateWeakRefList(weakRefList: Array<WeakRef<Element>>) {
110
- const alternative = [];
111
- for (const weakRef of weakRefList) {
112
- const element = weakRef.deref();
113
- if (element == null) {
114
- continue;
115
- }
116
- alternative.push(weakRef);
117
- }
118
- while (weakRefList.length > 0) {
119
- weakRefList.pop();
120
- }
121
- for (const weakRef of alternative) {
122
- weakRefList.push(weakRef);
123
- }
124
- return weakRefList;
125
- }
126
-
127
- export function getBoundingClientRect(
128
- element: Element,
129
- ): Nullable<BoundingRect> {
130
- if (element == null) {
131
- return null;
132
- }
133
- if (typeof element.getBoundingClientRect !== 'function') {
134
- return null;
135
- }
136
- let rect = null;
137
- try {
138
- rect = element.getBoundingClientRect();
139
- } catch {
140
- // do nothing
141
- }
142
- if (rect == null) {
143
- return null;
144
- }
145
- const scrollTop = window.scrollY;
146
- const scrollLeft = window.scrollX;
147
- const ret: BoundingRect = {} as unknown as BoundingRect;
148
- ret.bottom = rect.bottom;
149
- ret.height = rect.height;
150
- ret.left = rect.left;
151
- ret.right = rect.right;
152
- ret.top = rect.top;
153
- ret.width = rect.width;
154
- ret.x = rect.x;
155
- ret.y = rect.y;
156
- ret.scrollLeft = scrollLeft;
157
- ret.scrollTop = scrollTop;
158
- return ret as BoundingRect;
159
- }
160
-
161
- const _console = console;
162
- const _consoleLog = _console.log;
163
-
164
- export function consoleLog(...args: AnyValue[]) {
165
- _consoleLog.apply(_console, args);
166
- }
167
-
168
- const SESSION_STORAGE_KEY = 'memory_lens_session';
169
-
170
- function isSessionStorageAvailable(): boolean {
171
- try {
172
- const testKey = '__memory_lens_session_test__';
173
- sessionStorage.setItem(testKey, '1');
174
- sessionStorage.removeItem(testKey);
175
- return true;
176
- } catch {
177
- return false;
178
- }
179
- }
180
-
181
- export function hasRunInSession(): boolean {
182
- if (!isSessionStorageAvailable()) {
183
- return false;
184
- }
185
- try {
186
- return sessionStorage.getItem(SESSION_STORAGE_KEY) === 'true';
187
- } catch {
188
- return false;
189
- }
190
- }
191
-
192
- export function setRunInSession(): void {
193
- if (!isSessionStorageAvailable()) {
194
- return;
195
- }
196
- try {
197
- sessionStorage.setItem(SESSION_STORAGE_KEY, 'true');
198
- } catch {
199
- // do nothing
200
- }
201
- }