🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@solid-devtools/debugger

Package Overview
Dependencies
Maintainers
1
Versions
66
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@solid-devtools/debugger - npm Package Compare versions

Comparing version
0.11.1
to
0.12.0
+906
dist/chunk-YDYIFWRS.js
// src/roots.ts
import { createEffect as createEffect2, onCleanup as onCleanup2, untrack as untrack3 } from "solid-js";
import { throttle as throttle3 } from "@solid-primitives/scheduled";
import {
getOwner as getOwner2,
NodeType as NodeType4
} from "@solid-devtools/shared/graph";
import { INTERNAL as INTERNAL2 } from "@solid-devtools/shared/variables";
import { untrackedCallback as untrackedCallback2 } from "@solid-devtools/shared/primitives";
import { warn } from "@solid-devtools/shared/utils";
// src/walker.ts
import { NodeType as NodeType2 } from "@solid-devtools/shared/graph";
// src/utils.ts
import { createComputed, createRoot, onCleanup, runWithOwner } from "solid-js";
import { throttle } from "@solid-primitives/scheduled";
import {
NodeType,
getOwner
} from "@solid-devtools/shared/graph";
import { INTERNAL, UNNAMED } from "@solid-devtools/shared/variables";
import { trimString } from "@solid-devtools/shared/utils";
var isSolidComputation = (o) => "fn" in o;
var isSolidMemo = (o) => "sdtType" in o ? o.sdtType === NodeType.Memo : isSolidComputation(o) && _isMemo(o);
var isSolidOwner = (o) => "owned" in o;
var isSolidRoot = (o) => o.sdtType === NodeType.Root || !isSolidComputation(o);
var isSolidComponent = (o) => "props" in o;
var _isMemo = (o) => "value" in o && "comparator" in o && o.pure === true;
function getOwnerName(owner) {
const { name, componentName: component } = owner;
if (component && typeof component === "string")
return component.startsWith("_Hot$$") ? component.slice(6) : component;
return name || UNNAMED;
}
function getSignalName(signal) {
return signal.name || UNNAMED;
}
function getNodeName(o) {
const name = isSolidOwner(o) ? getOwnerName(o) : getSignalName(o);
return trimString(name, 16);
}
function getNodeType(o) {
if (isSolidOwner(o))
return getOwnerType(o);
return NodeType.Signal;
}
var getOwnerType = (o) => {
if (typeof o.sdtType !== "undefined")
return o.sdtType;
if (!isSolidComputation(o))
return NodeType.Root;
if (isSolidComponent(o))
return NodeType.Component;
if (_isMemo(o)) {
let parent, parentName;
if ((parent = o.owner) && isSolidComponent(parent) && (parentName = parent.componentName) && parentName.startsWith("_Hot$$"))
return NodeType.Refresh;
return NodeType.Memo;
}
if (o.pure === false) {
if (o.user === true)
return NodeType.Effect;
if (o.context !== null)
return NodeType.Context;
return NodeType.Render;
}
return NodeType.Computation;
};
function getComponentRefreshNode(owner) {
const { owned } = owner;
let refresh;
if (owned && owned.length === 1 && markOwnerType(refresh = owned[0]) === NodeType.Refresh) {
return refresh;
}
return null;
}
function resolveElements(value) {
let resolved = getResolvedElements(value);
if (Array.isArray(resolved) && !resolved.length)
resolved = null;
return resolved;
}
function getResolvedElements(value) {
if (typeof value === "function" && !value.length && value.name === "bound readSignal")
return getResolvedElements(value());
if (Array.isArray(value)) {
const results = [];
for (const item of value) {
const result = getResolvedElements(item);
if (result)
Array.isArray(result) ? results.push.apply(results, result) : results.push(result);
}
return results;
}
return value instanceof HTMLElement ? value : null;
}
function lookupOwner(owner, predicate) {
do {
if (predicate(owner))
return owner;
owner = owner.owner;
} while (owner.owner);
return null;
}
function setDebuggerContext(owner, ctx) {
owner.sdtContext = ctx;
}
function getDebuggerContext(owner) {
while (!owner.sdtContext && owner.owner)
owner = owner.owner;
return owner.sdtContext;
}
function removeDebuggerContext(owner) {
delete owner.sdtContext;
}
var tryOnCleanup = (fn) => getOwner() ? onCleanup(fn) : fn;
function onOwnerCleanup(owner, fn, prepend = false) {
if (owner.cleanups === null)
owner.cleanups = [fn];
else if (prepend)
owner.cleanups.splice(0, 0, fn);
else
owner.cleanups.push(fn);
return () => owner.cleanups?.splice(owner.cleanups.indexOf(fn), 1);
}
function onParentCleanup(owner, fn, prepend = false) {
if (owner.owner)
return onOwnerCleanup(owner.owner, fn, prepend);
return () => {
};
}
var DISPOSE_ID = Symbol("Dispose ID");
function createUnownedRoot(fn) {
return runWithOwner(null, () => createRoot(fn));
}
function getFunctionSources(fn) {
let nodes;
let init = true;
runWithOwner(
null,
() => createRoot(
(dispose) => createComputed(() => {
if (!init)
return;
init = false;
fn();
const sources = getOwner().sources;
if (sources)
nodes = [...sources];
dispose();
})
)
);
return nodes ?? [];
}
var LAST_ID = 0;
var getNewSdtId = () => (LAST_ID++).toString(36);
function markOwnerName(o) {
if (o.sdtName !== void 0)
return o.sdtName;
return o.sdtName = getNodeName(o);
}
function markOwnerType(o, type) {
if (o.sdtType !== void 0)
return o.sdtType;
return o.sdtType = type ?? getOwnerType(o);
}
function markNodeID(o) {
if (o.sdtId !== void 0)
return o.sdtId;
return o.sdtId = getNewSdtId();
}
function markNodesID(nodes) {
if (!nodes || !nodes.length)
return [];
return nodes.map(markNodeID);
}
var SkipInternalRoot = null;
var createInternalRoot = (fn, detachedOwner) => {
SkipInternalRoot = fn;
const v = createRoot((dispose) => {
const owner = getOwner();
setDebuggerContext(owner, INTERNAL);
return fn(dispose);
}, detachedOwner);
if (SkipInternalRoot === fn)
SkipInternalRoot = null;
return v;
};
var skipInternalRoot = () => {
const skip = !!SkipInternalRoot;
if (skip)
SkipInternalRoot = null;
return skip;
};
function createBatchedUpdateEmitter(emit) {
const updates = [];
const triggerUpdateEmit = throttle(() => {
const ids = /* @__PURE__ */ new Set();
const deduped = [];
for (let i = updates.length - 1; i >= 0; i--) {
const update = updates[i];
if (ids.has(update.id))
continue;
ids.add(update.id);
deduped.push(update);
}
updates.length = 0;
emit(deduped);
});
return (update) => {
updates.push(update);
triggerUpdateEmit();
};
}
// src/update.ts
import { untrack } from "solid-js";
import { Observable } from "object-observer";
import { WINDOW_WRAP_STORE_PROPERTY } from "@solid-devtools/shared/variables";
var GraphUpdateListeners = /* @__PURE__ */ new Set();
{
const runListeners = () => GraphUpdateListeners.forEach((f) => f());
if (typeof window._$afterUpdate === "function") {
GraphUpdateListeners.add(window._$afterUpdate);
}
window._$afterUpdate = runListeners;
}
function makeSolidUpdateListener(onUpdate2) {
GraphUpdateListeners.add(onUpdate2);
return tryOnCleanup(() => {
GraphUpdateListeners.delete(onUpdate2);
});
}
var CreateRootListeners = /* @__PURE__ */ new Set();
{
const runListeners = (root) => {
if (skipInternalRoot())
return;
CreateRootListeners.forEach((f) => f(root));
};
if (typeof window._$afterCreateRoot === "function") {
CreateRootListeners.add(window._$afterCreateRoot);
}
window._$afterCreateRoot = runListeners;
}
function makeCreateRootListener(onUpdate2) {
CreateRootListeners.add(onUpdate2);
return tryOnCleanup(() => CreateRootListeners.delete(onUpdate2));
}
window[WINDOW_WRAP_STORE_PROPERTY] = (init) => {
return Observable.from(init);
};
function makeStoreObserver(state, onUpdate2) {
if (!Observable.isObservable(state)) {
console.warn(`Object ${state} is not wrapped`);
return () => {
};
}
Observable.observe(state, onUpdate2);
return tryOnCleanup(() => Observable.unobserve(state, onUpdate2));
}
function observeComputationUpdate(owner, onRun) {
if (owner.onComputationUpdate)
return void (owner.onComputationUpdate = onRun);
owner.onComputationUpdate = onRun;
interceptComputationRerun(owner, (fn) => {
untrack(owner.onComputationUpdate);
fn();
});
}
function interceptComputationRerun(owner, onRun) {
const _fn = owner.fn;
let v;
let prev;
const fn = () => v = _fn(prev);
owner.fn = !!owner.fn.length ? (p) => {
onRun(fn, prev = p);
return v;
} : () => {
onRun(fn, void 0);
return v;
};
}
function observeValueUpdate(node, onUpdate2, symbol) {
if (node.onValueUpdate) {
node.onValueUpdate[symbol] = onUpdate2;
return;
}
const map = node.onValueUpdate = { [symbol]: onUpdate2 };
let value = node.value;
Object.defineProperty(node, "value", {
get: () => value,
set: (newValue) => {
for (let sym of Object.getOwnPropertySymbols(map))
map[sym](newValue, value);
value = newValue;
}
});
}
function removeValueUpdateObserver(node, symbol) {
if (node.onValueUpdate)
delete node.onValueUpdate[symbol];
}
function makeValueUpdateListener(node, onUpdate2, symbol) {
observeValueUpdate(node, onUpdate2, symbol);
tryOnCleanup(() => removeValueUpdateObserver(node, symbol));
}
// src/walker.ts
var $inspectedId;
var $rootId;
var $onComputationUpdate;
var $gatherComponents;
var $components = [];
var $inspectedOwner;
function mapChildren(owner) {
const { owned } = owner;
if (!owned || !owned.length)
return;
const children = Array(owned.length);
for (let i = 0; i < children.length; i++)
children[i] = mapOwner(owned[i]);
return children;
}
function mapOwner(owner) {
const type = markOwnerType(owner);
const id = markNodeID(owner);
const name = type === NodeType2.Component || type === NodeType2.Memo || type === NodeType2.Effect || type === NodeType2.Computation ? markOwnerName(owner) : void 0;
const mapped = { id, type };
if (name)
mapped.name = name;
if (id === $inspectedId)
$inspectedOwner = owner;
if (type === NodeType2.Component) {
let contextNode;
if (name === "provider" && owner.owned && owner.owned.length === 1 && markOwnerType(contextNode = owner.owned[0]) === NodeType2.Context) {
const id2 = markNodeID(contextNode);
if (id2 === $inspectedId)
$inspectedOwner = contextNode;
const mapped2 = { id: id2, type: NodeType2.Context };
const children2 = mapChildren(contextNode.owned[0]);
if (children2)
mapped2.children = children2;
return mapped2;
}
if ($gatherComponents) {
const element = resolveElements(owner.value);
if (element)
$components.push({ id, name, element });
}
let hmr = false;
let refresh = getComponentRefreshNode(owner);
if (refresh) {
hmr = true;
owner = refresh;
}
mapped.hmr = hmr;
} else if (type !== NodeType2.Context) {
observeComputationUpdate(
owner,
$onComputationUpdate.bind(void 0, $rootId, id)
);
if (!owner.sources || owner.sources.length === 0) {
mapped.frozen = true;
}
}
const children = mapChildren(owner);
if (children)
mapped.children = children;
return mapped;
}
function mapRoot(root, id, attached) {
if (id === $inspectedId)
$inspectedOwner = root;
const mapped = { id, type: NodeType2.Root };
const children = mapChildren(root);
if (children)
mapped.children = children;
if (attached)
mapped.attached = markNodeID(attached);
return mapped;
}
function walkSolidTree(owner, config) {
$inspectedId = config.inspectedId;
$rootId = config.rootId;
$onComputationUpdate = config.onComputationUpdate;
$gatherComponents = !!config.gatherComponents;
$inspectedOwner = null;
$components = [];
const root = mapRoot(owner, $rootId, owner.sdtAttached);
return { root, inspectedOwner: $inspectedOwner, components: $components };
}
// src/plugin.ts
import { createEffect, createSignal, untrack as untrack2 } from "solid-js";
import {
createEventHub,
createSimpleEmitter
} from "@solid-primitives/event-bus";
import { throttle as throttle2 } from "@solid-primitives/scheduled";
import { encodeValue as encodeValue2, ElementMap as ElementMap2 } from "@solid-devtools/shared/serialize";
import { createConsumers, untrackedCallback } from "@solid-devtools/shared/primitives";
// src/inspect.ts
import { NodeType as NodeType3 } from "@solid-devtools/shared/graph";
import { ElementMap, encodeValue, ValueType } from "@solid-devtools/shared/serialize";
import { $PROXY } from "solid-js";
var $elementMap;
var $signalMap;
var INSPECTOR = Symbol("inspector");
function mapSignalNode(node, handler) {
const id = markNodeID(node);
$signalMap[id] = node;
observeValueUpdate(node, (value) => handler(id, value), INSPECTOR);
return {
type: getNodeType(node),
name: getNodeName(node),
id,
observers: markNodesID(node.observers),
value: encodeValue(node.value, false, $elementMap)
};
}
function clearOwnerObservers(owner) {
if (isSolidComputation(owner)) {
removeValueUpdateObserver(owner, INSPECTOR);
}
if (owner.sourceMap) {
for (const node of Object.values(owner.sourceMap))
removeValueUpdateObserver(node, INSPECTOR);
}
if (owner.owned) {
for (const node of owner.owned)
removeValueUpdateObserver(node, INSPECTOR);
}
}
function encodeComponentProps(owner, config) {
if (!isSolidComponent(owner))
return null;
const { elementMap, inspectedProps } = config;
const { props } = owner;
const proxy = !!props[$PROXY];
const record = Object.entries(Object.getOwnPropertyDescriptors(props)).reduce(
(record2, [key, descriptor]) => {
record2[key] = "get" in descriptor ? { type: ValueType.Getter, value: key } : encodeValue(
descriptor.value,
inspectedProps ? inspectedProps.has(key) : false,
elementMap
);
return record2;
},
{}
);
return { proxy, record };
}
function collectOwnerDetails(owner, config) {
const { onSignalUpdate, onValueUpdate } = config;
$elementMap = new ElementMap();
$signalMap = {};
const type = markOwnerType(owner);
let { sourceMap, owned } = owner;
let getValue = () => owner.value;
if (type === NodeType3.Context) {
sourceMap = void 0;
owned = null;
const symbols = Object.getOwnPropertySymbols(owner.context);
if (symbols.length !== 1) {
console.warn("Context field has more than one symbol. This is not expected.");
getValue = () => void 0;
} else {
const contextValue = owner.context[symbols[0]];
getValue = () => contextValue;
}
}
let refresh;
if (isSolidComponent(owner) && (refresh = getComponentRefreshNode(owner))) {
sourceMap = refresh.sourceMap;
owned = refresh.owned;
getValue = () => refresh.value;
}
let signals;
if (sourceMap) {
const signalNodes = Object.values(sourceMap);
signals = Array(signalNodes.length);
for (let i = 0; i < signalNodes.length; i++) {
signals[i] = mapSignalNode(signalNodes[i], onSignalUpdate);
}
} else
signals = [];
if (owned) {
for (const node of owned) {
if (isSolidMemo(node))
signals.push(mapSignalNode(node, onSignalUpdate));
}
}
const details = {
id: markNodeID(owner),
name: markOwnerName(owner),
type: markOwnerType(owner),
signals
};
if (isSolidComputation(owner)) {
details.value = encodeValue(getValue(), false, $elementMap);
observeValueUpdate(owner, onValueUpdate, INSPECTOR);
details.sources = markNodesID(owner.sources);
if (isSolidMemo(owner)) {
details.observers = markNodesID(owner.observers);
}
const props = encodeComponentProps(owner, { elementMap: $elementMap });
if (props)
details.props = props;
}
return { details, signalMap: $signalMap, elementMap: $elementMap, getOwnerValue: getValue };
}
// src/plugin.ts
var debuggerConfig = {
gatherComponents: false
};
var exported = createInternalRoot(() => {
const [onUpdate2, triggerUpdate] = createSimpleEmitter();
const [onForceUpdate2, forceTriggerUpdate] = createSimpleEmitter();
const eventHub = createEventHub((bus) => ({
ComputationUpdates: bus(),
SignalUpdates: bus(),
PropsUpdate: bus(),
ValueUpdate: bus(),
StructureUpdates: bus()
}));
const [enabled2, addDebuggerConsumer] = createConsumers();
const [components, setComponents] = createSignal({});
const findComponent = (rootId, nodeId) => {
const componentsList = components()[rootId];
if (!componentsList)
return;
for (const c of componentsList) {
if (c.id === nodeId)
return c;
}
};
function removeRoot2(rootId) {
setComponents((prev) => {
const copy = Object.assign({}, prev);
delete copy[rootId];
return copy;
});
pushStructureUpdate({ removed: rootId });
}
function updateRoot2(newRoot, newComponents) {
setComponents((prev) => Object.assign(prev, { [newRoot.id]: newComponents }));
pushStructureUpdate({ updated: newRoot });
}
const pushStructureUpdate = (() => {
const updates = [];
const removedIds = /* @__PURE__ */ new Set();
const trigger = throttle2(() => {
const updated = {};
for (let i = updates.length - 1; i >= 0; i--) {
const update = updates[i];
const { id } = update;
if (!removedIds.has(id) && !updated[id])
updated[id] = update;
}
eventHub.emit("StructureUpdates", { updated, removed: [...removedIds] });
updates.length = 0;
removedIds.clear();
}, 50);
const pushStructureUpdate2 = (update) => {
if ("removed" in update)
removedIds.add(update.removed);
else if (removedIds.has(update.updated.id))
return;
else
updates.push(update.updated);
trigger();
};
return pushStructureUpdate2;
})();
const inspected = {
elementMap: new ElementMap2(),
signalMap: {},
owner: null,
signals: /* @__PURE__ */ new Set(),
props: /* @__PURE__ */ new Set(),
value: false,
getValue: () => null
};
const [details, setDetails] = createSignal(null);
const getElementById = (id) => inspected.elementMap.get(id);
const pushSignalUpdate = createBatchedUpdateEmitter((updates) => eventHub.emit("SignalUpdates", updates));
const onSignalUpdate = untrackedCallback((id, value) => {
if (!enabled2() || !inspected.owner)
return;
const isSelected = inspected.signals.has(id);
pushSignalUpdate({ id, value: encodeValue2(value, isSelected, inspected.elementMap) });
});
const triggerValueUpdate = (() => {
let updateNext = false;
const forceValueUpdate = () => {
if (!enabled2() || !inspected.owner)
return updateNext = false;
eventHub.emit("ValueUpdate", {
value: encodeValue2(inspected.getValue(), inspected.value, inspected.elementMap),
update: updateNext
});
updateNext = false;
};
const triggerValueUpdate2 = throttle2(forceValueUpdate);
function handleValueUpdate(update, force = false) {
if (update)
updateNext = true;
if (force)
forceValueUpdate();
else
triggerValueUpdate2();
}
return handleValueUpdate;
})();
const setInspectedDetails = untrackedCallback((owner) => {
inspected.owner && clearOwnerObservers(inspected.owner);
inspected.props.clear();
inspected.signals.clear();
inspected.owner = owner;
inspected.value = false;
const result = collectOwnerDetails(owner, {
onSignalUpdate,
onValueUpdate: () => triggerValueUpdate(true)
});
setDetails(result.details);
inspected.signalMap = result.signalMap;
inspected.elementMap = result.elementMap;
inspected.getValue = result.getOwnerValue;
});
const clearInspectedDetails = () => {
inspected.owner && clearOwnerObservers(inspected.owner);
inspected.owner = null;
setDetails(null);
inspected.signals.clear();
inspected.props.clear();
inspected.value = false;
};
function updateInspectedProps() {
if (!inspected.owner)
return;
const props = encodeComponentProps(inspected.owner, {
inspectedProps: inspected.props,
elementMap: inspected.elementMap
});
props && eventHub.emit("PropsUpdate", props);
}
createEffect(() => {
if (!enabled2())
inspected.owner && clearOwnerObservers(inspected.owner);
else
inspected.owner && setInspectedDetails(inspected.owner);
makeSolidUpdateListener(
throttle2(() => {
updateInspectedProps();
triggerValueUpdate(false);
}, 150)
);
});
const setInspectedNode = (payload) => {
if (!payload)
return clearInspectedDetails();
const { rootId, nodeId } = payload;
const walkResult = walkSolidRoot(rootId, nodeId);
if (!walkResult || !walkResult.inspectedOwner)
return clearInspectedDetails();
setInspectedDetails(walkResult.inspectedOwner);
};
const setInspectedSignal = (id, selected) => {
const signal = inspected.signalMap[id];
if (!signal)
return null;
if (selected)
inspected.signals.add(id);
else
inspected.signals.delete(id);
return untrack2(() => encodeValue2(signal.value, selected, inspected.elementMap));
};
const setInspectedProp = (key, selected) => {
if (selected)
inspected.props.add(key);
else
inspected.props.delete(key);
updateInspectedProps();
};
const setInspectedValue = (selected) => {
if (!inspected.owner)
return null;
inspected.value = selected;
triggerValueUpdate(false, true);
};
const _pushComputationUpdate = createBatchedUpdateEmitter(
(updates) => eventHub.emit("ComputationUpdates", updates)
);
const pushComputationUpdate2 = (rootId, id) => {
_pushComputationUpdate({ rootId, id });
};
const pluginData = {
listenTo: eventHub.on,
components,
findComponent,
triggerUpdate,
forceTriggerUpdate,
inspectedDetails: details,
setInspectedNode,
setInspectedSignal,
setInspectedProp,
setInspectedValue,
getElementById
};
function useDebugger2(options) {
const { enabled: enabled3, gatherComponents } = options;
enabled3 && addDebuggerConsumer(enabled3);
if (gatherComponents)
debuggerConfig.gatherComponents = true;
return pluginData;
}
return {
onUpdate: onUpdate2,
onForceUpdate: onForceUpdate2,
enabled: enabled2,
useDebugger: useDebugger2,
updateRoot: updateRoot2,
removeRoot: removeRoot2,
pushComputationUpdate: pushComputationUpdate2
};
});
var {
onUpdate,
onForceUpdate,
enabled,
useDebugger,
updateRoot,
removeRoot,
pushComputationUpdate
} = exported;
// src/roots.ts
var RootMap = {};
var walkSolidRoot = (rootId, inspectedId) => {
const walk = RootMap[rootId];
return walk ? walk(inspectedId) : null;
};
function createGraphRoot(owner) {
createInternalRoot((dispose) => {
onOwnerCleanup(owner, dispose);
const rootId = markNodeID(owner);
const onComputationUpdate = (rootId2, nodeId) => {
if (owner.isDisposed)
return;
if (untrack3(enabled))
triggerRootUpdate();
pushComputationUpdate(rootId2, nodeId);
};
const forceRootUpdate = untrackedCallback2((inspectedId) => {
if (owner.isDisposed)
return null;
const result = walkSolidTree(owner, {
...debuggerConfig,
onComputationUpdate,
rootId,
inspectedId: inspectedId ?? null
});
updateRoot(result.root, result.components);
return result;
});
const triggerRootUpdate = throttle3(forceRootUpdate, 300);
RootMap[rootId] = forceRootUpdate;
onUpdate(triggerRootUpdate);
onForceUpdate(forceRootUpdate);
createEffect2(() => {
enabled() && forceRootUpdate();
});
setDebuggerContext(owner, { rootId, triggerRootUpdate, forceRootUpdate });
onCleanup2(() => {
removeDebuggerContext(owner);
removeRoot(rootId);
owner.isDisposed = true;
delete RootMap[rootId];
});
});
}
function attachDebugger(_owner = getOwner2()) {
let owner = _owner;
if (!owner)
return warn("reatachOwner helper should be called synchronously in a reactive owner.");
forEachLookupRoot(owner, (root, ctx) => {
if (ctx === INTERNAL2)
return;
root.sdtAttached = null;
markOwnerType(root, NodeType4.Root);
createGraphRoot(root);
if (ctx) {
ctx.triggerRootUpdate();
let parent = findClosestAliveParent(root);
if (!parent.owner)
return warn("PARENT_SHOULD_BE_ALIVE");
root.sdtAttached = parent.owner;
const onParentCleanup2 = () => {
const newParent = findClosestAliveParent(root);
if (newParent.owner) {
parent = newParent;
root.sdtAttached = parent.owner;
onOwnerCleanup(parent.root, onParentCleanup2);
} else {
root.sdtAttached = null;
removeOwnCleanup();
}
};
const removeParentCleanup = onOwnerCleanup(parent.root, onParentCleanup2);
const removeOwnCleanup = onOwnerCleanup(root, () => {
root.isDisposed = true;
root.sdtAttached = null;
removeParentCleanup();
ctx.triggerRootUpdate();
});
}
});
}
function findClosestAliveParent(owner) {
let disposed = null;
let closestAliveRoot = null;
let current = owner;
while (current.owner && !closestAliveRoot) {
current = current.owner;
if (isSolidRoot(current)) {
if (current.isDisposed)
disposed = current;
else
closestAliveRoot = current;
}
}
if (!closestAliveRoot)
return { owner: null, root: null };
return { owner: disposed?.owner ?? owner.owner, root: closestAliveRoot };
}
function forEachLookupRoot(owner, callback) {
const roots = [];
let ctx;
do {
if (isSolidRoot(owner)) {
if ("sdtAttached" in owner) {
if (!ctx)
ctx = getDebuggerContext(owner);
break;
}
if (owner.sdtContext === INTERNAL2) {
ctx = INTERNAL2;
break;
}
roots.push(owner);
}
owner = owner.owner;
} while (owner);
for (let i = roots.length - 1; i >= 0; i--) {
const root = roots[i];
callback(root, ctx);
if (root.sdtContext)
ctx = root.sdtContext;
}
}
// src/index.ts
var Debugger = (props) => {
attachDebugger();
return props.children;
};
var autoattachEnabled = false;
function enableRootsAutoattach() {
if (autoattachEnabled)
return;
autoattachEnabled = true;
makeCreateRootListener((root) => attachDebugger(root));
}
export {
isSolidComputation,
isSolidMemo,
isSolidOwner,
isSolidRoot,
getNodeName,
getNodeType,
getOwnerType,
lookupOwner,
onOwnerCleanup,
onParentCleanup,
createUnownedRoot,
getFunctionSources,
createInternalRoot,
makeSolidUpdateListener,
makeCreateRootListener,
makeStoreObserver,
observeComputationUpdate,
interceptComputationRerun,
observeValueUpdate,
removeValueUpdateObserver,
makeValueUpdateListener,
useDebugger,
attachDebugger,
Debugger,
enableRootsAutoattach
};
+13
-7

