@appxiom/4react 0.1.6 → 0.1.7
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 +2 -2
- package/lifecycle/patch.js +27 -14
- package/lifecycle/react-internals.js +19 -0
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
|
|
18
18
|
## Requirements
|
|
19
19
|
|
|
20
|
-
- React 18 or
|
|
20
|
+
- React 18 or React 19.
|
|
21
21
|
- A browser environment. The SDK uses browser APIs and must not run during server-side rendering.
|
|
22
22
|
- Node.js 18 or later for package installation and builds.
|
|
23
23
|
|
|
@@ -90,7 +90,7 @@ ax.reportCustomIssue('Payment failed', 'Gateway timed out.', severity, {
|
|
|
90
90
|
|
|
91
91
|
After initialization, the integration adds automatic browser-side observation for React hook activity. It records lifecycle activity associated with `useEffect`, `useLayoutEffect`, `useState`, `useReducer`, `useMemo`, and `useCallback`. It also tracks `useRef` instances for leak analysis.
|
|
92
92
|
|
|
93
|
-
Initialize the package before rendering the application so the instrumentation is available when components begin rendering. These integrations are installed once per page and do not require component-level wrappers or hooks.
|
|
93
|
+
Initialize the package before rendering the application so the instrumentation is available when components begin rendering. These integrations are installed once per page and do not require component-level wrappers or hooks. React 18 and React 19 use different internal dispatcher locations; `@appxiom/4react` resolves the compatible location automatically.
|
|
94
94
|
|
|
95
95
|
## Vite
|
|
96
96
|
|
package/lifecycle/patch.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import React from 'react';
|
|
5
5
|
import { AX } from '@appxiom/core';
|
|
6
6
|
import { useRefLeakTracker } from '../memory/ax-react-useref-leak.js';
|
|
7
|
+
import { getDispatcherSlot, getReactInternals } from './react-internals.js';
|
|
7
8
|
|
|
8
9
|
function emitLifecycleEvent(name, payload = {}) {
|
|
9
10
|
try {
|
|
@@ -105,7 +106,7 @@ function getBestFrame(stack) {
|
|
|
105
106
|
}
|
|
106
107
|
|
|
107
108
|
function getComponentName() {
|
|
108
|
-
const internals = React
|
|
109
|
+
const internals = getReactInternals(React);
|
|
109
110
|
|
|
110
111
|
try {
|
|
111
112
|
const reactStack = internals?.getCurrentStack?.();
|
|
@@ -147,17 +148,24 @@ function wrapHook(dispatcher, name, wrapper) {
|
|
|
147
148
|
* Dispatcher patch (THIS is the critical layer)
|
|
148
149
|
* ----------------------------------------------------- */
|
|
149
150
|
function patchDispatcher() {
|
|
150
|
-
const internals =
|
|
151
|
-
|
|
151
|
+
const internals = getReactInternals(React);
|
|
152
|
+
const dispatcherSlot = getDispatcherSlot(internals);
|
|
153
|
+
|
|
154
|
+
if (!internals || !dispatcherSlot) return;
|
|
152
155
|
|
|
153
156
|
if (internals.__AX_DISPATCHER_PATCHED__) return;
|
|
154
|
-
|
|
157
|
+
try {
|
|
158
|
+
internals.__AX_DISPATCHER_PATCHED__ = true;
|
|
159
|
+
} catch {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
155
162
|
|
|
156
|
-
let currentDispatcher =
|
|
163
|
+
let currentDispatcher = dispatcherSlot.target[dispatcherSlot.key];
|
|
157
164
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
165
|
+
try {
|
|
166
|
+
Object.defineProperty(dispatcherSlot.target, dispatcherSlot.key, {
|
|
167
|
+
configurable: true,
|
|
168
|
+
get() {
|
|
161
169
|
const dispatcher = currentDispatcher;
|
|
162
170
|
|
|
163
171
|
if (!dispatcher || dispatcher.__AX_PATCHED__) {
|
|
@@ -276,12 +284,17 @@ function patchDispatcher() {
|
|
|
276
284
|
return original.apply(ctx, args);
|
|
277
285
|
});
|
|
278
286
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
287
|
+
return dispatcher;
|
|
288
|
+
},
|
|
289
|
+
set(v) {
|
|
290
|
+
currentDispatcher = v;
|
|
291
|
+
},
|
|
292
|
+
});
|
|
293
|
+
} catch {
|
|
294
|
+
try {
|
|
295
|
+
internals.__AX_DISPATCHER_PATCHED__ = false;
|
|
296
|
+
} catch {}
|
|
297
|
+
}
|
|
285
298
|
}
|
|
286
299
|
|
|
287
300
|
/* -------------------------------------------------------
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function getReactInternals(react) {
|
|
2
|
+
return react.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE
|
|
3
|
+
|| react.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
|
|
4
|
+
|| null;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function getDispatcherSlot(internals) {
|
|
8
|
+
if (!internals) return null;
|
|
9
|
+
|
|
10
|
+
if ('H' in internals) {
|
|
11
|
+
return { target: internals, key: 'H' };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
if (internals.ReactCurrentDispatcher) {
|
|
15
|
+
return { target: internals.ReactCurrentDispatcher, key: 'current' };
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
return null;
|
|
19
|
+
}
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"author": "BasilGregory Software Labs Private Limited",
|
|
6
6
|
"homepage": "https://appxiom.io",
|
|
7
|
-
"version": "0.1.
|
|
7
|
+
"version": "0.1.7",
|
|
8
8
|
"publishConfig": {
|
|
9
9
|
"access": "public"
|
|
10
10
|
},
|
|
@@ -29,10 +29,11 @@
|
|
|
29
29
|
"LICENSE"
|
|
30
30
|
],
|
|
31
31
|
"scripts": {
|
|
32
|
-
"check:files": "test -f index.js && test -f core/ax-react.js && test -f lifecycle/patch.js && test -f memory/ax-react-useref-leak.js",
|
|
32
|
+
"check:files": "test -f index.js && test -f core/ax-react.js && test -f lifecycle/patch.js && test -f lifecycle/react-internals.js && test -f memory/ax-react-useref-leak.js",
|
|
33
|
+
"check:react-compat": "node test/react-internals.test.js",
|
|
33
34
|
"check:types": "tsc --project test/types/tsconfig.json --noEmit",
|
|
34
35
|
"pack:dry-run": "npm pack --dry-run",
|
|
35
|
-
"prepublishOnly": "npm run check:files && npm run pack:dry-run"
|
|
36
|
+
"prepublishOnly": "npm run check:files && npm run check:react-compat && npm run pack:dry-run"
|
|
36
37
|
},
|
|
37
38
|
"sideEffects": true,
|
|
38
39
|
"main": "index.js",
|
|
@@ -44,7 +45,7 @@
|
|
|
44
45
|
"typescript": "^5.9.3"
|
|
45
46
|
},
|
|
46
47
|
"peerDependencies": {
|
|
47
|
-
"react": "
|
|
48
|
+
"react": "^18.0.0 || ^19.0.0"
|
|
48
49
|
},
|
|
49
50
|
"keywords": [
|
|
50
51
|
"appxiom",
|