@rozenite/runtime
Version:
Rozenite runtime for React Native DevTools.
520 lines (519 loc) • 17.2 kB
JavaScript
var G = Object.defineProperty;
var _ = (n) => {
throw TypeError(n);
};
var J = (n, i, e) => i in n ? G(n, i, { enumerable: !0, configurable: !0, writable: !0, value: e }) : n[i] = e;
var w = (n, i, e) => J(n, typeof i != "symbol" ? i + "" : i, e), D = (n, i, e) => i.has(n) || _("Cannot " + e);
var d = (n, i, e) => (D(n, i, "read from private field"), e ? e.call(n) : i.get(n)), g = (n, i, e) => i.has(n) ? _("Cannot add the same private member more than once") : i instanceof WeakSet ? i.add(n) : i.set(n, e), p = (n, i, e, t) => (D(n, i, "write to private field"), t ? t.call(n, e) : i.set(n, e), e), o = (n, i, e) => (D(n, i, "access private method"), e);
import * as u from "/rozenite/ui/legacy/legacy.js";
import * as c from "/rozenite/core/sdk/sdk.js";
import "/rozenite/models/react_native/react_native.js";
const O = async (n) => (await fetch(n + "/rozenite.json")).json(), I = "rozenite", k = "main", x = "__FUSEBOX_REACT_DEVTOOLS_DISPATCHER__";
class A extends c.SDKModel.SDKModel {
constructor() {
super(...arguments);
w(this, "messagingBindingName", null);
w(this, "enabled", !1);
w(this, "fuseboxDispatcherIsInitialized", !1);
w(this, "messageQueue", []);
w(this, "messageListeners", /* @__PURE__ */ new Set());
}
dispose() {
this.messageQueue = [];
const e = this.target().model(c.RuntimeModel.RuntimeModel);
e == null || e.removeEventListener(
"BindingCalled",
this.bindingCalled,
this
), e == null || e.removeEventListener(
"ExecutionContextCreated",
this.onExecutionContextCreated,
this
), e == null || e.removeEventListener(
"ExecutionContextDestroyed",
this.onExecutionContextDestroyed,
this
);
}
bindingCalled(e) {
if (this.messagingBindingName === null || e.data.name !== this.messagingBindingName)
return;
const t = e.data.payload;
let s = null;
try {
s = JSON.parse(t);
} catch {
throw new Error("Failed to parse bindingCalled event payload");
}
if (s) {
const r = s.domain;
if (s.domain !== I)
return;
if (this.fuseboxDispatcherIsInitialized) {
if (!this.isDomainMessagesQueueEmpty())
throw new Error(
`Attempted to send a message to domain ${r} while queue is not empty`
);
this.dispatchMessageToDomainEventListeners(s.message);
} else
this.queueMessage(s.message);
}
}
queueMessage(e) {
this.messageQueue.push(e);
}
flushOutDomainMessagesQueues() {
for (const e of this.messageQueue)
this.dispatchMessageToDomainEventListeners(e);
this.messageQueue = [];
}
isDomainMessagesQueueEmpty() {
return this.messageQueue.length === 0;
}
subscribeToDomainMessages(e) {
this.messageListeners.add(e);
}
unsubscribeFromDomainMessages(e) {
this.messageListeners.delete(e);
}
dispatchMessageToDomainEventListeners(e) {
const t = this.messageListeners, s = [];
for (const r of t)
try {
r(e);
} catch (M) {
s.push(M);
}
if (s.length > 0)
throw new Error(
"Error occurred in RozeniteBindingsModel while calling event listeners"
);
}
async initializeDomain() {
const e = this.target().model(c.RuntimeModel.RuntimeModel);
if (!e)
throw new Error(
"Failed to initialize domain for RozeniteBindingsModel: runtime model is not available"
);
await e.agent.invoke_evaluate({
expression: `void ${x}.initializeDomain('${I}')`
});
}
async sendMessage(e) {
if (!this.fuseboxDispatcherIsInitialized)
return;
const t = this.target().model(c.RuntimeModel.RuntimeModel);
if (!t)
throw new Error(
"Failed to send message from RozeniteBindingsModel: runtime model is not available"
);
const s = JSON.stringify(e), r = JSON.stringify(s);
await t.agent.invoke_evaluate({
expression: `${x}.sendMessage('${I}', ${r})`
});
}
async enable() {
if (this.enabled)
throw new Error("RozeniteBindingsModel is already enabled");
const e = this.target().model(c.RuntimeModel.RuntimeModel);
if (!e)
throw new Error(
"Failed to enable RozeniteBindingsModel: runtime model is not available"
);
await this.waitForFuseboxDispatcherToBeInitialized().then(
() => e.agent.invoke_evaluate({
expression: `${x}.BINDING_NAME`
})
).then((t) => {
if (t.exceptionDetails)
throw new Error(
"Failed to get binding name for RozeniteBindingsModel on a global: " + t.exceptionDetails.text
);
if (t.result.value === null || t.result.value === void 0)
throw new Error(
"Failed to get binding name for RozeniteBindingsModel on a global: returned value is " + String(t.result.value)
);
if (t.result.value === "")
throw new Error(
"Failed to get binding name for ReactDevToolsBindingsModel on a global: returned value is an empty string"
);
return t.result.value;
}).then((t) => (this.messagingBindingName = t, e.addEventListener(
"BindingCalled",
this.bindingCalled,
this
), e.agent.invoke_addBinding({ name: t }))).then((t) => {
const s = t.getError();
if (s)
throw new Error(
"Failed to add binding for ReactDevToolsBindingsModel: " + s
);
this.enabled = !0, this.initializeExecutionContextListeners();
});
}
isEnabled() {
return this.enabled;
}
initializeExecutionContextListeners() {
const e = this.target().model(c.RuntimeModel.RuntimeModel);
if (!e)
throw new Error(
"Failed to initialize execution context listeners for RozeniteBindingsModel: runtime model is not available"
);
e.addEventListener(
"ExecutionContextCreated",
this.onExecutionContextCreated,
this
), e.addEventListener(
"ExecutionContextDestroyed",
this.onExecutionContextDestroyed,
this
);
}
onExecutionContextCreated({
data: e
}) {
e.name === k && this.waitForFuseboxDispatcherToBeInitialized().then(() => {
this.dispatchEventToListeners("BackendExecutionContextCreated"), this.flushOutDomainMessagesQueues();
}).catch(
(t) => this.dispatchEventToListeners(
"BackendExecutionContextUnavailable",
t.message
)
);
}
onExecutionContextDestroyed({
data: e
}) {
e.name === k && (this.fuseboxDispatcherIsInitialized = !1, this.dispatchEventToListeners("BackendExecutionContextDestroyed"));
}
async waitForFuseboxDispatcherToBeInitialized(e = 1) {
if (e >= 20)
throw new Error("Failed to wait for initialization: it took too long");
const t = this.target().model(c.RuntimeModel.RuntimeModel);
if (!t)
throw new Error(
"Failed to wait for React DevTools dispatcher initialization: runtime model is not available"
);
await t.agent.invoke_evaluate({
expression: `globalThis.${x} != undefined`,
returnByValue: !0
}).then((s) => {
if (s.exceptionDetails)
throw new Error(
"Failed to wait for React DevTools dispatcher initialization: " + s.exceptionDetails.text
);
if (s.result.value === !1)
return new Promise((r) => setTimeout(r, 250)).then(
() => this.waitForFuseboxDispatcherToBeInitialized(e + 1)
);
this.fuseboxDispatcherIsInitialized = !0;
});
}
}
c.SDKModel.SDKModel.register(A, {
capabilities: 4,
autostart: !1
});
var h, m, E, f, l, K, $, C, z, L, R;
class U extends c.SDKModel.SDKModel {
constructor(e) {
super(e);
g(this, l);
g(this, h);
g(this, m, /* @__PURE__ */ new Set());
g(this, E, !1);
g(this, f, !1);
const t = e.model(A);
if (t === null)
throw new Error(
"Failed to construct RozenitePluginModel: RozeniteBindingsModel was null"
);
p(this, h, t), t.addEventListener(
"BackendExecutionContextCreated",
o(this, l, C),
this
), t.addEventListener(
"BackendExecutionContextUnavailable",
o(this, l, L),
this
), t.addEventListener(
"BackendExecutionContextDestroyed",
o(this, l, R),
this
);
}
dispose() {
d(this, h).removeEventListener(
"BackendExecutionContextCreated",
o(this, l, C),
this
), d(this, h).removeEventListener(
"BackendExecutionContextUnavailable",
o(this, l, L),
this
), d(this, h).removeEventListener(
"BackendExecutionContextDestroyed",
o(this, l, R),
this
), d(this, m).clear();
}
ensureInitialized() {
d(this, E) || (p(this, E, !0), o(this, l, K).call(this));
}
isInitialized() {
return d(this, f);
}
async sendMessage(e) {
const t = d(this, h);
if (!t)
throw new Error(
"RozenitePluginModel failed to send message: RozeniteBindingsModel was null"
);
return await t.sendMessage(e);
}
onMessage(e) {
return d(this, m).add(e), () => {
d(this, m).delete(e);
};
}
}
h = new WeakMap(), m = new WeakMap(), E = new WeakMap(), f = new WeakMap(), l = new WeakSet(), K = async function() {
try {
const e = d(this, h);
e.isEnabled() || await e.enable(), e.subscribeToDomainMessages(
(t) => o(this, l, $).call(this, t)
), await e.initializeDomain(), p(this, f, !0), o(this, l, z).call(this);
} catch (e) {
this.dispatchEventToListeners(
"InitializationFailed",
e.message
);
}
}, $ = function(e) {
if (e)
for (const t of d(this, m))
t(e);
}, C = function() {
const e = d(this, h);
if (!e)
throw new Error(
"RozenitePluginModel failed to handle BackendExecutionContextCreated event: RozeniteBindingsModel was null"
);
e.isEnabled() ? o(this, l, z).call(this) : this.ensureInitialized();
}, z = function() {
this.dispatchEventToListeners("InitializationCompleted");
}, L = function({
data: e
}) {
this.dispatchEventToListeners("InitializationFailed", e);
}, R = function() {
d(this, m).clear(), this.dispatchEventToListeners("Destroyed");
};
c.SDKModel.SDKModel.register(U, {
capabilities: 4,
autostart: !1
});
const F = () => globalThis.__ROZENITE__;
var v, b, a, B, T, P, V, S, Q, y;
class X extends u.View.SimpleView {
constructor(e, t, s, r) {
super(s + " 💎", !0, t);
g(this, a);
g(this, v, null);
g(this, b);
p(this, b, r), F().destroyOnDetachPlugins.includes(e) || this.setHideOnDetach(), c.TargetManager.TargetManager.instance().observeModels(
U,
this
), o(this, a, S).call(this);
}
modelAdded(e) {
p(this, v, e), e.addEventListener(
"InitializationCompleted",
o(this, a, B),
this
), e.addEventListener(
"InitializationFailed",
o(this, a, T),
this
), e.addEventListener("Destroyed", o(this, a, P), this), e.isInitialized() ? o(this, a, V).call(this) : e.ensureInitialized();
}
modelRemoved(e) {
e.removeEventListener(
"InitializationCompleted",
o(this, a, B),
this
), e.removeEventListener(
"InitializationFailed",
o(this, a, T),
this
), e.removeEventListener("Destroyed", o(this, a, P), this);
}
}
v = new WeakMap(), b = new WeakMap(), a = new WeakSet(), B = function() {
o(this, a, V).call(this);
}, T = function({
data: e
}) {
o(this, a, Q).call(this, e);
}, P = function() {
o(this, a, S).call(this);
}, V = function() {
o(this, a, y).call(this);
const e = d(this, v);
if (e === null)
throw new Error("Attempted to render panel, but the model was null");
const t = document.createElement("iframe");
t.src = d(this, b), t.style.height = "100%", t.style.width = "100%", window.addEventListener("message", (s) => {
s.source === t.contentWindow && e.sendMessage(s.data.payload);
}), e.onMessage((s) => {
var r;
(r = t.contentWindow) == null || r.postMessage(s, "*");
}), this.contentElement.appendChild(t);
}, S = function() {
o(this, a, y).call(this);
const e = document.createElement("div");
e.setAttribute(
"style",
"display: flex; flex: 1; justify-content: center; align-items: center"
);
const t = document.createElement("span");
t.classList.add("spinner"), e.appendChild(t), this.contentElement.appendChild(e);
}, Q = function(e) {
o(this, a, y).call(this);
const t = document.createElement("div");
t.setAttribute(
"style",
"display: flex; flex: 1; flex-direction: column; justify-content: center; align-items: center"
);
const s = document.createElement("div");
s.setAttribute("style", "font-size: 3rem"), s.innerHTML = "❗";
const r = document.createElement("p");
r.setAttribute("style", "user-select: all"), r.innerHTML = e, t.appendChild(s), t.appendChild(r), this.contentElement.appendChild(t);
}, y = function() {
let e = this.contentElement.lastElementChild;
for (; e; )
this.contentElement.removeChild(e), e = this.contentElement.lastElementChild;
};
const Z = (n, i, e, t) => new X(n, i, e, t), N = (n) => n.toLowerCase().replace(/[^a-z0-9]/g, " ").trim().replace(/\s+/g, " ").replace(/\s/g, ".").replace(/\.+/g, ".").replace(/^\.+|\.+$/g, ""), Y = (n, i, e) => {
try {
const t = N(n), s = N(i), r = `${t}.${s}`;
if (u.InspectorView.InspectorView.instance().hasPanel(r))
return;
const M = Z(n, r, i, e);
u.InspectorView.InspectorView.instance().addPanel(M);
} catch (t) {
throw console.error(t), t;
}
}, ee = (n) => {
const i = new URL(location.href);
return i.search = "", i.pathname = "/rozenite/plugins/" + n.replace("/", "_"), i.toString();
}, W = async (n) => {
const i = await O(n);
i.panels.forEach((e) => {
const t = n + e.source;
Y(i.name, e.name, t);
}), console.groupCollapsed(`📦 Plugin: ${i.name}`), console.log("Version:", i.version), console.log("Description:", i.description), console.log("Panels:", i.panels.map((e) => e.name).join(", ")), console.groupEnd();
}, te = async (n) => {
await W(ee(n));
}, j = "http://localhost:8888", ne = async () => {
try {
return await O(j), !0;
} catch {
return !1;
}
}, ie = async () => {
await ne() && (console.group("🔧 Rozenite Dev Mode"), console.log("We detected that you are developing a plugin."), console.log("This plugin will be automatically loaded with hot reload."), console.groupEnd(), await W(j));
}, q = "rozenite-welcome", se = "https://rozenite.dev/welcome";
class oe extends u.View.SimpleView {
constructor() {
super("Rozenite 💎", !0, q);
const { installedPlugins: i } = F(), e = i.length > 0, t = new URL(se, window.location.origin);
t.searchParams.set(
"withPluginsInstalled",
e.toString()
);
const s = document.createElement("iframe");
s.src = t.toString(), s.style.height = "100%", s.style.width = "100%", this.contentElement.appendChild(s);
}
}
const ae = () => {
const n = new oe();
u.InspectorView.InspectorView.instance().addPanel(n);
const i = u.InspectorView.InspectorView.instance().tabbedPane.tabsById.get(
q
);
if (!i)
throw new Error("Welcome view tab not found.");
u.InspectorView.InspectorView.instance().tabbedPane.insertBefore(
i,
0
), u.InspectorView.InspectorView.instance().tabbedPane.selectTab(
i.id
);
}, re = () => {
try {
const n = decodeURIComponent(window.location.href).match(
/[?&]device=([^&]+)/
);
return n ? n[1] : null;
} catch {
return null;
}
}, H = () => {
const n = re();
if (!n)
throw new Error("Device ID not found");
return `rozenite::selected-panel::${n}`;
}, le = (n) => {
try {
const i = H();
localStorage.setItem(i, n);
} catch (i) {
console.warn("Could not save selected panel:", i);
}
}, de = () => {
try {
const n = H();
return localStorage.getItem(n);
} catch (n) {
return console.warn("Could not get selected panel:", n), null;
}
}, ce = () => {
const n = de();
if (n)
try {
u.InspectorView.InspectorView.instance().tabbedPane.selectTab(n);
} catch (i) {
console.warn("Could not restore last selected panel:", i);
}
}, he = () => {
try {
u.InspectorView.InspectorView.instance().tabbedPane.addEventListener("TabSelected", (i) => {
const e = i.data.tabId;
e && le(e);
});
} catch (n) {
console.error("Could not initialize tab selected tracking:", n);
}
}, ue = async () => new Promise((n) => {
window.addEventListener("DOMContentLoaded", async () => {
new MutationObserver(async (e, t) => {
document.querySelector(".main-tabbed-pane") && (t.disconnect(), n());
}).observe(document.body, { childList: !0, subtree: !0 });
});
}), ge = async () => {
await ue();
const n = F().installedPlugins;
console.group("🚀 Rozenite DevTools Framework"), console.log("Devtools framework loaded"), console.log("Found plugins: " + n.join(", ")), console.groupEnd(), ae(), await Promise.all(
n.map(async (i) => {
await te(i);
})
), he(), ce(), await ie();
};
ge().catch((n) => {
console.group("❌ Rozenite Error"), console.error(
"Initialization failed. See the following error for more details:",
n
), console.groupEnd();
});