@@ -27,2 +27,3 @@ "use strict";

createUnownedRoot: () => createUnownedRoot,
enableRootsAutoattach: () => enableRootsAutoattach,
getFunctionSources: () => getFunctionSources,

@@ -169,6 +170,3 @@ getNodeName: () => getNodeName,

owner.cleanups.push(fn);
return () => {
var _a;
return (_a = owner.cleanups) == null ? void 0 : _a.splice(owner.cleanups.indexOf(fn), 1);
};
return () => owner.cleanups?.splice(owner.cleanups.indexOf(fn), 1);
}

@@ -709,3 +707,3 @@ function onParentCleanup(owner, fn, prepend = false) {

});
const setInspectedOwner = (payload) => {
const setInspectedNode = (payload) => {
if (!payload)

@@ -755,3 +753,3 @@ return clearInspectedDetails();

inspectedDetails: details,
setInspectedOwner,
setInspectedNode,
setInspectedSignal,

@@ -886,3 +884,3 @@ setInspectedProp,

return { owner: null, root: null };
return { owner: (disposed == null ? void 0 : disposed.owner) ?? owner.owner, root: closestAliveRoot };
return { owner: disposed?.owner ?? owner.owner, root: closestAliveRoot };
}

@@ -920,2 +918,9 @@ function forEachLookupRoot(owner, callback) {

};
var autoattachEnabled = false;
function enableRootsAutoattach() {
if (autoattachEnabled)
return;
autoattachEnabled = true;
makeCreateRootListener((root) => attachDebugger(root));
}
// Annotate the CommonJS export names for ESM import in node:

@@ -927,2 +932,3 @@ 0 && (module.exports = {

createUnownedRoot,
enableRootsAutoattach,
getFunctionSources,

@@ -929,0 +935,0 @@ getNodeName,

@@ -30,3 +30,3 @@ import { Accessor, createRoot, ParentComponent } from 'solid-js';

readonly inspectedDetails: Accessor<Mapped.OwnerDetails | null>;
readonly setInspectedOwner: (payload: {
readonly setInspectedNode: (payload: {
rootId: NodeID;

@@ -135,3 +135,4 @@ nodeId: NodeID;

declare const Debugger: ParentComponent;
declare function enableRootsAutoattach(): void;
export { AfterCrateRoot, BatchComputationUpdatesHandler, Debugger, PluginData, attachDebugger, createInternalRoot, createUnownedRoot, getFunctionSources, getNodeName, getNodeType, getOwnerType, interceptComputationRerun, isSolidComputation, isSolidMemo, isSolidOwner, isSolidRoot, lookupOwner, makeCreateRootListener, makeSolidUpdateListener, makeStoreObserver, makeValueUpdateListener, observeComputationUpdate, observeValueUpdate, onOwnerCleanup, onParentCleanup, removeValueUpdateObserver, useDebugger };
export { AfterCrateRoot, BatchComputationUpdatesHandler, Debugger, PluginData, attachDebugger, createInternalRoot, createUnownedRoot, enableRootsAutoattach, getFunctionSources, getNodeName, getNodeType, getOwnerType, interceptComputationRerun, isSolidComputation, isSolidMemo, isSolidOwner, isSolidRoot, lookupOwner, makeCreateRootListener, makeSolidUpdateListener, makeStoreObserver, makeValueUpdateListener, observeComputationUpdate, observeValueUpdate, onOwnerCleanup, onParentCleanup, removeValueUpdateObserver, useDebugger };

@@ -6,2 +6,3 @@ import {

createUnownedRoot,
enableRootsAutoattach,
getFunctionSources,

@@ -27,3 +28,3 @@ getNodeName,

useDebugger
} from "./chunk-IQYVDTNV.js";
} from "./chunk-YDYIFWRS.js";
export {

@@ -34,2 +35,3 @@ Debugger,

createUnownedRoot,
enableRootsAutoattach,
getFunctionSources,

@@ -36,0 +38,0 @@ getNodeName,

@@ -27,2 +27,3 @@ "use strict";

createUnownedRoot: () => createUnownedRoot,
enableRootsAutoattach: () => enableRootsAutoattach,
getFunctionSources: () => getFunctionSources2,

@@ -78,3 +79,3 @@ getNodeName: () => getNodeName2,

findComponent: () => void 0,
setInspectedOwner: () => {
setInspectedNode: () => {
},

@@ -90,2 +91,4 @@ getElementById: () => void 0,

});
var enableRootsAutoattach = () => {
};
var makeSolidUpdateListener = () => () => {

@@ -127,2 +130,3 @@ };

createUnownedRoot,
enableRootsAutoattach,
getFunctionSources,

@@ -129,0 +133,0 @@ getNodeName,

import {
createUnownedRoot
} from "./chunk-IQYVDTNV.js";
} from "./chunk-YDYIFWRS.js";

@@ -21,3 +21,3 @@ // src/server.ts

findComponent: () => void 0,
setInspectedOwner: () => {
setInspectedNode: () => {
},

@@ -33,2 +33,4 @@ getElementById: () => void 0,

});
var enableRootsAutoattach = () => {
};
var makeSolidUpdateListener = () => () => {

@@ -69,2 +71,3 @@ };

createUnownedRoot,
enableRootsAutoattach,
getFunctionSources,

@@ -71,0 +74,0 @@ getNodeName,

{
"name": "@solid-devtools/debugger",
"version": "0.11.1",
"version": "0.12.0",
"description": "Debugger of the Solid's reactivity graph — a cornerstone of all solid-devtools.",

@@ -47,20 +47,20 @@ "license": "MIT",

"devDependencies": {
"@babel/core": "^7.19.1",
"@babel/preset-env": "^7.19.1",
"@jest/globals": "^29.0.3",
"@jest/types": "^29.0.3",
"@babel/core": "^7.19.3",
"@babel/preset-env": "^7.19.3",
"@jest/globals": "^29.1.2",
"@jest/types": "^29.1.2",
"@testing-library/jest-dom": "^5.16.5",
"jest": "^29.0.3",
"jest-environment-jsdom": "^29.0.3",
"solid-js": "^1.5.5",
"ts-jest": "^29.0.1",
"jest": "^29.1.2",
"jest-environment-jsdom": "^29.1.2",
"solid-js": "^1.5.7",
"ts-jest": "^29.0.3",
"ts-node": "^10.9.1",
"tsup": "^6.2.3",
"typescript": "^4.8.3"
"typescript": "^4.8.4"
},
"dependencies": {
"@solid-devtools/shared": "^0.8.4",
"@solid-devtools/shared": "^0.9.0",
"@solid-primitives/event-bus": "^0.1.2",
"@solid-primitives/scheduled": "^1.0.1",
"object-observer": "^5.1.5",
"@solid-primitives/scheduled": "^1.0.2",
"object-observer": "^5.1.6",
"type-fest": "^2.19.0"

@@ -72,5 +72,5 @@ },

"optionalDependencies": {
"@solid-devtools/transform": "^0.7.3"
"@solid-devtools/transform": "^0.7.5"
},
"packageManager": "pnpm@7.12.0",
"packageManager": "pnpm@7.13.0",
"scripts": {

@@ -77,0 +77,0 @@ "dev": "tsup --watch",

@@ -9,2 +9,6 @@ <a href="https://github.com/thetarnav/solid-devtools/tree/main/packages/debugger#readme" target="_blank">

[![pnpm](https://img.shields.io/badge/maintained%20with-pnpm-cc00ff.svg?style=for-the-badge&logo=pnpm)](https://pnpm.io/)
[![version](https://img.shields.io/npm/v/@solid-devtools/debugger?style=for-the-badge)](https://www.npmjs.com/package/@solid-devtools/debugger)
[![npm](https://img.shields.io/npm/dw/@solid-devtools/debugger?style=for-the-badge)](https://www.npmjs.com/package/@solid-devtools/debugger)
A runtime package, used to get information and track changes of the Solid's reactivity graph. It's a cornerstone of the rest of the packages.

@@ -33,3 +37,3 @@

```ts
import { attachDebugger, makeCreateRootListener } from "@solid-devtools/debugger"
import { attachDebugger, makeCreateRootListener } from '@solid-devtools/debugger'

@@ -50,4 +54,4 @@ makeCreateRootListener(root => attachDebugger(root))

```tsx
import { render } from "solid-js/web"
import { attachDebugger } from "@solid-devtools/debugger"
import { render } from 'solid-js/web'
import { attachDebugger } from '@solid-devtools/debugger'

@@ -57,3 +61,3 @@ render(() => {

return <App />
}, document.getElementById("root"))
}, document.getElementById('root'))

@@ -72,4 +76,4 @@ // or inside the App component:

```tsx
import { render } from "solid-js/web"
import { Debugger } from "@solid-devtools/debugger"
import { render } from 'solid-js/web'
import { Debugger } from '@solid-devtools/debugger'

@@ -82,3 +86,3 @@ render(

),
document.getElementById("root"),
document.getElementById('root'),
)

@@ -85,0 +89,0 @@ ```

// src/roots.ts
import { createEffect as createEffect2, onCleanup as onCleanup2, untrack as untrack3 } from "solid-js";
import { throttle as throttle3 } from "@solid-primitives/scheduled";
import {
getOwner as getOwner2,
NodeType as NodeType4
} from "@solid-devtools/shared/graph";
import { INTERNAL as INTERNAL2 } from "@solid-devtools/shared/variables";
import { untrackedCallback as untrackedCallback2 } from "@solid-devtools/shared/primitives";
import { warn } from "@solid-devtools/shared/utils";
// src/walker.ts
import { NodeType as NodeType2 } from "@solid-devtools/shared/graph";
// src/utils.ts
import { createComputed, createRoot, onCleanup, runWithOwner } from "solid-js";
import { throttle } from "@solid-primitives/scheduled";
import {
NodeType,
getOwner
} from "@solid-devtools/shared/graph";
import { INTERNAL, UNNAMED } from "@solid-devtools/shared/variables";
import { trimString } from "@solid-devtools/shared/utils";
var isSolidComputation = (o) => "fn" in o;
var isSolidMemo = (o) => "sdtType" in o ? o.sdtType === NodeType.Memo : isSolidComputation(o) && _isMemo(o);
var isSolidOwner = (o) => "owned" in o;
var isSolidRoot = (o) => o.sdtType === NodeType.Root || !isSolidComputation(o);
var isSolidComponent = (o) => "props" in o;
var _isMemo = (o) => "value" in o && "comparator" in o && o.pure === true;
function getOwnerName(owner) {
const { name, componentName: component } = owner;
if (component && typeof component === "string")
return component.startsWith("_Hot$$") ? component.slice(6) : component;
return name || UNNAMED;
}
function getSignalName(signal) {
return signal.name || UNNAMED;
}
function getNodeName(o) {
const name = isSolidOwner(o) ? getOwnerName(o) : getSignalName(o);
return trimString(name, 16);
}
function getNodeType(o) {
if (isSolidOwner(o))
return getOwnerType(o);
return NodeType.Signal;
}
var getOwnerType = (o) => {
if (typeof o.sdtType !== "undefined")
return o.sdtType;
if (!isSolidComputation(o))
return NodeType.Root;
if (isSolidComponent(o))
return NodeType.Component;
if (_isMemo(o)) {
let parent, parentName;
if ((parent = o.owner) && isSolidComponent(parent) && (parentName = parent.componentName) && parentName.startsWith("_Hot$$"))
return NodeType.Refresh;
return NodeType.Memo;
}
if (o.pure === false) {
if (o.user === true)
return NodeType.Effect;
if (o.context !== null)
return NodeType.Context;
return NodeType.Render;
}
return NodeType.Computation;
};
function getComponentRefreshNode(owner) {
const { owned } = owner;
let refresh;
if (owned && owned.length === 1 && markOwnerType(refresh = owned[0]) === NodeType.Refresh) {
return refresh;
}
return null;
}
function resolveElements(value) {
let resolved = getResolvedElements(value);
if (Array.isArray(resolved) && !resolved.length)
resolved = null;
return resolved;
}
function getResolvedElements(value) {
if (typeof value === "function" && !value.length && value.name === "bound readSignal")
return getResolvedElements(value());
if (Array.isArray(value)) {
const results = [];
for (const item of value) {
const result = getResolvedElements(item);
if (result)
Array.isArray(result) ? results.push.apply(results, result) : results.push(result);
}
return results;
}
return value instanceof HTMLElement ? value : null;
}
function lookupOwner(owner, predicate) {
do {
if (predicate(owner))
return owner;
owner = owner.owner;
} while (owner.owner);
return null;
}
function setDebuggerContext(owner, ctx) {
owner.sdtContext = ctx;
}
function getDebuggerContext(owner) {
while (!owner.sdtContext && owner.owner)
owner = owner.owner;
return owner.sdtContext;
}
function removeDebuggerContext(owner) {
delete owner.sdtContext;
}
var tryOnCleanup = (fn) => getOwner() ? onCleanup(fn) : fn;
function onOwnerCleanup(owner, fn, prepend = false) {
if (owner.cleanups === null)
owner.cleanups = [fn];
else if (prepend)
owner.cleanups.splice(0, 0, fn);
else
owner.cleanups.push(fn);
return () => {
var _a;
return (_a = owner.cleanups) == null ? void 0 : _a.splice(owner.cleanups.indexOf(fn), 1);
};
}
function onParentCleanup(owner, fn, prepend = false) {
if (owner.owner)
return onOwnerCleanup(owner.owner, fn, prepend);
return () => {
};
}
var DISPOSE_ID = Symbol("Dispose ID");
function createUnownedRoot(fn) {
return runWithOwner(null, () => createRoot(fn));
}
function getFunctionSources(fn) {
let nodes;
let init = true;
runWithOwner(
null,
() => createRoot(
(dispose) => createComputed(() => {
if (!init)
return;
init = false;
fn();
const sources = getOwner().sources;
if (sources)
nodes = [...sources];
dispose();
})
)
);
return nodes ?? [];
}
var LAST_ID = 0;
var getNewSdtId = () => (LAST_ID++).toString(36);
function markOwnerName(o) {
if (o.sdtName !== void 0)
return o.sdtName;
return o.sdtName = getNodeName(o);
}
function markOwnerType(o, type) {
if (o.sdtType !== void 0)
return o.sdtType;
return o.sdtType = type ?? getOwnerType(o);
}
function markNodeID(o) {
if (o.sdtId !== void 0)
return o.sdtId;
return o.sdtId = getNewSdtId();
}
function markNodesID(nodes) {
if (!nodes || !nodes.length)
return [];
return nodes.map(markNodeID);
}
var SkipInternalRoot = null;
var createInternalRoot = (fn, detachedOwner) => {
SkipInternalRoot = fn;
const v = createRoot((dispose) => {
const owner = getOwner();
setDebuggerContext(owner, INTERNAL);
return fn(dispose);
}, detachedOwner);
if (SkipInternalRoot === fn)
SkipInternalRoot = null;
return v;
};
var skipInternalRoot = () => {
const skip = !!SkipInternalRoot;
if (skip)
SkipInternalRoot = null;
return skip;
};
function createBatchedUpdateEmitter(emit) {
const updates = [];
const triggerUpdateEmit = throttle(() => {
const ids = /* @__PURE__ */ new Set();
const deduped = [];
for (let i = updates.length - 1; i >= 0; i--) {
const update = updates[i];
if (ids.has(update.id))
continue;
ids.add(update.id);
deduped.push(update);
}
updates.length = 0;
emit(deduped);
});
return (update) => {
updates.push(update);
triggerUpdateEmit();
};
}
// src/update.ts
import { untrack } from "solid-js";
import { Observable } from "object-observer";
import { WINDOW_WRAP_STORE_PROPERTY } from "@solid-devtools/shared/variables";
var GraphUpdateListeners = /* @__PURE__ */ new Set();
{
const runListeners = () => GraphUpdateListeners.forEach((f) => f());
if (typeof window._$afterUpdate === "function") {
GraphUpdateListeners.add(window._$afterUpdate);
}
window._$afterUpdate = runListeners;
}
function makeSolidUpdateListener(onUpdate2) {
GraphUpdateListeners.add(onUpdate2);
return tryOnCleanup(() => {
GraphUpdateListeners.delete(onUpdate2);
});
}
var CreateRootListeners = /* @__PURE__ */ new Set();
{
const runListeners = (root) => {
if (skipInternalRoot())
return;
CreateRootListeners.forEach((f) => f(root));
};
if (typeof window._$afterCreateRoot === "function") {
CreateRootListeners.add(window._$afterCreateRoot);
}
window._$afterCreateRoot = runListeners;
}
function makeCreateRootListener(onUpdate2) {
CreateRootListeners.add(onUpdate2);
return tryOnCleanup(() => CreateRootListeners.delete(onUpdate2));
}
window[WINDOW_WRAP_STORE_PROPERTY] = (init) => {
return Observable.from(init);
};
function makeStoreObserver(state, onUpdate2) {
if (!Observable.isObservable(state)) {
console.warn(`Object ${state} is not wrapped`);
return () => {
};
}
Observable.observe(state, onUpdate2);
return tryOnCleanup(() => Observable.unobserve(state, onUpdate2));
}
function observeComputationUpdate(owner, onRun) {
if (owner.onComputationUpdate)
return void (owner.onComputationUpdate = onRun);
owner.onComputationUpdate = onRun;
interceptComputationRerun(owner, (fn) => {
untrack(owner.onComputationUpdate);
fn();
});
}
function interceptComputationRerun(owner, onRun) {
const _fn = owner.fn;
let v;
let prev;
const fn = () => v = _fn(prev);
owner.fn = !!owner.fn.length ? (p) => {
onRun(fn, prev = p);
return v;
} : () => {
onRun(fn, void 0);
return v;
};
}
function observeValueUpdate(node, onUpdate2, symbol) {
if (node.onValueUpdate) {
node.onValueUpdate[symbol] = onUpdate2;
return;
}
const map = node.onValueUpdate = { [symbol]: onUpdate2 };
let value = node.value;
Object.defineProperty(node, "value", {
get: () => value,
set: (newValue) => {
for (let sym of Object.getOwnPropertySymbols(map))
map[sym](newValue, value);
value = newValue;
}
});
}
function removeValueUpdateObserver(node, symbol) {
if (node.onValueUpdate)
delete node.onValueUpdate[symbol];
}
function makeValueUpdateListener(node, onUpdate2, symbol) {
observeValueUpdate(node, onUpdate2, symbol);
tryOnCleanup(() => removeValueUpdateObserver(node, symbol));
}
// src/walker.ts
var $inspectedId;
var $rootId;
var $onComputationUpdate;
var $gatherComponents;
var $components = [];
var $inspectedOwner;
function mapChildren(owner) {
const { owned } = owner;
if (!owned || !owned.length)
return;
const children = Array(owned.length);
for (let i = 0; i < children.length; i++)
children[i] = mapOwner(owned[i]);
return children;
}
function mapOwner(owner) {
const type = markOwnerType(owner);
const id = markNodeID(owner);
const name = type === NodeType2.Component || type === NodeType2.Memo || type === NodeType2.Effect || type === NodeType2.Computation ? markOwnerName(owner) : void 0;
const mapped = { id, type };
if (name)
mapped.name = name;
if (id === $inspectedId)
$inspectedOwner = owner;
if (type === NodeType2.Component) {
let contextNode;
if (name === "provider" && owner.owned && owner.owned.length === 1 && markOwnerType(contextNode = owner.owned[0]) === NodeType2.Context) {
const id2 = markNodeID(contextNode);
if (id2 === $inspectedId)
$inspectedOwner = contextNode;
const mapped2 = { id: id2, type: NodeType2.Context };
const children2 = mapChildren(contextNode.owned[0]);
if (children2)
mapped2.children = children2;
return mapped2;
}
if ($gatherComponents) {
const element = resolveElements(owner.value);
if (element)
$components.push({ id, name, element });
}
let hmr = false;
let refresh = getComponentRefreshNode(owner);
if (refresh) {
hmr = true;
owner = refresh;
}
mapped.hmr = hmr;
} else if (type !== NodeType2.Context) {
observeComputationUpdate(
owner,
$onComputationUpdate.bind(void 0, $rootId, id)
);
if (!owner.sources || owner.sources.length === 0) {
mapped.frozen = true;
}
}
const children = mapChildren(owner);
if (children)
mapped.children = children;
return mapped;
}
function mapRoot(root, id, attached) {
if (id === $inspectedId)
$inspectedOwner = root;
const mapped = { id, type: NodeType2.Root };
const children = mapChildren(root);
if (children)
mapped.children = children;
if (attached)
mapped.attached = markNodeID(attached);
return mapped;
}
function walkSolidTree(owner, config) {
$inspectedId = config.inspectedId;
$rootId = config.rootId;
$onComputationUpdate = config.onComputationUpdate;
$gatherComponents = !!config.gatherComponents;
$inspectedOwner = null;
$components = [];
const root = mapRoot(owner, $rootId, owner.sdtAttached);
return { root, inspectedOwner: $inspectedOwner, components: $components };
}
// src/plugin.ts
import { createEffect, createSignal, untrack as untrack2 } from "solid-js";
import {
createEventHub,
createSimpleEmitter
} from "@solid-primitives/event-bus";
import { throttle as throttle2 } from "@solid-primitives/scheduled";
import { encodeValue as encodeValue2, ElementMap as ElementMap2 } from "@solid-devtools/shared/serialize";
import { createConsumers, untrackedCallback } from "@solid-devtools/shared/primitives";
// src/inspect.ts
import { NodeType as NodeType3 } from "@solid-devtools/shared/graph";
import { ElementMap, encodeValue, ValueType } from "@solid-devtools/shared/serialize";
import { $PROXY } from "solid-js";
var $elementMap;
var $signalMap;
var INSPECTOR = Symbol("inspector");
function mapSignalNode(node, handler) {
const id = markNodeID(node);
$signalMap[id] = node;
observeValueUpdate(node, (value) => handler(id, value), INSPECTOR);
return {
type: getNodeType(node),
name: getNodeName(node),
id,
observers: markNodesID(node.observers),
value: encodeValue(node.value, false, $elementMap)
};
}
function clearOwnerObservers(owner) {
if (isSolidComputation(owner)) {
removeValueUpdateObserver(owner, INSPECTOR);
}
if (owner.sourceMap) {
for (const node of Object.values(owner.sourceMap))
removeValueUpdateObserver(node, INSPECTOR);
}
if (owner.owned) {
for (const node of owner.owned)
removeValueUpdateObserver(node, INSPECTOR);
}
}
function encodeComponentProps(owner, config) {
if (!isSolidComponent(owner))
return null;
const { elementMap, inspectedProps } = config;
const { props } = owner;
const proxy = !!props[$PROXY];
const record = Object.entries(Object.getOwnPropertyDescriptors(props)).reduce(
(record2, [key, descriptor]) => {
record2[key] = "get" in descriptor ? { type: ValueType.Getter, value: key } : encodeValue(
descriptor.value,
inspectedProps ? inspectedProps.has(key) : false,
elementMap
);
return record2;
},
{}
);
return { proxy, record };
}
function collectOwnerDetails(owner, config) {
const { onSignalUpdate, onValueUpdate } = config;
$elementMap = new ElementMap();
$signalMap = {};
const type = markOwnerType(owner);
let { sourceMap, owned } = owner;
let getValue = () => owner.value;
if (type === NodeType3.Context) {
sourceMap = void 0;
owned = null;
const symbols = Object.getOwnPropertySymbols(owner.context);
if (symbols.length !== 1) {
console.warn("Context field has more than one symbol. This is not expected.");
getValue = () => void 0;
} else {
const contextValue = owner.context[symbols[0]];
getValue = () => contextValue;
}
}
let refresh;
if (isSolidComponent(owner) && (refresh = getComponentRefreshNode(owner))) {
sourceMap = refresh.sourceMap;
owned = refresh.owned;
getValue = () => refresh.value;
}
let signals;
if (sourceMap) {
const signalNodes = Object.values(sourceMap);
signals = Array(signalNodes.length);
for (let i = 0; i < signalNodes.length; i++) {
signals[i] = mapSignalNode(signalNodes[i], onSignalUpdate);
}
} else
signals = [];
if (owned) {
for (const node of owned) {
if (isSolidMemo(node))
signals.push(mapSignalNode(node, onSignalUpdate));
}
}
const details = {
id: markNodeID(owner),
name: markOwnerName(owner),
type: markOwnerType(owner),
signals
};
if (isSolidComputation(owner)) {
details.value = encodeValue(getValue(), false, $elementMap);
observeValueUpdate(owner, onValueUpdate, INSPECTOR);
details.sources = markNodesID(owner.sources);
if (isSolidMemo(owner)) {
details.observers = markNodesID(owner.observers);
}
const props = encodeComponentProps(owner, { elementMap: $elementMap });
if (props)
details.props = props;
}
return { details, signalMap: $signalMap, elementMap: $elementMap, getOwnerValue: getValue };
}
// src/plugin.ts
var debuggerConfig = {
gatherComponents: false
};
var exported = createInternalRoot(() => {
const [onUpdate2, triggerUpdate] = createSimpleEmitter();
const [onForceUpdate2, forceTriggerUpdate] = createSimpleEmitter();
const eventHub = createEventHub((bus) => ({
ComputationUpdates: bus(),
SignalUpdates: bus(),
PropsUpdate: bus(),
ValueUpdate: bus(),
StructureUpdates: bus()
}));
const [enabled2, addDebuggerConsumer] = createConsumers();
const [components, setComponents] = createSignal({});
const findComponent = (rootId, nodeId) => {
const componentsList = components()[rootId];
if (!componentsList)
return;
for (const c of componentsList) {
if (c.id === nodeId)
return c;
}
};
function removeRoot2(rootId) {
setComponents((prev) => {
const copy = Object.assign({}, prev);
delete copy[rootId];
return copy;
});
pushStructureUpdate({ removed: rootId });
}
function updateRoot2(newRoot, newComponents) {
setComponents((prev) => Object.assign(prev, { [newRoot.id]: newComponents }));
pushStructureUpdate({ updated: newRoot });
}
const pushStructureUpdate = (() => {
const updates = [];
const removedIds = /* @__PURE__ */ new Set();
const trigger = throttle2(() => {
const updated = {};
for (let i = updates.length - 1; i >= 0; i--) {
const update = updates[i];
const { id } = update;
if (!removedIds.has(id) && !updated[id])
updated[id] = update;
}
eventHub.emit("StructureUpdates", { updated, removed: [...removedIds] });
updates.length = 0;
removedIds.clear();
}, 50);
const pushStructureUpdate2 = (update) => {
if ("removed" in update)
removedIds.add(update.removed);
else if (removedIds.has(update.updated.id))
return;
else
updates.push(update.updated);
trigger();
};
return pushStructureUpdate2;
})();
const inspected = {
elementMap: new ElementMap2(),
signalMap: {},
owner: null,
signals: /* @__PURE__ */ new Set(),
props: /* @__PURE__ */ new Set(),
value: false,
getValue: () => null
};
const [details, setDetails] = createSignal(null);
const getElementById = (id) => inspected.elementMap.get(id);
const pushSignalUpdate = createBatchedUpdateEmitter((updates) => eventHub.emit("SignalUpdates", updates));
const onSignalUpdate = untrackedCallback((id, value) => {
if (!enabled2() || !inspected.owner)
return;
const isSelected = inspected.signals.has(id);
pushSignalUpdate({ id, value: encodeValue2(value, isSelected, inspected.elementMap) });
});
const triggerValueUpdate = (() => {
let updateNext = false;
const forceValueUpdate = () => {
if (!enabled2() || !inspected.owner)
return updateNext = false;
eventHub.emit("ValueUpdate", {
value: encodeValue2(inspected.getValue(), inspected.value, inspected.elementMap),
update: updateNext
});
updateNext = false;
};
const triggerValueUpdate2 = throttle2(forceValueUpdate);
function handleValueUpdate(update, force = false) {
if (update)
updateNext = true;
if (force)
forceValueUpdate();
else
triggerValueUpdate2();
}
return handleValueUpdate;
})();
const setInspectedDetails = untrackedCallback((owner) => {
inspected.owner && clearOwnerObservers(inspected.owner);
inspected.props.clear();
inspected.signals.clear();
inspected.owner = owner;
inspected.value = false;
const result = collectOwnerDetails(owner, {
onSignalUpdate,
onValueUpdate: () => triggerValueUpdate(true)
});
setDetails(result.details);
inspected.signalMap = result.signalMap;
inspected.elementMap = result.elementMap;
inspected.getValue = result.getOwnerValue;
});
const clearInspectedDetails = () => {
inspected.owner && clearOwnerObservers(inspected.owner);
inspected.owner = null;
setDetails(null);
inspected.signals.clear();
inspected.props.clear();
inspected.value = false;
};
function updateInspectedProps() {
if (!inspected.owner)
return;
const props = encodeComponentProps(inspected.owner, {
inspectedProps: inspected.props,
elementMap: inspected.elementMap
});
props && eventHub.emit("PropsUpdate", props);
}
createEffect(() => {
if (!enabled2())
inspected.owner && clearOwnerObservers(inspected.owner);
else
inspected.owner && setInspectedDetails(inspected.owner);
makeSolidUpdateListener(
throttle2(() => {
updateInspectedProps();
triggerValueUpdate(false);
}, 150)
);
});
const setInspectedOwner = (payload) => {
if (!payload)
return clearInspectedDetails();
const { rootId, nodeId } = payload;
const walkResult = walkSolidRoot(rootId, nodeId);
if (!walkResult || !walkResult.inspectedOwner)
return clearInspectedDetails();
setInspectedDetails(walkResult.inspectedOwner);
};
const setInspectedSignal = (id, selected) => {
const signal = inspected.signalMap[id];
if (!signal)
return null;
if (selected)
inspected.signals.add(id);
else
inspected.signals.delete(id);
return untrack2(() => encodeValue2(signal.value, selected, inspected.elementMap));
};
const setInspectedProp = (key, selected) => {
if (selected)
inspected.props.add(key);
else
inspected.props.delete(key);
updateInspectedProps();
};
const setInspectedValue = (selected) => {
if (!inspected.owner)
return null;
inspected.value = selected;
triggerValueUpdate(false, true);
};
const _pushComputationUpdate = createBatchedUpdateEmitter(
(updates) => eventHub.emit("ComputationUpdates", updates)
);
const pushComputationUpdate2 = (rootId, id) => {
_pushComputationUpdate({ rootId, id });
};
const pluginData = {
listenTo: eventHub.on,
components,
findComponent,
triggerUpdate,
forceTriggerUpdate,
inspectedDetails: details,
setInspectedOwner,
setInspectedSignal,
setInspectedProp,
setInspectedValue,
getElementById
};
function useDebugger2(options) {
const { enabled: enabled3, gatherComponents } = options;
enabled3 && addDebuggerConsumer(enabled3);
if (gatherComponents)
debuggerConfig.gatherComponents = true;
return pluginData;
}
return {
onUpdate: onUpdate2,
onForceUpdate: onForceUpdate2,
enabled: enabled2,
useDebugger: useDebugger2,
updateRoot: updateRoot2,
removeRoot: removeRoot2,
pushComputationUpdate: pushComputationUpdate2
};
});
var {
onUpdate,
onForceUpdate,
enabled,
useDebugger,
updateRoot,
removeRoot,
pushComputationUpdate
} = exported;
// src/roots.ts
var RootMap = {};
var walkSolidRoot = (rootId, inspectedId) => {
const walk = RootMap[rootId];
return walk ? walk(inspectedId) : null;
};
function createGraphRoot(owner) {
createInternalRoot((dispose) => {
onOwnerCleanup(owner, dispose);
const rootId = markNodeID(owner);
const onComputationUpdate = (rootId2, nodeId) => {
if (owner.isDisposed)
return;
if (untrack3(enabled))
triggerRootUpdate();
pushComputationUpdate(rootId2, nodeId);
};
const forceRootUpdate = untrackedCallback2((inspectedId) => {
if (owner.isDisposed)
return null;
const result = walkSolidTree(owner, {
...debuggerConfig,
onComputationUpdate,
rootId,
inspectedId: inspectedId ?? null
});
updateRoot(result.root, result.components);
return result;
});
const triggerRootUpdate = throttle3(forceRootUpdate, 300);
RootMap[rootId] = forceRootUpdate;
onUpdate(triggerRootUpdate);
onForceUpdate(forceRootUpdate);
createEffect2(() => {
enabled() && forceRootUpdate();
});
setDebuggerContext(owner, { rootId, triggerRootUpdate, forceRootUpdate });
onCleanup2(() => {
removeDebuggerContext(owner);
removeRoot(rootId);
owner.isDisposed = true;
delete RootMap[rootId];
});
});
}
function attachDebugger(_owner = getOwner2()) {
let owner = _owner;
if (!owner)
return warn("reatachOwner helper should be called synchronously in a reactive owner.");
forEachLookupRoot(owner, (root, ctx) => {
if (ctx === INTERNAL2)
return;
root.sdtAttached = null;
markOwnerType(root, NodeType4.Root);
createGraphRoot(root);
if (ctx) {
ctx.triggerRootUpdate();
let parent = findClosestAliveParent(root);
if (!parent.owner)
return warn("PARENT_SHOULD_BE_ALIVE");
root.sdtAttached = parent.owner;
const onParentCleanup2 = () => {
const newParent = findClosestAliveParent(root);
if (newParent.owner) {
parent = newParent;
root.sdtAttached = parent.owner;
onOwnerCleanup(parent.root, onParentCleanup2);
} else {
root.sdtAttached = null;
removeOwnCleanup();
}
};
const removeParentCleanup = onOwnerCleanup(parent.root, onParentCleanup2);
const removeOwnCleanup = onOwnerCleanup(root, () => {
root.isDisposed = true;
root.sdtAttached = null;
removeParentCleanup();
ctx.triggerRootUpdate();
});
}
});
}
function findClosestAliveParent(owner) {
let disposed = null;
let closestAliveRoot = null;
let current = owner;
while (current.owner && !closestAliveRoot) {
current = current.owner;
if (isSolidRoot(current)) {
if (current.isDisposed)
disposed = current;
else
closestAliveRoot = current;
}
}
if (!closestAliveRoot)
return { owner: null, root: null };
return { owner: (disposed == null ? void 0 : disposed.owner) ?? owner.owner, root: closestAliveRoot };
}
function forEachLookupRoot(owner, callback) {
const roots = [];
let ctx;
do {
if (isSolidRoot(owner)) {
if ("sdtAttached" in owner) {
if (!ctx)
ctx = getDebuggerContext(owner);
break;
}
if (owner.sdtContext === INTERNAL2) {
ctx = INTERNAL2;
break;
}
roots.push(owner);
}
owner = owner.owner;
} while (owner);
for (let i = roots.length - 1; i >= 0; i--) {
const root = roots[i];
callback(root, ctx);
if (root.sdtContext)
ctx = root.sdtContext;
}
}
// src/index.ts
var Debugger = (props) => {
attachDebugger();
return props.children;
};
export {
isSolidComputation,
isSolidMemo,
isSolidOwner,
isSolidRoot,
getNodeName,
getNodeType,
getOwnerType,
lookupOwner,
onOwnerCleanup,
onParentCleanup,
createUnownedRoot,
getFunctionSources,
createInternalRoot,
makeSolidUpdateListener,
makeCreateRootListener,
makeStoreObserver,
observeComputationUpdate,
interceptComputationRerun,
observeValueUpdate,
removeValueUpdateObserver,
makeValueUpdateListener,
useDebugger,
attachDebugger,
Debugger
};