@solid-devtools/debugger
Advanced tools
| // 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, |
+3
-2
@@ -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 }; |
+3
-1
@@ -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, |
+5
-1
@@ -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, |
+5
-2
| 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, |
+15
-15
| { | ||
| "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", |
+11
-7
@@ -9,2 +9,6 @@ <a href="https://github.com/thetarnav/solid-devtools/tree/main/packages/debugger#readme" target="_blank"> | ||
| [](https://pnpm.io/) | ||
| [](https://www.npmjs.com/package/@solid-devtools/debugger) | ||
| [](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 | ||
| }; |
79408
1.3%2250
0.94%116
3.57%- Removed
Updated