bippy
Version:
hack into react internals
226 lines (224 loc) • 6.32 kB
JavaScript
/**
* @license bippy
*
* Copyright (c) Aiden Bai
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
//#region src/rdt-hook.ts
const version = "0.3.17";
const BIPPY_INSTRUMENTATION_STRING = `bippy-${version}`;
const objectDefineProperty = Object.defineProperty;
const objectHasOwnProperty = Object.prototype.hasOwnProperty;
const NO_OP = () => {};
const checkDCE = (fn) => {
try {
const code = Function.prototype.toString.call(fn);
if (code.indexOf("^_^") > -1) setTimeout(() => {
throw new Error("React is running in production mode, but dead code elimination has not been applied. Read how to correctly configure React for production: https://reactjs.org/link/perf-use-production-build");
});
} catch {}
};
const isRealReactDevtools = (rdtHook = getRDTHook()) => {
return "getFiberRoots" in rdtHook;
};
let isReactRefreshOverride = false;
let injectFnStr = void 0;
const isReactRefresh = (rdtHook = getRDTHook()) => {
if (isReactRefreshOverride) return true;
if (typeof rdtHook.inject === "function") injectFnStr = rdtHook.inject.toString();
return Boolean(injectFnStr?.includes("(injected)"));
};
const onActiveListeners = new Set();
const _renderers = new Set();
const installRDTHook = (onActive) => {
const renderers = new Map();
let i = 0;
let rdtHook = {
checkDCE,
supportsFiber: true,
supportsFlight: true,
hasUnsupportedRendererAttached: false,
renderers,
onCommitFiberRoot: NO_OP,
onCommitFiberUnmount: NO_OP,
onPostCommitFiberRoot: NO_OP,
inject(renderer) {
const nextID = ++i;
renderers.set(nextID, renderer);
_renderers.add(renderer);
if (!rdtHook._instrumentationIsActive) {
rdtHook._instrumentationIsActive = true;
onActiveListeners.forEach((listener) => listener());
}
return nextID;
},
_instrumentationSource: BIPPY_INSTRUMENTATION_STRING,
_instrumentationIsActive: false
};
try {
objectDefineProperty(globalThis, "__REACT_DEVTOOLS_GLOBAL_HOOK__", {
get() {
return rdtHook;
},
set(newHook) {
if (newHook && typeof newHook === "object") {
const ourRenderers = rdtHook.renderers;
rdtHook = newHook;
if (ourRenderers.size > 0) {
ourRenderers.forEach((renderer, id) => {
_renderers.add(renderer);
newHook.renderers.set(id, renderer);
});
patchRDTHook(onActive);
}
}
},
configurable: true,
enumerable: true
});
const originalWindowHasOwnProperty = window.hasOwnProperty;
let hasRanHack = false;
objectDefineProperty(window, "hasOwnProperty", {
value: function() {
try {
if (!hasRanHack && arguments[0] === "__REACT_DEVTOOLS_GLOBAL_HOOK__") {
globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__ = void 0;
hasRanHack = true;
return -0;
}
} catch {}
return originalWindowHasOwnProperty.apply(this, arguments);
},
configurable: true,
writable: true
});
} catch {
patchRDTHook(onActive);
}
return rdtHook;
};
const patchRDTHook = (onActive) => {
if (onActive) onActiveListeners.add(onActive);
try {
const rdtHook = globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;
if (!rdtHook) return;
if (!rdtHook._instrumentationSource) {
rdtHook.checkDCE = checkDCE;
rdtHook.supportsFiber = true;
rdtHook.supportsFlight = true;
rdtHook.hasUnsupportedRendererAttached = false;
rdtHook._instrumentationSource = BIPPY_INSTRUMENTATION_STRING;
rdtHook._instrumentationIsActive = false;
if (rdtHook.renderers.size) {
rdtHook._instrumentationIsActive = true;
onActiveListeners.forEach((listener) => listener());
return;
}
const prevInject = rdtHook.inject;
if (isReactRefresh(rdtHook) && !isRealReactDevtools()) {
isReactRefreshOverride = true;
const nextID = rdtHook.inject({ scheduleRefresh() {} });
if (nextID) rdtHook._instrumentationIsActive = true;
}
rdtHook.inject = (renderer) => {
const id = prevInject(renderer);
_renderers.add(renderer);
rdtHook._instrumentationIsActive = true;
onActiveListeners.forEach((listener) => listener());
return id;
};
}
if (rdtHook.renderers.size || rdtHook._instrumentationIsActive || isReactRefresh()) onActive?.();
} catch {}
};
const hasRDTHook = () => {
return objectHasOwnProperty.call(globalThis, "__REACT_DEVTOOLS_GLOBAL_HOOK__");
};
/**
* Returns the current React DevTools global hook.
*/
const getRDTHook = (onActive) => {
if (!hasRDTHook()) return installRDTHook(onActive);
patchRDTHook(onActive);
return globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;
};
const isClientEnvironment = () => {
return Boolean(typeof window !== "undefined" && (window.document?.createElement || window.navigator?.product === "ReactNative"));
};
/**
* Usually used purely for side effect
*/
const safelyInstallRDTHook = () => {
try {
if (isClientEnvironment()) getRDTHook();
} catch {}
};
//#endregion
Object.defineProperty(exports, 'BIPPY_INSTRUMENTATION_STRING', {
enumerable: true,
get: function () {
return BIPPY_INSTRUMENTATION_STRING;
}
});
Object.defineProperty(exports, '_renderers', {
enumerable: true,
get: function () {
return _renderers;
}
});
Object.defineProperty(exports, 'getRDTHook', {
enumerable: true,
get: function () {
return getRDTHook;
}
});
Object.defineProperty(exports, 'hasRDTHook', {
enumerable: true,
get: function () {
return hasRDTHook;
}
});
Object.defineProperty(exports, 'installRDTHook', {
enumerable: true,
get: function () {
return installRDTHook;
}
});
Object.defineProperty(exports, 'isClientEnvironment', {
enumerable: true,
get: function () {
return isClientEnvironment;
}
});
Object.defineProperty(exports, 'isReactRefresh', {
enumerable: true,
get: function () {
return isReactRefresh;
}
});
Object.defineProperty(exports, 'isRealReactDevtools', {
enumerable: true,
get: function () {
return isRealReactDevtools;
}
});
Object.defineProperty(exports, 'patchRDTHook', {
enumerable: true,
get: function () {
return patchRDTHook;
}
});
Object.defineProperty(exports, 'safelyInstallRDTHook', {
enumerable: true,
get: function () {
return safelyInstallRDTHook;
}
});
Object.defineProperty(exports, 'version', {
enumerable: true,
get: function () {
return version;
}
});