@three-flatland/devtools 0.1.0-alpha.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +82 -0
- package/dist/buffers-modal.cjs +491 -0
- package/dist/buffers-modal.cjs.map +1 -0
- package/dist/buffers-modal.d.cts +62 -0
- package/dist/buffers-modal.d.ts +62 -0
- package/dist/buffers-modal.js +467 -0
- package/dist/buffers-modal.js.map +1 -0
- package/dist/buffers-view.cjs +269 -0
- package/dist/buffers-view.cjs.map +1 -0
- package/dist/buffers-view.d.cts +39 -0
- package/dist/buffers-view.d.ts +39 -0
- package/dist/buffers-view.js +245 -0
- package/dist/buffers-view.js.map +1 -0
- package/dist/create-pane.cjs +203 -0
- package/dist/create-pane.cjs.map +1 -0
- package/dist/create-pane.d.cts +66 -0
- package/dist/create-pane.d.ts +66 -0
- package/dist/create-pane.js +178 -0
- package/dist/create-pane.js.map +1 -0
- package/dist/dashboard/app.tsx +42 -0
- package/dist/dashboard/client.ts +21 -0
- package/dist/dashboard/export.ts +84 -0
- package/dist/dashboard/hooks.ts +75 -0
- package/dist/dashboard/index.html +1149 -0
- package/dist/dashboard/index.tsx +18 -0
- package/dist/dashboard/panels/batches.tsx +282 -0
- package/dist/dashboard/panels/buffers.tsx +425 -0
- package/dist/dashboard/panels/env.tsx +85 -0
- package/dist/dashboard/panels/header-stats.tsx +30 -0
- package/dist/dashboard/panels/producer-select.tsx +81 -0
- package/dist/dashboard/panels/protocol-log.tsx +743 -0
- package/dist/dashboard/panels/registry.tsx +642 -0
- package/dist/dashboard/panels/stats.tsx +431 -0
- package/dist/dashboard/protocol-store.ts +312 -0
- package/dist/dashboard/tsconfig.json +19 -0
- package/dist/dashboard/vendor/hooks.module.js +1 -0
- package/dist/dashboard/vendor/jsx-runtime.js +22 -0
- package/dist/dashboard/vendor/preact.module.js +12 -0
- package/dist/devtools-client.cjs +870 -0
- package/dist/devtools-client.cjs.map +1 -0
- package/dist/devtools-client.d.cts +362 -0
- package/dist/devtools-client.d.ts +362 -0
- package/dist/devtools-client.js +852 -0
- package/dist/devtools-client.js.map +1 -0
- package/dist/index.cjs +42 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/perf-trace.cjs +103 -0
- package/dist/perf-trace.cjs.map +1 -0
- package/dist/perf-trace.d.cts +27 -0
- package/dist/perf-trace.d.ts +27 -0
- package/dist/perf-trace.js +79 -0
- package/dist/perf-trace.js.map +1 -0
- package/dist/plugins.cjs +44 -0
- package/dist/plugins.cjs.map +1 -0
- package/dist/plugins.d.cts +7 -0
- package/dist/plugins.d.ts +7 -0
- package/dist/plugins.js +9 -0
- package/dist/plugins.js.map +1 -0
- package/dist/provider-switcher.cjs +95 -0
- package/dist/provider-switcher.cjs.map +1 -0
- package/dist/provider-switcher.d.cts +18 -0
- package/dist/provider-switcher.d.ts +18 -0
- package/dist/provider-switcher.js +71 -0
- package/dist/provider-switcher.js.map +1 -0
- package/dist/react/devtools-provider.cjs +59 -0
- package/dist/react/devtools-provider.cjs.map +1 -0
- package/dist/react/devtools-provider.d.cts +39 -0
- package/dist/react/devtools-provider.d.ts +39 -0
- package/dist/react/devtools-provider.js +38 -0
- package/dist/react/devtools-provider.js.map +1 -0
- package/dist/react/use-fps-graph.cjs +49 -0
- package/dist/react/use-fps-graph.cjs.map +1 -0
- package/dist/react/use-fps-graph.d.cts +15 -0
- package/dist/react/use-fps-graph.d.ts +15 -0
- package/dist/react/use-fps-graph.js +25 -0
- package/dist/react/use-fps-graph.js.map +1 -0
- package/dist/react/use-pane-button.cjs +58 -0
- package/dist/react/use-pane-button.cjs.map +1 -0
- package/dist/react/use-pane-button.d.cts +10 -0
- package/dist/react/use-pane-button.d.ts +10 -0
- package/dist/react/use-pane-button.js +34 -0
- package/dist/react/use-pane-button.js.map +1 -0
- package/dist/react/use-pane-folder.cjs +48 -0
- package/dist/react/use-pane-folder.cjs.map +1 -0
- package/dist/react/use-pane-folder.d.cts +15 -0
- package/dist/react/use-pane-folder.d.ts +15 -0
- package/dist/react/use-pane-folder.js +24 -0
- package/dist/react/use-pane-folder.js.map +1 -0
- package/dist/react/use-pane-input.cjs +70 -0
- package/dist/react/use-pane-input.cjs.map +1 -0
- package/dist/react/use-pane-input.d.cts +44 -0
- package/dist/react/use-pane-input.d.ts +44 -0
- package/dist/react/use-pane-input.js +46 -0
- package/dist/react/use-pane-input.js.map +1 -0
- package/dist/react/use-pane-radio-grid.cjs +78 -0
- package/dist/react/use-pane-radio-grid.cjs.map +1 -0
- package/dist/react/use-pane-radio-grid.d.cts +35 -0
- package/dist/react/use-pane-radio-grid.d.ts +35 -0
- package/dist/react/use-pane-radio-grid.js +54 -0
- package/dist/react/use-pane-radio-grid.js.map +1 -0
- package/dist/react/use-pane.cjs +45 -0
- package/dist/react/use-pane.cjs.map +1 -0
- package/dist/react/use-pane.d.cts +40 -0
- package/dist/react/use-pane.d.ts +40 -0
- package/dist/react/use-pane.js +21 -0
- package/dist/react/use-pane.js.map +1 -0
- package/dist/react.cjs +50 -0
- package/dist/react.cjs.map +1 -0
- package/dist/react.d.cts +12 -0
- package/dist/react.d.ts +12 -0
- package/dist/react.js +19 -0
- package/dist/react.js.map +1 -0
- package/dist/registry-view.cjs +371 -0
- package/dist/registry-view.cjs.map +1 -0
- package/dist/registry-view.d.cts +24 -0
- package/dist/registry-view.d.ts +24 -0
- package/dist/registry-view.js +347 -0
- package/dist/registry-view.js.map +1 -0
- package/dist/stats-graph.cjs +297 -0
- package/dist/stats-graph.cjs.map +1 -0
- package/dist/stats-graph.d.cts +40 -0
- package/dist/stats-graph.d.ts +40 -0
- package/dist/stats-graph.js +273 -0
- package/dist/stats-graph.js.map +1 -0
- package/dist/stats-row.cjs +153 -0
- package/dist/stats-row.cjs.map +1 -0
- package/dist/stats-row.d.cts +24 -0
- package/dist/stats-row.d.ts +24 -0
- package/dist/stats-row.js +129 -0
- package/dist/stats-row.js.map +1 -0
- package/dist/theme.cjs +260 -0
- package/dist/theme.cjs.map +1 -0
- package/dist/theme.d.cts +10 -0
- package/dist/theme.d.ts +10 -0
- package/dist/theme.js +235 -0
- package/dist/theme.js.map +1 -0
- package/dist/vite-plugin.cjs +113 -0
- package/dist/vite-plugin.cjs.map +1 -0
- package/dist/vite-plugin.d.cts +9 -0
- package/dist/vite-plugin.d.ts +9 -0
- package/dist/vite-plugin.js +88 -0
- package/dist/vite-plugin.js.map +1 -0
- package/package.json +124 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/devtools-client.ts"],"sourcesContent":["import type {\n BatchesPayload,\n BatchInfo,\n BufferChunkPayload,\n BufferDisplayMode,\n BufferSubscriptionEntry,\n BuffersPayload,\n DebugFeature,\n DebugMessage,\n EnvPayload,\n PassEvent,\n ProviderIdentity,\n RegistryEntryKind,\n RegistryPayload,\n StatsPayload,\n TexturePixelType,\n} from 'three-flatland/debug-protocol'\nimport {\n ACK_INTERVAL_MS,\n DEBUG_PROTOCOL_VERSION,\n DISCOVERY_CHANNEL,\n SERVER_LIVENESS_MS,\n providerChannelName,\n} from 'three-flatland/debug-protocol'\nimport { tracePerf } from './perf-trace.js'\n\n/**\n * Construction options for `DevtoolsClient`.\n */\nexport interface DevtoolsClientOptions {\n /** Features to subscribe to. */\n features: DebugFeature[]\n /**\n * Override the discovery (bonjour) channel name. Rarely needed — only\n * for isolated test sessions.\n */\n discoveryChannelName?: string\n /**\n * Optional first listener, equivalent to calling `addListener(cb)`\n * after construction.\n */\n onChange?: (state: DevtoolsState) => void\n}\n\n/** Listener signature for `DevtoolsClient.addListener`. */\nexport type DevtoolsStateListener = (state: DevtoolsState) => void\n\n/** Listener for incoming WebCodecs buffer chunks. */\nexport type { BufferChunkPayload }\nexport type BufferChunkListener = (chunk: BufferChunkPayload) => void\n\n/** Listener for raw protocol messages. Direction is `in` for messages\n * received from the bus, `out` for messages the client posts. */\nexport type RawMessageListener = (msg: DebugMessage, direction: 'in' | 'out') => void\n\n/**\n * Discovery retry backoff. Starts at `QUERY_RETRY_MIN_MS`, doubles each\n * attempt, caps at `QUERY_RETRY_MAX_MS`, and gives up after `QUERY_MAX_RETRIES`\n * total tries. After giving up, a provider that comes online later will\n * still wire us up via its own startup `provider:announce`.\n */\nconst QUERY_RETRY_MIN_MS = 500\nconst QUERY_RETRY_MAX_MS = 5000\nconst QUERY_MAX_RETRIES = 10\n\n/**\n * Size of the client-side decoded series rings. Sized generously so\n * downstream consumers (graphs, percentile detail panels) have plenty\n * of history across both 4 Hz batch and 60 Hz sample cadences. 1024 ×\n * Float32 × ~9 fields ≈ 36 KB total — negligible.\n */\nconst CLIENT_SERIES_SIZE = 1024\n\n/** Shared zero-length placeholder used for metadata-only registry snapshots. */\nconst EMPTY_SAMPLE: Float32Array = new Float32Array(0)\n\n/** Per-field time-series ring. */\nexport interface DevtoolsSeries {\n /** Pre-allocated Float32 buffer. Read via (write - i - 1 + size) % size. */\n readonly data: Float32Array\n /** Next write index. */\n write: number\n /** Valid sample count (<= size). */\n length: number\n}\n\n/**\n * Snapshot of a registered CPU array as seen by the client. The\n * `sample` typed array is owned by this object (structured-cloned from\n * the provider) — read-only by contract; don't mutate in place.\n */\nexport interface RegistryEntrySnapshot {\n name: string\n kind: RegistryEntryKind\n version: number\n count: number\n sample: Float32Array | Uint32Array | Int32Array\n label?: string\n}\n\n/** Snapshot of a registered debug buffer as seen by the client. */\n/**\n * Client-side view of one render-pass event. Shallow copies of\n * `PassEvent` from the wire — the provider reuses its scratch pool\n * every frame, so we copy fields into fresh objects once on receive.\n */\nexport interface BatchPassSnapshot {\n label: string\n calls: number\n triangles: number\n cpuMs: number\n depth: number\n parent: number\n}\n\n/** Client-side view of one batched-draw row. */\nexport interface BatchSnapshot {\n frame: number\n passes: BatchPassSnapshot[]\n batches: Array<{\n runKey: number\n materialId: number\n layer: number\n materialName: string\n spriteCount: number\n batchIdx: number\n /** Subsystem tag (e.g. `'sprite'`, `'tilechunk'`). Defaults to `'sprite'` on the client when absent. */\n kind: string\n /** Per-batch label (e.g. `'chunk(0,2)'`). Empty string when the source didn't set one. */\n label: string\n }>\n}\n\nexport interface BufferSnapshot {\n name: string\n /** Dimensions of the pixels currently stored in `pixels` — equal to\n * source dims in stream mode, downsampled dims in thumbnail mode. */\n width: number\n height: number\n /** Source (pre-downsample) dimensions — the \"true\" buffer size.\n * Equals width/height in stream mode. */\n srcWidth: number\n srcHeight: number\n pixelType: TexturePixelType\n /** How the consumer should visualise this buffer (defaults applied by producer). */\n display: BufferDisplayMode\n version: number\n /** Latest CPU readback; `null` until the provider has served a sample. */\n pixels: Uint8Array | Float32Array | null\n label?: string\n}\n\n/**\n * Accumulated state the consumer keeps up-to-date by merging deltas\n * from `data` packets. Callers bind UI to this object and refresh\n * when `onChange` fires.\n *\n * All fields start `undefined`; the first `data` packet (or\n * `subscribe:ack.env` bootstrap) populates them. Subsequent deltas\n * overwrite specific fields; `null` on the wire clears a field back\n * to `undefined`.\n */\nexport interface DevtoolsState {\n /** Engine frame counter — last frame index covered by the latest batch. */\n frame?: number\n\n // --- Stats scalars — mean across the most recent batch window. --------\n // Naturally smoothed (roughly 500 ms of samples per batch); good for\n // text display. For per-frame granularity use `series.*` instead.\n drawCalls?: number\n triangles?: number\n /** Lines + points aggregated. */\n primitives?: number\n geometries?: number\n textures?: number\n cpuMs?: number\n fps?: number\n gpuMs?: number\n /** JS heap used, MB. `undefined` on Safari / Firefox. */\n heapUsedMB?: number\n /** JS heap limit, MB. Static per environment. */\n heapLimitMB?: number\n\n // --- Per-frame time series (decoded + de-scaled on arrival). -------------\n // Each ring is a Float32Array of `CLIENT_SERIES_SIZE` values. Read\n // most-recent-first via `(write - i - 1 + size) % size`.\n series: {\n fps: DevtoolsSeries\n cpuMs: DevtoolsSeries\n gpuMs: DevtoolsSeries\n heapUsedMB: DevtoolsSeries\n drawCalls: DevtoolsSeries\n triangles: DevtoolsSeries\n primitives: DevtoolsSeries\n geometries: DevtoolsSeries\n textures: DevtoolsSeries\n }\n\n // --- Env (merged from data.features.env + subscribe:ack.env bootstrap) ---\n threeFlatlandVersion?: string\n threeRevision?: string\n backendName?: string\n backendTrackTimestamp?: boolean\n backendDisjoint?: boolean | null\n gpuModeEnabled?: boolean\n canvasWidth?: number\n canvasHeight?: number\n canvasPixelRatio?: number\n\n // --- Registry (live CPU array readouts from the provider) --------------\n /**\n * Named CPU arrays the provider has registered. Entries update on the\n * `registry` feature of each data batch; keys are entry names, values\n * are the latest sample + metadata. Removed entries are pruned.\n */\n registry: Map<string, RegistryEntrySnapshot>\n\n /**\n * Named debug buffers — same lifecycle as `registry`, but backed by\n * periodic GPU readbacks through the `buffers` feature. `pixels` is\n * `null` until the provider has delivered a sample (metadata arrives\n * first so the UI can list the entry for selection).\n */\n buffers: Map<string, BufferSnapshot>\n\n /**\n * Most recent batch inspector snapshot — per-pass draw events + active\n * batch registry contents. Client stores shallow copies of the arrays\n * so subsequent bus messages don't mutate UI state under a render.\n */\n batches: BatchSnapshot\n\n // --- Provider selection ------------------------------------------------\n /** All providers currently announced on the bus (updated live). */\n providers: ProviderIdentity[]\n /** The provider this client is subscribed to. `null` until discovery picks one. */\n selectedProviderId: string | null\n\n // --- Liveness (client-tracked) -----------------------------------------\n /** Is the selected provider considered alive? False after `SERVER_LIVENESS_MS` silence. */\n serverAlive: boolean\n /** ms since the last message from the selected provider. */\n serverLagMs: number\n}\n\n/**\n * Bus consumer. One per viewing surface (tweakpane panel, pop-out\n * window, remote dashboard). Owns:\n *\n * - A stable consumer id (UUID v4).\n * - A `BroadcastChannel` subscription.\n * - Accumulated `DevtoolsState` derived from `data` packet deltas.\n * - Ack timer (1 s, starts on `subscribe:ack`).\n * - Server-liveness monitor; re-subscribes if no server message\n * within `SERVER_LIVENESS_MS`.\n *\n * Call `start()` to send the initial subscribe + begin timers.\n * `dispose()` sends unsubscribe, clears timers, closes the channel.\n */\nexport class DevtoolsClient {\n readonly id: string\n readonly state: DevtoolsState\n\n /** Shared discovery bus — carries query/announce/gone only. */\n private _discoveryBus: BroadcastChannel\n /** Per-provider data bus. Opened when we subscribe; closed on switch / gone. */\n private _dataBus: BroadcastChannel | null = null\n /** Bound handler for the current `_dataBus`. Tracked so we can detach on close. */\n private _dataHandler: ((ev: MessageEvent<DebugMessage>) => void) | null = null\n private _features: DebugFeature[]\n /**\n * Registry entry filter. `null` = all entries; `string[]` = only\n * these. Starts empty-array so providers don't drain (sometimes\n * expensive) registry payloads until the pane actually needs them.\n */\n private _registrySelection: string[] | null = []\n /**\n * Buffer subscription. Map of entry-name → { mode, thumbSize? }.\n * Empty map = metadata-only (consumer is connected to the `buffers`\n * feature but isn't actually watching anything — provider skips all\n * readbacks). `null` is not a distinct state; represented by `{}`.\n */\n private _buffersSelection: Record<string, BufferSubscriptionEntry> = {}\n private _listeners = new Set<DevtoolsStateListener>()\n private _chunkListeners = new Set<BufferChunkListener>()\n private _rawMessageListeners = new Set<RawMessageListener>()\n\n private _ackTimer: ReturnType<typeof setInterval> | null = null\n private _livenessTimer: ReturnType<typeof setInterval> | null = null\n private _queryRetryTimer: ReturnType<typeof setTimeout> | null = null\n private _lastServerAt = 0\n private _subscribed = false\n private _disposed = false\n\n /** Known providers by id — updated live via `provider:announce` + `provider:gone`. */\n private _providers = new Map<string, ProviderIdentity>()\n\n constructor(options: DevtoolsClientOptions) {\n this.id = generateUuid()\n this._features = [...options.features]\n if (options.onChange) this._listeners.add(options.onChange)\n this._discoveryBus = new BroadcastChannel(options.discoveryChannelName ?? DISCOVERY_CHANNEL)\n const mkSeries = (): DevtoolsSeries => ({\n data: new Float32Array(CLIENT_SERIES_SIZE),\n write: 0,\n length: 0,\n })\n this.state = {\n series: {\n fps: mkSeries(),\n cpuMs: mkSeries(),\n gpuMs: mkSeries(),\n heapUsedMB: mkSeries(),\n drawCalls: mkSeries(),\n triangles: mkSeries(),\n primitives: mkSeries(),\n geometries: mkSeries(),\n textures: mkSeries(),\n },\n registry: new Map(),\n buffers: new Map(),\n batches: { frame: 0, passes: [], batches: [] },\n providers: [],\n selectedProviderId: null,\n serverAlive: false,\n serverLagMs: 0,\n }\n\n // Discovery handler — only processes provider:announce / provider:gone.\n this._discoveryBus.addEventListener('message', (ev: MessageEvent<DebugMessage>) => {\n this._onDiscoveryMessage(ev.data)\n })\n }\n\n /**\n * Begin discovery + subscription. Sends a `provider:query`, waits\n * `DISCOVERY_WINDOW_MS` for `provider:announce` responses, then picks\n * the best provider (user > system) and subscribes to it.\n *\n * Idempotent — calling again while already started is a no-op.\n */\n start(): void {\n if (this._disposed || this._subscribed) return\n this._subscribed = true\n\n // Broadcast who we are and ask providers to announce. First announce\n // received triggers subscribe directly from the message handler —\n // no fixed window. If no provider is up yet (or our query/their\n // announce was lost), retry with exponential backoff up to\n // `QUERY_MAX_RETRIES` tries. After we give up, a provider that\n // starts later will announce on its own construct, wiring us up\n // without further polling.\n this._sendQuery()\n let retries = 0\n let nextDelay = QUERY_RETRY_MIN_MS\n const tick = () => {\n if (this._disposed || this.state.selectedProviderId !== null) {\n this._queryRetryTimer = null\n return\n }\n if (retries >= QUERY_MAX_RETRIES) {\n this._queryRetryTimer = null\n return\n }\n retries++\n this._sendQuery()\n nextDelay = Math.min(nextDelay * 2, QUERY_RETRY_MAX_MS)\n this._queryRetryTimer = setTimeout(tick, nextDelay)\n }\n this._queryRetryTimer = setTimeout(tick, nextDelay)\n\n // Liveness watcher — fires every second, flips serverAlive false and\n // re-subscribes if we've gone silent past the grace window.\n this._livenessTimer = setInterval(() => this._checkLiveness(), 1000)\n }\n\n private _sendQuery(): void {\n this._postDiscovery({\n type: 'provider:query',\n payload: { requesterId: this.id },\n })\n }\n\n /**\n * Update the feature set. Re-posts `subscribe` on the current\n * provider's data channel.\n */\n setFeatures(features: DebugFeature[]): void {\n if (sameSet(this._features, features)) return\n this._features = [...features]\n this._resubscribe()\n }\n\n /**\n * Update the registry entry filter. Pass `null` for \"every entry\",\n * `[]` to stop all registry traffic, or a list of names to narrow.\n * Re-posts `subscribe` if the filter actually changed.\n */\n /**\n * Narrow which registry entries the provider should ship samples\n * for. `null` = all entries; `[]` = none; `[name, …]` = only these.\n * Metadata still flows regardless — only sample bytes are gated.\n */\n setRegistry(names: string[] | null): void {\n if (sameFilter(this._registrySelection, names)) return\n this._registrySelection = names === null ? null : [...names]\n this._resubscribe()\n }\n\n /**\n * Update the buffer subscription. Map of entry-name → (mode, thumbSize?).\n * - Empty map / missing names → metadata-only (provider sends no pixels,\n * runs no readbacks). This is the idle state when no preview or\n * modal is visible.\n * - `{ name: { mode: 'thumbnail', thumbSize: 256 } }` → small\n * downsampled preview. Use when a thumbnail card is visible.\n * - `{ name: { mode: 'stream' } }` → full-size VP9 video stream.\n * Use when the fullscreen modal is open.\n *\n * Mode changes (incl. unsubscribing) take effect on the next\n * provider flush; the producer will drop old readbacks immediately.\n */\n setBuffers(subscription: Record<string, BufferSubscriptionEntry>): void {\n if (sameBufferSubscription(this._buffersSelection, subscription)) return\n this._buffersSelection = { ...subscription }\n this._resubscribe()\n }\n\n private _resubscribe(): void {\n if (this._subscribed && this._dataBus !== null) {\n const hasBuffers = Object.keys(this._buffersSelection).length > 0\n this._postData({\n type: 'subscribe',\n payload: {\n id: this.id,\n features: this._features,\n registry: this._registrySelection ?? undefined,\n buffers: hasBuffers ? this._buffersSelection : undefined,\n },\n })\n }\n }\n\n /**\n * Manually switch to a different provider. No-op if unknown or if\n * already selected. Closes the old data channel and opens the new one.\n */\n selectProvider(providerId: string): void {\n if (!this._providers.has(providerId)) return\n if (this.state.selectedProviderId === providerId) return\n this._leaveDataChannel()\n this.state.selectedProviderId = providerId\n this._resetAccumulatedState()\n this._joinDataChannel(providerId)\n this._postData({\n type: 'subscribe',\n payload: {\n id: this.id,\n features: this._features,\n registry: this._registrySelection ?? undefined,\n buffers:\n Object.keys(this._buffersSelection).length > 0\n ? this._buffersSelection\n : undefined,\n },\n })\n this._fire()\n }\n\n dispose(): void {\n if (this._disposed) return\n this._disposed = true\n\n this._leaveDataChannel()\n this._subscribed = false\n if (this._ackTimer !== null) {\n clearInterval(this._ackTimer)\n this._ackTimer = null\n }\n if (this._livenessTimer !== null) {\n clearInterval(this._livenessTimer)\n this._livenessTimer = null\n }\n if (this._queryRetryTimer !== null) {\n clearTimeout(this._queryRetryTimer)\n this._queryRetryTimer = null\n }\n try { this._discoveryBus.close() } catch { /* already closed */ }\n }\n\n /**\n * Open a fresh per-provider data channel and start listening on it.\n * Caller is responsible for posting the initial `subscribe`.\n */\n private _joinDataChannel(providerId: string): void {\n this._dataBus = new BroadcastChannel(providerChannelName(providerId))\n this._dataHandler = (ev: MessageEvent<DebugMessage>) => {\n this._onDataMessage(ev.data)\n }\n this._dataBus.addEventListener('message', this._dataHandler)\n }\n\n /**\n * Send `unsubscribe` (if we have someone to tell) and close the data\n * channel. Idempotent — safe to call when there's no active channel.\n */\n private _leaveDataChannel(): void {\n if (this._dataBus !== null) {\n if (this._subscribed) {\n try {\n this._postData({ type: 'unsubscribe', payload: { id: this.id } })\n } catch { /* bus may already be closing */ }\n }\n if (this._dataHandler !== null) {\n try { this._dataBus.removeEventListener('message', this._dataHandler) } catch { /* ignore */ }\n }\n try { this._dataBus.close() } catch { /* already closed */ }\n this._dataBus = null\n this._dataHandler = null\n }\n }\n\n // ── Internal ──────────────────────────────────────────────────────────\n\n /**\n * Handler for the shared discovery bus. Only discovery messages land\n * here by protocol; anything else is ignored.\n */\n private _onDiscoveryMessage(msg: DebugMessage | undefined): void {\n if (!msg || typeof msg !== 'object' || !('type' in msg)) return\n tracePerf(msg)\n\n switch (msg.type) {\n case 'provider:announce': {\n const id = msg.payload.identity.id\n this._providers.set(id, msg.payload.identity)\n this.state.providers = Array.from(this._providers.values())\n this._fire()\n if (this.state.selectedProviderId === null) this._pickProviderAndSubscribe()\n break\n }\n case 'provider:gone': {\n const id = msg.payload.id\n if (!this._providers.has(id)) return\n this._providers.delete(id)\n this.state.providers = Array.from(this._providers.values())\n if (this.state.selectedProviderId === id) {\n this._leaveDataChannel()\n this.state.selectedProviderId = null\n this._resetAccumulatedState()\n this._pickProviderAndSubscribe()\n }\n this._fire()\n break\n }\n default:\n break\n }\n }\n\n /**\n * Handler for the per-provider data channel. Everything here is\n * already implicitly addressed to us (we opened the channel with the\n * provider's id), so no per-message filtering is required beyond\n * matching our consumer `id` on `subscribe:ack`.\n */\n private _onDataMessage(msg: DebugMessage | undefined): void {\n if (!msg || typeof msg !== 'object' || !('type' in msg)) return\n tracePerf(msg)\n\n // Tap for protocol-log panels. Fires for every inbound message,\n // including our own echoes — intentional: seeing our outbound traffic\n // is half the reason the devtools exists. Kept free-form (no\n // byte-count, no decoded size) because computing that per-message\n // noticeably shows up on streaming workloads; panels that care can\n // derive it themselves.\n if (this._rawMessageListeners.size > 0) {\n for (const cb of this._rawMessageListeners) {\n try { cb(msg, 'in') } catch { /* listener errors shouldn't break the bus */ }\n }\n }\n\n switch (msg.type) {\n case 'subscribe:ack': {\n if (msg.payload.id !== this.id) return\n this._markServerAlive()\n this._applyEnv(msg.payload.env)\n if (this._ackTimer === null) {\n this._ackTimer = setInterval(() => this._sendAck(), ACK_INTERVAL_MS)\n }\n this._fire()\n break\n }\n case 'data': {\n this._markServerAlive()\n this.state.frame = msg.payload.frame\n const features = msg.payload.features\n if (features.stats !== undefined) this._applyStats(features.stats)\n if (features.env !== undefined) this._applyEnv(features.env)\n if (features.registry !== undefined) this._applyRegistry(features.registry)\n if (features.buffers !== undefined) this._applyBuffers(features.buffers)\n if (features.batches !== undefined) this._applyBatches(features.batches)\n this._fire()\n break\n }\n case 'buffer:chunk': {\n this._markServerAlive()\n const payload = msg.payload\n for (const cb of this._chunkListeners) {\n try { cb(payload) } catch { /* listener errors shouldn't break the bus */ }\n }\n break\n }\n case 'buffer:raw': {\n this._markServerAlive()\n const payload = msg.payload\n let snap = this.state.buffers.get(payload.name)\n if (snap !== undefined) {\n // buffer:raw only carries the converted RGBA8 pixels and the\n // shipped dims. Don't overwrite pixelType/display/srcWidth —\n // those belong to the source metadata set by _applyBuffers.\n snap.pixels = new Uint8Array(payload.data)\n snap.width = payload.width\n snap.height = payload.height\n snap.version++\n } else {\n snap = {\n name: payload.name,\n width: payload.width,\n height: payload.height,\n srcWidth: payload.width,\n srcHeight: payload.height,\n pixelType: 'rgba8',\n display: 'colors',\n version: 0,\n pixels: new Uint8Array(payload.data),\n }\n this.state.buffers.set(payload.name, snap)\n }\n this._fire()\n break\n }\n case 'ping': {\n this._markServerAlive()\n break\n }\n default:\n break\n }\n }\n\n private _markServerAlive(): void {\n this._lastServerAt = Date.now()\n if (!this.state.serverAlive) {\n this.state.serverAlive = true\n this._fire()\n }\n }\n\n /**\n * Pick the best provider from the currently-known set and subscribe\n * to it. Preference: `user` over `system`; first-announced as\n * tiebreak. No-op if zero providers are known (we'll stay waiting;\n * any future `provider:announce` that arrives doesn't auto-trigger\n * this — call it again or restart discovery).\n */\n private _pickProviderAndSubscribe(): void {\n if (this.state.selectedProviderId !== null) return\n const providers = Array.from(this._providers.values())\n if (providers.length === 0) return\n const user = providers.find((p) => p.kind === 'user')\n const chosen = user ?? providers[0]!\n this.state.selectedProviderId = chosen.id\n this._joinDataChannel(chosen.id)\n this._postData({\n type: 'subscribe',\n payload: {\n id: this.id,\n features: this._features,\n registry: this._registrySelection ?? undefined,\n buffers:\n Object.keys(this._buffersSelection).length > 0\n ? this._buffersSelection\n : undefined,\n },\n })\n this._fire()\n }\n\n /** Clear all feature-derived state so the next data packet can start fresh. */\n private _resetAccumulatedState(): void {\n this.state.frame = undefined\n this._applyStats(null)\n this._applyEnv(null)\n this.state.registry.clear()\n this.state.buffers.clear()\n this._applyBatches(null)\n }\n\n /**\n * Apply a stats batch. Null = reset (feature cleared / provider gone).\n * Otherwise: decode each typed array onto the matching Float32 ring\n * and update the scalar with the batch mean (natural smoothing for\n * the text label).\n */\n private _applyStats(batch: StatsPayload | null): void {\n if (batch === null) {\n this.state.drawCalls = undefined\n this.state.triangles = undefined\n this.state.primitives = undefined\n this.state.geometries = undefined\n this.state.textures = undefined\n this.state.cpuMs = undefined\n this.state.fps = undefined\n this.state.gpuMs = undefined\n this.state.heapUsedMB = undefined\n this.state.heapLimitMB = undefined\n const s = this.state.series\n s.fps.write = 0; s.fps.length = 0\n s.cpuMs.write = 0; s.cpuMs.length = 0\n s.gpuMs.write = 0; s.gpuMs.length = 0\n s.heapUsedMB.write = 0; s.heapUsedMB.length = 0\n s.drawCalls.write = 0; s.drawCalls.length = 0\n s.triangles.write = 0; s.triangles.length = 0\n s.primitives.write = 0; s.primitives.length = 0\n s.geometries.write = 0; s.geometries.length = 0\n s.textures.write = 0; s.textures.length = 0\n return\n }\n const count = batch.count\n if (count <= 0) return\n const s = this.state.series\n if (batch.fps) this.state.fps = this._ingestI16(s.fps, batch.fps, count, 0.1)\n if (batch.cpuMs) this.state.cpuMs = this._ingestU16(s.cpuMs, batch.cpuMs, count, 0.01)\n if (batch.gpuMs) this.state.gpuMs = this._ingestU16(s.gpuMs, batch.gpuMs, count, 0.01)\n if (batch.heapUsedMB) this.state.heapUsedMB = this._ingestU16(s.heapUsedMB, batch.heapUsedMB, count, 1)\n if (batch.drawCalls) this.state.drawCalls = this._ingestU32(s.drawCalls, batch.drawCalls, count)\n if (batch.triangles) this.state.triangles = this._ingestU32(s.triangles, batch.triangles, count)\n if (batch.primitives) this.state.primitives = this._ingestU32(s.primitives, batch.primitives, count)\n if (batch.geometries) this.state.geometries = this._ingestU32(s.geometries, batch.geometries, count)\n if (batch.textures) this.state.textures = this._ingestU32(s.textures, batch.textures, count)\n if (batch.heapLimitMB !== undefined) this.state.heapLimitMB = batch.heapLimitMB\n }\n\n /**\n * Append `count` samples from a scaled integer view to a Float32 ring;\n * return the batch mean (scaled). Zero-alloc past the ring itself.\n */\n private _ingestI16(ring: DevtoolsSeries, src: Int16Array, count: number, scale: number): number {\n const size = ring.data.length\n let sum = 0\n let w = ring.write\n for (let i = 0; i < count; i++) {\n const v = src[i]! * scale\n ring.data[w] = v\n sum += v\n w = (w + 1) % size\n }\n ring.write = w\n ring.length = Math.min(size, ring.length + count)\n return sum / count\n }\n private _ingestU16(ring: DevtoolsSeries, src: Uint16Array, count: number, scale: number): number {\n const size = ring.data.length\n let sum = 0\n let w = ring.write\n for (let i = 0; i < count; i++) {\n const v = src[i]! * scale\n ring.data[w] = v\n sum += v\n w = (w + 1) % size\n }\n ring.write = w\n ring.length = Math.min(size, ring.length + count)\n return sum / count\n }\n private _ingestU32(ring: DevtoolsSeries, src: Uint32Array, count: number): number {\n const size = ring.data.length\n let sum = 0\n let w = ring.write\n for (let i = 0; i < count; i++) {\n const v = src[i]!\n ring.data[w] = v\n sum += v\n w = (w + 1) % size\n }\n ring.write = w\n ring.length = Math.min(size, ring.length + count)\n return sum / count\n }\n\n /**\n * Apply a batches feature payload — replaces the snapshot wholesale.\n * The wire arrays are scratch pools on the producer; we truncate by\n * the provided counts and copy fields into persistent snapshot\n * objects the UI can hold across subsequent frames.\n *\n * The client-side snapshot arrays grow monotonically to the high\n * watermark and entries are overwritten in place — same alloc\n * discipline as the producer.\n */\n private _applyBatches(delta: BatchesPayload | null): void {\n if (delta === null) {\n this.state.batches.frame = 0\n this.state.batches.passes.length = 0\n this.state.batches.batches.length = 0\n return\n }\n this.state.batches.frame = delta.frame\n\n const passesIn = delta.passes\n const passCount = delta.passCount | 0\n const passesOut = this.state.batches.passes\n if (passesIn !== undefined) {\n for (let i = 0; i < passCount; i++) {\n const src = passesIn[i] as PassEvent | undefined\n if (src === undefined) continue\n let dst = passesOut[i]\n if (dst === undefined) {\n dst = { label: '', calls: 0, triangles: 0, cpuMs: 0, depth: 0, parent: -1 }\n passesOut[i] = dst\n }\n dst.label = src.label\n dst.calls = src.calls\n dst.triangles = src.triangles\n dst.cpuMs = src.cpuMs\n dst.depth = src.depth\n dst.parent = src.parent\n }\n }\n if (passesOut.length > passCount) passesOut.length = passCount\n\n const batchesIn = delta.batches\n const batchCount = delta.batchCount | 0\n const batchesOut = this.state.batches.batches\n if (batchesIn !== undefined) {\n for (let i = 0; i < batchCount; i++) {\n const src = batchesIn[i] as BatchInfo | undefined\n if (src === undefined) continue\n let dst = batchesOut[i]\n if (dst === undefined) {\n dst = {\n runKey: 0,\n materialId: 0,\n layer: 0,\n materialName: '',\n spriteCount: 0,\n batchIdx: 0,\n kind: 'sprite',\n label: '',\n }\n batchesOut[i] = dst\n }\n dst.runKey = src.runKey\n dst.materialId = src.materialId\n dst.layer = src.layer\n dst.materialName = src.materialName\n dst.spriteCount = src.spriteCount\n dst.batchIdx = src.batchIdx\n dst.kind = src.kind ?? 'sprite'\n dst.label = src.label ?? ''\n }\n }\n if (batchesOut.length > batchCount) batchesOut.length = batchCount\n }\n\n /**\n * Apply a registry delta. `entries[name] === null` → remove;\n * `entries[name]` present → upsert a snapshot keyed by `name`.\n * A `null` batch (feature cleared) drops every entry.\n */\n private _applyRegistry(delta: RegistryPayload | null): void {\n if (delta === null) {\n this.state.registry.clear()\n return\n }\n if (!delta.entries) return\n const entries = delta.entries\n // `for…in` to avoid the `Object.entries` array allocation each\n // batch; mutate existing snapshots in place so steady state is\n // alloc-free past the first sight of each entry.\n for (const name in entries) {\n const d = entries[name]\n if (d === undefined) continue\n if (d === null) {\n this.state.registry.delete(name)\n continue\n }\n let snap = this.state.registry.get(name)\n const sample = d.sample ?? snap?.sample ?? EMPTY_SAMPLE\n if (snap === undefined) {\n snap = {\n name,\n kind: d.kind,\n version: d.version,\n count: d.count,\n sample,\n label: d.label,\n }\n this.state.registry.set(name, snap)\n } else {\n snap.kind = d.kind\n snap.version = d.version\n snap.count = d.count\n snap.sample = sample\n snap.label = d.label\n }\n }\n }\n\n /**\n * Apply a buffers delta. Metadata (width/height/version/pixelType)\n * ships regardless of the client's selection; `pixels` only arrives\n * when this entry is in the current selection. Retain the previous\n * `pixels` when the delta is metadata-only so the UI keeps showing\n * the last thumbnail while browsing.\n */\n private _applyBuffers(delta: BuffersPayload | null): void {\n if (delta === null) {\n this.state.buffers.clear()\n return\n }\n if (!delta.entries) return\n const entries = delta.entries\n for (const name in entries) {\n const d = entries[name]\n if (d === undefined) continue\n if (d === null) {\n this.state.buffers.delete(name)\n continue\n }\n let snap = this.state.buffers.get(name)\n const pixels = d.pixels ?? snap?.pixels ?? null\n const isFloat = d.pixelType === 'rgba16f' || d.pixelType === 'rgba32f'\n const display = d.display ?? (isFloat ? 'normalize' : 'colors')\n const srcW = d.srcWidth ?? d.width\n const srcH = d.srcHeight ?? d.height\n if (snap === undefined) {\n snap = {\n name,\n width: d.width,\n height: d.height,\n srcWidth: srcW,\n srcHeight: srcH,\n pixelType: d.pixelType,\n display,\n version: d.version,\n pixels,\n label: d.label,\n }\n this.state.buffers.set(name, snap)\n } else {\n snap.width = d.width\n snap.height = d.height\n snap.srcWidth = srcW\n snap.srcHeight = srcH\n snap.pixelType = d.pixelType\n snap.display = display\n snap.version = d.version\n snap.pixels = pixels\n snap.label = d.label\n }\n }\n }\n\n private _applyEnv(delta: EnvPayload | null): void {\n if (delta === null) {\n this.state.threeFlatlandVersion = undefined\n this.state.threeRevision = undefined\n this.state.backendName = undefined\n this.state.backendTrackTimestamp = undefined\n this.state.backendDisjoint = undefined\n this.state.gpuModeEnabled = undefined\n this.state.canvasWidth = undefined\n this.state.canvasHeight = undefined\n this.state.canvasPixelRatio = undefined\n return\n }\n if ('threeFlatlandVersion' in delta) this.state.threeFlatlandVersion = delta.threeFlatlandVersion ?? undefined\n if ('threeRevision' in delta) this.state.threeRevision = delta.threeRevision ?? undefined\n if (delta.backend !== undefined) {\n const b = delta.backend\n if (b === null) {\n this.state.backendName = undefined\n this.state.backendTrackTimestamp = undefined\n this.state.backendDisjoint = undefined\n this.state.gpuModeEnabled = undefined\n } else {\n if ('name' in b) this.state.backendName = b.name ?? undefined\n if ('trackTimestamp' in b) this.state.backendTrackTimestamp = b.trackTimestamp ?? undefined\n if ('disjoint' in b) this.state.backendDisjoint = b.disjoint ?? undefined\n if ('gpuModeEnabled' in b) this.state.gpuModeEnabled = b.gpuModeEnabled ?? undefined\n }\n }\n if (delta.canvas !== undefined) {\n const c = delta.canvas\n if (c === null) {\n this.state.canvasWidth = undefined\n this.state.canvasHeight = undefined\n this.state.canvasPixelRatio = undefined\n } else {\n if ('width' in c) this.state.canvasWidth = c.width ?? undefined\n if ('height' in c) this.state.canvasHeight = c.height ?? undefined\n if ('pixelRatio' in c) this.state.canvasPixelRatio = c.pixelRatio ?? undefined\n }\n }\n }\n\n private _checkLiveness(): void {\n const now = Date.now()\n const lag = this._lastServerAt === 0 ? now : now - this._lastServerAt\n this.state.serverLagMs = lag\n\n if (this._lastServerAt !== 0 && lag > SERVER_LIVENESS_MS) {\n // Server has gone silent. Flip to dead, then re-subscribe to\n // force a fresh snapshot when it comes back.\n if (this.state.serverAlive) {\n this.state.serverAlive = false\n }\n // Idempotent re-subscribe. Server's onSubscribe handler resets\n // the per-feature delta so we get a full snapshot on the next\n // data packet.\n if (this._dataBus !== null) {\n this._postData({\n type: 'subscribe',\n payload: {\n id: this.id,\n features: this._features,\n registry: this._registrySelection ?? undefined,\n buffers:\n Object.keys(this._buffersSelection).length > 0\n ? this._buffersSelection\n : undefined,\n },\n })\n }\n }\n this._fire()\n }\n\n private _sendAck(): void {\n if (this._disposed || this._dataBus === null) return\n this._postData({ type: 'ack', payload: { id: this.id } })\n }\n\n private _postDiscovery(body: Omit<DebugMessage, 'v' | 'ts'>): void {\n const msg = { v: DEBUG_PROTOCOL_VERSION, ts: Date.now(), ...body } as DebugMessage\n this._fireRawMessage(msg, 'out')\n try {\n this._discoveryBus.postMessage(msg)\n } catch { /* bus may be closing */ }\n }\n\n private _postData(body: Omit<DebugMessage, 'v' | 'ts'>): void {\n if (this._dataBus === null) return\n const msg = { v: DEBUG_PROTOCOL_VERSION, ts: Date.now(), ...body } as DebugMessage\n this._fireRawMessage(msg, 'out')\n try {\n this._dataBus.postMessage(msg)\n } catch { /* bus may be closing */ }\n }\n\n private _fireRawMessage(msg: DebugMessage, direction: 'in' | 'out'): void {\n if (this._rawMessageListeners.size === 0) return\n for (const cb of this._rawMessageListeners) {\n try { cb(msg, direction) } catch { /* listener errors shouldn't break the bus */ }\n }\n }\n\n /** Subscribe to state-change events. Returns an unsubscribe function. */\n addListener(cb: DevtoolsStateListener): () => void {\n this._listeners.add(cb)\n return () => { this._listeners.delete(cb) }\n }\n\n /** Explicit remove — equivalent to calling the unsubscribe returned from `addListener`. */\n removeListener(cb: DevtoolsStateListener): void {\n this._listeners.delete(cb)\n }\n\n /** Subscribe to incoming WebCodecs buffer chunks. Returns an unsubscribe function. */\n addChunkListener(cb: BufferChunkListener): () => void {\n this._chunkListeners.add(cb)\n return () => { this._chunkListeners.delete(cb) }\n }\n\n /**\n * Subscribe to every bus message — both inbound (from providers) and\n * outbound (our own `subscribe`/`ack`/etc.). Used by the dashboard's\n * protocol-log panel. Listeners fire on the hot path so keep them\n * cheap — filter and format lazily.\n */\n addRawMessageListener(cb: RawMessageListener): () => void {\n this._rawMessageListeners.add(cb)\n return () => { this._rawMessageListeners.delete(cb) }\n }\n\n private _fire(): void {\n for (const cb of this._listeners) {\n try { cb(this.state) } catch { /* listener errors shouldn't break the bus */ }\n }\n }\n}\n\n// Cheap UUID v4 for consumer ids. Prefer `crypto.randomUUID()` when\n// available; fall back to a hex-derived UUID otherwise.\n/** Cheap equality for two small feature lists treated as sets. */\nfunction sameSet(a: readonly string[], b: readonly string[]): boolean {\n if (a.length !== b.length) return false\n for (const v of a) if (!b.includes(v)) return false\n return true\n}\n\n/** Equality for registry filters (where `null` has a distinct meaning). */\nfunction sameFilter(a: readonly string[] | null, b: readonly string[] | null): boolean {\n if (a === b) return true\n if (a === null || b === null) return false\n return sameSet(a, b)\n}\n\n/** Equality for buffer subscription records. Compares keys and nested fields. */\nfunction sameBufferSubscription(\n a: Record<string, BufferSubscriptionEntry>,\n b: Record<string, BufferSubscriptionEntry>,\n): boolean {\n const ak = Object.keys(a)\n const bk = Object.keys(b)\n if (ak.length !== bk.length) return false\n for (const k of ak) {\n const av = a[k]\n const bv = b[k]\n if (av === undefined || bv === undefined) return false\n if (av.mode !== bv.mode) return false\n if ((av.thumbSize ?? 256) !== (bv.thumbSize ?? 256)) return false\n }\n return true\n}\n\nfunction generateUuid(): string {\n const c = typeof crypto !== 'undefined' ? crypto : undefined\n if (c && typeof c.randomUUID === 'function') return c.randomUUID()\n const bytes = new Uint8Array(16)\n if (c && typeof c.getRandomValues === 'function') c.getRandomValues(bytes)\n else for (let i = 0; i < 16; i++) bytes[i] = Math.floor(Math.random() * 256)\n bytes[6] = (bytes[6]! & 0x0f) | 0x40\n bytes[8] = (bytes[8]! & 0x3f) | 0x80\n const h = Array.from(bytes, (b) => b.toString(16).padStart(2, '0'))\n return `${h.slice(0, 4).join('')}-${h.slice(4, 6).join('')}-${h.slice(6, 8).join('')}-${h.slice(8, 10).join('')}-${h.slice(10).join('')}`\n}\n"],"mappings":"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","names":["s"]}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var index_exports = {};
|
|
20
|
+
__export(index_exports, {
|
|
21
|
+
DevtoolsClient: () => import_devtools_client.DevtoolsClient,
|
|
22
|
+
EssentialsPlugin: () => import_plugins.EssentialsPlugin,
|
|
23
|
+
FLATLAND_THEME: () => import_theme.FLATLAND_THEME,
|
|
24
|
+
applyTheme: () => import_theme.applyTheme,
|
|
25
|
+
createPane: () => import_create_pane.createPane,
|
|
26
|
+
registerPlugins: () => import_plugins.registerPlugins
|
|
27
|
+
});
|
|
28
|
+
module.exports = __toCommonJS(index_exports);
|
|
29
|
+
var import_create_pane = require("./create-pane.js");
|
|
30
|
+
var import_theme = require("./theme.js");
|
|
31
|
+
var import_plugins = require("./plugins.js");
|
|
32
|
+
var import_devtools_client = require("./devtools-client.js");
|
|
33
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
34
|
+
0 && (module.exports = {
|
|
35
|
+
DevtoolsClient,
|
|
36
|
+
EssentialsPlugin,
|
|
37
|
+
FLATLAND_THEME,
|
|
38
|
+
applyTheme,
|
|
39
|
+
createPane,
|
|
40
|
+
registerPlugins
|
|
41
|
+
});
|
|
42
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export { createPane } from './create-pane.js'\nexport type { CreatePaneOptions, PaneBundle } from './create-pane.js'\nexport { applyTheme, FLATLAND_THEME } from './theme.js'\nexport { registerPlugins, EssentialsPlugin } from './plugins.js'\n\n// Bus consumer — advanced; normal users don't touch this directly.\n// The stats graph + stats row (auto-mounted by `createPane`) drive off a\n// shared instance under the hood. Exposed for callers who want a\n// secondary consumer on the same bus (e.g., a custom visualisation).\nexport { DevtoolsClient } from './devtools-client.js'\nexport type {\n DevtoolsClientOptions,\n DevtoolsState,\n DevtoolsStateListener,\n} from './devtools-client.js'\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,yBAA2B;AAE3B,mBAA2C;AAC3C,qBAAkD;AAMlD,6BAA+B;","names":[]}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { CreatePaneOptions, PaneBundle, createPane } from './create-pane.cjs';
|
|
2
|
+
export { FLATLAND_THEME, applyTheme } from './theme.cjs';
|
|
3
|
+
export { registerPlugins } from './plugins.cjs';
|
|
4
|
+
export { DevtoolsClient, DevtoolsClientOptions, DevtoolsState, DevtoolsStateListener } from './devtools-client.cjs';
|
|
5
|
+
import * as pluginEssentials from '@tweakpane/plugin-essentials';
|
|
6
|
+
export { pluginEssentials as EssentialsPlugin };
|
|
7
|
+
import 'tweakpane';
|
|
8
|
+
import 'three-flatland/debug-protocol';
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { CreatePaneOptions, PaneBundle, createPane } from './create-pane.js';
|
|
2
|
+
export { FLATLAND_THEME, applyTheme } from './theme.js';
|
|
3
|
+
export { registerPlugins } from './plugins.js';
|
|
4
|
+
export { DevtoolsClient, DevtoolsClientOptions, DevtoolsState, DevtoolsStateListener } from './devtools-client.js';
|
|
5
|
+
import * as pluginEssentials from '@tweakpane/plugin-essentials';
|
|
6
|
+
export { pluginEssentials as EssentialsPlugin };
|
|
7
|
+
import 'tweakpane';
|
|
8
|
+
import 'three-flatland/debug-protocol';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { createPane } from "./create-pane.js";
|
|
2
|
+
import { applyTheme, FLATLAND_THEME } from "./theme.js";
|
|
3
|
+
import { registerPlugins, EssentialsPlugin } from "./plugins.js";
|
|
4
|
+
import { DevtoolsClient } from "./devtools-client.js";
|
|
5
|
+
export {
|
|
6
|
+
DevtoolsClient,
|
|
7
|
+
EssentialsPlugin,
|
|
8
|
+
FLATLAND_THEME,
|
|
9
|
+
applyTheme,
|
|
10
|
+
createPane,
|
|
11
|
+
registerPlugins
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["export { createPane } from './create-pane.js'\nexport type { CreatePaneOptions, PaneBundle } from './create-pane.js'\nexport { applyTheme, FLATLAND_THEME } from './theme.js'\nexport { registerPlugins, EssentialsPlugin } from './plugins.js'\n\n// Bus consumer — advanced; normal users don't touch this directly.\n// The stats graph + stats row (auto-mounted by `createPane`) drive off a\n// shared instance under the hood. Exposed for callers who want a\n// secondary consumer on the same bus (e.g., a custom visualisation).\nexport { DevtoolsClient } from './devtools-client.js'\nexport type {\n DevtoolsClientOptions,\n DevtoolsState,\n DevtoolsStateListener,\n} from './devtools-client.js'\n"],"mappings":"AAAA,SAAS,kBAAkB;AAE3B,SAAS,YAAY,sBAAsB;AAC3C,SAAS,iBAAiB,wBAAwB;AAMlD,SAAS,sBAAsB;","names":[]}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var perf_trace_exports = {};
|
|
20
|
+
__export(perf_trace_exports, {
|
|
21
|
+
tracePerf: () => tracePerf
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(perf_trace_exports);
|
|
24
|
+
const TRACK_NAME = "devtools";
|
|
25
|
+
const TRACK_GROUP = "three-flatland";
|
|
26
|
+
const COLOR_BY_TYPE = {
|
|
27
|
+
data: "primary",
|
|
28
|
+
ping: "secondary-light",
|
|
29
|
+
"subscribe:ack": "tertiary",
|
|
30
|
+
subscribe: "tertiary-light",
|
|
31
|
+
ack: "secondary",
|
|
32
|
+
unsubscribe: "tertiary-dark",
|
|
33
|
+
"provider:announce": "primary-light",
|
|
34
|
+
"provider:query": "primary-light",
|
|
35
|
+
"provider:gone": "error"
|
|
36
|
+
};
|
|
37
|
+
function tracePerf(msg) {
|
|
38
|
+
if (msg === void 0) return;
|
|
39
|
+
if (typeof performance === "undefined" || typeof performance.measure !== "function") return;
|
|
40
|
+
const ts = msg.ts;
|
|
41
|
+
if (typeof ts !== "number" || ts <= 0) return;
|
|
42
|
+
try {
|
|
43
|
+
const start = ts - performance.timeOrigin;
|
|
44
|
+
const end = performance.now();
|
|
45
|
+
if (end < start) return;
|
|
46
|
+
const bytes = estimatePayloadBytes(msg.payload);
|
|
47
|
+
performance.measure(`bus:${msg.type}`, {
|
|
48
|
+
start,
|
|
49
|
+
end,
|
|
50
|
+
detail: {
|
|
51
|
+
devtools: {
|
|
52
|
+
dataType: "track-entry",
|
|
53
|
+
track: TRACK_NAME,
|
|
54
|
+
trackGroup: TRACK_GROUP,
|
|
55
|
+
color: COLOR_BY_TYPE[msg.type] ?? "primary",
|
|
56
|
+
// Chrome's User Timings extension surfaces `properties` as a
|
|
57
|
+
// key/value table in the entry detail panel — perfect for
|
|
58
|
+
// per-message bandwidth at-a-glance.
|
|
59
|
+
properties: bytes > 0 ? [
|
|
60
|
+
["type", msg.type],
|
|
61
|
+
["bytes", formatBytes(bytes)]
|
|
62
|
+
] : [["type", msg.type]]
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
} catch {
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function estimatePayloadBytes(payload) {
|
|
70
|
+
if (payload === null || typeof payload !== "object") return 0;
|
|
71
|
+
let total = 0;
|
|
72
|
+
const features = payload.features;
|
|
73
|
+
if (features !== void 0) {
|
|
74
|
+
for (const f of Object.values(features)) {
|
|
75
|
+
total += sumTypedArrays(f);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return total;
|
|
79
|
+
}
|
|
80
|
+
function sumTypedArrays(node) {
|
|
81
|
+
if (node === null || typeof node !== "object") return 0;
|
|
82
|
+
let total = 0;
|
|
83
|
+
for (const v of Object.values(node)) {
|
|
84
|
+
if (v && typeof v === "object" && v.byteLength !== void 0 && ArrayBuffer.isView(v)) {
|
|
85
|
+
total += v.byteLength;
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (v && typeof v === "object") {
|
|
89
|
+
total += sumTypedArrays(v);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return total;
|
|
93
|
+
}
|
|
94
|
+
function formatBytes(n) {
|
|
95
|
+
if (n < 1024) return `${n} B`;
|
|
96
|
+
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
|
|
97
|
+
return `${(n / (1024 * 1024)).toFixed(2)} MB`;
|
|
98
|
+
}
|
|
99
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
100
|
+
0 && (module.exports = {
|
|
101
|
+
tracePerf
|
|
102
|
+
});
|
|
103
|
+
//# sourceMappingURL=perf-trace.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/perf-trace.ts"],"sourcesContent":["/**\n * Log inbound bus messages as User Timing spans on the shared\n * **Devtools** track under the **three-flatland** group in Chrome's\n * Performance panel. Each span covers the window from when the sender\n * stamped the message to when the handler received it — end-to-end\n * `BroadcastChannel` delivery latency.\n *\n * Convention matches `packages/three-flatland/src/debug/perf-track.ts`:\n * - track group: `three-flatland`\n * - track: `Devtools`\n * - entry name: `bus:<type>` (`bus:data`, `bus:ping`, `bus:subscribe:ack`, …)\n *\n * Older Chromes silently ignore the `detail.devtools` payload and the\n * spans show up on the default Timings track instead.\n *\n * Usage: call `tracePerf(msg)` at the top of the receive handler\n * (both the discovery and data routers). Safe in non-performance\n * environments — every call is wrapped in a capability check and a\n * try/catch so a failed measurement never takes down the client.\n */\n\nconst TRACK_NAME = 'devtools'\nconst TRACK_GROUP = 'three-flatland'\n\nconst COLOR_BY_TYPE: Record<string, string> = {\n data: 'primary',\n ping: 'secondary-light',\n 'subscribe:ack': 'tertiary',\n subscribe: 'tertiary-light',\n ack: 'secondary',\n unsubscribe: 'tertiary-dark',\n 'provider:announce': 'primary-light',\n 'provider:query': 'primary-light',\n 'provider:gone': 'error',\n}\n\nexport function tracePerf(msg: { ts: number; type: string; payload?: unknown } | undefined): void {\n if (msg === undefined) return\n if (typeof performance === 'undefined' || typeof performance.measure !== 'function') return\n const ts = msg.ts\n if (typeof ts !== 'number' || ts <= 0) return\n try {\n // `msg.ts` is `Date.now()` (wall clock). Convert to the\n // `performance.now()` origin by subtracting `timeOrigin`. Skip if\n // clocks disagree enough to make the span go backwards.\n const start = ts - performance.timeOrigin\n const end = performance.now()\n if (end < start) return\n\n // Compute the heavy-data byte count from the message we just got.\n // Walks typed-array fields only (ignoring object/scalar overhead,\n // which is dominated by the typed arrays for `data` packets).\n const bytes = estimatePayloadBytes(msg.payload)\n\n performance.measure(`bus:${msg.type}`, {\n start,\n end,\n detail: {\n devtools: {\n dataType: 'track-entry',\n track: TRACK_NAME,\n trackGroup: TRACK_GROUP,\n color: COLOR_BY_TYPE[msg.type] ?? 'primary',\n // Chrome's User Timings extension surfaces `properties` as a\n // key/value table in the entry detail panel — perfect for\n // per-message bandwidth at-a-glance.\n properties: bytes > 0\n ? [\n ['type', msg.type],\n ['bytes', formatBytes(bytes)],\n ]\n : [['type', msg.type]],\n },\n },\n })\n } catch {\n // DevTools may reject the extension payload in older Chromes;\n // ignore.\n }\n}\n\n/**\n * Walk a structured-cloned payload and sum the `byteLength` of every\n * typed array we encounter (one level deep into `features.*` for data\n * packets, one level into `entries[*]` for registry/buffers payloads).\n * Doesn't recurse into arbitrary nested objects — anything past these\n * known shapes contributes 0, which is fine because real bandwidth\n * lives in the typed arrays.\n */\nfunction estimatePayloadBytes(payload: unknown): number {\n if (payload === null || typeof payload !== 'object') return 0\n let total = 0\n // Direct `features` shape on data packets.\n const features = (payload as { features?: Record<string, unknown> }).features\n if (features !== undefined) {\n for (const f of Object.values(features)) {\n total += sumTypedArrays(f)\n }\n }\n return total\n}\n\nfunction sumTypedArrays(node: unknown): number {\n if (node === null || typeof node !== 'object') return 0\n let total = 0\n for (const v of Object.values(node)) {\n if (v && typeof v === 'object' && (v as { byteLength?: number }).byteLength !== undefined && ArrayBuffer.isView(v as ArrayBufferView)) {\n total += (v as ArrayBufferView).byteLength\n continue\n }\n if (v && typeof v === 'object') {\n total += sumTypedArrays(v)\n }\n }\n return total\n}\n\nfunction formatBytes(n: number): string {\n if (n < 1024) return `${n} B`\n if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`\n return `${(n / (1024 * 1024)).toFixed(2)} MB`\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAqBA,MAAM,aAAa;AACnB,MAAM,cAAc;AAEpB,MAAM,gBAAwC;AAAA,EAC5C,MAAM;AAAA,EACN,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,WAAW;AAAA,EACX,KAAK;AAAA,EACL,aAAa;AAAA,EACb,qBAAqB;AAAA,EACrB,kBAAkB;AAAA,EAClB,iBAAiB;AACnB;AAEO,SAAS,UAAU,KAAwE;AAChG,MAAI,QAAQ,OAAW;AACvB,MAAI,OAAO,gBAAgB,eAAe,OAAO,YAAY,YAAY,WAAY;AACrF,QAAM,KAAK,IAAI;AACf,MAAI,OAAO,OAAO,YAAY,MAAM,EAAG;AACvC,MAAI;AAIF,UAAM,QAAQ,KAAK,YAAY;AAC/B,UAAM,MAAM,YAAY,IAAI;AAC5B,QAAI,MAAM,MAAO;AAKjB,UAAM,QAAQ,qBAAqB,IAAI,OAAO;AAE9C,gBAAY,QAAQ,OAAO,IAAI,IAAI,IAAI;AAAA,MACrC;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,QACN,UAAU;AAAA,UACR,UAAU;AAAA,UACV,OAAO;AAAA,UACP,YAAY;AAAA,UACZ,OAAO,cAAc,IAAI,IAAI,KAAK;AAAA;AAAA;AAAA;AAAA,UAIlC,YAAY,QAAQ,IAChB;AAAA,YACE,CAAC,QAAQ,IAAI,IAAI;AAAA,YACjB,CAAC,SAAS,YAAY,KAAK,CAAC;AAAA,UAC9B,IACA,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC;AAAA,QACzB;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH,QAAQ;AAAA,EAGR;AACF;AAUA,SAAS,qBAAqB,SAA0B;AACtD,MAAI,YAAY,QAAQ,OAAO,YAAY,SAAU,QAAO;AAC5D,MAAI,QAAQ;AAEZ,QAAM,WAAY,QAAmD;AACrE,MAAI,aAAa,QAAW;AAC1B,eAAW,KAAK,OAAO,OAAO,QAAQ,GAAG;AACvC,eAAS,eAAe,CAAC;AAAA,IAC3B;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,eAAe,MAAuB;AAC7C,MAAI,SAAS,QAAQ,OAAO,SAAS,SAAU,QAAO;AACtD,MAAI,QAAQ;AACZ,aAAW,KAAK,OAAO,OAAO,IAAI,GAAG;AACnC,QAAI,KAAK,OAAO,MAAM,YAAa,EAA8B,eAAe,UAAa,YAAY,OAAO,CAAoB,GAAG;AACrI,eAAU,EAAsB;AAChC;AAAA,IACF;AACA,QAAI,KAAK,OAAO,MAAM,UAAU;AAC9B,eAAS,eAAe,CAAC;AAAA,IAC3B;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,YAAY,GAAmB;AACtC,MAAI,IAAI,KAAM,QAAO,GAAG,CAAC;AACzB,MAAI,IAAI,OAAO,KAAM,QAAO,IAAI,IAAI,MAAM,QAAQ,CAAC,CAAC;AACpD,SAAO,IAAI,KAAK,OAAO,OAAO,QAAQ,CAAC,CAAC;AAC1C;","names":[]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log inbound bus messages as User Timing spans on the shared
|
|
3
|
+
* **Devtools** track under the **three-flatland** group in Chrome's
|
|
4
|
+
* Performance panel. Each span covers the window from when the sender
|
|
5
|
+
* stamped the message to when the handler received it — end-to-end
|
|
6
|
+
* `BroadcastChannel` delivery latency.
|
|
7
|
+
*
|
|
8
|
+
* Convention matches `packages/three-flatland/src/debug/perf-track.ts`:
|
|
9
|
+
* - track group: `three-flatland`
|
|
10
|
+
* - track: `Devtools`
|
|
11
|
+
* - entry name: `bus:<type>` (`bus:data`, `bus:ping`, `bus:subscribe:ack`, …)
|
|
12
|
+
*
|
|
13
|
+
* Older Chromes silently ignore the `detail.devtools` payload and the
|
|
14
|
+
* spans show up on the default Timings track instead.
|
|
15
|
+
*
|
|
16
|
+
* Usage: call `tracePerf(msg)` at the top of the receive handler
|
|
17
|
+
* (both the discovery and data routers). Safe in non-performance
|
|
18
|
+
* environments — every call is wrapped in a capability check and a
|
|
19
|
+
* try/catch so a failed measurement never takes down the client.
|
|
20
|
+
*/
|
|
21
|
+
declare function tracePerf(msg: {
|
|
22
|
+
ts: number;
|
|
23
|
+
type: string;
|
|
24
|
+
payload?: unknown;
|
|
25
|
+
} | undefined): void;
|
|
26
|
+
|
|
27
|
+
export { tracePerf };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Log inbound bus messages as User Timing spans on the shared
|
|
3
|
+
* **Devtools** track under the **three-flatland** group in Chrome's
|
|
4
|
+
* Performance panel. Each span covers the window from when the sender
|
|
5
|
+
* stamped the message to when the handler received it — end-to-end
|
|
6
|
+
* `BroadcastChannel` delivery latency.
|
|
7
|
+
*
|
|
8
|
+
* Convention matches `packages/three-flatland/src/debug/perf-track.ts`:
|
|
9
|
+
* - track group: `three-flatland`
|
|
10
|
+
* - track: `Devtools`
|
|
11
|
+
* - entry name: `bus:<type>` (`bus:data`, `bus:ping`, `bus:subscribe:ack`, …)
|
|
12
|
+
*
|
|
13
|
+
* Older Chromes silently ignore the `detail.devtools` payload and the
|
|
14
|
+
* spans show up on the default Timings track instead.
|
|
15
|
+
*
|
|
16
|
+
* Usage: call `tracePerf(msg)` at the top of the receive handler
|
|
17
|
+
* (both the discovery and data routers). Safe in non-performance
|
|
18
|
+
* environments — every call is wrapped in a capability check and a
|
|
19
|
+
* try/catch so a failed measurement never takes down the client.
|
|
20
|
+
*/
|
|
21
|
+
declare function tracePerf(msg: {
|
|
22
|
+
ts: number;
|
|
23
|
+
type: string;
|
|
24
|
+
payload?: unknown;
|
|
25
|
+
} | undefined): void;
|
|
26
|
+
|
|
27
|
+
export { tracePerf };
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const TRACK_NAME = "devtools";
|
|
2
|
+
const TRACK_GROUP = "three-flatland";
|
|
3
|
+
const COLOR_BY_TYPE = {
|
|
4
|
+
data: "primary",
|
|
5
|
+
ping: "secondary-light",
|
|
6
|
+
"subscribe:ack": "tertiary",
|
|
7
|
+
subscribe: "tertiary-light",
|
|
8
|
+
ack: "secondary",
|
|
9
|
+
unsubscribe: "tertiary-dark",
|
|
10
|
+
"provider:announce": "primary-light",
|
|
11
|
+
"provider:query": "primary-light",
|
|
12
|
+
"provider:gone": "error"
|
|
13
|
+
};
|
|
14
|
+
function tracePerf(msg) {
|
|
15
|
+
if (msg === void 0) return;
|
|
16
|
+
if (typeof performance === "undefined" || typeof performance.measure !== "function") return;
|
|
17
|
+
const ts = msg.ts;
|
|
18
|
+
if (typeof ts !== "number" || ts <= 0) return;
|
|
19
|
+
try {
|
|
20
|
+
const start = ts - performance.timeOrigin;
|
|
21
|
+
const end = performance.now();
|
|
22
|
+
if (end < start) return;
|
|
23
|
+
const bytes = estimatePayloadBytes(msg.payload);
|
|
24
|
+
performance.measure(`bus:${msg.type}`, {
|
|
25
|
+
start,
|
|
26
|
+
end,
|
|
27
|
+
detail: {
|
|
28
|
+
devtools: {
|
|
29
|
+
dataType: "track-entry",
|
|
30
|
+
track: TRACK_NAME,
|
|
31
|
+
trackGroup: TRACK_GROUP,
|
|
32
|
+
color: COLOR_BY_TYPE[msg.type] ?? "primary",
|
|
33
|
+
// Chrome's User Timings extension surfaces `properties` as a
|
|
34
|
+
// key/value table in the entry detail panel — perfect for
|
|
35
|
+
// per-message bandwidth at-a-glance.
|
|
36
|
+
properties: bytes > 0 ? [
|
|
37
|
+
["type", msg.type],
|
|
38
|
+
["bytes", formatBytes(bytes)]
|
|
39
|
+
] : [["type", msg.type]]
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
});
|
|
43
|
+
} catch {
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function estimatePayloadBytes(payload) {
|
|
47
|
+
if (payload === null || typeof payload !== "object") return 0;
|
|
48
|
+
let total = 0;
|
|
49
|
+
const features = payload.features;
|
|
50
|
+
if (features !== void 0) {
|
|
51
|
+
for (const f of Object.values(features)) {
|
|
52
|
+
total += sumTypedArrays(f);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return total;
|
|
56
|
+
}
|
|
57
|
+
function sumTypedArrays(node) {
|
|
58
|
+
if (node === null || typeof node !== "object") return 0;
|
|
59
|
+
let total = 0;
|
|
60
|
+
for (const v of Object.values(node)) {
|
|
61
|
+
if (v && typeof v === "object" && v.byteLength !== void 0 && ArrayBuffer.isView(v)) {
|
|
62
|
+
total += v.byteLength;
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (v && typeof v === "object") {
|
|
66
|
+
total += sumTypedArrays(v);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return total;
|
|
70
|
+
}
|
|
71
|
+
function formatBytes(n) {
|
|
72
|
+
if (n < 1024) return `${n} B`;
|
|
73
|
+
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
|
|
74
|
+
return `${(n / (1024 * 1024)).toFixed(2)} MB`;
|
|
75
|
+
}
|
|
76
|
+
export {
|
|
77
|
+
tracePerf
|
|
78
|
+
};
|
|
79
|
+
//# sourceMappingURL=perf-trace.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/perf-trace.ts"],"sourcesContent":["/**\n * Log inbound bus messages as User Timing spans on the shared\n * **Devtools** track under the **three-flatland** group in Chrome's\n * Performance panel. Each span covers the window from when the sender\n * stamped the message to when the handler received it — end-to-end\n * `BroadcastChannel` delivery latency.\n *\n * Convention matches `packages/three-flatland/src/debug/perf-track.ts`:\n * - track group: `three-flatland`\n * - track: `Devtools`\n * - entry name: `bus:<type>` (`bus:data`, `bus:ping`, `bus:subscribe:ack`, …)\n *\n * Older Chromes silently ignore the `detail.devtools` payload and the\n * spans show up on the default Timings track instead.\n *\n * Usage: call `tracePerf(msg)` at the top of the receive handler\n * (both the discovery and data routers). Safe in non-performance\n * environments — every call is wrapped in a capability check and a\n * try/catch so a failed measurement never takes down the client.\n */\n\nconst TRACK_NAME = 'devtools'\nconst TRACK_GROUP = 'three-flatland'\n\nconst COLOR_BY_TYPE: Record<string, string> = {\n data: 'primary',\n ping: 'secondary-light',\n 'subscribe:ack': 'tertiary',\n subscribe: 'tertiary-light',\n ack: 'secondary',\n unsubscribe: 'tertiary-dark',\n 'provider:announce': 'primary-light',\n 'provider:query': 'primary-light',\n 'provider:gone': 'error',\n}\n\nexport function tracePerf(msg: { ts: number; type: string; payload?: unknown } | undefined): void {\n if (msg === undefined) return\n if (typeof performance === 'undefined' || typeof performance.measure !== 'function') return\n const ts = msg.ts\n if (typeof ts !== 'number' || ts <= 0) return\n try {\n // `msg.ts` is `Date.now()` (wall clock). Convert to the\n // `performance.now()` origin by subtracting `timeOrigin`. Skip if\n // clocks disagree enough to make the span go backwards.\n const start = ts - performance.timeOrigin\n const end = performance.now()\n if (end < start) return\n\n // Compute the heavy-data byte count from the message we just got.\n // Walks typed-array fields only (ignoring object/scalar overhead,\n // which is dominated by the typed arrays for `data` packets).\n const bytes = estimatePayloadBytes(msg.payload)\n\n performance.measure(`bus:${msg.type}`, {\n start,\n end,\n detail: {\n devtools: {\n dataType: 'track-entry',\n track: TRACK_NAME,\n trackGroup: TRACK_GROUP,\n color: COLOR_BY_TYPE[msg.type] ?? 'primary',\n // Chrome's User Timings extension surfaces `properties` as a\n // key/value table in the entry detail panel — perfect for\n // per-message bandwidth at-a-glance.\n properties: bytes > 0\n ? [\n ['type', msg.type],\n ['bytes', formatBytes(bytes)],\n ]\n : [['type', msg.type]],\n },\n },\n })\n } catch {\n // DevTools may reject the extension payload in older Chromes;\n // ignore.\n }\n}\n\n/**\n * Walk a structured-cloned payload and sum the `byteLength` of every\n * typed array we encounter (one level deep into `features.*` for data\n * packets, one level into `entries[*]` for registry/buffers payloads).\n * Doesn't recurse into arbitrary nested objects — anything past these\n * known shapes contributes 0, which is fine because real bandwidth\n * lives in the typed arrays.\n */\nfunction estimatePayloadBytes(payload: unknown): number {\n if (payload === null || typeof payload !== 'object') return 0\n let total = 0\n // Direct `features` shape on data packets.\n const features = (payload as { features?: Record<string, unknown> }).features\n if (features !== undefined) {\n for (const f of Object.values(features)) {\n total += sumTypedArrays(f)\n }\n }\n return total\n}\n\nfunction sumTypedArrays(node: unknown): number {\n if (node === null || typeof node !== 'object') return 0\n let total = 0\n for (const v of Object.values(node)) {\n if (v && typeof v === 'object' && (v as { byteLength?: number }).byteLength !== undefined && ArrayBuffer.isView(v as ArrayBufferView)) {\n total += (v as ArrayBufferView).byteLength\n continue\n }\n if (v && typeof v === 'object') {\n total += sumTypedArrays(v)\n }\n }\n return total\n}\n\nfunction formatBytes(n: number): string {\n if (n < 1024) return `${n} B`\n if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`\n return `${(n / (1024 * 1024)).toFixed(2)} MB`\n}\n"],"mappings":"AAqBA,MAAM,aAAa;AACnB,MAAM,cAAc;AAEpB,MAAM,gBAAwC;AAAA,EAC5C,MAAM;AAAA,EACN,MAAM;AAAA,EACN,iBAAiB;AAAA,EACjB,WAAW;AAAA,EACX,KAAK;AAAA,EACL,aAAa;AAAA,EACb,qBAAqB;AAAA,EACrB,kBAAkB;AAAA,EAClB,iBAAiB;AACnB;AAEO,SAAS,UAAU,KAAwE;AAChG,MAAI,QAAQ,OAAW;AACvB,MAAI,OAAO,gBAAgB,eAAe,OAAO,YAAY,YAAY,WAAY;AACrF,QAAM,KAAK,IAAI;AACf,MAAI,OAAO,OAAO,YAAY,MAAM,EAAG;AACvC,MAAI;AAIF,UAAM,QAAQ,KAAK,YAAY;AAC/B,UAAM,MAAM,YAAY,IAAI;AAC5B,QAAI,MAAM,MAAO;AAKjB,UAAM,QAAQ,qBAAqB,IAAI,OAAO;AAE9C,gBAAY,QAAQ,OAAO,IAAI,IAAI,IAAI;AAAA,MACrC;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,QACN,UAAU;AAAA,UACR,UAAU;AAAA,UACV,OAAO;AAAA,UACP,YAAY;AAAA,UACZ,OAAO,cAAc,IAAI,IAAI,KAAK;AAAA;AAAA;AAAA;AAAA,UAIlC,YAAY,QAAQ,IAChB;AAAA,YACE,CAAC,QAAQ,IAAI,IAAI;AAAA,YACjB,CAAC,SAAS,YAAY,KAAK,CAAC;AAAA,UAC9B,IACA,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC;AAAA,QACzB;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH,QAAQ;AAAA,EAGR;AACF;AAUA,SAAS,qBAAqB,SAA0B;AACtD,MAAI,YAAY,QAAQ,OAAO,YAAY,SAAU,QAAO;AAC5D,MAAI,QAAQ;AAEZ,QAAM,WAAY,QAAmD;AACrE,MAAI,aAAa,QAAW;AAC1B,eAAW,KAAK,OAAO,OAAO,QAAQ,GAAG;AACvC,eAAS,eAAe,CAAC;AAAA,IAC3B;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,eAAe,MAAuB;AAC7C,MAAI,SAAS,QAAQ,OAAO,SAAS,SAAU,QAAO;AACtD,MAAI,QAAQ;AACZ,aAAW,KAAK,OAAO,OAAO,IAAI,GAAG;AACnC,QAAI,KAAK,OAAO,MAAM,YAAa,EAA8B,eAAe,UAAa,YAAY,OAAO,CAAoB,GAAG;AACrI,eAAU,EAAsB;AAChC;AAAA,IACF;AACA,QAAI,KAAK,OAAO,MAAM,UAAU;AAC9B,eAAS,eAAe,CAAC;AAAA,IAC3B;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,YAAY,GAAmB;AACtC,MAAI,IAAI,KAAM,QAAO,GAAG,CAAC;AACzB,MAAI,IAAI,OAAO,KAAM,QAAO,IAAI,IAAI,MAAM,QAAQ,CAAC,CAAC;AACpD,SAAO,IAAI,KAAK,OAAO,OAAO,QAAQ,CAAC,CAAC;AAC1C;","names":[]}
|
package/dist/plugins.cjs
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var plugins_exports = {};
|
|
30
|
+
__export(plugins_exports, {
|
|
31
|
+
EssentialsPlugin: () => EssentialsPlugin,
|
|
32
|
+
registerPlugins: () => registerPlugins
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(plugins_exports);
|
|
35
|
+
var EssentialsPlugin = __toESM(require("@tweakpane/plugin-essentials"), 1);
|
|
36
|
+
function registerPlugins(pane) {
|
|
37
|
+
pane.registerPlugin(EssentialsPlugin);
|
|
38
|
+
}
|
|
39
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
40
|
+
0 && (module.exports = {
|
|
41
|
+
EssentialsPlugin,
|
|
42
|
+
registerPlugins
|
|
43
|
+
});
|
|
44
|
+
//# sourceMappingURL=plugins.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/plugins.ts"],"sourcesContent":["import type { Pane } from 'tweakpane'\nimport * as EssentialsPlugin from '@tweakpane/plugin-essentials'\n\nexport function registerPlugins(pane: Pane): void {\n pane.registerPlugin(EssentialsPlugin)\n}\n\nexport { EssentialsPlugin }\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,uBAAkC;AAE3B,SAAS,gBAAgB,MAAkB;AAChD,OAAK,eAAe,gBAAgB;AACtC;","names":[]}
|
package/dist/plugins.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/plugins.ts"],"sourcesContent":["import type { Pane } from 'tweakpane'\nimport * as EssentialsPlugin from '@tweakpane/plugin-essentials'\n\nexport function registerPlugins(pane: Pane): void {\n pane.registerPlugin(EssentialsPlugin)\n}\n\nexport { EssentialsPlugin }\n"],"mappings":"AACA,YAAY,sBAAsB;AAE3B,SAAS,gBAAgB,MAAkB;AAChD,OAAK,eAAe,gBAAgB;AACtC;","names":[]}
|