@askrjs/askr 0.0.37 → 0.0.38
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/dist/bench/components/benchmark-table.js +1 -1
- package/dist/benchmark.js +2 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/runtime/state.d.ts +12 -4
- package/dist/runtime/state.d.ts.map +1 -1
- package/dist/runtime/state.js +1 -1
- package/dist/runtime/state.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx } from "../../jsx-runtime.js";
|
|
2
|
-
import "../../jsx-runtime2.js";
|
|
3
2
|
import { For } from "../../control/for.js";
|
|
4
3
|
import "../../control/index.js";
|
|
4
|
+
import "../../jsx-runtime2.js";
|
|
5
5
|
import { BenchmarkRow } from "./benchmark-row.js";
|
|
6
6
|
//#region src/bench/components/benchmark-table.tsx
|
|
7
7
|
function BenchmarkTable({ rows, isSelected, onSelect, onRemove }) {
|
package/dist/benchmark.js
CHANGED
|
@@ -10,8 +10,8 @@ import { BenchmarkTable } from "./bench/components/benchmark-table.js";
|
|
|
10
10
|
installRendererBridge();
|
|
11
11
|
const benchmarkMetadata = {
|
|
12
12
|
packageName: "@askrjs/askr",
|
|
13
|
-
packageVersion: "0.0.
|
|
14
|
-
buildLabel: "0.0.
|
|
13
|
+
packageVersion: "0.0.38",
|
|
14
|
+
buildLabel: "0.0.38-local"
|
|
15
15
|
};
|
|
16
16
|
function getBenchmarkMetadata() {
|
|
17
17
|
return { ...benchmarkMetadata };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { Props } from "./common/props.js";
|
|
2
2
|
import { Fragment } from "./common/jsx.js";
|
|
3
|
-
import { State, state } from "./runtime/state.js";
|
|
3
|
+
import { State, StateSetter, StateTuple, state } from "./runtime/state.js";
|
|
4
4
|
import { Context, defineContext, readContext } from "./runtime/context.js";
|
|
5
5
|
import { getSignal } from "./runtime/component.js";
|
|
6
|
+
import { For, ForProps } from "./control/for.js";
|
|
7
|
+
import { Show, ShowProps } from "./control/show.js";
|
|
8
|
+
import { Case, CaseProps, Match, MatchProps } from "./control/case.js";
|
|
6
9
|
import { Derived, derive } from "./runtime/derive.js";
|
|
7
10
|
import { Selector, selector } from "./runtime/selector.js";
|
|
8
11
|
import { jsx, jsxs } from "./jsx-runtime.js";
|
|
9
|
-
export { type Context, type Derived, Fragment, type Props, type Selector, type State, defineContext, derive, getSignal, jsx, jsxs, readContext, selector, state };
|
|
12
|
+
export { Case, type CaseProps, type Context, type Derived, For, type ForProps, Fragment, Match, type MatchProps, type Props, type Selector, Show, type ShowProps, type State, type StateSetter, type StateTuple, defineContext, derive, getSignal, jsx, jsxs, readContext, selector, state };
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,10 @@ import { installRendererBridge } from "./renderer/index.js";
|
|
|
6
6
|
import { state } from "./runtime/state.js";
|
|
7
7
|
import { derive } from "./runtime/derive.js";
|
|
8
8
|
import { selector } from "./runtime/selector.js";
|
|
9
|
+
import { For } from "./control/for.js";
|
|
10
|
+
import { Show } from "./control/show.js";
|
|
11
|
+
import { Case, Match } from "./control/case.js";
|
|
12
|
+
import "./control/index.js";
|
|
9
13
|
import "./jsx-runtime2.js";
|
|
10
14
|
//#region src/index.ts
|
|
11
15
|
/**
|
|
@@ -15,6 +19,6 @@ import "./jsx-runtime2.js";
|
|
|
15
19
|
*/
|
|
16
20
|
installRendererBridge();
|
|
17
21
|
//#endregion
|
|
18
|
-
export { Fragment, defineContext, derive, getSignal, jsx, jsxs, readContext, selector, state };
|
|
22
|
+
export { Case, For, Fragment, Match, Show, defineContext, derive, getSignal, jsx, jsxs, readContext, selector, state };
|
|
19
23
|
|
|
20
24
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * Askr: Actor-backed deterministic UI framework\n *\n * Public API surface — only users should import from here\n */\n\nimport { installRendererBridge } from './renderer';\n\ninstallRendererBridge();\n\n// Runtime primitives\nexport { state } from './runtime/state';\nexport type { State } from './runtime/state';\nexport { derive } from './runtime/derive';\nexport type { Derived } from './runtime/derive';\nexport { getSignal } from './runtime/component';\nexport { selector } from './runtime/selector';\nexport type { Selector } from './runtime/selector';\n\n// Context\nexport { defineContext, readContext } from './runtime/context';\nexport type { Context } from './runtime/context';\n\n// Re-export JSX runtime for tsconfig jsxImportSource\nexport { jsx, jsxs, Fragment } from './jsx-runtime';\n\n// Public types\nexport type { Props } from './common/props';\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["/**\n * Askr: Actor-backed deterministic UI framework\n *\n * Public API surface — only users should import from here\n */\n\nimport { installRendererBridge } from './renderer';\n\ninstallRendererBridge();\n\n// Runtime primitives\nexport { state } from './runtime/state';\nexport type { State, StateSetter, StateTuple } from './runtime/state';\nexport { derive } from './runtime/derive';\nexport type { Derived } from './runtime/derive';\nexport { getSignal } from './runtime/component';\nexport { selector } from './runtime/selector';\nexport type { Selector } from './runtime/selector';\n\n// Control flow\nexport { Case, For, Match, Show } from './control';\nexport type { CaseProps, ForProps, MatchProps, ShowProps } from './control';\n\n// Context\nexport { defineContext, readContext } from './runtime/context';\nexport type { Context } from './runtime/context';\n\n// Re-export JSX runtime for tsconfig jsxImportSource\nexport { jsx, jsxs, Fragment } from './jsx-runtime';\n\n// Public types\nexport type { Props } from './common/props';\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAQA,uBAAuB"}
|
package/dist/runtime/state.d.ts
CHANGED
|
@@ -12,8 +12,16 @@ interface State<T> extends ReadableSource<T> {
|
|
|
12
12
|
(): T;
|
|
13
13
|
set(value: T): void;
|
|
14
14
|
set(updater: (prev: T) => T): void;
|
|
15
|
-
[Symbol.iterator]():
|
|
15
|
+
[Symbol.iterator](): IterableIterator<StateTuple<T>[number]>;
|
|
16
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Public setter type for state cells.
|
|
19
|
+
*/
|
|
20
|
+
type StateSetter<T> = State<T>['set'];
|
|
21
|
+
/**
|
|
22
|
+
* Tuple-first state handle returned by `state()`.
|
|
23
|
+
*/
|
|
24
|
+
type StateTuple<T> = [get: State<T>, set: StateSetter<T>] & State<T>;
|
|
17
25
|
/**
|
|
18
26
|
* Creates a local state value for a component
|
|
19
27
|
* Optimized for:
|
|
@@ -29,7 +37,7 @@ interface State<T> extends ReadableSource<T> {
|
|
|
29
37
|
* ```ts
|
|
30
38
|
* // ✅ Correct: called during render
|
|
31
39
|
* export function Counter() {
|
|
32
|
-
* const count = state(0);
|
|
40
|
+
* const [count, setCount] = state(0);
|
|
33
41
|
* return { type: 'button', children: [count()] };
|
|
34
42
|
* }
|
|
35
43
|
*
|
|
@@ -40,7 +48,7 @@ interface State<T> extends ReadableSource<T> {
|
|
|
40
48
|
* }
|
|
41
49
|
* ```
|
|
42
50
|
*/
|
|
43
|
-
declare function state<T>(initialValue: T):
|
|
51
|
+
declare function state<T>(initialValue: T): StateTuple<T>;
|
|
44
52
|
//#endregion
|
|
45
|
-
export { State, state };
|
|
53
|
+
export { State, StateSetter, StateTuple, state };
|
|
46
54
|
//# sourceMappingURL=state.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.d.ts","names":[],"sources":["../../src/runtime/state.ts"],"mappings":";;;;;;;;;;UAkCiB,KAAA,YAAiB,cAAA,CAAe,CAAA;EAAA,IAC3C,CAAA;EACJ,GAAA,CAAI,KAAA,EAAO,CAAA;EACX,GAAA,CAAI,OAAA,GAAU,IAAA,EAAM,CAAA,KAAM,CAAA;EAAA,CACzB,MAAA,CAAO,QAAP,KAAoB,
|
|
1
|
+
{"version":3,"file":"state.d.ts","names":[],"sources":["../../src/runtime/state.ts"],"mappings":";;;;;;;;;;UAkCiB,KAAA,YAAiB,cAAA,CAAe,CAAA;EAAA,IAC3C,CAAA;EACJ,GAAA,CAAI,KAAA,EAAO,CAAA;EACX,GAAA,CAAI,OAAA,GAAU,IAAA,EAAM,CAAA,KAAM,CAAA;EAAA,CACzB,MAAA,CAAO,QAAP,KAAoB,gBAAA,CAAiB,UAAA,CAAW,CAAA;AAAA;;;;KAMvC,WAAA,MAAiB,KAAA,CAAM,CAAA;;;;KAKvB,UAAA,OAAiB,GAAA,EAAK,KAAA,CAAM,CAAA,GAAI,GAAA,EAAK,WAAA,CAAY,CAAA,KAAM,KAAA,CAAM,CAAA;;;;AALzE;;;;;;;;;AAKA;;;;;;;;;;;;;;iBA4BgB,KAAA,GAAA,CAAS,YAAA,EAAc,CAAA,GAAI,UAAA,CAAW,CAAA"}
|
package/dist/runtime/state.js
CHANGED
|
@@ -29,7 +29,7 @@ import { claimHookIndex, getCurrentInstance } from "./component.js";
|
|
|
29
29
|
* ```ts
|
|
30
30
|
* // ✅ Correct: called during render
|
|
31
31
|
* export function Counter() {
|
|
32
|
-
* const count = state(0);
|
|
32
|
+
* const [count, setCount] = state(0);
|
|
33
33
|
* return { type: 'button', children: [count()] };
|
|
34
34
|
* }
|
|
35
35
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"state.js","names":[],"sources":["../../src/runtime/state.ts"],"sourcesContent":["/**\n * State primitive for Askr components\n * Optimized for minimal overhead and fast updates\n *\n * INVARIANTS ENFORCED:\n * - state() only callable during component render (currentInstance exists)\n * - state() called at top-level only (indices must be monotonically increasing)\n * - state values persist across re-renders (stored in stateValues array)\n * - state.set() cannot be called during render (causes infinite loops)\n * - state.set() always enqueues through scheduler (never direct mutation)\n * - state.set() callback (notifyUpdate) always available\n */\n\nimport {\n claimHookIndex,\n getCurrentInstance,\n type ComponentInstance,\n} from './component';\nimport { isBulkCommitActive } from './fastlane';\nimport {\n recordReadableRead,\n type ReadableSource,\n markReadableDerivedSubscribersDirty,\n markReactivePropsDirtySource,\n notifyReadableReaders,\n} from './readable';\n\n/**\n * State value holder - callable to read, has set method to update\n * @example\n * const count = state(0);\n * count(); // read: 0\n * count.set(1); // write: triggers re-render\n */\nexport interface State<T> extends ReadableSource<T> {\n (): T;\n set(value: T): void;\n set(updater: (prev: T) => T): void;\n [Symbol.iterator]():
|
|
1
|
+
{"version":3,"file":"state.js","names":[],"sources":["../../src/runtime/state.ts"],"sourcesContent":["/**\n * State primitive for Askr components\n * Optimized for minimal overhead and fast updates\n *\n * INVARIANTS ENFORCED:\n * - state() only callable during component render (currentInstance exists)\n * - state() called at top-level only (indices must be monotonically increasing)\n * - state values persist across re-renders (stored in stateValues array)\n * - state.set() cannot be called during render (causes infinite loops)\n * - state.set() always enqueues through scheduler (never direct mutation)\n * - state.set() callback (notifyUpdate) always available\n */\n\nimport {\n claimHookIndex,\n getCurrentInstance,\n type ComponentInstance,\n} from './component';\nimport { isBulkCommitActive } from './fastlane';\nimport {\n recordReadableRead,\n type ReadableSource,\n markReadableDerivedSubscribersDirty,\n markReactivePropsDirtySource,\n notifyReadableReaders,\n} from './readable';\n\n/**\n * State value holder - callable to read, has set method to update\n * @example\n * const count = state(0);\n * count(); // read: 0\n * count.set(1); // write: triggers re-render\n */\nexport interface State<T> extends ReadableSource<T> {\n (): T;\n set(value: T): void;\n set(updater: (prev: T) => T): void;\n [Symbol.iterator](): IterableIterator<StateTuple<T>[number]>; // Allows destructuring: const [get, set] = state(0)\n}\n\n/**\n * Public setter type for state cells.\n */\nexport type StateSetter<T> = State<T>['set'];\n\n/**\n * Tuple-first state handle returned by `state()`.\n */\nexport type StateTuple<T> = [get: State<T>, set: StateSetter<T>] & State<T>;\n\n/**\n * Creates a local state value for a component\n * Optimized for:\n * - O(1) read performance\n * - Minimal allocation per state\n * - Fast scheduler integration\n *\n * IMPORTANT: state() must be called during component render execution.\n * It captures the current component instance from context.\n * Calling outside a component function will throw an error.\n *\n * @example\n * ```ts\n * // ✅ Correct: called during render\n * export function Counter() {\n * const [count, setCount] = state(0);\n * return { type: 'button', children: [count()] };\n * }\n *\n * // ❌ Wrong: called outside component\n * const count = state(0);\n * export function BadComponent() {\n * return { type: 'div' };\n * }\n * ```\n */\nexport function state<T>(initialValue: T): StateTuple<T> {\n // INVARIANT: state() must be called during component render\n const instance = getCurrentInstance();\n if (!instance) {\n throw new Error(\n 'state() can only be called during component render execution. ' +\n 'Move state() calls to the top level of your component function.'\n );\n }\n\n const index = claimHookIndex(instance, 'state');\n const stateValues = instance.stateValues;\n\n // INVARIANT: Reuse existing state if it exists (fast path on re-renders)\n // This ensures state identity and persistence and enforces ownership stability\n if (stateValues[index]) {\n const existing = stateValues[index] as State<T> & {\n _owner?: ComponentInstance;\n };\n // Ownership must be stable: the state cell belongs to the instance that\n // created it and must never change. This checks for accidental reuse.\n if (existing._owner !== instance) {\n throw new Error(\n `State ownership violation: state() called at index ${index} is owned by a different component instance. ` +\n `State ownership is positional and immutable.`\n );\n }\n return existing as StateTuple<T>;\n }\n\n // Create new state (slow path, only on first render) — delegated to helper\n const cell = createStateCell(initialValue, instance);\n\n // INVARIANT: Store state in instance for persistence across renders\n stateValues[index] = cell;\n\n return cell as StateTuple<T>;\n}\n\n/**\n * Internal helper: create the backing state cell (value + readers + set semantics)\n * This extraction makes it easier to later split hook wiring from storage.\n */\nfunction createStateCell<T>(\n initialValue: T,\n instance: ComponentInstance\n): State<T> {\n let value = initialValue;\n\n // Per-state reader map: component -> last-committed render token\n const readers = new Map<ComponentInstance, number>();\n\n // Use a function as the state object (callable directly)\n function read(): T {\n (read as State<T>)._hasBeenRead = true;\n recordReadableRead(read as State<T>);\n\n return value;\n }\n\n // Attach the readers map to the callable so other runtime parts can access it\n (read as State<T>)._readers = readers;\n\n // Record explicit ownership of this state cell. Ownership is the component\n // instance that created the state cell and must never change for the life\n // of the cell. We expose this for runtime invariant checks/tests.\n (read as State<T> & { _owner?: ComponentInstance })._owner = instance;\n\n // Attach set method directly to function\n read.set = (newValueOrUpdater: T | ((prev: T) => T)): void => {\n // INVARIANT: State cannot be mutated during component render\n // (when currentInstance is non-null). It must be scheduled for consistency.\n const currentInst = getCurrentInstance();\n if (currentInst !== null) {\n throw new Error(\n `[Askr] state.set() cannot be called during component render. ` +\n `State mutations during render break the actor model and cause infinite loops. ` +\n `Move state updates to event handlers or use conditional rendering instead.`\n );\n }\n\n // Compute new value if an updater was provided\n let newValue: T;\n if (typeof newValueOrUpdater === 'function') {\n // Note: function-valued state cannot be set directly via a function argument;\n // such an argument is treated as a functional updater (this follows the common\n // convention from other libraries). If you need to store a function as state,\n // wrap it in an object.\n const updater = newValueOrUpdater as (prev: T) => T;\n newValue = updater(value);\n } else {\n newValue = newValueOrUpdater as T;\n }\n\n // Skip work if value didn't change\n if (Object.is(value, newValue)) return;\n\n // If a bulk commit is active, update backing value only and DO NOT notify or enqueue.\n // Bulk commits must be side-effect silent with respect to runtime notifications.\n if (isBulkCommitActive()) {\n // In bulk commit mode we must be side-effect free: update backing\n // value only and do not notify, enqueue, or log.\n value = newValue;\n return;\n }\n\n // INVARIANT: Update the value\n value = newValue;\n\n markReadableDerivedSubscribersDirty(read as State<T>);\n markReactivePropsDirtySource(read as State<T>);\n\n // notifyUpdate may be temporarily unavailable (e.g. during hydration).\n // We intentionally avoid logging here to keep the state mutation path\n // side-effect free. The scheduler will process updates when the system\n // is stable.\n // After value change, notify only components that *read* this state in their last committed render.\n void notifyReadableReaders(read as State<T>);\n };\n\n // Allow destructuring assignment: const [get, set] = state(0);\n // The state function is iterable and yields the getter then the setter\n (\n read as unknown as {\n [Symbol.iterator]?: () => Iterator<State<T> | State<T>['set']>;\n }\n )[Symbol.iterator] = function* (): Generator<\n State<T> | State<T>['set'],\n void,\n unknown\n > {\n yield read;\n yield read.set;\n };\n\n return read as State<T>;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6EA,SAAgB,MAAS,cAAgC;CAEvD,MAAM,WAAW,oBAAoB;CACrC,IAAI,CAAC,UACH,MAAM,IAAI,MACR,gIAED;CAGH,MAAM,QAAQ,eAAe,UAAU,QAAQ;CAC/C,MAAM,cAAc,SAAS;CAI7B,IAAI,YAAY,QAAQ;EACtB,MAAM,WAAW,YAAY;EAK7B,IAAI,SAAS,WAAW,UACtB,MAAM,IAAI,MACR,sDAAsD,MAAM,2FAE7D;EAEH,OAAO;;CAIT,MAAM,OAAO,gBAAgB,cAAc,SAAS;CAGpD,YAAY,SAAS;CAErB,OAAO;;;;;;AAOT,SAAS,gBACP,cACA,UACU;CACV,IAAI,QAAQ;CAGZ,MAAM,0BAAU,IAAI,KAAgC;CAGpD,SAAS,OAAU;EACjB,KAAmB,eAAe;EAClC,mBAAmB,KAAiB;EAEpC,OAAO;;CAIT,KAAmB,WAAW;CAK9B,KAAoD,SAAS;CAG7D,KAAK,OAAO,sBAAkD;EAI5D,IADoB,oBAChB,KAAgB,MAClB,MAAM,IAAI,MACR,wNAGD;EAIH,IAAI;EACJ,IAAI,OAAO,sBAAsB,YAM/B,WAAW,kBAAQ,MAAM;OAEzB,WAAW;EAIb,IAAI,OAAO,GAAG,OAAO,SAAS,EAAE;EAIhC,IAAI,oBAAoB,EAAE;GAGxB,QAAQ;GACR;;EAIF,QAAQ;EAER,oCAAoC,KAAiB;EACrD,6BAA6B,KAAiB;EAO9C,AAAK,sBAAsB,KAAiB;;CAK9C,KAIE,OAAO,YAAY,aAInB;EACA,MAAM;EACN,MAAM,KAAK;;CAGb,OAAO"}
|