| # Repairing Solid reactivity from diagnostic codes | ||
| Solid's dev builds emit structured diagnostics with stable codes. When you see | ||
| a code — in the console, in a test failure, or in a captured artifact from | ||
| `@solidjs/diagnostics` — this guide maps it to the repair. Each entry says | ||
| what the runtime observed and what to change. Do not suppress a diagnostic | ||
| you do not understand; every one of these is a real defect or a real cost. | ||
| Severity `error` codes indicate broken behavior; `warn` codes indicate code | ||
| that works but is structurally wrong or expensive. | ||
| ## Tracking mistakes (reads in the wrong place) | ||
| ### STRICT_READ_UNTRACKED | ||
| A reactive value was read outside any tracking scope (e.g. destructured props | ||
| or a signal called in the component body). The read got the current value | ||
| once and will never update. Move the read into a tracking scope: JSX, a | ||
| memo, or an effect's compute function. If you intentionally want a one-time | ||
| snapshot, wrap the read in `untrack()` to say so explicitly. | ||
| ### PENDING_ASYNC_UNTRACKED_READ | ||
| Same shape as above but the value was a pending async computation, so there | ||
| is nothing to read yet at all. Async values must be read where tracking can | ||
| suspend and resume: JSX, a memo, or an effect's compute function. | ||
| ### PENDING_ASYNC_FORBIDDEN_SCOPE | ||
| A pending async value was read inside `createTrackedEffect` or `onSettled`, | ||
| which cannot suspend — it throws. Use `createEffect` (separate compute and | ||
| effect phases) which is async-aware: put the async read in the compute | ||
| function. | ||
| ## Write/imperative-code placement mistakes | ||
| ### REACTIVE_WRITE_IN_OWNED_SCOPE | ||
| A signal/store write (or `refresh()`) executed during an owned scope — a | ||
| component body or a computation. Pure scopes must not cause state changes. | ||
| Move the write to an event handler or effect phase. If the write is genuinely | ||
| intentional initialization, pass the `ownedWrite` option on the setter call. | ||
| ### ACTION_CALLED_IN_OWNED_SCOPE | ||
| An action was invoked during a component body or computation. Actions are | ||
| imperative entry points — call them from event handlers or other imperative | ||
| code. | ||
| ### FLUSH_IN_EFFECT_CALLBACK | ||
| `flush()` was called inside an effect callback, where it is a no-op (the | ||
| flush running effects is already in progress). Writes made there are handled | ||
| in the same flush's continuation. If you truly need a drain afterwards, | ||
| defer it: `queueMicrotask(() => flush())`. Usually the right fix is deleting | ||
| the call. | ||
| ## Ownership/lifecycle mistakes (leaks) | ||
| ### NO_OWNER_EFFECT / NO_OWNER_BOUNDARY | ||
| An effect or boundary was created outside any reactive context (no root, no | ||
| component). It will never be disposed — a leak. Create it under a component | ||
| or `createRoot`, or use `runWithOwner` to attach it to an existing owner. | ||
| ### NO_OWNER_CLEANUP | ||
| `onCleanup` was called outside a reactive context; the callback will never | ||
| run. Same fix: register it under an owner. | ||
| ### CLEANUP_IN_FORBIDDEN_SCOPE | ||
| `onCleanup` inside `createTrackedEffect` or `onSettled` is not supported — | ||
| return a cleanup function from the callback instead. | ||
| ### SETTLED_CLEANUP_UNOWNED | ||
| `onSettled` returned a cleanup while running in an unowned scope, so the | ||
| cleanup cannot be honored. Call the setup helper from an owned scope (the | ||
| component body), not from an event handler, tracked effect, or another | ||
| `onSettled`. | ||
| ### RUN_WITH_DISPOSED_OWNER | ||
| `runWithOwner` received an owner that was already disposed; anything created | ||
| inside leaks. This usually means a stale owner captured across an await or | ||
| stored past its lifetime — re-capture the owner at call time or guard with | ||
| `isDisposed()`. | ||
| ## API misuse | ||
| ### MISSING_EFFECT_FN | ||
| `createEffect(compute)` with a single argument is not supported. Split the | ||
| work: `createEffect(() => signal(), value => doWork(value))`. For a derived | ||
| value use `createMemo`; for a one-shot side effect just call the function. | ||
| ### PRIMITIVE_IN_FORBIDDEN_SCOPE | ||
| Reactive primitives cannot be created inside `createTrackedEffect` or | ||
| owner-backed `onSettled`. Hoist the primitive to the component body. | ||
| ### INVALID_REFRESH_TARGET | ||
| `refresh()` expects a Solid source accessor or refreshable store — not a | ||
| wrapper function or a derived property read. Pass the original source. | ||
| ### INVALID_AFFECTS_TARGET | ||
| `affects()` expects a Solid source accessor or store node, with at most one | ||
| optional key (keys only valid on store targets). Fix the target or drop the | ||
| extra keys. | ||
| ### SYNC_NODE_RECEIVED_ASYNC | ||
| A computed/effect created with `sync: true` returned a Promise or | ||
| AsyncIterable; the value would be stored as-is, never awaited, in | ||
| production. Remove `sync: true` to use async-aware behavior, or unwrap | ||
| before returning. | ||
| ## Hard failures | ||
| ### REACTIVITY_HALTED | ||
| An earlier uncaught error halted the reactive system; subsequent updates are | ||
| ignored. Do not treat this code as the bug — find the original error above | ||
| it (or add an error boundary via `createErrorBoundary`/`<Errored>`) and fix | ||
| that. | ||
| ### INVARIANT_VIOLATION | ||
| The reactive system contradicted itself — an internal bug, not user error. | ||
| Report it upstream with a reproduction; do not work around it silently. | ||
| ## Performance pathologies (from the attribution engine) | ||
| These fire only while attribution is enabled and describe cost, not | ||
| incorrect behavior. The numbers in the message are measurements, not | ||
| guesses. | ||
| ### HUGE_FAN_OUT / WIDE_WRITE | ||
| One value has very many subscribers, so a single change re-runs all of them. | ||
| Classic signature: every row of a list comparing against one selected id. | ||
| Invert the question with `createSelector` or a per-key store/projection so | ||
| only the keys whose answer flipped update. | ||
| ### HUGE_FAN_IN / WIDE_SCOPE_DEPS | ||
| One computation reads very many sources, so it re-runs when any of them | ||
| change. Narrow its reads or split it into smaller memos that each track only | ||
| what they need. The message lists the sources — start with those. | ||
| ### HOT_SCOPE_RERUNS | ||
| A scope re-ran far more often than any UI cadence justifies — a hot signal | ||
| (often per-frame or per-event) is leaking into it. The message names the | ||
| latest cause; either move that read out of the scope or derive a slower | ||
| value (e.g. a memo with an equality gate) between them. | ||
| ### HOT_SCOPE_TIME | ||
| A scope's summed compute time blew its per-window budget — a | ||
| few-but-expensive scope that run counts miss. Profile what it computes; | ||
| usually the fix is memoizing sub-derivations or moving work off the reactive | ||
| path. | ||
| ### UNSTABLE_MEMO_OUTPUT | ||
| A memo keeps producing referentially-new but shallowly-equivalent | ||
| objects/arrays, so its equality gate never closes and every subscriber | ||
| re-runs on every upstream change. Return stable references or pass an | ||
| `equals` option. | ||
| ## Verifying a fix | ||
| If you are working with `@solidjs/diagnostics`, re-run the capture after the | ||
| repair: the code should disappear from `artifact.diagnostics`, and for the | ||
| performance codes, `expectRerunBudget`/`expectNoWaste` should now pass. See | ||
| the `agent-loops` skill in `@solidjs/diagnostics` for the full loop. |
+56
-8
@@ -335,3 +335,24 @@ 'use strict'; | ||
| if (!isAsyncIterable(loaded)) return null; | ||
| const it = normalizeIterator(loaded[Symbol.asyncIterator](), hasLoadingWindow(options)); | ||
| const base = normalizeIterator(loaded[Symbol.asyncIterator](), hasLoadingWindow(options)); | ||
| let terminal = false; | ||
| const it = { | ||
| next() { | ||
| const p = base.next(); | ||
| return { | ||
| then(res, rej) { | ||
| return p.then(r => { | ||
| if (r.done) terminal = true; | ||
| return res(r); | ||
| }, e => { | ||
| terminal = true; | ||
| if (rej) return rej(e); | ||
| throw e; | ||
| }); | ||
| } | ||
| }; | ||
| }, | ||
| return(value) { | ||
| return base.return(value); | ||
| } | ||
| }; | ||
| const iterable = { | ||
@@ -343,2 +364,3 @@ [Symbol.asyncIterator]() { | ||
| return coreFn(prev => { | ||
| if (terminal) return compute(prev); | ||
| subFetch(compute, prev); | ||
@@ -358,3 +380,9 @@ return iterable; | ||
| let buffered = null; | ||
| let terminal = false; | ||
| const fail = e => { | ||
| terminal = true; | ||
| throw e; | ||
| }; | ||
| return coreFn(draft => { | ||
| if (terminal) return fn(draft); | ||
| const { | ||
@@ -365,6 +393,9 @@ proxy | ||
| const process = res => { | ||
| if (res.done) return { | ||
| done: true, | ||
| value: undefined | ||
| }; | ||
| if (res.done) { | ||
| terminal = true; | ||
| return { | ||
| done: true, | ||
| value: undefined | ||
| }; | ||
| } | ||
| if (isFirst) { | ||
@@ -402,3 +433,16 @@ isFirst = false; | ||
| then(fn, rej) { | ||
| r.then(v => fn(process(v)), rej); | ||
| r.then(v => { | ||
| let out; | ||
| try { | ||
| out = process(v); | ||
| } catch (e) { | ||
| terminal = true; | ||
| rej(e); | ||
| return; | ||
| } | ||
| fn(out); | ||
| }, e => { | ||
| terminal = true; | ||
| rej(e); | ||
| }); | ||
| } | ||
@@ -416,7 +460,7 @@ }; | ||
| buffered = null; | ||
| return b.then(process); | ||
| return b.then(process, fail); | ||
| } | ||
| let r = srcIt.next(); | ||
| if (r && typeof r.then === "function") { | ||
| return r.then(process); | ||
| return r.then(process, fail); | ||
| } | ||
@@ -1381,2 +1425,6 @@ return new Promise(resolvePull => { | ||
| }); | ||
| Object.defineProperty(exports, "resetErrorHalt", { | ||
| enumerable: true, | ||
| get: function () { return signals.resetErrorHalt; } | ||
| }); | ||
| Object.defineProperty(exports, "resolve", { | ||
@@ -1383,0 +1431,0 @@ enumerable: true, |
+53
-9
| import { getContext, createMemo as createMemo$1, flatten, createRoot, setContext, getOwner, untrack, createOwner, runWithOwner, createEffect as createEffect$1, createErrorBoundary as createErrorBoundary$1, createLoadingBoundary as createLoadingBoundary$1, createOptimistic as createOptimistic$1, createOptimisticStore as createOptimisticStore$1, createProjection as createProjection$1, createRenderEffect as createRenderEffect$1, createRevealOrder as createRevealOrder$1, createSignal as createSignal$1, createStore as createStore$1, setSnapshotCapture, releaseSnapshotScope, NotReadyError, peekNextChildId, getNextChildId, clearSnapshots, flush, markSnapshotScope, onCleanup, isDisposed, mapArray, repeat, DEV as DEV$1 } from '@solidjs/signals'; | ||
| export { $PROXY, $REFRESH, $TRACK, NotReadyError, action, affects, createOwner, createReaction, createRoot, createTrackedEffect, deep, enableExternalSource, enforceLoadingBoundary, flatten, flush, getNextChildId, getObserver, getOwner, isDisposed, isEqual, isPending, isWrappable, latest, mapArray, merge, omit, onCleanup, onSettled, reconcile, refresh, repeat, resolve, runWithOwner, snapshot, storePath, untrack } from '@solidjs/signals'; | ||
| export { $PROXY, $REFRESH, $TRACK, NotReadyError, action, affects, createOwner, createReaction, createRoot, createTrackedEffect, deep, enableExternalSource, enforceLoadingBoundary, flatten, flush, getNextChildId, getObserver, getOwner, isDisposed, isEqual, isPending, isWrappable, latest, mapArray, merge, omit, onCleanup, onSettled, reconcile, refresh, repeat, resetErrorHalt, resolve, runWithOwner, snapshot, storePath, untrack } from '@solidjs/signals'; | ||
@@ -334,3 +334,24 @@ const $DEVCOMP = Symbol("COMPONENT_DEV" ); | ||
| if (!isAsyncIterable(loaded)) return null; | ||
| const it = normalizeIterator(loaded[Symbol.asyncIterator](), hasLoadingWindow(options)); | ||
| const base = normalizeIterator(loaded[Symbol.asyncIterator](), hasLoadingWindow(options)); | ||
| let terminal = false; | ||
| const it = { | ||
| next() { | ||
| const p = base.next(); | ||
| return { | ||
| then(res, rej) { | ||
| return p.then(r => { | ||
| if (r.done) terminal = true; | ||
| return res(r); | ||
| }, e => { | ||
| terminal = true; | ||
| if (rej) return rej(e); | ||
| throw e; | ||
| }); | ||
| } | ||
| }; | ||
| }, | ||
| return(value) { | ||
| return base.return(value); | ||
| } | ||
| }; | ||
| const iterable = { | ||
@@ -342,2 +363,3 @@ [Symbol.asyncIterator]() { | ||
| return coreFn(prev => { | ||
| if (terminal) return compute(prev); | ||
| subFetch(compute, prev); | ||
@@ -357,3 +379,9 @@ return iterable; | ||
| let buffered = null; | ||
| let terminal = false; | ||
| const fail = e => { | ||
| terminal = true; | ||
| throw e; | ||
| }; | ||
| return coreFn(draft => { | ||
| if (terminal) return fn(draft); | ||
| const { | ||
@@ -364,6 +392,9 @@ proxy | ||
| const process = res => { | ||
| if (res.done) return { | ||
| done: true, | ||
| value: undefined | ||
| }; | ||
| if (res.done) { | ||
| terminal = true; | ||
| return { | ||
| done: true, | ||
| value: undefined | ||
| }; | ||
| } | ||
| if (isFirst) { | ||
@@ -401,3 +432,16 @@ isFirst = false; | ||
| then(fn, rej) { | ||
| r.then(v => fn(process(v)), rej); | ||
| r.then(v => { | ||
| let out; | ||
| try { | ||
| out = process(v); | ||
| } catch (e) { | ||
| terminal = true; | ||
| rej(e); | ||
| return; | ||
| } | ||
| fn(out); | ||
| }, e => { | ||
| terminal = true; | ||
| rej(e); | ||
| }); | ||
| } | ||
@@ -415,7 +459,7 @@ }; | ||
| buffered = null; | ||
| return b.then(process); | ||
| return b.then(process, fail); | ||
| } | ||
| let r = srcIt.next(); | ||
| if (r && typeof r.then === "function") { | ||
| return r.then(process); | ||
| return r.then(process, fail); | ||
| } | ||
@@ -422,0 +466,0 @@ return new Promise(resolvePull => { |
@@ -158,2 +158,3 @@ 'use strict'; | ||
| function patchRegistry(oldRegistry, newRegistry) { | ||
| solidJs.resetErrorHalt(); | ||
| return patchComponents(oldRegistry, newRegistry); | ||
@@ -160,0 +161,0 @@ } |
@@ -1,2 +0,2 @@ | ||
| import { createSignal, untrack, getOwner, onCleanup, $DEVCOMP, createMemo, DEV, sharedConfig } from 'solid-js'; | ||
| import { createSignal, untrack, getOwner, onCleanup, $DEVCOMP, createMemo, DEV, sharedConfig, resetErrorHalt } from 'solid-js'; | ||
@@ -156,2 +156,3 @@ function setComponentProperty(component, key, value) { | ||
| function patchRegistry(oldRegistry, newRegistry) { | ||
| resetErrorHalt(); | ||
| return patchComponents(oldRegistry, newRegistry); | ||
@@ -158,0 +159,0 @@ } |
+56
-8
@@ -315,3 +315,24 @@ 'use strict'; | ||
| if (!isAsyncIterable(loaded)) return null; | ||
| const it = normalizeIterator(loaded[Symbol.asyncIterator](), hasLoadingWindow(options)); | ||
| const base = normalizeIterator(loaded[Symbol.asyncIterator](), hasLoadingWindow(options)); | ||
| let terminal = false; | ||
| const it = { | ||
| next() { | ||
| const p = base.next(); | ||
| return { | ||
| then(res, rej) { | ||
| return p.then(r => { | ||
| if (r.done) terminal = true; | ||
| return res(r); | ||
| }, e => { | ||
| terminal = true; | ||
| if (rej) return rej(e); | ||
| throw e; | ||
| }); | ||
| } | ||
| }; | ||
| }, | ||
| return(value) { | ||
| return base.return(value); | ||
| } | ||
| }; | ||
| const iterable = { | ||
@@ -323,2 +344,3 @@ [Symbol.asyncIterator]() { | ||
| return coreFn(prev => { | ||
| if (terminal) return compute(prev); | ||
| subFetch(compute, prev); | ||
@@ -338,3 +360,9 @@ return iterable; | ||
| let buffered = null; | ||
| let terminal = false; | ||
| const fail = e => { | ||
| terminal = true; | ||
| throw e; | ||
| }; | ||
| return coreFn(draft => { | ||
| if (terminal) return fn(draft); | ||
| const { | ||
@@ -345,6 +373,9 @@ proxy | ||
| const process = res => { | ||
| if (res.done) return { | ||
| done: true, | ||
| value: undefined | ||
| }; | ||
| if (res.done) { | ||
| terminal = true; | ||
| return { | ||
| done: true, | ||
| value: undefined | ||
| }; | ||
| } | ||
| if (isFirst) { | ||
@@ -382,3 +413,16 @@ isFirst = false; | ||
| then(fn, rej) { | ||
| r.then(v => fn(process(v)), rej); | ||
| r.then(v => { | ||
| let out; | ||
| try { | ||
| out = process(v); | ||
| } catch (e) { | ||
| terminal = true; | ||
| rej(e); | ||
| return; | ||
| } | ||
| fn(out); | ||
| }, e => { | ||
| terminal = true; | ||
| rej(e); | ||
| }); | ||
| } | ||
@@ -396,7 +440,7 @@ }; | ||
| buffered = null; | ||
| return b.then(process); | ||
| return b.then(process, fail); | ||
| } | ||
| let r = srcIt.next(); | ||
| if (r && typeof r.then === "function") { | ||
| return r.then(process); | ||
| return r.then(process, fail); | ||
| } | ||
@@ -1342,2 +1386,6 @@ return new Promise(resolvePull => { | ||
| }); | ||
| Object.defineProperty(exports, "resetErrorHalt", { | ||
| enumerable: true, | ||
| get: function () { return signals.resetErrorHalt; } | ||
| }); | ||
| Object.defineProperty(exports, "resolve", { | ||
@@ -1344,0 +1392,0 @@ enumerable: true, |
+53
-9
| import { getContext, createMemo as createMemo$1, flatten, createRoot, setContext, createOwner, runWithOwner, createEffect as createEffect$1, createErrorBoundary as createErrorBoundary$1, createLoadingBoundary as createLoadingBoundary$1, createOptimistic as createOptimistic$1, createOptimisticStore as createOptimisticStore$1, createProjection as createProjection$1, createRenderEffect as createRenderEffect$1, createRevealOrder as createRevealOrder$1, createSignal as createSignal$1, createStore as createStore$1, setSnapshotCapture, releaseSnapshotScope, NotReadyError, getOwner, peekNextChildId, getNextChildId, clearSnapshots, flush, markSnapshotScope, onCleanup, isDisposed, untrack, mapArray, repeat } from '@solidjs/signals'; | ||
| export { $PROXY, $REFRESH, $TRACK, NotReadyError, action, affects, createOwner, createReaction, createRoot, createTrackedEffect, deep, enableExternalSource, enforceLoadingBoundary, flatten, flush, getNextChildId, getObserver, getOwner, isDisposed, isEqual, isPending, isWrappable, latest, mapArray, merge, omit, onCleanup, onSettled, reconcile, refresh, repeat, resolve, runWithOwner, snapshot, storePath, untrack } from '@solidjs/signals'; | ||
| export { $PROXY, $REFRESH, $TRACK, NotReadyError, action, affects, createOwner, createReaction, createRoot, createTrackedEffect, deep, enableExternalSource, enforceLoadingBoundary, flatten, flush, getNextChildId, getObserver, getOwner, isDisposed, isEqual, isPending, isWrappable, latest, mapArray, merge, omit, onCleanup, onSettled, reconcile, refresh, repeat, resetErrorHalt, resolve, runWithOwner, snapshot, storePath, untrack } from '@solidjs/signals'; | ||
@@ -314,3 +314,24 @@ const IS_DEV = false; | ||
| if (!isAsyncIterable(loaded)) return null; | ||
| const it = normalizeIterator(loaded[Symbol.asyncIterator](), hasLoadingWindow(options)); | ||
| const base = normalizeIterator(loaded[Symbol.asyncIterator](), hasLoadingWindow(options)); | ||
| let terminal = false; | ||
| const it = { | ||
| next() { | ||
| const p = base.next(); | ||
| return { | ||
| then(res, rej) { | ||
| return p.then(r => { | ||
| if (r.done) terminal = true; | ||
| return res(r); | ||
| }, e => { | ||
| terminal = true; | ||
| if (rej) return rej(e); | ||
| throw e; | ||
| }); | ||
| } | ||
| }; | ||
| }, | ||
| return(value) { | ||
| return base.return(value); | ||
| } | ||
| }; | ||
| const iterable = { | ||
@@ -322,2 +343,3 @@ [Symbol.asyncIterator]() { | ||
| return coreFn(prev => { | ||
| if (terminal) return compute(prev); | ||
| subFetch(compute, prev); | ||
@@ -337,3 +359,9 @@ return iterable; | ||
| let buffered = null; | ||
| let terminal = false; | ||
| const fail = e => { | ||
| terminal = true; | ||
| throw e; | ||
| }; | ||
| return coreFn(draft => { | ||
| if (terminal) return fn(draft); | ||
| const { | ||
@@ -344,6 +372,9 @@ proxy | ||
| const process = res => { | ||
| if (res.done) return { | ||
| done: true, | ||
| value: undefined | ||
| }; | ||
| if (res.done) { | ||
| terminal = true; | ||
| return { | ||
| done: true, | ||
| value: undefined | ||
| }; | ||
| } | ||
| if (isFirst) { | ||
@@ -381,3 +412,16 @@ isFirst = false; | ||
| then(fn, rej) { | ||
| r.then(v => fn(process(v)), rej); | ||
| r.then(v => { | ||
| let out; | ||
| try { | ||
| out = process(v); | ||
| } catch (e) { | ||
| terminal = true; | ||
| rej(e); | ||
| return; | ||
| } | ||
| fn(out); | ||
| }, e => { | ||
| terminal = true; | ||
| rej(e); | ||
| }); | ||
| } | ||
@@ -395,7 +439,7 @@ }; | ||
| buffered = null; | ||
| return b.then(process); | ||
| return b.then(process, fail); | ||
| } | ||
| let r = srcIt.next(); | ||
| if (r && typeof r.then === "function") { | ||
| return r.then(process); | ||
| return r.then(process, fail); | ||
| } | ||
@@ -402,0 +446,0 @@ return new Promise(resolvePull => { |
+17
-16
| { | ||
| "name": "solid-js", | ||
| "description": "Reactive JavaScript library for building user interfaces. Compiles JSX to real DOM with fine-grained signal-based updates — no virtual DOM.", | ||
| "version": "2.0.0-rc.2", | ||
| "version": "2.0.0-rc.3", | ||
| "author": "Ryan Carniato", | ||
@@ -25,3 +25,4 @@ "license": "MIT", | ||
| "package.json", | ||
| "CHEATSHEET.md" | ||
| "CHEATSHEET.md", | ||
| "skills" | ||
| ], | ||
@@ -122,2 +123,14 @@ "exports": { | ||
| }, | ||
| "scripts": { | ||
| "build": "npm-run-all -nl build:*", | ||
| "build:clean": "rimraf dist/ coverage/", | ||
| "build:js": "rollup -c", | ||
| "types": "npm-run-all -nl types:clean types:src types:cjs", | ||
| "types:clean": "rimraf types/ types-cjs/", | ||
| "types:src": "tsc --project ./tsconfig.build.json", | ||
| "types:cjs": "node ../../scripts/sync-dual-types.mjs ./types ./types-cjs", | ||
| "test": "vitest run", | ||
| "coverage": "vitest run --coverage", | ||
| "test-types": "tsc --project tsconfig.test.json && tsc --project tsconfig.no-dom.json" | ||
| }, | ||
| "keywords": [ | ||
@@ -133,19 +146,7 @@ "solid", | ||
| "dependencies": { | ||
| "@solidjs/signals": "^2.0.0-rc.2", | ||
| "@solidjs/signals": "^2.0.0-rc.3", | ||
| "csstype": "^3.1.0", | ||
| "seroval": "~1.5.4", | ||
| "seroval-plugins": "~1.5.4" | ||
| }, | ||
| "scripts": { | ||
| "build": "npm-run-all -nl build:*", | ||
| "build:clean": "rimraf dist/ coverage/", | ||
| "build:js": "rollup -c", | ||
| "types": "npm-run-all -nl types:clean types:src types:cjs", | ||
| "types:clean": "rimraf types/ types-cjs/", | ||
| "types:src": "tsc --project ./tsconfig.build.json", | ||
| "types:cjs": "node ../../scripts/sync-dual-types.mjs ./types ./types-cjs", | ||
| "test": "vitest run", | ||
| "coverage": "vitest run --coverage", | ||
| "test-types": "tsc --project tsconfig.test.json && tsc --project tsconfig.no-dom.json" | ||
| } | ||
| } | ||
| } |
+2
-2
@@ -44,6 +44,6 @@ <p> | ||
| npm i solid-js @solidjs/web | ||
| npm i -D babel-preset-solid | ||
| npm i -D @solidjs/babel-plugin | ||
| ``` | ||
| Add `babel-preset-solid` to your Babel config (or use Vite's Solid plugin), and set `tsconfig.json`: | ||
| Add `@solidjs/babel-plugin` to your Babel config (or use Vite's Solid plugin), and set `tsconfig.json`: | ||
@@ -50,0 +50,0 @@ ```json |
@@ -1,2 +0,2 @@ | ||
| export { $PROXY, $REFRESH, $TRACK, action, affects, createOwner, createReaction, createRoot, createTrackedEffect, deep, flatten, flush, getNextChildId, getObserver, getOwner, isDisposed, isEqual, isPending, isWrappable, mapArray, merge, omit, onCleanup, onSettled, latest, reconcile, refresh, repeat, resolve, NotReadyError, runWithOwner, enableExternalSource, enforceLoadingBoundary, snapshot, storePath, untrack } from "@solidjs/signals"; | ||
| export { $PROXY, $REFRESH, $TRACK, action, affects, createOwner, createReaction, createRoot, createTrackedEffect, deep, flatten, flush, getNextChildId, getObserver, getOwner, isDisposed, isEqual, isPending, isWrappable, mapArray, merge, omit, onCleanup, onSettled, latest, reconcile, refresh, repeat, resetErrorHalt, resolve, NotReadyError, runWithOwner, enableExternalSource, enforceLoadingBoundary, snapshot, storePath, untrack } from "@solidjs/signals"; | ||
| export type { Accessor, ComputeFunction, EffectBundle, EffectFunction, EffectOptions, ExternalSource, ExternalSourceConfig, ExternalSourceFactory, Merge, MemoOptions, NoInfer, NotWrappable, Omit, Owner, ProjectionOptions, Refreshable, Signal, SignalOptions, SourceAccessor, Setter, Store, StoreReturn, ProjectionStoreReturn, StoreOptions, SolidStore, StoreNode, StoreSetter, StorePathRange, ArrayFilterFn, CustomPartial, Part, PathSetter } from "@solidjs/signals"; | ||
@@ -3,0 +3,0 @@ export { $DEVCOMP, children, createContext, useContext } from "./client/core.cjs"; |
@@ -1,2 +0,2 @@ | ||
| export { $PROXY, $REFRESH, $TRACK, action, affects, createEffect, createMemo, createOptimistic, createOptimisticStore, createErrorBoundary, createOwner, creationStamp, createProjection, createReaction, createRenderEffect, createRevealOrder, createRoot, createSignal, createStore, createTrackedEffect, deep, flatten, flush, getNextChildId, getObserver, getOwner, isDisposed, isEqual, isPending, isWrappable, mapArray, merge, omit, onCleanup, onSettled, latest, reconcile, refresh, repeat, resolve, NotReadyError, runInServerComponentScope, inServerComponentScope, getProjectionTrace, runWithOwner, snapshot, storePath, createDeepProxy, enableExternalSource, enforceLoadingBoundary, untrack } from "./signals.cjs"; | ||
| export { $PROXY, $REFRESH, $TRACK, action, affects, createEffect, createMemo, createOptimistic, createOptimisticStore, createErrorBoundary, createOwner, creationStamp, createProjection, createReaction, createRenderEffect, createRevealOrder, createRoot, createSignal, createStore, createTrackedEffect, deep, flatten, flush, getNextChildId, getObserver, getOwner, isDisposed, isEqual, isPending, isWrappable, mapArray, merge, omit, onCleanup, onSettled, latest, reconcile, refresh, repeat, resetErrorHalt, resolve, NotReadyError, runInServerComponentScope, inServerComponentScope, getProjectionTrace, runWithOwner, snapshot, storePath, createDeepProxy, enableExternalSource, enforceLoadingBoundary, untrack } from "./signals.cjs"; | ||
| export type { Accessor, ComputeFunction, EffectFunction, EffectOptions, ExternalSource, ExternalSourceConfig, ExternalSourceFactory, Merge, NoInfer, NotWrappable, Omit, Owner, Refreshable, Signal, SignalOptions, Setter, Store, SolidStore, StoreNode, StoreSetter, StorePathRange, ArrayFilterFn, CustomPartial, Part, PathSetter, PatchOp } from "./signals.cjs"; | ||
@@ -3,0 +3,0 @@ export { $DEVCOMP, children, createContext, useContext } from "./core.cjs"; |
@@ -50,3 +50,3 @@ import type { Context } from "./signals.cjs"; | ||
| * Resolve a module's JS and CSS assets from the asset manifest. Set by | ||
| * dom-expressions. Resolver manifests (dev servers answering from a live | ||
| * the @solidjs/web server renderer. Resolver manifests (dev servers answering from a live | ||
| * module graph) may return a promise and may resolve css entries to | ||
@@ -57,3 +57,3 @@ * inline-style descriptors instead of URLs. | ||
| /** | ||
| * Synchronous resolution fast path. Set by dom-expressions for object | ||
| * Synchronous resolution fast path. Set by @solidjs/web for object | ||
| * manifests (sync by nature) and for resolver manifests providing | ||
@@ -65,3 +65,3 @@ * `resolveSync`; used by sync consumers like lazy's moduleUrl getter. | ||
| getBoundaryModules?: (id: string) => Record<string, string> | null; | ||
| /** @internal Tracks which Loading boundary is currently rendering. Set by dom-expressions via applyAssetTracking(). */ | ||
| /** @internal Tracks which Loading boundary is currently rendering. Set by @solidjs/web via applyAssetTracking(). */ | ||
| _currentBoundaryId?: string | null; | ||
@@ -71,3 +71,3 @@ /** | ||
| * (boundary retries, flush passes), where nothing is on the stack to catch | ||
| * a throw. Set by dom-expressions' renderToStream: reports through the | ||
| * a throw. Set by @solidjs/web's renderToStream: reports through the | ||
| * render's onError and winds the render down — the request fails, the | ||
@@ -89,3 +89,3 @@ * process survives. | ||
| * `runWithBoundaryErrorContext` when a boundaryId is passed; read by | ||
| * dom-expressions' head registry to escalate pending head-tag props into a | ||
| * @solidjs/web's head registry to escalate pending head-tag props into a | ||
| * boundary suspension instead of a flush-time warn-and-drop. | ||
@@ -116,3 +116,3 @@ */ | ||
| * trace) — keeps the response open until it completes. Set by | ||
| * dom-expressions' render core; holds gate only the end of the response. | ||
| * @solidjs/web's render core; holds gate only the end of the response. | ||
| */ | ||
@@ -119,0 +119,0 @@ hold?: () => () => void; |
@@ -144,3 +144,10 @@ import { $REFRESH } from "@solidjs/signals"; | ||
| }): [get: Store<T>, set: StoreSetter<T>]; | ||
| export declare const createOptimisticStore: typeof createStore; | ||
| export declare function createOptimisticStore<T extends object>(store: T | Store<T>, options?: { | ||
| name?: string; | ||
| shallow?: boolean; | ||
| }): [get: Store<T>, set: StoreSetter<T>]; | ||
| export declare function createOptimisticStore<T extends object>(fn: (store: T) => void | T | Promise<void | T>, store: Partial<T> | Store<T>, options?: ServerStoreOptions & { | ||
| name?: string; | ||
| shallow?: boolean; | ||
| }): [get: Store<T>, set: StoreSetter<T>]; | ||
| export interface ProjectionTrace { | ||
@@ -268,2 +275,3 @@ /** An independent consumer: snapshot at subscribe, then every batch after. */ | ||
| export declare function flush(): void; | ||
| export declare function resetErrorHalt(): void; | ||
| export declare function resolve<T>(fn: () => T): Promise<T>; | ||
@@ -270,0 +278,0 @@ export declare function isPending(fn: () => any): boolean; |
+1
-1
@@ -1,2 +0,2 @@ | ||
| export { $PROXY, $REFRESH, $TRACK, action, affects, createOwner, createReaction, createRoot, createTrackedEffect, deep, flatten, flush, getNextChildId, getObserver, getOwner, isDisposed, isEqual, isPending, isWrappable, mapArray, merge, omit, onCleanup, onSettled, latest, reconcile, refresh, repeat, resolve, NotReadyError, runWithOwner, enableExternalSource, enforceLoadingBoundary, snapshot, storePath, untrack } from "@solidjs/signals"; | ||
| export { $PROXY, $REFRESH, $TRACK, action, affects, createOwner, createReaction, createRoot, createTrackedEffect, deep, flatten, flush, getNextChildId, getObserver, getOwner, isDisposed, isEqual, isPending, isWrappable, mapArray, merge, omit, onCleanup, onSettled, latest, reconcile, refresh, repeat, resetErrorHalt, resolve, NotReadyError, runWithOwner, enableExternalSource, enforceLoadingBoundary, snapshot, storePath, untrack } from "@solidjs/signals"; | ||
| export type { Accessor, ComputeFunction, EffectBundle, EffectFunction, EffectOptions, ExternalSource, ExternalSourceConfig, ExternalSourceFactory, Merge, MemoOptions, NoInfer, NotWrappable, Omit, Owner, ProjectionOptions, Refreshable, Signal, SignalOptions, SourceAccessor, Setter, Store, StoreReturn, ProjectionStoreReturn, StoreOptions, SolidStore, StoreNode, StoreSetter, StorePathRange, ArrayFilterFn, CustomPartial, Part, PathSetter } from "@solidjs/signals"; | ||
@@ -3,0 +3,0 @@ export { $DEVCOMP, children, createContext, useContext } from "./client/core.js"; |
@@ -1,2 +0,2 @@ | ||
| export { $PROXY, $REFRESH, $TRACK, action, affects, createEffect, createMemo, createOptimistic, createOptimisticStore, createErrorBoundary, createOwner, creationStamp, createProjection, createReaction, createRenderEffect, createRevealOrder, createRoot, createSignal, createStore, createTrackedEffect, deep, flatten, flush, getNextChildId, getObserver, getOwner, isDisposed, isEqual, isPending, isWrappable, mapArray, merge, omit, onCleanup, onSettled, latest, reconcile, refresh, repeat, resolve, NotReadyError, runInServerComponentScope, inServerComponentScope, getProjectionTrace, runWithOwner, snapshot, storePath, createDeepProxy, enableExternalSource, enforceLoadingBoundary, untrack } from "./signals.js"; | ||
| export { $PROXY, $REFRESH, $TRACK, action, affects, createEffect, createMemo, createOptimistic, createOptimisticStore, createErrorBoundary, createOwner, creationStamp, createProjection, createReaction, createRenderEffect, createRevealOrder, createRoot, createSignal, createStore, createTrackedEffect, deep, flatten, flush, getNextChildId, getObserver, getOwner, isDisposed, isEqual, isPending, isWrappable, mapArray, merge, omit, onCleanup, onSettled, latest, reconcile, refresh, repeat, resetErrorHalt, resolve, NotReadyError, runInServerComponentScope, inServerComponentScope, getProjectionTrace, runWithOwner, snapshot, storePath, createDeepProxy, enableExternalSource, enforceLoadingBoundary, untrack } from "./signals.js"; | ||
| export type { Accessor, ComputeFunction, EffectFunction, EffectOptions, ExternalSource, ExternalSourceConfig, ExternalSourceFactory, Merge, NoInfer, NotWrappable, Omit, Owner, Refreshable, Signal, SignalOptions, Setter, Store, SolidStore, StoreNode, StoreSetter, StorePathRange, ArrayFilterFn, CustomPartial, Part, PathSetter, PatchOp } from "./signals.js"; | ||
@@ -3,0 +3,0 @@ export { $DEVCOMP, children, createContext, useContext } from "./core.js"; |
@@ -50,3 +50,3 @@ import type { Context } from "./signals.js"; | ||
| * Resolve a module's JS and CSS assets from the asset manifest. Set by | ||
| * dom-expressions. Resolver manifests (dev servers answering from a live | ||
| * the @solidjs/web server renderer. Resolver manifests (dev servers answering from a live | ||
| * module graph) may return a promise and may resolve css entries to | ||
@@ -57,3 +57,3 @@ * inline-style descriptors instead of URLs. | ||
| /** | ||
| * Synchronous resolution fast path. Set by dom-expressions for object | ||
| * Synchronous resolution fast path. Set by @solidjs/web for object | ||
| * manifests (sync by nature) and for resolver manifests providing | ||
@@ -65,3 +65,3 @@ * `resolveSync`; used by sync consumers like lazy's moduleUrl getter. | ||
| getBoundaryModules?: (id: string) => Record<string, string> | null; | ||
| /** @internal Tracks which Loading boundary is currently rendering. Set by dom-expressions via applyAssetTracking(). */ | ||
| /** @internal Tracks which Loading boundary is currently rendering. Set by @solidjs/web via applyAssetTracking(). */ | ||
| _currentBoundaryId?: string | null; | ||
@@ -71,3 +71,3 @@ /** | ||
| * (boundary retries, flush passes), where nothing is on the stack to catch | ||
| * a throw. Set by dom-expressions' renderToStream: reports through the | ||
| * a throw. Set by @solidjs/web's renderToStream: reports through the | ||
| * render's onError and winds the render down — the request fails, the | ||
@@ -89,3 +89,3 @@ * process survives. | ||
| * `runWithBoundaryErrorContext` when a boundaryId is passed; read by | ||
| * dom-expressions' head registry to escalate pending head-tag props into a | ||
| * @solidjs/web's head registry to escalate pending head-tag props into a | ||
| * boundary suspension instead of a flush-time warn-and-drop. | ||
@@ -116,3 +116,3 @@ */ | ||
| * trace) — keeps the response open until it completes. Set by | ||
| * dom-expressions' render core; holds gate only the end of the response. | ||
| * @solidjs/web's render core; holds gate only the end of the response. | ||
| */ | ||
@@ -119,0 +119,0 @@ hold?: () => () => void; |
@@ -144,3 +144,10 @@ import { $REFRESH } from "@solidjs/signals"; | ||
| }): [get: Store<T>, set: StoreSetter<T>]; | ||
| export declare const createOptimisticStore: typeof createStore; | ||
| export declare function createOptimisticStore<T extends object>(store: T | Store<T>, options?: { | ||
| name?: string; | ||
| shallow?: boolean; | ||
| }): [get: Store<T>, set: StoreSetter<T>]; | ||
| export declare function createOptimisticStore<T extends object>(fn: (store: T) => void | T | Promise<void | T>, store: Partial<T> | Store<T>, options?: ServerStoreOptions & { | ||
| name?: string; | ||
| shallow?: boolean; | ||
| }): [get: Store<T>, set: StoreSetter<T>]; | ||
| export interface ProjectionTrace { | ||
@@ -268,2 +275,3 @@ /** An independent consumer: snapshot at subscribe, then every batch after. */ | ||
| export declare function flush(): void; | ||
| export declare function resetErrorHalt(): void; | ||
| export declare function resolve<T>(fn: () => T): Promise<T>; | ||
@@ -270,0 +278,0 @@ export declare function isPending(fn: () => any): boolean; |
-21
| MIT License | ||
| Copyright (c) 2016-2025 Ryan Carniato | ||
| Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| of this software and associated documentation files (the "Software"), to deal | ||
| in the Software without restriction, including without limitation the rights | ||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| copies of the Software, and to permit persons to whom the Software is | ||
| furnished to do so, subject to the following conditions: | ||
| The above copyright notice and this permission notice shall be included in all | ||
| copies or substantial portions of the Software. | ||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| SOFTWARE. |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
555790
2.84%12530
2.18%Updated