bippy 0.6.1-dev.3a24abf → 0.6.1-dev.b88fcb4
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/LICENSE +1 -1
- package/README.md +7 -1
- package/dist/core.cjs +1 -1
- package/dist/core.d.cts +39 -41
- package/dist/core.d.ts +39 -41
- package/dist/core.js +1 -1
- package/dist/core2.cjs +1 -1
- package/dist/core2.d.cts +11 -3
- package/dist/core2.d.ts +11 -3
- package/dist/core2.js +1 -1
- package/dist/{types.d.cts → errors.d.cts} +205 -31
- package/dist/{types.d.ts → errors.d.ts} +205 -31
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +11 -3
- package/dist/index.d.ts +11 -3
- package/dist/index.iife.js +1 -1
- package/dist/index.js +1 -1
- package/dist/install-hook-only.cjs +1 -1
- package/dist/install-hook-only.d.cts +8 -0
- package/dist/install-hook-only.d.ts +8 -0
- package/dist/install-hook-only.iife.js +1 -1
- package/dist/install-hook-only.js +1 -1
- package/dist/rdt-hook.cjs +1 -1
- package/dist/rdt-hook.js +1 -1
- package/dist/source.cjs +13 -13
- package/dist/source.d.cts +27 -9
- package/dist/source.d.ts +27 -9
- package/dist/source.js +13 -13
- package/package.json +10 -6
- package/src/core.ts +269 -224
- package/src/errors.ts +99 -0
- package/src/rdt-hook.ts +154 -99
- package/src/react-internals/generated/react-work-tags.ts +314 -0
- package/src/react-internals/index.ts +67 -0
- package/src/react-internals/semver.ts +78 -0
- package/src/{types.ts → react-internals/types.ts} +13 -3
- package/src/source/error-stack.ts +11 -0
- package/src/source/get-display-name-from-source.ts +1 -1
- package/src/source/get-source.ts +2 -2
- package/src/source/index.ts +9 -1
- package/src/source/inspect-hooks.ts +199 -165
- package/src/source/owner-stack.ts +26 -39
- package/src/source/parse-debug-stack.ts +4 -4
- package/src/source/parse-hook-names.ts +1 -1
- package/src/source/symbolication.ts +468 -101
- package/src/generated/react-work-tags.ts +0 -169
- package/src/react-internals.ts +0 -67
- package/src/unsubscribe.ts +0 -17
package/src/errors.ts
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
export class BippyError extends Error {
|
|
2
|
+
constructor(message: string, cause?: unknown) {
|
|
3
|
+
super(message, { cause });
|
|
4
|
+
this.name = "BippyError";
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class BippyInstrumentationError extends BippyError {
|
|
9
|
+
readonly callbackName: string;
|
|
10
|
+
readonly instrumentationName: string;
|
|
11
|
+
|
|
12
|
+
constructor(instrumentationName: string, callbackName: string, cause: unknown) {
|
|
13
|
+
super(
|
|
14
|
+
`Bippy instrumentation "${instrumentationName}" callback "${callbackName}" failed`,
|
|
15
|
+
cause,
|
|
16
|
+
);
|
|
17
|
+
this.name = "BippyInstrumentationError";
|
|
18
|
+
this.callbackName = callbackName;
|
|
19
|
+
this.instrumentationName = instrumentationName;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export class BippyReactDevToolsError extends BippyError {
|
|
24
|
+
readonly callbackName: string;
|
|
25
|
+
|
|
26
|
+
constructor(callbackName: string, cause: unknown) {
|
|
27
|
+
super(`React DevTools callback "${callbackName}" failed`, cause);
|
|
28
|
+
this.name = "BippyReactDevToolsError";
|
|
29
|
+
this.callbackName = callbackName;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export class BippyHookListenerError extends BippyError {
|
|
34
|
+
readonly listenerName: string;
|
|
35
|
+
|
|
36
|
+
constructor(listenerName: string, cause: unknown) {
|
|
37
|
+
super(`Bippy hook listener "${listenerName}" failed`, cause);
|
|
38
|
+
this.name = "BippyHookListenerError";
|
|
39
|
+
this.listenerName = listenerName;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export class BippyHookInstallationError extends BippyError {
|
|
44
|
+
constructor(cause: unknown) {
|
|
45
|
+
super("Bippy could not install the React DevTools hook", cause);
|
|
46
|
+
this.name = "BippyHookInstallationError";
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export class BippyReactBuildError extends BippyError {
|
|
51
|
+
constructor(message: string, cause?: unknown) {
|
|
52
|
+
super(message, cause);
|
|
53
|
+
this.name = "BippyReactBuildError";
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export class BippyHookInspectionError extends BippyError {
|
|
58
|
+
constructor(message: string, cause?: unknown) {
|
|
59
|
+
super(message, cause);
|
|
60
|
+
this.name = "BippyHookInspectionError";
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export class BippyUnsupportedHookError extends BippyHookInspectionError {
|
|
65
|
+
constructor(message: string, cause?: unknown) {
|
|
66
|
+
super(message, cause);
|
|
67
|
+
this.name = "BippyUnsupportedHookError";
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export class BippyHookRenderError extends BippyHookInspectionError {
|
|
72
|
+
constructor(message: string, cause?: unknown) {
|
|
73
|
+
super(message, cause);
|
|
74
|
+
this.name = "BippyHookRenderError";
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export class BippySourceMapError extends BippyError {
|
|
79
|
+
constructor(message: string, cause?: unknown) {
|
|
80
|
+
super(message, cause);
|
|
81
|
+
this.name = "BippySourceMapError";
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
interface BippyErrorFactory {
|
|
86
|
+
(cause: unknown): BippyError;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export const runWithBippyError = <Result>(
|
|
90
|
+
callback: () => Result,
|
|
91
|
+
createError: BippyErrorFactory,
|
|
92
|
+
): Result => {
|
|
93
|
+
try {
|
|
94
|
+
return callback();
|
|
95
|
+
} catch (cause) {
|
|
96
|
+
if (cause instanceof BippyError) throw cause;
|
|
97
|
+
throw createError(cause);
|
|
98
|
+
}
|
|
99
|
+
};
|
package/src/rdt-hook.ts
CHANGED
|
@@ -1,23 +1,50 @@
|
|
|
1
1
|
// This module must load before React so renderers can inject into the hook.
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
|
|
3
|
+
import {
|
|
4
|
+
BippyHookInstallationError,
|
|
5
|
+
BippyHookListenerError,
|
|
6
|
+
BippyReactBuildError,
|
|
7
|
+
runWithBippyError,
|
|
8
|
+
} from "./errors.js";
|
|
9
|
+
import type { ReactDevToolsGlobalHook, ReactRenderer } from "./react-internals/index.js";
|
|
10
|
+
|
|
11
|
+
export interface Unsubscribe extends Disposable {
|
|
12
|
+
(): void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface ActiveListener {
|
|
16
|
+
(): unknown;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface RendererInjectListener {
|
|
20
|
+
(renderer: ReactRenderer): void;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
interface RDTHookReplaceListener {
|
|
24
|
+
(rdtHook: ReactDevToolsGlobalHook): void;
|
|
25
|
+
}
|
|
5
26
|
|
|
6
27
|
export const version = process.env.VERSION;
|
|
7
28
|
export const BIPPY_INSTRUMENTATION_STRING = `bippy-${version}`;
|
|
8
29
|
|
|
9
30
|
const objectDefineProperty = Object.defineProperty;
|
|
10
|
-
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
11
|
-
const objectHasOwnProperty = Object.prototype.hasOwnProperty;
|
|
12
31
|
|
|
13
|
-
const
|
|
32
|
+
const noOp = (): void => {};
|
|
33
|
+
|
|
34
|
+
export const createUnsubscribe = (unsubscribe: () => void): Unsubscribe =>
|
|
35
|
+
Object.assign(unsubscribe, { [Symbol.dispose]: unsubscribe });
|
|
36
|
+
|
|
37
|
+
const runHookListener = (listenerName: string, callback: () => unknown): void => {
|
|
38
|
+
runWithBippyError(callback, (cause) => new BippyHookListenerError(listenerName, cause));
|
|
39
|
+
};
|
|
14
40
|
|
|
15
41
|
const checkDCE = (functionToCheck: unknown): void => {
|
|
16
42
|
try {
|
|
17
43
|
const code = Function.prototype.toString.call(functionToCheck);
|
|
18
44
|
if (code.includes("^_^")) {
|
|
45
|
+
// HACK: React DevTools reports failed dead-code elimination asynchronously.
|
|
19
46
|
setTimeout(() => {
|
|
20
|
-
throw new
|
|
47
|
+
throw new BippyReactBuildError(
|
|
21
48
|
"React is running in production mode, but dead code " +
|
|
22
49
|
"elimination has not been applied. Read how to correctly " +
|
|
23
50
|
"configure React for production: " +
|
|
@@ -34,49 +61,75 @@ export const isRealReactDevtools = (
|
|
|
34
61
|
return Boolean(rdtHook && "getFiberRoots" in rdtHook);
|
|
35
62
|
};
|
|
36
63
|
|
|
37
|
-
export const _onActiveListeners = new Set<
|
|
64
|
+
export const _onActiveListeners = new Set<ActiveListener>();
|
|
38
65
|
|
|
39
66
|
export const _renderers = new Set<ReactRenderer>();
|
|
40
67
|
|
|
41
|
-
const rendererInjectListeners = new Set<
|
|
68
|
+
const rendererInjectListeners = new Set<RendererInjectListener>();
|
|
69
|
+
const rdtHookReplaceListeners = new Set<RDTHookReplaceListener>();
|
|
42
70
|
// HACK: Hook replacement can leave an old inject wrapper in the call chain, so notifications must be deduplicated.
|
|
43
71
|
const notifiedRenderers = new WeakSet<ReactRenderer>();
|
|
44
|
-
|
|
72
|
+
const notifyingInjectByHook = new WeakMap<
|
|
73
|
+
ReactDevToolsGlobalHook,
|
|
74
|
+
ReactDevToolsGlobalHook["inject"]
|
|
75
|
+
>();
|
|
76
|
+
|
|
77
|
+
const notifyActiveListeners = (): void => {
|
|
78
|
+
for (const listener of _onActiveListeners) {
|
|
79
|
+
runHookListener("onActive", listener);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
45
82
|
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
83
|
+
const notifyRendererInjectListeners = (renderer: ReactRenderer): void => {
|
|
84
|
+
for (const listener of rendererInjectListeners) {
|
|
85
|
+
runHookListener("onRendererInject", () => listener(renderer));
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
const notifyRDTHookReplaceListeners = (rdtHook: ReactDevToolsGlobalHook): void => {
|
|
90
|
+
for (const listener of rdtHookReplaceListeners) {
|
|
91
|
+
runHookListener("onRDTHookReplace", () => listener(rdtHook));
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
const setRendererInjectDispatcher = (rdtHook: ReactDevToolsGlobalHook): void => {
|
|
96
|
+
if (rdtHook.inject === notifyingInjectByHook.get(rdtHook)) return;
|
|
97
|
+
const previousInject = rdtHook.inject;
|
|
49
98
|
const nextInject = (renderer: ReactRenderer) => {
|
|
50
|
-
const rendererId =
|
|
99
|
+
const rendererId = previousInject.call(rdtHook, renderer);
|
|
51
100
|
if (!notifiedRenderers.has(renderer)) {
|
|
52
101
|
notifiedRenderers.add(renderer);
|
|
53
|
-
|
|
54
|
-
listener(renderer);
|
|
55
|
-
}
|
|
102
|
+
notifyRendererInjectListeners(renderer);
|
|
56
103
|
}
|
|
57
104
|
return rendererId;
|
|
58
105
|
};
|
|
59
106
|
rdtHook.inject = nextInject;
|
|
60
|
-
|
|
107
|
+
notifyingInjectByHook.set(rdtHook, nextInject);
|
|
61
108
|
};
|
|
62
109
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
ensureInjectNotifiesListeners(getRDTHook());
|
|
110
|
+
export const onRendererInject = (listener: RendererInjectListener): Unsubscribe => {
|
|
111
|
+
setRendererInjectDispatcher(getRDTHook());
|
|
66
112
|
rendererInjectListeners.add(listener);
|
|
67
|
-
return
|
|
113
|
+
return createUnsubscribe(() => {
|
|
68
114
|
rendererInjectListeners.delete(listener);
|
|
69
115
|
});
|
|
70
116
|
};
|
|
71
117
|
|
|
72
|
-
const
|
|
118
|
+
export const onRDTHookReplace = (listener: RDTHookReplaceListener): Unsubscribe => {
|
|
119
|
+
rdtHookReplaceListeners.add(listener);
|
|
120
|
+
return createUnsubscribe(() => {
|
|
121
|
+
rdtHookReplaceListeners.delete(listener);
|
|
122
|
+
});
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const getRendererMap = (rdtHook: ReactDevToolsGlobalHook): Map<number, ReactRenderer> => {
|
|
73
126
|
if (!(rdtHook.renderers instanceof Map)) {
|
|
74
127
|
rdtHook.renderers = new Map();
|
|
75
128
|
}
|
|
76
129
|
return rdtHook.renderers;
|
|
77
130
|
};
|
|
78
131
|
|
|
79
|
-
export const installRDTHook = (onActive?:
|
|
132
|
+
export const installRDTHook = (onActive?: ActiveListener): ReactDevToolsGlobalHook => {
|
|
80
133
|
if (onActive) {
|
|
81
134
|
_onActiveListeners.add(onActive);
|
|
82
135
|
}
|
|
@@ -87,20 +140,20 @@ export const installRDTHook = (onActive?: () => unknown): ReactDevToolsGlobalHoo
|
|
|
87
140
|
_instrumentationSource: BIPPY_INSTRUMENTATION_STRING,
|
|
88
141
|
checkDCE,
|
|
89
142
|
hasUnsupportedRendererAttached: false,
|
|
90
|
-
inject(renderer) {
|
|
143
|
+
inject: (renderer) => {
|
|
91
144
|
const nextRendererId = ++rendererIdCounter;
|
|
92
145
|
renderers.set(nextRendererId, renderer);
|
|
93
146
|
_renderers.add(renderer);
|
|
94
147
|
if (!rdtHook._instrumentationIsActive) {
|
|
95
148
|
rdtHook._instrumentationIsActive = true;
|
|
96
|
-
|
|
149
|
+
notifyActiveListeners();
|
|
97
150
|
}
|
|
98
151
|
return nextRendererId;
|
|
99
152
|
},
|
|
100
|
-
on:
|
|
101
|
-
onCommitFiberRoot:
|
|
102
|
-
onCommitFiberUnmount:
|
|
103
|
-
onPostCommitFiberRoot:
|
|
153
|
+
on: noOp,
|
|
154
|
+
onCommitFiberRoot: noOp,
|
|
155
|
+
onCommitFiberUnmount: noOp,
|
|
156
|
+
onPostCommitFiberRoot: noOp,
|
|
104
157
|
renderers,
|
|
105
158
|
supportsFiber: true,
|
|
106
159
|
supportsFlight: true,
|
|
@@ -116,92 +169,106 @@ export const installRDTHook = (onActive?: () => unknown): ReactDevToolsGlobalHoo
|
|
|
116
169
|
if (newHook && typeof newHook === "object") {
|
|
117
170
|
const ourRenderers = rdtHook.renderers;
|
|
118
171
|
rdtHook = newHook;
|
|
119
|
-
const nextRenderers =
|
|
172
|
+
const nextRenderers = getRendererMap(rdtHook);
|
|
120
173
|
if (ourRenderers.size > 0) {
|
|
121
|
-
ourRenderers.forEach((renderer,
|
|
174
|
+
ourRenderers.forEach((renderer, rendererId) => {
|
|
122
175
|
_renderers.add(renderer);
|
|
123
|
-
nextRenderers.set(
|
|
176
|
+
nextRenderers.set(rendererId, renderer);
|
|
124
177
|
});
|
|
178
|
+
}
|
|
179
|
+
if (ourRenderers.size > 0 || rdtHookReplaceListeners.size > 0) {
|
|
125
180
|
patchRDTHook(onActive);
|
|
126
181
|
}
|
|
182
|
+
notifyRDTHookReplaceListeners(rdtHook);
|
|
127
183
|
}
|
|
128
184
|
},
|
|
129
185
|
});
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
186
|
+
if (typeof window !== "undefined") {
|
|
187
|
+
// HACK: The DevTools extension uses hasOwnProperty to decide whether it may replace an earlier hook.
|
|
188
|
+
const originalWindowHasOwnProperty = window.hasOwnProperty.bind(window);
|
|
189
|
+
const originalHasOwnPropertyDescriptor = Object.getOwnPropertyDescriptor(
|
|
190
|
+
window,
|
|
191
|
+
"hasOwnProperty",
|
|
192
|
+
);
|
|
193
|
+
let didRunHasOwnPropertyHack = false;
|
|
194
|
+
const restoreWindowHasOwnProperty = (): void => {
|
|
195
|
+
if (originalHasOwnPropertyDescriptor) {
|
|
196
|
+
objectDefineProperty(window, "hasOwnProperty", originalHasOwnPropertyDescriptor);
|
|
197
|
+
} else {
|
|
198
|
+
Reflect.deleteProperty(window, "hasOwnProperty");
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
objectDefineProperty(window, "hasOwnProperty", {
|
|
202
|
+
configurable: true,
|
|
203
|
+
value: (...propertyKeys: [PropertyKey]) => {
|
|
204
|
+
if (!didRunHasOwnPropertyHack && propertyKeys[0] === "__REACT_DEVTOOLS_GLOBAL_HOOK__") {
|
|
205
|
+
didRunHasOwnPropertyHack = true;
|
|
206
|
+
restoreWindowHasOwnProperty();
|
|
139
207
|
globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__ = undefined;
|
|
140
|
-
|
|
141
|
-
return -0;
|
|
208
|
+
return false;
|
|
142
209
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
210
|
+
return originalWindowHasOwnProperty(...propertyKeys);
|
|
211
|
+
},
|
|
212
|
+
writable: true,
|
|
213
|
+
});
|
|
214
|
+
}
|
|
148
215
|
} catch {
|
|
149
216
|
patchRDTHook(onActive);
|
|
150
217
|
}
|
|
151
218
|
return rdtHook;
|
|
152
219
|
};
|
|
153
220
|
|
|
154
|
-
export const patchRDTHook = (onActive?:
|
|
221
|
+
export const patchRDTHook = (onActive?: ActiveListener): void => {
|
|
155
222
|
if (onActive) {
|
|
156
223
|
_onActiveListeners.add(onActive);
|
|
157
224
|
}
|
|
158
225
|
let didNotifyActiveListeners = false;
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
rdtHook.on = NO_OP;
|
|
174
|
-
}
|
|
175
|
-
if (renderers.size) {
|
|
176
|
-
renderers.forEach((renderer) => _renderers.add(renderer));
|
|
177
|
-
rdtHook._instrumentationIsActive = true;
|
|
178
|
-
_onActiveListeners.forEach((listener) => listener());
|
|
179
|
-
didNotifyActiveListeners = true;
|
|
180
|
-
}
|
|
181
|
-
const prevInject = rdtHook.inject;
|
|
182
|
-
rdtHook.inject = (renderer) => {
|
|
183
|
-
const rendererId = prevInject(renderer);
|
|
184
|
-
_renderers.add(renderer);
|
|
185
|
-
renderers.set(rendererId, renderer);
|
|
186
|
-
rdtHook._instrumentationIsActive = true;
|
|
187
|
-
_onActiveListeners.forEach((listener) => listener());
|
|
188
|
-
return rendererId;
|
|
189
|
-
};
|
|
226
|
+
const rdtHook = globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
227
|
+
if (!rdtHook) return;
|
|
228
|
+
const renderers = getRendererMap(rdtHook);
|
|
229
|
+
if (!rdtHook._instrumentationSource) {
|
|
230
|
+
rdtHook.checkDCE = checkDCE;
|
|
231
|
+
rdtHook.supportsFiber = true;
|
|
232
|
+
rdtHook.supportsFlight = true;
|
|
233
|
+
rdtHook.hasUnsupportedRendererAttached = false;
|
|
234
|
+
rdtHook._instrumentationSource = BIPPY_INSTRUMENTATION_STRING;
|
|
235
|
+
rdtHook._instrumentationIsActive = false;
|
|
236
|
+
// HACK: DevTools detection must happen after setting the source to avoid recursive patching.
|
|
237
|
+
const isReactDevtools = isRealReactDevtools(rdtHook);
|
|
238
|
+
if (!isReactDevtools) {
|
|
239
|
+
rdtHook.on = noOp;
|
|
190
240
|
}
|
|
191
|
-
if (
|
|
192
|
-
|
|
241
|
+
if (renderers.size) {
|
|
242
|
+
renderers.forEach((renderer) => _renderers.add(renderer));
|
|
243
|
+
rdtHook._instrumentationIsActive = true;
|
|
244
|
+
notifyActiveListeners();
|
|
245
|
+
didNotifyActiveListeners = true;
|
|
193
246
|
}
|
|
194
|
-
|
|
247
|
+
const previousInject = rdtHook.inject;
|
|
248
|
+
rdtHook.inject = (renderer) => {
|
|
249
|
+
const rendererId = previousInject.call(rdtHook, renderer);
|
|
250
|
+
_renderers.add(renderer);
|
|
251
|
+
renderers.set(rendererId, renderer);
|
|
252
|
+
if (!rdtHook._instrumentationIsActive) {
|
|
253
|
+
rdtHook._instrumentationIsActive = true;
|
|
254
|
+
notifyActiveListeners();
|
|
255
|
+
}
|
|
256
|
+
return rendererId;
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
if (!didNotifyActiveListeners && (renderers.size || rdtHook._instrumentationIsActive)) {
|
|
260
|
+
if (onActive) runHookListener("onActive", onActive);
|
|
261
|
+
}
|
|
195
262
|
};
|
|
196
263
|
|
|
197
264
|
export const hasRDTHook = (): boolean => {
|
|
198
|
-
return
|
|
265
|
+
return Object.hasOwn(globalThis, "__REACT_DEVTOOLS_GLOBAL_HOOK__");
|
|
199
266
|
};
|
|
200
267
|
|
|
201
268
|
/**
|
|
202
269
|
* Returns the current React DevTools global hook.
|
|
203
270
|
*/
|
|
204
|
-
export const getRDTHook = (onActive?:
|
|
271
|
+
export const getRDTHook = (onActive?: ActiveListener): ReactDevToolsGlobalHook => {
|
|
205
272
|
if (!hasRDTHook()) {
|
|
206
273
|
return installRDTHook(onActive);
|
|
207
274
|
}
|
|
@@ -210,18 +277,6 @@ export const getRDTHook = (onActive?: () => unknown): ReactDevToolsGlobalHook =>
|
|
|
210
277
|
return globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__ ?? installRDTHook(onActive);
|
|
211
278
|
};
|
|
212
279
|
|
|
213
|
-
export const
|
|
214
|
-
|
|
215
|
-
typeof window !== "undefined" &&
|
|
216
|
-
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
217
|
-
(window.document?.createElement || window.navigator?.product === "ReactNative"),
|
|
218
|
-
);
|
|
219
|
-
};
|
|
220
|
-
|
|
221
|
-
export const safelyInstallRDTHook = () => {
|
|
222
|
-
try {
|
|
223
|
-
if (isClientEnvironment()) {
|
|
224
|
-
getRDTHook();
|
|
225
|
-
}
|
|
226
|
-
} catch {}
|
|
280
|
+
export const safelyInstallRDTHook = (): void => {
|
|
281
|
+
runWithBippyError(getRDTHook, (cause) => new BippyHookInstallationError(cause));
|
|
227
282
|
};
|