@wcstack/state 4.0.0-rc.7 → 4.0.0-rc.8
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/README.ja.md +28 -33
- package/README.md +28 -33
- package/dist/auto.min.js +2 -1
- package/dist/auto.min.js.map +1 -0
- package/dist/index.esm.js +2 -1
- package/dist/index.esm.js.map +1 -0
- package/dist/split/auto.js +2 -1
- package/dist/split/auto.js.map +1 -0
- package/dist/split/chunks/{chunk-V34ZHCK5.js → chunk-4NJBYXIT.js} +2 -1
- package/dist/split/chunks/chunk-4NJBYXIT.js.map +1 -0
- package/dist/split/chunks/{chunk-JMPQHCIT.js → chunk-55J45X6H.js} +2 -1
- package/dist/split/chunks/chunk-55J45X6H.js.map +1 -0
- package/dist/split/chunks/{chunk-LTBR3OV5.js → chunk-7AYOQHZH.js} +2 -1
- package/dist/split/chunks/chunk-7AYOQHZH.js.map +1 -0
- package/dist/split/chunks/chunk-EIMTT5I3.js +2 -0
- package/dist/split/chunks/chunk-EIMTT5I3.js.map +1 -0
- package/dist/split/chunks/chunk-L3PFEJP7.js +2 -0
- package/dist/split/chunks/chunk-L3PFEJP7.js.map +1 -0
- package/dist/split/chunks/chunk-LXEEVZIB.js +2 -0
- package/dist/split/chunks/chunk-LXEEVZIB.js.map +1 -0
- package/dist/split/chunks/{chunk-W5KT4PQ3.js → chunk-M5SODAAE.js} +2 -1
- package/dist/split/chunks/chunk-M5SODAAE.js.map +1 -0
- package/dist/split/chunks/{chunk-SPWZUBQS.js → chunk-NOPTR2L3.js} +2 -1
- package/dist/split/chunks/chunk-NOPTR2L3.js.map +1 -0
- package/dist/split/chunks/{chunk-ARPZVNKL.js → chunk-UD3AYVP2.js} +2 -1
- package/dist/split/chunks/chunk-UD3AYVP2.js.map +1 -0
- package/dist/split/chunks/{chunk-XF6V6DWR.js → chunk-W4KOY6GT.js} +2 -1
- package/dist/split/chunks/chunk-W4KOY6GT.js.map +1 -0
- package/dist/split/chunks/{chunk-2EGTC36Y.js → chunk-ZN52NEIB.js} +2 -1
- package/dist/split/chunks/chunk-ZN52NEIB.js.map +1 -0
- package/dist/split/core.js +2 -1
- package/dist/split/core.js.map +1 -0
- package/dist/split/features/devtools.js +2 -1
- package/dist/split/features/devtools.js.map +1 -0
- package/dist/split/features/diagnostics.js +2 -1
- package/dist/split/features/diagnostics.js.map +1 -0
- package/dist/split/features/formats.js +2 -1
- package/dist/split/features/formats.js.map +1 -0
- package/dist/split/features/list-keys.js +2 -1
- package/dist/split/features/list-keys.js.map +1 -0
- package/dist/split/features/native-commands.js +2 -1
- package/dist/split/features/native-commands.js.map +1 -0
- package/dist/split/features/recursion.js +2 -1
- package/dist/split/features/recursion.js.map +1 -0
- package/dist/split/features/scopes.js +2 -1
- package/dist/split/features/scopes.js.map +1 -0
- package/dist/split/features/ssr.js +2 -1
- package/dist/split/features/ssr.js.map +1 -0
- package/dist/split/features/temporal.js +2 -1
- package/dist/split/features/temporal.js.map +1 -0
- package/package.json +1 -1
- package/dist/split/chunks/chunk-27N3IPIZ.js +0 -1
- package/dist/split/chunks/chunk-7EWPQMA6.js +0 -1
- package/dist/split/chunks/chunk-ALVA5TQM.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["loads","readyByRoot","WeakMap","enroll","el","root","getRootNode","set","get","filter","e","i","a","isConnected","lastIndexOf","getBindingsReady","list","els","Promise","any","map","initializePromise","then","bound","connectedCallbackPromise","length","reject","errors","HTMLElementBase","HTMLElement","WcsState","constructor","super","this","engine","started","failed","initial","claimed","loaded","receiveInitial","resolve","resolveConnected","rejectConnected","catch","resolveInitialize","hasConnectedCallbackPromise","connectedCallback","connected","engines","has","drainBinds","hooks","element","rerun","claim","lenient","parentNode","ShadowRoot","load","loadState","state","start","built","fail","disconnectedCallback","disconnected","delete","setInitialState","raise","reset","receive","createState","mutability","callback","readonlyDepth","proxy","createStateAsync","Proxy","t","k","receiver","v","Reflect","id","getAttribute","find","r","querySelectorAll","x","script","document","Error","text","JSON","parse","textContent","src","async","url","URL","baseURI","href","test","res","fetch","ok","status","json","default","loadSrc","querySelector","blocked","seen","effectiveDirective","startsWith","addEventListener","blob","createObjectURL","Blob","type","encodeURIComponent","setTimeout","message","String","cause","removeEventListener","revokeObjectURL","loadInnerScript","host","hasAttribute","requireFeature","loading","loadFeatures","other","Engine","DirtyStrategy","mount","watchRendered","callHook","report","at","flatMap","n","console","error","localName","name","refs","registries","deref","bootstrapState","partial","registry","setConfig","customElements","installBinder","includes","push","WeakRef","tag","config","tagNames","define","tags","buildBindings","b","j","I","z","q"],"sources":["../../../src/element.ts"],"sourcesContent":["import type { IWritableConfig } from \"./public/types\";\nimport { Engine } from \"./engine\";\nimport { engines, mount } from \"./dom/mount\";\nimport { drainBinds, installBinder } from \"./dom/binder\";\nimport { DirtyStrategy } from \"./strategy/dirty\";\nimport { config, setConfig } from \"./config\";\nimport type { Strategy } from \"./strategy/types\";\nimport { raise, M, text } from \"./messages\";\nimport { hooks, loadFeatures, requireFeature, type Claimed } from \"./hooks\";\n\nlet makeStrategy: () => Strategy = () => new DirtyStrategy();\n\n/** Chooses the invalidation strategy of every engine created from now on. */\nexport function configure(factory: () => Strategy): void {\n makeStrategy = factory;\n}\n\nlet loads = 0;\n\nasync function loadInnerScript(script: HTMLScriptElement): Promise<Record<string, any>> {\n // an import a Content-Security-Policy blocked rejects without saying why: the violation event\n // is the only witness (docs/csp.md §9)\n let blocked = false;\n const seen = (e: SecurityPolicyViolationEvent): void => {\n if (e.effectiveDirective.startsWith(\"script-src\")) blocked = true;\n };\n document.addEventListener(\"securitypolicyviolation\", seen);\n // a server (@wcstack/server) removes createObjectURL: a data: URL, unique so no load is cached\n const blob = typeof URL.createObjectURL === \"function\";\n const url = blob\n ? URL.createObjectURL(new Blob([script.text], { type: \"application/javascript\" }))\n : \"data:text/javascript;charset=utf-8,\" + encodeURIComponent(`${script.text}\\n//${++loads}`);\n try {\n const mod = await import(/* @vite-ignore */ url);\n return (mod.default ?? {}) as Record<string, any>;\n } catch (e) {\n // Firefox fires the violation a task after the rejection (Chromium and WebKit before it)\n await new Promise((r) => setTimeout(r));\n throw new Error(`[@wcstack/state] ${blocked ? text(M.InlineBlocked) : text(M.InlineFailed, [e instanceof Error ? e.message : String(e)])}`, { cause: e });\n } finally {\n document.removeEventListener(\"securitypolicyviolation\", seen);\n if (blob) URL.revokeObjectURL(url);\n }\n}\n\nasync function loadSrc(src: string): Promise<Record<string, any>> {\n const url = new URL(src, document.baseURI).href;\n if (/\\.json(?:[?#]|$)/.test(url)) {\n const res = await fetch(url);\n if (!res.ok) raise(M.LoadFailed, [src, res.status]);\n return (await res.json()) as Record<string, any>;\n }\n const mod = await import(/* @vite-ignore */ url);\n return (mod.default ?? {}) as Record<string, any>;\n}\n\n/**\n * The root `<wcs-state>` elements of each root node (and the one a component mount or a DCC definition\n * has in its shadow root): a new list whenever one connects, without the ones no longer in the page.\n */\nconst readyByRoot = new WeakMap<Node, WcsState[]>();\n\n/**\n * Puts `el` among the `<wcs-state>` elements of `root` (a new list, without the ones that left) — or,\n * taken out of it, takes it off: the list holds nothing of a page that went.\n */\nfunction enroll(el: WcsState, root: Node = el.getRootNode()): void {\n readyByRoot.set(root, [...(readyByRoot.get(root) ?? []), el].filter((e, i, a) => e.isConnected && a.lastIndexOf(e) === i));\n}\n\n/**\n * Resolves when the bindings of `root` are built — by any `<wcs-state>` in it now, whatever its\n * `$connectedCallback` does then, as 3.x — and rejects, with the first failure, only when every one\n * failed before building them. A stray one (a second root, #47; one that fails to load) changes\n * nothing while another binds the root; one taken out of the page (or moved to another root) counts\n * no more (a root replaced: the new one decides). With none in it — none ever, or only ones that left —\n * it resolves at once: there is nothing to wait for (a page without state).\n */\nexport function getBindingsReady(root: Node): Promise<void> {\n const list = readyByRoot.get(root) ?? [];\n const els = list.filter((e) => e.getRootNode() === root);\n return Promise.any(els.map((el) => el.initializePromise.then((): unknown => el.bound || el.connectedCallbackPromise))).then(\n () => {},\n // none, or every one failed: one connected since (the list is a new one) may still bind the root\n // (quoted: `errors` is a name the build shortens, an AggregateError's is not)\n (e: AggregateError) => (els.length ? readyByRoot.get(root) !== list ? getBindingsReady(root) : Promise.reject(e[\"errors\"][0]) : undefined),\n );\n}\n\n/**\n * The base of the package's elements: HTMLElement, or — where there is none (Node without a DOM)\n * — an inert class, so the entries can be imported headless (a tool reading the manifest, a\n * server framework importing at the top level), as 3.x. Making an element stays a browser's.\n */\nexport const HTMLElementBase = (typeof HTMLElement === \"undefined\" ? class {} : HTMLElement) as typeof HTMLElement;\n\n/**\n * `<wcs-state>` — one engine per element, bound to the element's root node.\n * State resolution order: `state` (id of a JSON script) → `src` → `json` → inner\n * `<script type=\"module\">` → wait for `setInitialState()`.\n */\nexport class WcsState extends HTMLElementBase {\n static getBindingsReady = getBindingsReady;\n /** Servers (@wcstack/server) wait on connectedCallbackPromise when this is set. */\n static hasConnectedCallbackPromise = true;\n\n engine: Engine | null = null;\n readonly connectedCallbackPromise: Promise<void>;\n /**\n * Resolves once the state is loaded and bound (before `$connectedCallback`) — and also when\n * initialization fails: the failure is delivered on connectedCallbackPromise.\n */\n readonly initializePromise: Promise<void>;\n private resolveInitialize!: () => void;\n private resolveConnected!: () => void;\n private rejectConnected!: (e: unknown) => void;\n private started = false;\n /** Initialization failed before the page was bound: `setInitialState` refuses (#14). */\n private failed = false;\n private initial: Record<string, any> | null = null;\n /** Taken over by an add-on (a volume, a DCC definition): it never becomes a root. */\n private claimed: Claimed | null = null;\n /** A claimed element's state is loaded: `setInitialState` from now on is the add-on's re-set. */\n private loaded = false;\n /** The root's bindings are built (getBindingsReady resolves, whatever `$connectedCallback` does). */\n bound?: boolean;\n private receiveInitial: ((state: Record<string, any>) => void) | null = null;\n\n constructor() {\n super();\n this.connectedCallbackPromise = new Promise<void>((resolve, reject) => {\n this.resolveConnected = resolve;\n this.rejectConnected = reject;\n });\n this.connectedCallbackPromise.catch(() => {});\n this.initializePromise = new Promise<void>((resolve) => {\n this.resolveInitialize = resolve;\n });\n }\n\n connectedCallback(): void {\n if (this.started) {\n if (this.claimed !== null) {\n this.claimed.connected();\n return;\n }\n enroll(this);\n const engine = this.engine;\n if (engine !== null) {\n // back in the page: it holds its root again (unless another <wcs-state> bound it meanwhile),\n // binds what was handed over while it was out, and the add-ons hear of it (the volumes that\n // connected meanwhile graft) — then $connectedCallback runs again\n const root = engine.root;\n if (root === this.getRootNode() && !engines.has(root)) engines.set(root, engine);\n drainBinds();\n hooks.element?.(engine, \"back\");\n this.rerun(\"$connectedCallback\", M.ConnectedFailed, () => {\n if (this.isConnected) hooks.element?.(engine, \"connected\");\n });\n }\n return;\n }\n this.started = true;\n const root = this.getRootNode();\n const claimed = hooks.claim?.(this, root);\n if (claimed) {\n this.claimed = claimed;\n // the `<wcs-state>` of the shadow root it binds (a component's, a DCC definition's) is that\n // root's, as 3.x: getBindingsReady there waits for it — until its bindings are built, as a\n // root's — and fails with it (a volume never fails)\n if (!claimed.lenient && this.parentNode instanceof ShadowRoot) enroll(this);\n void (claimed.load === undefined ? this.loadState() : claimed.load()).then((state) => {\n this.loaded = true;\n return claimed.start(state, () => this.built());\n }).then(() => {\n this.resolveInitialize();\n this.resolveConnected();\n }, (e) => this.fail(e, claimed.lenient));\n return;\n }\n void this.start(root);\n enroll(this);\n }\n\n disconnectedCallback(): void {\n if (this.claimed !== null) {\n this.claimed.disconnected();\n return;\n }\n const engine = this.engine;\n if (engine === null) return;\n // out of the page, it lets go of its root (it holds it again when it is back): what outlives the\n // page's content — its root node, the document — does not keep its state and the DOM it bound\n // (a root that failed before its mount has none: enroll takes the root it is in now)\n const root = engine.root;\n if (engines.get(root!) === engine) engines.delete(root!);\n enroll(this, root);\n this.rerun(\"$disconnectedCallback\", M.DisconnectedFailed);\n hooks.element?.(engine, \"disconnected\");\n }\n\n /**\n * Supplies the initial state; on an initialized element, replaces the whole state and\n * re-applies every binding to it before returning (not a write: no `$renderedCallback`).\n */\n setInitialState(state: Record<string, any>): void {\n if (this.failed) raise(M.ElementFailed);\n // (until a claimed element's state is loaded, this supplies it like a root's)\n if (this.loaded) {\n this.claimed!.reset(state);\n return;\n }\n if (this.engine !== null) {\n this.engine.reset(state);\n return;\n }\n if (this.receiveInitial !== null) {\n const receive = this.receiveInitial;\n this.receiveInitial = null;\n receive(state);\n } else {\n this.initial = state;\n }\n }\n\n /** Runs `callback` with a state proxy; its writes are applied in the next drain. */\n createState(mutability: \"readonly\" | \"writable\", callback: (state: Record<string, any>) => void): void {\n const engine = this.engine;\n if (engine === null) raise(M.NotInitialized);\n if (mutability === \"readonly\") engine.readonlyDepth++;\n try {\n callback(engine.proxy);\n } finally {\n if (mutability === \"readonly\") engine.readonlyDepth--;\n }\n }\n\n /** `createState` whose callback may await; a readonly proxy stays readonly across its awaits. */\n async createStateAsync(mutability: \"readonly\" | \"writable\", callback: (state: Record<string, any>) => Promise<void>): Promise<void> {\n const engine = this.engine;\n if (engine === null) raise(M.NotInitialized);\n await callback(mutability === \"writable\" ? engine.proxy : new Proxy(engine.proxy, {\n // as in createState(\"readonly\"), the writes of $setAll and $resolve (path, indexes, value) refuse;\n // read with this view as the receiver, a method comes as it is and runs on this view\n get(t, k, receiver) {\n const v = Reflect.get(t, k, receiver);\n return k === \"$setAll\" || k === \"$resolve\" ? (...a: unknown[]) => (a.length > 2 && raise(M.Readonly), v(...a)) : v;\n },\n set() {\n raise(M.Readonly);\n },\n }));\n }\n\n private async loadState(): Promise<Record<string, any>> {\n // a parser that inserts the element before its children (a server render) has added them by now\n await 0;\n const id = this.getAttribute(\"state\");\n if (id !== null) {\n // a JSON script of that id (an element of user content with the same id, earlier, is not it)\n const find = (r: Node): HTMLScriptElement | undefined =>\n [...(r as Document).querySelectorAll<HTMLScriptElement>('script[type=\"application/json\"]')].find((x) => x.id === id);\n const script = find(this.getRootNode()) ?? find(document);\n if (script === undefined) return Promise.reject(new Error(`[@wcstack/state] ${text(M.NoScript, [id])}`));\n return Promise.resolve(JSON.parse(script.textContent || \"{}\"));\n }\n const src = this.getAttribute(\"src\");\n if (src !== null) return loadSrc(src);\n const json = this.getAttribute(\"json\");\n if (json !== null) return Promise.resolve(JSON.parse(json));\n const script = this.querySelector('script[type=\"module\"]') as HTMLScriptElement | null;\n if (script !== null) return loadInnerScript(script);\n if (this.initial !== null) return Promise.resolve(this.initial);\n return new Promise((resolve) => {\n this.receiveInitial = resolve;\n });\n }\n\n private async start(root: Node): Promise<void> {\n try {\n // what an add-on serves: a volume, a component mount, a DCC definition, server rendering\n const host = (root as ShadowRoot).host;\n if (this.hasAttribute(\"mount\") || this.hasAttribute(\"bind-component\") || host?.hasAttribute(\"data-wc-definition\")) {\n requireFeature(\"scopes\", \"<wcs-state>\");\n }\n const state = await this.loadState();\n const loading = loadFeatures(state);\n if (loading) await loading;\n // taken out of its root while it loaded (the page's content replaced, or moved to another root):\n // nothing is mounted on the root it left. It starts again where it is now, or when it connects\n // again. A state given by setInitialState() is kept for that; a state= / src= / json= / inline\n // script source is read again (a fetch runs again, an inline module is evaluated again)\n if (this.getRootNode() !== root) {\n this.initial = state;\n this.started = false;\n if (this.isConnected) this.connectedCallback();\n return;\n }\n if (this.hasAttribute(\"enable-ssr\")) requireFeature(\"ssr\", \"enable-ssr\");\n // one state tree per root: another <wcs-state> already bound this root (and still does —\n // whatever its $connectedCallback did then), or a component's took it\n const other = engines.get(root)?.element as WcsState | undefined;\n if (other?.isConnected && (other.bound || other.claimed)) raise(M.SecondRoot);\n const engine = new Engine(state, makeStrategy());\n engine.element = this;\n this.engine = engine;\n hooks.element?.(engine, \"mounting\");\n mount(engine, root as Document | ShadowRoot);\n drainBinds();\n engine.watchRendered();\n this.built();\n await engine.callHook(\"$connectedCallback\");\n if (this.isConnected) hooks.element?.(engine, \"connected\");\n this.resolveConnected();\n } catch (e) {\n // (a root that bound its page and whose $connectedCallback then failed has not: re-set stays open)\n this.failed = !this.bound;\n this.fail(e);\n }\n }\n\n /** The bindings are built (before `$connectedCallback`): getBindingsReady resolves, initializePromise too. */\n private built(): void {\n this.bound = true;\n this.resolveInitialize();\n }\n\n /**\n * Initialization failed: reported once, the element (and where its state comes from) before what\n * was thrown, as 3.5 — `<wcs-state src=\"./state.js\"> failed to initialize.`, or, once its\n * bindings were built, `… $connectedCallback failed.` — and connectedCallbackPromise rejects with\n * it, or resolves for a claim that is `lenient` (a volume).\n */\n private fail(e: unknown, lenient?: boolean): void {\n this.report(this.bound ? M.ConnectedFailed : M.InitFailed, e);\n this.resolveInitialize();\n if (lenient) this.resolveConnected();\n else this.rejectConnected(e);\n }\n\n /** Reports a failure once: the element (and where its state comes from), then what was thrown. */\n private report(id: M, e: unknown): void {\n const at = [\"mount\", \"bind-component\", \"state\", \"src\"].flatMap((n) => (this.hasAttribute(n) ? [n, this.getAttribute(n)] : []));\n console.error(`[@wcstack/state] ${text(id, [this.localName, ...at])}`, e);\n }\n\n /**\n * Runs a lifecycle callback of a root that connected before (on reconnect, on disconnect) at once: a\n * failure — thrown or rejected — is reported as a first connection's is, never thrown out of the\n * element's callback.\n */\n private rerun(name: string, id: M, then?: () => void): void {\n void (async () => this.engine!.callHook(name))().then(then, (e) => this.report(id, e));\n }\n}\n\n/**\n * The registries `<wcs-state>` was defined in: an add-on installed later defines its tags there\n * too. Weak: a server creates a registry per render, and holding them would keep every render's\n * registry (and every constructor defined in it) alive.\n */\nlet refs: WeakRef<CustomElementRegistry>[] = [];\n\n/**\n * The registries still alive (dead references are dropped). A registry deref() returned stays\n * alive until the end of this job, so the second deref() of each kept reference finds it.\n */\nexport function registries(): CustomElementRegistry[] {\n refs = refs.filter((r) => r.deref());\n return refs.map((r) => r.deref()!);\n}\n\n/**\n * Registers `<wcs-state>` (and the installed add-ons' tags) in `registry` — a scoped registry\n * does not inherit the global one, so a tree using one needs its own definitions.\n */\nexport function define(registry: CustomElementRegistry = customElements): void {\n installBinder();\n if (!registries().includes(registry)) refs.push(new WeakRef(registry));\n const tag = config.tagNames.state;\n if (registry.get(tag) === undefined) registry.define(tag, class extends WcsState {});\n hooks.tags?.(registry);\n}\n\n/** Applies `config` and registers `<wcs-state>`. The core only: install the add-ons first. */\nexport function bootstrapState(partial?: IWritableConfig, registry?: CustomElementRegistry): void {\n if (partial) setConfig(partial);\n define(registry);\n}\n\n/**\n * Waits for the bindings under `root` (3.x built them here; the new engine builds them when the\n * root's `<wcs-state>` loads its state, so this only waits — the same as getBindingsReady).\n */\nexport const buildBindings = (root: Document | ShadowRoot): Promise<void> => getBindingsReady(root);\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import{e as t}from"./chunk-
|
|
1
|
+
import{e as t}from"./chunk-M5SODAAE.js";import{b as r}from"./chunk-EIMTT5I3.js";function n(t){r(26,[t])}function e(t){r(27,[t])}function o(t){r(28,[t])}function a(t){r(29,[t])}function f(t){r(30,[t])}function u(t){return!(!t||isNaN(Number(t)))}function i(t,r){return u(t)||e(r),Number(t)}function y(t,r,e){return i(t?.[r]??n(e),e)}function c(t,r){return void 0!==r&&r.length>0?r[0]:t}var s=(t,r)=>({factory:n=>{let e=y(n,0,t);return n=>("number"!=typeof n&&o(t),r(n,e))},arity:[1,1]}),m={eq:{factory:(t,r)=>{let o=t?.[0]??n("eq"),a=c(o,r);return t=>"number"==typeof t?"string"!=typeof a?t===a:(u(o)||e("eq"),t===Number(o)):"string"==typeof t?t===o:t===a},arity:[1,1]},ne:{factory:(t,r)=>{let o=t?.[0]??n("ne"),a=c(o,r);return t=>"number"==typeof t?"string"!=typeof a?t!==a:(u(o)||e("ne"),t!==Number(o)):"string"==typeof t?t!==o:t!==a},arity:[1,1]},not:{factory:()=>t=>!t,arity:[0,0]},lt:s("lt",(t,r)=>t<r),le:s("le",(t,r)=>t<=r),gt:s("gt",(t,r)=>t>r),ge:s("ge",(t,r)=>t>=r),falsy:{factory:()=>t=>!t,arity:[0,0]},truthy:{factory:()=>t=>!!t,arity:[0,0]},boolean:{factory:()=>t=>!!t,arity:[0,0]}},b=!1;function g(){b||(b=!0,t(m))}export{n as a,o as b,a as c,f as d,i as e,y as f,c as g,s as h,m as i,g as j};
|
|
2
|
+
//# sourceMappingURL=chunk-W4KOY6GT.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["optionsRequired","fnName","raise","optionMustBeNumber","valueMustBeNumber","valueMustBeDate","valueMustBeArray","validateNumberString","value","isNaN","Number","numberOption","requiredNumberOption","options","index","firstLiteral","opt","literals","length","numeric","name","op","factory","arity","coreFilters","eq","literal","ne","not","lt","le","gt","ge","falsy","truthy","boolean","installed","installCoreFilters","registerFilters","u","y","M","R","m","b","p","l","x","S"],"sources":["../../../src/filters/errorMessages.ts","../../../src/filters/options.ts","../../../src/filters/core.ts"],"sourcesContent":["/**\n * filters/errorMessages.ts — the filters' error messages, ported from `@wcstack/state`\n * (`formats/errorMessages.ts`). Numbered core messages (src/messages.ts): the sentences, the same\n * as the source's, are the diagnostics add-on's.\n */\n\nimport { raise, M } from \"../messages\";\n\n/** The filter requires an option but none was given (the factory-side guard; arity usually fires first). */\nexport function optionsRequired(fnName: string): never {\n raise(M.FilterOptionsRequired, [fnName]);\n}\n\n/** A numeric option is not a number. */\nexport function optionMustBeNumber(fnName: string): never {\n raise(M.FilterOptionNotNumber, [fnName]);\n}\n\n/** The value given to a numeric filter is not a number. */\nexport function valueMustBeNumber(fnName: string): never {\n raise(M.FilterValueNotNumber, [fnName]);\n}\n\n/** The value given to a date filter is not a Date. */\nexport function valueMustBeDate(fnName: string): never {\n raise(M.FilterValueNotDate, [fnName]);\n}\n\n/** The value given to an array filter is not an array. */\nexport function valueMustBeArray(fnName: string): never {\n raise(M.FilterValueNotArray, [fnName]);\n}\n","/**\n * filters/options.ts — option parsing shared by the core set and the formats add-on, ported\n * verbatim from `@wcstack/state` (`formats/builtinFilters.ts`).\n *\n * Numeric options are read **once, when the filter is built**: the checks stay in one place and the\n * `Number()` conversion stays off the apply path.\n */\nimport { optionMustBeNumber, optionsRequired } from \"./errorMessages\";\n\n/** `\"\"` and anything `Number()` cannot read are rejected (so `lt('')` is an error, not `lt(0)`). */\nexport function validateNumberString(value: string): boolean {\n if (!value || isNaN(Number(value))) {\n return false;\n }\n return true;\n}\n\n/** One numeric option, converted: non-numeric → `optionMustBeNumber`. */\nexport function numberOption(value: string, fnName: string): number {\n if (!validateNumberString(value)) {optionMustBeNumber(fnName);}\n return Number(value);\n}\n\n/** A required numeric option: missing → `optionsRequired`, non-numeric → `optionMustBeNumber`. */\nexport function requiredNumberOption(options: readonly string[] | undefined, index: number, fnName: string): number {\n return numberOption(options?.[index] ?? optionsRequired(fnName), fnName);\n}\n\n/**\n * The typed literal of the first argument (requirement B9): an unquoted `true` / `false` / `null` /\n * number arrives typed, a quoted argument as a string. Without literals (tooling calling a factory\n * directly) the raw option text stands in.\n */\nexport function firstLiteral(opt: string, literals: readonly unknown[] | undefined): unknown {\n return literals !== undefined && literals.length > 0 ? literals[0] : opt;\n}\n","/**\n * filters/core.ts — the core filter set (10): the conditions a binding tests, as opposed to the\n * values the formats add-on (`./formats`) computes and shows. Ported from `@wcstack/state`\n * (`formats/builtinFilters.ts`) with the semantics unchanged.\n *\n * - conditions: `eq ne not lt le gt ge truthy falsy boolean`\n *\n * The arithmetic (`add sub mul div mod abs clamp`), conversion (`number string int float`) and\n * missing-value (`defaults coalesce nullIfEmpty`) filters were here up to 4.0.0-rc.3; they are the\n * formats add-on's since, for the core's size target.\n *\n * `installCoreFilters()` puts them in the registry; the engine calls it before it plans bindings\n * (`else:` is built with an injected `not`, so the core set is never optional).\n */\nimport { optionMustBeNumber, optionsRequired, valueMustBeNumber } from \"./errorMessages\";\nimport { firstLiteral, requiredNumberOption, validateNumberString } from \"./options\";\nimport { registerFilters, type FilterDefinition, type FilterFn } from \"./registry\";\n\n/** Equality — compares with the option (a typed literal compares as itself, B9). */\nconst eq = (options: string[], literals?: readonly unknown[]): FilterFn => {\n const opt = options?.[0] ?? optionsRequired('eq');\n const literal = firstLiteral(opt, literals);\n return (value: unknown): boolean => {\n if (typeof value === 'number') {\n // A typed literal that is not a string compares as itself (B9): a number is never equal to\n // `true` / `false` / `null`, so `selectedId|eq(null)` is false once the id is a number instead\n // of throwing on every apply. Only an unquoted non-number (`eq(abc)`) still reports the type\n // mismatch, and it has to stay here: `eq` accepts values of any type (`status|eq(active)` is\n // valid), so it cannot be rejected at construction the way `lt` / `add` can.\n if (typeof literal !== 'string') {return value === literal;}\n if (!validateNumberString(opt)) {optionMustBeNumber('eq');}\n return value === Number(opt);\n }\n if (typeof value === 'string') {\n return value === opt;\n }\n // Booleans, null and the rest compare with the typed literal: eq(true) matches true (B9)\n return value === literal;\n };\n};\n\n/** Inequality — the negation of `eq`, with the same typing rules (B9). */\nconst ne = (options: string[], literals?: readonly unknown[]): FilterFn => {\n const opt = options?.[0] ?? optionsRequired('ne');\n const literal = firstLiteral(opt, literals);\n return (value: unknown): boolean => {\n if (typeof value === 'number') {\n if (typeof literal !== 'string') {return value !== literal;}\n if (!validateNumberString(opt)) {optionMustBeNumber('ne');}\n return value !== Number(opt);\n }\n if (typeof value === 'string') {\n return value !== opt;\n }\n return value !== literal;\n };\n};\n\n/**\n * Inverts truthiness (lenient `!value`). `else:` is built as the `if` condition plus an injected\n * `not`, and `if:` coerces with `Boolean()`; a strict `not` made `else:` throw — rendering neither\n * branch — whenever the condition was a falsy non-boolean (`0` / `\"\"` / `undefined` / `null`).\n */\nconst not = (): FilterFn => (value: unknown): boolean => !value;\n\n/**\n * A comparison or arithmetic filter: one numeric option, a number value (`lt` … `ge` here, `add` …\n * `mod` in the formats add-on).\n */\nexport const numeric = (name: string, op: (value: number, opt: number) => unknown): FilterDefinition => ({\n factory: (options: string[]): FilterFn => {\n const opt = requiredNumberOption(options, 0, name);\n return (value: unknown): unknown => {\n if (typeof value !== 'number') {valueMustBeNumber(name);}\n return op(value, opt);\n };\n },\n arity: [1, 1],\n});\n\n/** JavaScript's truthiness, the same as `boolean` (B10). */\nconst truthy = (): FilterFn => (value: unknown): boolean => !!value;\n\n/** JavaScript's falsiness (`!value`: false, null, undefined, 0, -0, 0n, '' and NaN — B10). */\nconst falsy = (): FilterFn => (value: unknown): boolean => !value;\n\nconst boolean = (): FilterFn => (value: unknown): boolean => Boolean(value);\n\n/**\n * The core set: factory and [min, max] argument count (B3 — the same bounds lint uses).\n *\n * The key order is the source's (`builtinFilterMeta`, which lint reads): the did-you-mean\n * suggestion breaks ties by registration order (see `installFormats` for the order the full\n * build registers).\n */\nexport const coreFilters: Readonly<Record<string, FilterDefinition>> = {\n eq: { factory: eq, arity: [1, 1] },\n ne: { factory: ne, arity: [1, 1] },\n not: { factory: not, arity: [0, 0] },\n lt: numeric('lt', (value, opt) => value < opt),\n le: numeric('le', (value, opt) => value <= opt),\n gt: numeric('gt', (value, opt) => value > opt),\n ge: numeric('ge', (value, opt) => value >= opt),\n falsy: { factory: falsy, arity: [0, 0] },\n truthy: { factory: truthy, arity: [0, 0] },\n boolean: { factory: boolean, arity: [0, 0] },\n};\n\nlet installed = false;\n\n/** Puts the core set in the registry. Idempotent; the engine calls it before planning any binding. */\nexport function installCoreFilters(): void {\n if (installed) return;\n installed = true;\n registerFilters(coreFilters);\n}\n"],"mappings":"gFASO,SAASA,EAAgBC,GAC9BC,KAA+B,CAACD,GAClC,CAGO,SAASE,EAAmBF,GACjCC,KAA+B,CAACD,GAClC,CAGO,SAASG,EAAkBH,GAChCC,KAA8B,CAACD,GACjC,CAGO,SAASI,EAAgBJ,GAC9BC,KAA4B,CAACD,GAC/B,CAGO,SAASK,EAAiBL,GAC/BC,KAA6B,CAACD,GAChC,CCrBO,SAASM,EAAqBC,GACnC,SAAKA,GAASC,MAAMC,OAAOF,IAI7B,CAGO,SAASG,EAAaH,EAAeP,GAC1C,OAAKM,EAAqBC,IAASL,EAAmBF,GAC/CS,OAAOF,EAChB,CAGO,SAASI,EAAqBC,EAAwCC,EAAeb,GAC1F,OAAOU,EAAaE,IAAUC,IAAUd,EAAgBC,GAASA,EACnE,CAOO,SAASc,EAAaC,EAAaC,GACxC,YAAoB,IAAbA,GAA0BA,EAASC,OAAS,EAAID,EAAS,GAAKD,CACvE,CChBA,IAkDaG,EAAU,CAACC,EAAcC,MACpCC,QAAUT,IACR,IAAMG,EAAMJ,EAAqBC,EAAS,EAAGO,GAC7C,OAAQZ,IACe,iBAAVA,GAAqBJ,EAAkBgB,GAC3CC,EAAGb,EAAOQ,KAGrBO,MAAO,CAAC,EAAG,KAkBAC,EAA0D,CACrEC,GAAI,CAAEH,QA7EG,CAACT,EAAmBI,KAC7B,IAAMD,EAAMH,IAAU,IAAMb,EAAgB,MACtC0B,EAAUX,EAAaC,EAAKC,GAClC,OAAQT,GACe,iBAAVA,EAMc,iBAAZkB,EAA8BlB,IAAUkB,GAC9CnB,EAAqBS,IAAOb,EAAmB,MAC7CK,IAAUE,OAAOM,IAEL,iBAAVR,EACFA,IAAUQ,EAGZR,IAAUkB,GA2DAH,MAAO,CAAC,EAAG,IAC9BI,GAAI,CAAEL,QAvDG,CAACT,EAAmBI,KAC7B,IAAMD,EAAMH,IAAU,IAAMb,EAAgB,MACtC0B,EAAUX,EAAaC,EAAKC,GAClC,OAAQT,GACe,iBAAVA,EACc,iBAAZkB,EAA8BlB,IAAUkB,GAC9CnB,EAAqBS,IAAOb,EAAmB,MAC7CK,IAAUE,OAAOM,IAEL,iBAAVR,EACFA,IAAUQ,EAEZR,IAAUkB,GA2CAH,MAAO,CAAC,EAAG,IAC9BK,IAAK,CAAEN,QAnCG,IAAiBd,IAA6BA,EAmCnCe,MAAO,CAAC,EAAG,IAChCM,GAAIV,EAAQ,KAAM,CAACX,EAAOQ,IAAQR,EAAQQ,GAC1Cc,GAAIX,EAAQ,KAAM,CAACX,EAAOQ,IAAQR,GAASQ,GAC3Ce,GAAIZ,EAAQ,KAAM,CAACX,EAAOQ,IAAQR,EAAQQ,GAC1CgB,GAAIb,EAAQ,KAAM,CAACX,EAAOQ,IAAQR,GAASQ,GAC3CiB,MAAO,CAAEX,QAnBG,IAAiBd,IAA6BA,EAmBjCe,MAAO,CAAC,EAAG,IACpCW,OAAQ,CAAEZ,QAvBG,IAAiBd,KAA8BA,EAuBjCe,MAAO,CAAC,EAAG,IACtCY,QAAS,CAAEb,QAnBG,IAAiBd,KAAoCA,EAmBtCe,MAAO,CAAC,EAAG,KAGtCa,GAAY,EAGT,SAASC,IACVD,IACJA,GAAY,EACZE,EAAgBd,GAClB,QAAAe,OAAAC,OAAAC,OAAAC,OAAAC,OAAAC,OAAAC,OAAAC,OAAAC,OAAAC","ignoreList":[]}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
var t=class{constructor(t,l,i){this.c=[],this.getter=null,this.ie=null,this.se=!1,this.M=[],this.
|
|
1
|
+
var t=class{constructor(t,l,i){this.c=[],this.getter=null,this.ie=null,this.se=!1,this.M=[],this.J=[],this.ft=null,this.A=-1,this.z=s,this.Ce=null,this.Ct=null,this.It=null,this.W=null,this.pn=!1,this.mn=!1,this.Wn=!1,this.Z=0,this.pt=new Set,this.t=t,this.d=i,this.s=l;let e=null===i?[null]:i.h.slice(),h="*"===l;h&&e.push(i),this.n=e.length-1,this.q=h?[]:null===i?[l]:[...i.q,l],this.h=e}_n(t){this.pt.has(t)||(this.pt.add(t),this.M.push(t),t.J.push(this))}Io(t){this.pt.delete(t);let s=this.M;s.splice(s.indexOf(t),1)}jo(){this.getter=null,this.ie=null,this.A=-1,this.z=s,this.M.length=0,this.pt.clear(),this.J.length=0,this.ft=null,this.Ce=null,this.Ct=null,this.It=null,this.W=null}ee(t){let s=this;for(;null!==s;){if(s===t)return!0;s=s.d}return!1}},s=Symbol("unset"),l=Symbol("dirty"),i=Symbol("failed"),e=class{constructor(t=null){this.mt=new Map,this.Vn=t}jt(t){return this.mt.get(t)}get(s){let l=this.mt.get(s);if(void 0!==l)return l;let i=s.lastIndexOf("."),e=i<0?null:this.get(s.slice(0,i));return l=new t(s,s.slice(i+1),e),this.Vn?.(l),this.mt.set(s,l),e&&e.c.push(l),l}all(){return this.mt.values()}Dt(t){this.mt.delete(t.t)}},h=new Map;function n(t){let s=h.get(t);if(void 0!==s)return s;let l=!0,i=t.split("."),e=[];for(let t=0;t<i.length;t++){let s=i[t],h=s.charCodeAt(0);t>0&&h>=48&&h<=57?(l=!1,e.push(Number(s)),i[t]="*"):"*"===s&&e.push(-1)}if(!l)return{o:i.join("."),indexes:e};let n={o:t,indexes:null};return h.size>4095&&h.clear(),h.set(t,n),n}export{s as a,l as b,i as c,e as d,n as e};
|
|
2
|
+
//# sourceMappingURL=chunk-ZN52NEIB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["Pattern","constructor","path","last","parent","this","children","getter","setter","underGetter","dependents","sources","crossSources","slot","rootValue","UNSET","eqIndexWatchers","eqIndexKeys","indexWatchers","eqSubs","pinned","dead","markup","mark","dependentSet","Set","lists","slice","w","push","depth","length","tail","addDependent","has","add","dropDependent","delete","d","splice","indexOf","forget","clear","isUnder","ancestor","p","Symbol","DIRTY","FAILED","PatternTable","onCreate","byPath","Map","peek","get","i","lastIndexOf","set","all","values","drop","literalCache","parsePath","cached","literal","segs","split","indexes","s","c","charCodeAt","Number","pattern","join","parsed","size","P","f","g"],"sources":["../../../src/pattern.ts"],"sourcesContent":["/**\n * Path patterns.\n *\n * A pattern is the authoring-level path with every list position written as `*`\n * (`data.*.label`). Each engine interns its patterns once; everything at run time\n * refers to the Pattern object, never to a path string. A concrete location is a\n * pattern plus the row that owns its last wildcard — there is no address object.\n */\n\nexport const WILDCARD = \"*\";\n\nexport class Pattern {\n readonly path: string;\n readonly parent: Pattern | null;\n readonly last: string;\n /** Number of `*` segments. 0 = a location on the root, n = a location inside a depth-n row. */\n readonly depth: number;\n /** Segments after the last `*` (all segments when depth is 0). Read from the row item / the root. */\n readonly tail: readonly string[];\n /** `lists[k]` is the list pattern whose rows the k-th wildcard (1-based) ranges over. */\n readonly lists: readonly (Pattern | null)[];\n children: Pattern[] = [];\n\n // --- filled in by the engine ---\n getter: (() => unknown) | null = null;\n setter: ((value: unknown) => void) | null = null;\n /** true when some proper ancestor is an accessor (read through it instead of walking data). */\n underGetter = false;\n /** Getter patterns whose evaluation read this pattern. */\n readonly dependents: Pattern[] = [];\n /** Patterns this getter read (union over its evaluations). */\n sources: Pattern[] = [];\n /** Sources read from a row other than the evaluating row's own chain (fan out on change). */\n crossSources: Set<Pattern> | null = null;\n /** Cache slot of a row-level getter on its rows. -1 when not a row-level getter. */\n slot = -1;\n /** Root-level getter cache (depth 0). */\n rootValue: unknown = UNSET;\n /** `$eqIndex(this path)` watchers: getters keyed on the index of their row at `level`. */\n eqIndexWatchers: { getter: Pattern; level: number }[] | null = null;\n /** On a list pattern: the `$eqIndex` registrations over its rows (re-keyed on reorder). */\n eqIndexKeys: { source: Pattern; getter: Pattern }[] | null = null;\n /** On a list pattern: getters that read the index (`$k`) of this list's rows. */\n indexWatchers: Pattern[] | null = null;\n /** `$eq(this path, key)` subscriptions: getter occurrences keyed by the value they wait for. */\n eqSubs: Map<unknown, Set<EqSub>> | null = null;\n /**\n * Something outside a path's read or write holds it (a binding, a list, an add-on: Engine.pattern):\n * never swept. A pattern only a path made (`this[\"users.\" + id]`) goes when it holds nothing (Engine.sweep).\n */\n pinned = false;\n /** Swept: out of the table (a later use of its path makes a new one). */\n dead = false;\n /** Its accessor is the engine's own for an index path (Engine.markupAccessor), not the author's or an add-on's. */\n markup = false;\n /** Scratch of Engine.prune: the evaluation that read it. */\n mark = 0;\n\n private readonly dependentSet = new Set<Pattern>();\n\n constructor(path: string, last: string, parent: Pattern | null) {\n this.path = path;\n this.parent = parent;\n this.last = last;\n // the parent's list table, plus our own when we are a wildcard segment\n const lists: (Pattern | null)[] = parent === null ? [null] : parent.lists.slice();\n const w = last === WILDCARD;\n if (w) lists.push(parent);\n this.depth = lists.length - 1;\n this.tail = w ? [] : parent === null ? [last] : [...parent.tail, last];\n this.lists = lists;\n }\n\n addDependent(getter: Pattern): void {\n if (this.dependentSet.has(getter)) return;\n this.dependentSet.add(getter);\n this.dependents.push(getter);\n getter.sources.push(this);\n }\n\n /** `getter` reads this no more (its side, `sources`, is the caller's). */\n dropDependent(getter: Pattern): void {\n this.dependentSet.delete(getter);\n const d = this.dependents;\n d.splice(d.indexOf(getter), 1);\n }\n\n /** A re-set replaced the state: forget its accessors and everything learned from them. */\n forget(): void {\n this.getter = null;\n this.setter = null;\n this.slot = -1;\n this.rootValue = UNSET;\n this.dependents.length = 0;\n this.dependentSet.clear();\n this.sources.length = 0;\n this.crossSources = null;\n this.eqIndexWatchers = null;\n this.eqIndexKeys = null;\n this.indexWatchers = null;\n this.eqSubs = null;\n }\n\n /** true when `this` is `ancestor` or lies under it. */\n isUnder(ancestor: Pattern): boolean {\n let p: Pattern | null = this;\n while (p !== null) {\n if (p === ancestor) return true;\n p = p.parent;\n }\n return false;\n }\n}\n\n/** One getter occurrence subscribed under a key of a `$eq` source. */\nexport interface EqSub {\n getter: Pattern;\n row: import(\"./list\").StateRow | null;\n}\n\n/** Sentinel for \"no cached value\". */\nexport const UNSET: unique symbol = Symbol(\"unset\") as never;\n/** Sentinel for \"cached value is stale\" (dirty strategy). */\nexport const DIRTY: unique symbol = Symbol(\"dirty\") as never;\n/**\n * Sentinel for \"evaluated, but it threw\" (or stale with its readers dropped by a cut drain):\n * someone read it, so a change of its sources must reach it.\n */\nexport const FAILED: unique symbol = Symbol(\"failed\") as never;\n\nexport class PatternTable {\n private readonly byPath = new Map<string, Pattern>();\n private readonly onCreate: ((p: Pattern) => void) | null;\n\n constructor(onCreate: ((p: Pattern) => void) | null = null) {\n this.onCreate = onCreate;\n }\n\n peek(path: string): Pattern | undefined {\n return this.byPath.get(path);\n }\n\n get(path: string): Pattern {\n let p = this.byPath.get(path);\n if (p !== undefined) return p;\n const i = path.lastIndexOf(\".\");\n const parent = i < 0 ? null : this.get(path.slice(0, i));\n p = new Pattern(path, path.slice(i + 1), parent);\n this.onCreate?.(p);\n this.byPath.set(path, p);\n if (parent) parent.children.push(p);\n return p;\n }\n\n all(): IterableIterator<Pattern> {\n return this.byPath.values();\n }\n\n drop(p: Pattern): void {\n this.byPath.delete(p.path);\n }\n}\n\n/**\n * A concrete path (`data.3.label`, `data.*.label`, `selectedIndex`) split into its\n * pattern and the explicit indexes it carries. `*` segments take their index from the\n * evaluation context, so they are returned as `-1`. A leading numeric segment is a key of\n * the root (`2024.total`), never an index: the root is not a list.\n */\nexport interface ParsedPath {\n pattern: string;\n indexes: number[] | null;\n}\n\nconst literalCache = new Map<string, ParsedPath>();\n\nexport function parsePath(path: string): ParsedPath {\n const cached = literalCache.get(path);\n if (cached !== undefined) return cached;\n let literal = true;\n const segs = path.split(\".\");\n const indexes: number[] = [];\n for (let i = 0; i < segs.length; i++) {\n const s = segs[i];\n const c = s.charCodeAt(0);\n if (i > 0 && c >= 48 && c <= 57) {\n literal = false;\n indexes.push(Number(s));\n segs[i] = WILDCARD;\n } else if (s === WILDCARD) indexes.push(-1);\n }\n if (!literal) return { pattern: segs.join(\".\"), indexes };\n const parsed: ParsedPath = { pattern: path, indexes: null };\n // literal paths (no explicit index) are few and reused: keep them — up to a bound, as a key built\n // from data (`this[\"users.\" + id]`) makes a new one each time\n if (literalCache.size > 4095) literalCache.clear();\n literalCache.set(path, parsed);\n return parsed;\n}\n"],"mappings":"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","ignoreList":[]}
|
package/dist/split/core.js
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import{a as s}from"./chunks/chunk-
|
|
1
|
+
import{a as s}from"./chunks/chunk-LXEEVZIB.js";import{a as n,d as t,e as u}from"./chunks/chunk-UD3AYVP2.js";import"./chunks/chunk-55J45X6H.js";import"./chunks/chunk-L3PFEJP7.js";import"./chunks/chunk-W4KOY6GT.js";import{g as a,h as c,i as h}from"./chunks/chunk-7AYOQHZH.js";import{c as i}from"./chunks/chunk-M5SODAAE.js";import"./chunks/chunk-ZN52NEIB.js";import"./chunks/chunk-NOPTR2L3.js";import"./chunks/chunk-EIMTT5I3.js";import{g as o}from"./chunks/chunk-4NJBYXIT.js";function r(s){return s}export{a as TRUSTED_TYPES_POLICY_SLOT,s as VERSION,t as bootstrapState,u as buildBindings,r as defineState,n as getBindingsReady,i as getConfig,c as getTrustedTypesPolicy,o as installFeatures,h as setTrustedTypesPolicy};
|
|
2
|
+
//# sourceMappingURL=core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["defineState","definition","r","d","i","y","l","o","n","s","t","a"],"sources":["../../src/public/defineState.ts"],"sourcesContent":["/**\n * defineState.ts\n *\n * 状態オブジェクトに型付けを提供するためのユーティリティ。\n * defineState() はアイデンティティ関数で、ThisType<> を付与することで\n * メソッド・computed getter 内の this に型補完を提供する。\n *\n * テンプレートリテラル型によるドットパスの型解決:\n * - WcsPaths<T> : T から生成される全ドットパスの union\n * - WcsPathValue<T,P>: パス P に対応する値の型\n * - WcsPathAccessor<T>: ブラケットアクセス用マップ型\n */\n\n// ============================================================\n// Internal helper types\n// ============================================================\n\n/**\n * `any` 型を検出する。\n * `0 extends (1 & T)` は T が `any` の場合のみ true になる。\n */\ntype IsAny<T> = 0 extends (1 & T) ? true : false;\n\n/**\n * T がドットパス再帰の対象となる「プレーンなデータオブジェクト」かどうかを判定する。\n * プリミティブ、組み込みオブジェクト (Date, Map 等)、関数、配列、any は除外。\n */\ntype IsPlainObject<T> =\n IsAny<T> extends true ? false :\n T extends\n | string | number | boolean | null | undefined | symbol | bigint\n | ((...args: any[]) => any) | Date | RegExp | Error\n | Map<any, any> | Set<any> | WeakMap<any, any> | WeakSet<any>\n | Promise<any> | readonly any[]\n ? false\n : T extends Record<string, any>\n ? true\n : false;\n\n/**\n * T のキーのうち、関数でないもの(データプロパティ・computed getter)を抽出する。\n * メソッド(イベントハンドラ等)はドットパスの対象外。\n * `$` プレフィックスキー($streams / $commandTokens / $on 等の予約宣言)もドットパスにならない。\n * any 型のプロパティは除外せず保持する。\n */\ntype DataKeys<T> = {\n [K in keyof T & string]:\n K extends `$${string}` ? never :\n IsAny<T[K]> extends true ? K : T[K] extends (...args: any[]) => any ? never : K;\n}[keyof T & string];\n\n// ============================================================\n// WcsPaths — ドットパスの union 生成\n// ============================================================\n\n/**\n * 型 T から生成される全てのドットパスの union。\n * 配列プロパティはワイルドカード `*` を使用: `items.*.name`\n *\n * 再帰の深さは最大4レベルに制限(コンパイル性能の確保)。\n *\n * @example\n * ```ts\n * type S = {\n * count: number;\n * users: { name: string; age: number }[];\n * cart: { items: { price: number }[] };\n * };\n * type P = WcsPaths<S>;\n * // = \"count\" | \"users\" | \"users.*\" | \"users.*.name\" | \"users.*.age\"\n * // | \"cart\" | \"cart.items\" | \"cart.items.*\" | \"cart.items.*.price\"\n * ```\n */\nexport type WcsPaths<T, Depth extends readonly any[] = []> =\n Depth[\"length\"] extends 4 ? never :\n {\n [K in DataKeys<T>]:\n | K\n | (T[K] extends readonly (infer E)[]\n ? IsPlainObject<E> extends true\n ? `${K}.*` | WcsSubPaths<E, `${K}.*.`, [...Depth, 0]>\n : `${K}.*`\n : IsPlainObject<T[K]> extends true\n ? WcsSubPaths<T[K], `${K}.`, [...Depth, 0]>\n : never)\n }[DataKeys<T>];\n\n/** @internal プレフィックス付きサブパスの生成ヘルパー */\ntype WcsSubPaths<T, Prefix extends string, Depth extends readonly any[]> =\n WcsPaths<T, Depth> extends infer P extends string\n ? `${Prefix}${P}`\n : never;\n\n// ============================================================\n// WcsPathValue — パスから値の型を解決\n// ============================================================\n\n/**\n * ドットパス P に対応する値の型を T から解決する。\n *\n * 解決順序:\n * 1. T の直接キー(computed getter 含む)\n * 2. `K.*` → 配列要素型\n * 3. `K.rest` → オブジェクト/配列のネストを再帰的に辿る\n *\n * @example\n * ```ts\n * type S = { cart: { items: { price: number; qty: number }[] } };\n * type V1 = WcsPathValue<S, \"cart.items.*.price\">; // number\n * type V2 = WcsPathValue<S, \"cart.items.*\">; // { price: number; qty: number }\n * type V3 = WcsPathValue<S, \"cart\">; // { items: ... }\n * ```\n */\nexport type WcsPathValue<T, P extends string> =\n // 1. Direct key (includes computed getters like \"users.*.ageCategory\")\n P extends keyof T\n ? T[P]\n // 2. K.* → array element type\n : P extends `${infer K}.*`\n ? K extends keyof T\n ? T[K] extends readonly (infer E)[] ? E : never\n : never\n // 3. K.rest → recurse into nested structure\n : P extends `${infer K}.${infer Rest}`\n ? K extends keyof T\n ? T[K] extends readonly (infer E)[]\n // Array: expect *.subpath or *\n ? Rest extends `*.${infer SubRest}`\n ? WcsPathValue<E, SubRest>\n : Rest extends \"*\"\n ? E\n : never\n // Object: recurse\n : T[K] extends Record<string, any>\n ? WcsPathValue<T[K], Rest>\n : never\n : never\n : never;\n\n// ============================================================\n// WcsPathAccessor — ブラケットアクセス用マップ型\n// ============================================================\n\n/**\n * 全ドットパスに対する型付きブラケットアクセスを提供するマップ型。\n *\n * `this[\"users.*.name\"]` のようなアクセスに対して、\n * WcsPaths で生成されたパスに対応する値の型を返す。\n */\ntype WcsPathAccessor<T> = {\n [P in WcsPaths<T>]: WcsPathValue<T, P>;\n};\n\n// ============================================================\n// State Proxy API — this 経由でアクセスできるAPI\n// ============================================================\n\n/**\n * `<wcs-state>` の Proxy 経由で提供されるAPIメソッド。\n * state定義オブジェクト内のメソッド・getter で `this.` 経由で利用可能。\n */\nexport interface WcsStateApi {\n /**\n * ワイルドカードを含むパスにマッチする全要素を配列で取得する。\n *\n * @param path - ワイルドカードを含むパス\n * @param indexes - 各ワイルドカード階層のインデックス(前方一致の接頭辞。`[]` は全階層を展開)。\n * 省略時はループ文脈の添字(`[$1..$n]` 相当)のうち path と共有するワイルドカード連鎖の\n * 分が接頭辞として敷かれる(文脈が path より深い分は切り詰め)。共有が無いのに文脈が\n * 添字を持つ場合は throw する — 異なる文脈の添字は流用しない。\n *\n * @example\n * ```ts\n * get \"cart.totalPrice\"() {\n * return this.$getAll(\"cart.items.*.price\").reduce((sum, v) => sum + v, 0);\n * }\n * ```\n */\n $getAll<V = any>(path: string, indexes?: number[]): V[];\n\n /**\n * ワイルドカードを含むパスにマッチする**全アドレスへ一括で書き込む**(`$getAll` の対称形)。\n *\n * 配列を作り直さずに一括更新するための API。`this.users = this.users.map(...)` は\n * ListIndex・行 getter キャッシュ・差分描画をまとめて作り直すが、`$setAll` は\n * in-place な個別書き込みに分解するのでリストの同一性が保たれる。\n *\n * - `indexes` は `$getAll` と同じ**前方一致の接頭辞**(`[]` で全階層を展開)。省略は不可。\n * - 関数を渡すと **mapper**(`(current, ...indexes) => next`)として要素ごとに評価される。\n * - 配列は既定でブロードキャストされる。1 件ずつ配るには `{ spread: true }` を明示する。\n * - `undefined` を書こうとした要素はスキップされる(クリアは `null`)。\n *\n * @returns 実際に書き込んだ件数(`undefined` でスキップした分を含まない)\n *\n * @example\n * ```ts\n * toggleAll(e: Event) {\n * this.$setAll(\"users.*.selected\", [], (e.target as HTMLInputElement).checked);\n * }\n * invertAll() {\n * this.$setAll(\"users.*.selected\", [], cur => !cur);\n * }\n * ```\n */\n $setAll<V = any>(\n path: string,\n indexes: number[],\n value: V | ((current: V, ...indexes: number[]) => V | undefined),\n ): number;\n $setAll<V = any>(\n path: string,\n indexes: number[],\n values: readonly V[],\n options: { spread: true },\n ): number;\n\n /**\n * 指定パスの更新を手動でトリガーする。\n * Proxy の set トラップを経由せずに内部状態を変更した場合に使用。\n */\n $postUpdate(path: string): void;\n\n /**\n * パスとインデックス配列を指定して、ワイルドカードを解決した値を取得・設定する。\n *\n * @param path - ワイルドカードを含むパス\n * @param indexes - 各ワイルドカード階層のインデックス\n * @param value - 設定する値(省略時は取得)\n */\n $resolve(path: string, indexes: number[], value?: any): any;\n\n /**\n * 指定パスへの依存関係を明示的に登録する。\n * computed getter 内で動的にパスを組み立てる場合に使用。\n */\n $dependOn(path: string): void;\n\n /**\n * コールバック実行中の依存追跡(動的依存・`$1` インデックス依存の登録)を\n * 抑止して fn を実行し、その戻り値を返す。\n * リスト行 getter が「行外の単一値」を読みたいが、その値の変更で全行を\n * 再評価させたくない場合に使う(該当行へ直接書き込む設計と組で用いる)。\n */\n $untracked<T>(fn: () => T): T;\n\n /**\n * 鍵付き購読: `path` の現在値が `key` に等しいかを返し、評価中のリスト行 getter を\n * その鍵で購読する。`path` への書き込みは旧値・新値の鍵の行だけを再評価する\n * (パターン依存なら全行)。`path` 自体は依存として追跡しない。\n * 例: `get \"items.*.selected\"() { return this.$eq(\"selectedId\", this.$untracked(() => this[\"items.*.id\"])); }`\n */\n $eq(path: string, key: unknown): boolean;\n\n /**\n * `$eq` の鍵を `keyPath`(ワイルドカードは評価中の行で解決)から依存を張らずに読む形。\n * 例: `get \"items.*.selected\"() { return this.$eqPath(\"selectedId\", \"items.*.id\"); }`\n */\n $eqPath(path: string, keyPath: string): boolean;\n\n /**\n * `$eq` の鍵を評価中の行の index(`$1` 相当。`level` でワイルドカード段を選ぶ)にする形。\n * getter を index 依存には記録せず、行の移動時はリスト差分が鍵を付け替えるので、\n * 1 行削除で再評価されるのは高々 2 行。\n * 例: `get \"items.*.selected\"() { return this.$eqIndex(\"selectedIndex\"); }`\n */\n $eqIndex(path: string, level?: number): boolean;\n\n /** `<wcs-state>` 要素への参照 */\n readonly $stateElement: HTMLElement;\n\n /**\n * `$commandTokens` で宣言した command token の名前空間。\n * `this.$command.<name>` で token を解決できる(バインディングでは\n * `onclick: $command.<name>` / `command.<method>: $command.<name>`)。\n */\n readonly $command: Record<string, { emit(...args: any[]): any }>;\n\n /** `$stream` 各エントリの状態(\"idle\" | \"active\" | \"done\" | \"error\")を返す読み取り専用名前空間 */\n readonly $streamStatus: Record<string, \"idle\" | \"active\" | \"done\" | \"error\">;\n\n /** `$stream` 各エントリの直近エラーを返す読み取り専用名前空間 */\n readonly $streamError: Record<string, unknown>;\n\n // computed getter 内での依存追跡付き読み取りの正規形は dotted パス\n // (`this[\"$streamStatus.<name>\"]` — docs/state-streams-design.md §4-3)\n readonly [key: `$streamStatus.${string}`]: \"idle\" | \"active\" | \"done\" | \"error\";\n readonly [key: `$streamError.${string}`]: unknown;\n\n // ループインデックス変数 ($1〜$9)\n // for テンプレート内のイベントハンドラで、ネストされたループの\n // 各階層のインデックスにアクセスするために使用。\n // (ランタイムは $1〜$128 まで解決するが、型宣言は実用域の $9 までとする)\n readonly $1: number;\n readonly $2: number;\n readonly $3: number;\n readonly $4: number;\n readonly $5: number;\n readonly $6: number;\n readonly $7: number;\n readonly $8: number;\n readonly $9: number;\n\n // `$recursion` 宣言済みの再帰パス(`this[\"nodes.**.total\"]`)。深さの族なので\n // `WcsPaths<T>` の有限展開には現れず、getter のキーに書いた 1 本しか T に現れない。\n // パターン索引で「`**` を含むキーは読める」とだけ言う(型は any — 深さを型で表せない\n // 以上、値の型も辿れない)。パターンは `**` を必ず含むので、通常のドットパスの型付けは\n // 損なわない。VS Code 拡張の preamble(vscode-wcs src/language/preamble.ts)と同じ形 —\n // 公開型面とエディタの型面は対で保つ。\n // 素の `nodes.**`(再帰 getter の中でノード自身に束縛される読み)は `.**.` を含まないので、\n // 末尾が `.**` のキーにも同じ索引を置く。\n readonly [key: `${string}.**.${string}`]: any;\n readonly [key: `${string}.**`]: any;\n}\n\n// ============================================================\n// WcsThis — state メソッド/getter 内の this の型\n// ============================================================\n\n/**\n * state定義オブジェクト内の `this` の型。\n *\n * - `T` のプロパティに型付きでアクセス可能(直接キー)\n * - `WcsPathAccessor<T>` によるネストされたドットパスの型付きアクセス\n * - `WcsStateApi` のメソッド ($getAll, $postUpdate 等) にアクセス可能\n * - 動的パス (`this[\\`items.${i}.name\\`]`) は型チェック対象外(キャストが必要)\n *\n * @example\n * ```ts\n * defineState({\n * count: 0,\n * users: [] as { name: string; age: number }[],\n * increment() {\n * this.count++; // number\n * this[\"users.*.name\"]; // string (パス型解決)\n * this.$getAll(\"users.*.age\"); // API\n * }\n * });\n * ```\n */\nexport type WcsThis<T> = T & WcsStateApi & WcsPathAccessor<T>;\n\n// ============================================================\n// defineState — 型付き状態定義関数\n// ============================================================\n\n/**\n * `<wcs-state>` 用の型付き状態オブジェクトを定義する。\n *\n * ランタイムではアイデンティティ関数(引数をそのまま返す)として動作し、\n * コストはゼロ。TypeScript の `ThisType<>` を利用して、メソッド・getter 内の\n * `this` に型補完を提供する。\n *\n * ### 基本的な使い方 (TypeScript)\n * ```ts\n * import { defineState } from '@wcstack/state/define';\n *\n * export default defineState({\n * count: 0,\n * users: [] as { name: string; age: number }[],\n *\n * increment() {\n * this.count++; // ✅ number\n * this[\"users.*.name\"]; // ✅ string (ドットパス型解決)\n * },\n *\n * get \"users.*.ageCategory\"() {\n * return this[\"users.*.age\"] < 25 ? \"Young\" : \"Adult\";\n * }\n * });\n * ```\n *\n * ### JavaScript (JSDoc)\n * ```js\n * import { defineState } from '@wcstack/state/define';\n *\n * export default defineState({\n * count: 0,\n * increment() {\n * this.count++; // ✅ JSDoc + tsconfig checkJs で型補完\n * }\n * });\n * ```\n *\n * ### HTML インラインスクリプト\n * ```html\n * <wcs-state>\n * <script type=\"module\">\n * import { defineState } from '@wcstack/state/define';\n * export default defineState({\n * count: 0,\n * increment() { this.count++; }\n * });\n * </script>\n * </wcs-state>\n * ```\n *\n * ### ライフサイクルコールバック\n * ```ts\n * export default defineState({\n * data: null,\n * async $connectedCallback() {\n * this.data = await fetch('/api/data').then(r => r.json());\n * },\n * $disconnectedCallback() {\n * // cleanup\n * },\n * $renderedCallback() {\n * // called after the bindings are applied\n * }\n * });\n * ```\n */\nexport function defineState<T extends Record<string, any>>(\n definition: T & ThisType<WcsThis<T>>\n): T {\n return definition;\n}\n"],"mappings":"ydA4ZO,SAASA,EACdC,GAEA,OAAOA,CACT,QAAAC,+BAAAC,aAAAC,oBAAAC,mBAAAC,iBAAAC,sBAAAC,eAAAC,2BAAAC,qBAAAC","ignoreList":[]}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import{a as e}from"../chunks/chunk-
|
|
1
|
+
import{a as e}from"../chunks/chunk-LXEEVZIB.js";import{c as t,d as n,e as l,f as o,g as s,h as r,i as a,n as i}from"../chunks/chunk-L3PFEJP7.js";import"../chunks/chunk-W4KOY6GT.js";import"../chunks/chunk-7AYOQHZH.js";import"../chunks/chunk-M5SODAAE.js";import"../chunks/chunk-ZN52NEIB.js";import"../chunks/chunk-NOPTR2L3.js";import"../chunks/chunk-EIMTT5I3.js";import{a as u,b as d}from"../chunks/chunk-4NJBYXIT.js";var f="__WCSTACK_DEVTOOLS_HOOK__",c=null,m=new Set,p=(e,t,n)=>({absolutePathInfo:{pathInfo:{path:t.t},stateElement:e.element},listIndex:null===n?null:{indexes:e.H(n)}}),h=new WeakMap,k=0;var v=new WeakMap;function g(e){if(null===c)return;let i=v.get(e),u=m.has(e)?function(e,i){let u=new Map,d=new Set,f=(r,a,d,f,c,m)=>{if(r===s)return;let v=function(e,s){return e===t?"textContent":e===n?`class.${s}`:e===l?`attr.${s}`:e===o?`style.${s}`:s}(r,a),g=0===f.n?null:c,w=`${(e=>{let t=h.get(e);return void 0===t&&h.set(e,t=++k),t})(d)}|${v}|${f.t}|${null===g?"":e.H(g).join(",")}`;if(u.has(w))return;let y=i?.get(w);u.set(w,y??{binding:{propName:v,statePathName:f.t,bindingType:m,node:d,replaceNode:d},absoluteAddress:p(e,f,g)})},c=e=>f(e.i,e.name,e.a,e.o,e.r,e.nn()),m=e=>{if(!d.has(e)){if(d.add(e),null!==e.he)for(let t of e.he)c(t);if(e instanceof r&&null!==e.fe){let n=e.F.ze;for(let l=0;l<n.length;l++){let o=e.V?.[l];void 0!==o?c(o):f(n[l].i,n[l].name,e.fe[2*l],n[l].o,e.r,n[l].i===t?"text":"prop")}}if(null!==e.c)for(let t of e.c)v(t)}},v=e=>{if(!d.has(e))if(d.add(e),e instanceof a){f(-1,"for",e.S,e.l.o,e.l.ae,"for");for(let t of e.Ne)m(t)}else null!==e.O&&m(e.O)};for(let t of e.ce.values())for(let e of t)c(e),null!==e._&&v(e._);for(let t of e.oe.values())if(null!==t.E&&v(t.E),null!==t.L)for(let e of t.L)v(e);return u}(e,i):new Map;if(void 0!==i)for(let[e,t]of i)u.has(e)||c({type:"state:binding-removed",...t});for(let[e,t]of u)(void 0===i||!i.has(e))&&c({type:"state:binding-added",...t});v.set(e,u)}function w(e){let t=i.get(e);if(void 0===t)throw new Error("[@wcstack/state] devtools: no state tree on this root");return t}function y(e){let t=new Set,n=new Set,l=new Set,o=new Set;for(let s of e.I.all()){for(let e=1;e<=s.n;e++)t.add(s.h[e].t);"*"===s.s&&n.add(s.t),null!==s.getter&&l.add(s.t),null!==s.ie&&o.add(s.t)}let s=e.target;return{rootNode:e.root,element:e.element,paths:{list:t,element:n,getter:l,setter:o},commandTokenNames:new Set(Object.keys(e.commands)),eventTokenNames:new Set(e.Re.keys()),staticDependency:new Map,dynamicDependency:new Map,watchPaths:null!==s.$watch&&"object"==typeof s.$watch?new Set(Object.keys(s.$watch)):null,keyedListPaths:null!==s.$listKeys&&"object"==typeof s.$listKeys?new Set(Object.keys(s.$listKeys)):null}}var S=new WeakSet,b=new WeakMap;function j(e,t){if(("mounting"===t||"reset"===t)&&function(e){let t=(t,n)=>{if(S.has(t))return;S.add(t);let l=t.emit;t.emit=(...o)=>(null!==c&&c({type:"state:token-emit",kind:n,tokenName:t.name,args:o,subscriberCount:t.size,stateElement:e.element}),l.apply(t,o))};for(let n of Object.values(e.commands))t(n,"command");for(let n of e.Re.values())t(n,"event")}(e),"connected"===t){if(m.has(e))return;m.add(e),c?.({type:"state:element-registered",rootNode:e.root,element:e.element}),g(e)}else"disconnected"===t&&(m.delete(e),g(e),c?.({type:"state:element-unregistered",rootNode:e.root,element:e.element}))}function O(e,t,n,l,o,s){if(null===c)return;let r=p(e,t,0===t.n?null:n),a=b.get(e);void 0===a&&b.set(e,a=new Set),a.add(r),s&&c({type:"state:write",absoluteAddress:r,value:o,oldValue:l,hasOldValue:!0})}function $(e){if(null===c)return;let t=b.get(e);b.delete(e),void 0!==t&&c({type:"state:update-batch",addresses:t}),g(e)}function E(e,t,n){c?.({type:"state:binding-apply-error",path:n.o.t,bindingType:n.nn(),error:t})}var N={name:"devtools",install(){u.element=d(u.element,j),u.be=d(u.be,O),u.Fe=d(u.Fe,$),u.Ke=d(u.Ke,E),function(){if(typeof document>"u"||document.documentElement?.hasAttribute("data-wcs-server"))return;let t=globalThis,n=t[f]??(t[f]=function(){let e=new Map,t=new Set,n=e=>{0===t.size?e._setSink(null):e._setSink(n=>{for(let l of t)l.onEvent?.(e.id,n)})};return{version:2,sources:e,register(l){if(!e.has(l.id)){e.set(l.id,l),n(l);for(let e of t)e.onSourceRegistered?.(l)}},unregister(n){let l=e.get(n);if(void 0!==l){l._setSink(null),e.delete(n);for(let e of t)e.onSourceUnregistered?.(n)}},addListener(l){t.add(l);for(let t of e.values())n(t),l.onSourceRegistered?.(t);return()=>{if(t.delete(l))for(let t of e.values())n(t)}}}}());2!==n.version&&console.warn(`[@wcstack/state] devtools hook registry version ${n.version}, expected 2: keeping the existing one.`),n.register({id:`state:${Math.random().toString(36).slice(2,10)}`,kind:"state",packageVersion:e,getStateElements:()=>[...m].map(y),overlays:()=>[],keyedSubscriptions:e=>function(e){let t=[];for(let n of e.I.all()){let l=n.W,o=n.Ce?.length??0;if((null===l||0===l.size)&&0===o)continue;let s,r=0;if(null!==l)for(let e of l.values())r+=e.size;try{s=0===n.n?e.v(n,null):void 0}catch{s=void 0}t.push({path:n.t,tracked:!1,rows:r,keys:null===l?0:l.size,lists:o,lastValue:s})}return t}(w(e)),keys(e){let t=w(e).target;return Object.keys(t).filter(e=>{if(e.includes("*")||"$"===e[0])return!1;let n=Object.getOwnPropertyDescriptor(t,e);return void 0!==n.get||"function"!=typeof n.value})},read(e,t,n){let l;return w(e).element.createState("readonly",e=>{l=e.$resolve(t,n??[])}),l},write(e,t,n,l){w(e).element.createState("writable",e=>{e.$resolve(t,l??[],n)})},_setSink(e){let t=null===c&&null!==e;c=e,null===e&&(v=new WeakMap),u.st=e&&((e,t)=>c?.({...t,stateElement:e.element})),t&&queueMicrotask(()=>{for(let e of m)g(e)})}})}()}},M=N;export{M as default,N as devtools};
|
|
2
|
+
//# sourceMappingURL=devtools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["HOOK","sink","live","Set","address","engine","p","row","absolutePathInfo","pathInfo","path","stateElement","element","listIndex","indexes","indexesOf","nodeIds","WeakMap","nodeSeq","ledgers","sync","old","get","now","has","out","Map","seen","add","kind","name","node","type","K_EVENT","prop","K_TEXT","K_CLASS","K_ATTR","K_STYLE","propName","r","depth","key","n","id","set","idOf","join","kept","binding","statePathName","bindingType","replaceNode","absoluteAddress","b","pattern","typeName","block","bindings","x","RowView","slots","lazy","plan","k","length","made","bound","children","v","view","ForView","anchor","list","parentRow","rv","rowViews","current","bs","rootBindings","values","chain","l","rootLists","extra","snapshot","e","engineOf","root","engines","Error","summary","getter","setter","patterns","all","lists","last","t","target","rootNode","paths","commandTokenNames","Object","keys","commands","eventTokenNames","events","staticDependency","dynamicDependency","watchPaths","$watch","keyedListPaths","$listKeys","wrapped","WeakSet","batches","devtoolsElement","phase","wrap","emit","args","tokenName","subscriberCount","size","apply","wrapTokens","delete","devtoolsWritten","value","direct","a","batch","oldValue","hasOldValue","devtoolsDrained","addresses","devtoolsFailed","_engine","error","devtools","install","hooks","written","drained","failed","document","documentElement","hasAttribute","g","globalThis","registry","sources","listeners","s","_setSink","event","onEvent","version","register","onSourceRegistered","unregister","onSourceUnregistered","addListener","createRegistry","console","warn","Math","random","toString","slice","packageVersion","VERSION","getStateElements","map","overlays","keyedSubscriptions","subs","eqSubs","eqIndexWatchers","lastValue","rows","readUntracked","push","tracked","filter","includes","d","getOwnPropertyDescriptor","read","createState","$resolve","write","next","attached","noticed","queueMicrotask","registerSource","devtools_default"],"sources":["../../../src/devtools/devtools.ts","../../../src/features/devtools.ts"],"sourcesContent":["/**\n * DevTools (`@wcstack/devtools`) — the DevTools Hook Protocol v2 (docs/devtools-hook-protocol.ja.md),\n * spoken by an add-on so the engine pays nothing while no DevTools is attached.\n *\n * The protocol's pulls (the roster, keys, read, write, keyed subscriptions) read the engines; its\n * events come from the add-on hooks (written, drained, failed, the element lifecycle) and from\n * the tokens, wrapped per engine. Addresses and bindings are small plain objects of the shape\n * DevTools reads (`absolutePathInfo.pathInfo.path`, `listIndex.indexes`, `propName`,\n * `statePathName`, `bindingType`, `node`), built only while a sink is set. Every key that\n * crosses to DevTools is quoted: the build shortens internal names, some of which (`kind`,\n * `path`, `node`, `propName`, …) are also the protocol's.\n *\n * The one part v2 builds from the engine's own bookkeeping — \"binding added / removed\" — the new\n * engine does not have (row bindings are lazy slots, made on their first change). While DevTools\n * is attached, the add-on takes the list of bindings after every drain (materialized ones and\n * slots alike) and reports the difference: DevTools sees the same live ledger, at a cost paid\n * only then.\n */\nimport type { Engine } from \"../engine\";\nimport type { Pattern } from \"../pattern\";\nimport type { StateRow } from \"../list\";\nimport type { Token } from \"../token\";\nimport { ForView, IfView, K_ATTR, K_CLASS, K_EVENT, K_STYLE, K_TEXT, type Binding, type Block, RowView, type Spec } from \"../dom/view\";\nimport { engines as byRoot } from \"../dom/mount\";\nimport { VERSION } from \"../version\";\nimport { hooks } from \"../hooks\";\n\nconst HOOK = \"__WCSTACK_DEVTOOLS_HOOK__\";\nconst PROTOCOL = 2;\n\ntype Sink = (event: Record<string, unknown>) => void;\ntype Source = Record<string, any>;\n\nlet sink: Sink | null = null;\n/** The attached DevTools' sink (analyzeContract forwards its events there). */\nexport const devtoolsSink = (): Sink | null => sink;\nconst live = new Set<Engine>();\n\n// ---------------------------------------------------------------- registry (first one wins)\n\nfunction createRegistry(): Record<string, unknown> {\n const sources = new Map<string, Source>();\n const listeners = new Set<Record<string, (...a: any[]) => void>>();\n const apply = (s: Source): void => {\n if (listeners.size === 0) s[\"_setSink\"](null);\n else s[\"_setSink\"]((event: unknown) => { for (const l of listeners) l[\"onEvent\"]?.(s[\"id\"], event); });\n };\n return {\n \"version\": PROTOCOL,\n \"sources\": sources,\n \"register\"(s: Source): void {\n if (sources.has(s[\"id\"])) return;\n sources.set(s[\"id\"], s);\n apply(s);\n for (const l of listeners) l[\"onSourceRegistered\"]?.(s);\n },\n \"unregister\"(id: string): void {\n const s = sources.get(id);\n if (s === undefined) return;\n s[\"_setSink\"](null);\n sources.delete(id);\n for (const l of listeners) l[\"onSourceUnregistered\"]?.(id);\n },\n \"addListener\"(l: Record<string, (...a: any[]) => void>): () => void {\n listeners.add(l);\n for (const s of sources.values()) {\n apply(s);\n l[\"onSourceRegistered\"]?.(s);\n }\n return () => {\n if (listeners.delete(l)) for (const s of sources.values()) apply(s);\n };\n },\n };\n}\n\n// ---------------------------------------------------------------- shapes DevTools reads\n\nconst address = (engine: Engine, p: Pattern, row: StateRow | null): Record<string, unknown> => ({\n \"absolutePathInfo\": { \"pathInfo\": { \"path\": p.path }, \"stateElement\": engine.element },\n \"listIndex\": row === null ? null : { \"indexes\": engine.indexesOf(row) },\n});\n\nfunction propName(kind: number, name: string): string {\n if (kind === K_TEXT) return \"textContent\";\n if (kind === K_CLASS) return `class.${name}`;\n if (kind === K_ATTR) return `attr.${name}`;\n if (kind === K_STYLE) return `style.${name}`;\n return name;\n}\n\n/** A binding as DevTools reads it: `{ binding, absoluteAddress }`. */\ntype Entry = Record<string, unknown>;\n\nconst nodeIds = new WeakMap<Node, number>();\nlet nodeSeq = 0;\nconst idOf = (n: Node): number => {\n let id = nodeIds.get(n);\n if (id === undefined) nodeIds.set(n, (id = ++nodeSeq));\n return id;\n};\n\n/** Every binding of the engine now — materialized ones and row slots alike — by identity. */\nfunction snapshot(engine: Engine, old: Map<string, Entry> | undefined): Map<string, Entry> {\n const out = new Map<string, Entry>();\n const seen = new Set<object>();\n const add = (kind: number, name: string, node: Node, p: Pattern, row: StateRow | null, type: string): void => {\n if (kind === K_EVENT) return;\n const prop = propName(kind, name);\n const r = p.depth === 0 ? null : row;\n const key = `${idOf(node)}|${prop}|${p.path}|${r === null ? \"\" : engine.indexesOf(r).join(\",\")}`;\n if (out.has(key)) return;\n const kept = old?.get(key);\n out.set(key, kept ?? {\n \"binding\": { \"propName\": prop, \"statePathName\": p.path, \"bindingType\": type, \"node\": node, \"replaceNode\": node },\n \"absoluteAddress\": address(engine, p, r),\n });\n };\n const binding = (b: Binding): void => add(b.kind, b.name, b.node, b.pattern, b.row, b.typeName());\n const block = (b: Block): void => {\n if (seen.has(b)) return;\n seen.add(b);\n if (b.bindings !== null) for (const x of b.bindings) binding(x);\n if (b instanceof RowView && b.slots !== null) {\n const lazy: Spec[] = b.plan.lazy;\n for (let k = 0; k < lazy.length; k++) {\n const made = b.bound?.[k];\n if (made !== undefined) binding(made);\n else add(lazy[k].kind, lazy[k].name, b.slots[2 * k] as Node, lazy[k].pattern!, b.row, lazy[k].kind === K_TEXT ? \"text\" : \"prop\");\n }\n }\n if (b.children !== null) for (const v of b.children) view(v);\n };\n const view = (v: ForView | IfView): void => {\n if (seen.has(v)) return;\n seen.add(v);\n if (v instanceof ForView) {\n // the list binding itself: v2 has one per `for`, on the anchor that replaced the template\n add(-1, \"for\", v.anchor, v.list.pattern, v.list.parentRow, \"for\");\n for (const rv of v.rowViews) block(rv);\n } else if (v.current !== null) block(v.current);\n };\n for (const bs of engine.rootBindings.values()) {\n for (const b of bs) {\n binding(b);\n if (b.chain !== null) view(b.chain);\n }\n }\n for (const l of engine.rootLists.values()) {\n if (l.view !== null) view(l.view);\n if (l.extra !== null) for (const v of l.extra) view(v);\n }\n return out;\n}\n\nlet ledgers = new WeakMap<Engine, Map<string, Entry>>();\n\n/** Reports the bindings added and removed since the last look. */\nfunction sync(engine: Engine): void {\n if (sink === null) return;\n const old = ledgers.get(engine);\n const now = live.has(engine) ? snapshot(engine, old) : new Map<string, Entry>();\n if (old !== undefined) for (const [k, e] of old) if (!now.has(k)) sink({ \"type\": \"state:binding-removed\", ...e });\n for (const [k, e] of now) if (old === undefined || !old.has(k)) sink({ \"type\": \"state:binding-added\", ...e });\n ledgers.set(engine, now);\n}\n\n// ---------------------------------------------------------------- the pulls\n\nfunction engineOf(root: Node): Engine {\n const e = byRoot.get(root);\n if (e === undefined) throw new Error(\"[@wcstack/state] devtools: no state tree on this root\");\n return e;\n}\n\nfunction summary(engine: Engine): Record<string, unknown> {\n const list = new Set<string>();\n const element = new Set<string>();\n const getter = new Set<string>();\n const setter = new Set<string>();\n for (const p of engine.patterns.all()) {\n for (let k = 1; k <= p.depth; k++) list.add(p.lists[k]!.path);\n if (p.last === \"*\") element.add(p.path);\n if (p.getter !== null) getter.add(p.path);\n if (p.setter !== null) setter.add(p.path);\n }\n const t = engine.target;\n return {\n \"rootNode\": engine.root,\n \"element\": engine.element,\n \"paths\": { \"list\": list, \"element\": element, \"getter\": getter, \"setter\": setter },\n \"commandTokenNames\": new Set(Object.keys(engine.commands)),\n \"eventTokenNames\": new Set(engine.events.keys()),\n \"staticDependency\": new Map(),\n \"dynamicDependency\": new Map(),\n \"watchPaths\": t.$watch !== null && typeof t.$watch === \"object\" ? new Set(Object.keys(t.$watch)) : null,\n \"keyedListPaths\": t.$listKeys !== null && typeof t.$listKeys === \"object\" ? new Set(Object.keys(t.$listKeys)) : null,\n };\n}\n\nfunction keyedSubscriptions(engine: Engine): Record<string, unknown>[] {\n const out: Record<string, unknown>[] = [];\n for (const p of engine.patterns.all()) {\n const subs = p.eqSubs;\n const lists = p.eqIndexWatchers?.length ?? 0;\n if ((subs === null || subs.size === 0) && lists === 0) continue;\n let rows = 0;\n if (subs !== null) for (const s of subs.values()) rows += s.size;\n let lastValue: unknown;\n try { lastValue = p.depth === 0 ? engine.readUntracked(p, null) : undefined; } catch { lastValue = undefined; }\n out.push({ \"path\": p.path, \"tracked\": false, \"rows\": rows, \"keys\": subs === null ? 0 : subs.size, \"lists\": lists, \"lastValue\": lastValue });\n }\n return out;\n}\n\nfunction createSource(): Source {\n return {\n \"id\": `state:${Math.random().toString(36).slice(2, 10)}`,\n \"kind\": \"state\",\n \"packageVersion\": VERSION,\n \"getStateElements\": () => [...live].map(summary),\n \"overlays\": () => [],\n \"keyedSubscriptions\": (root: Node) => keyedSubscriptions(engineOf(root)),\n \"keys\"(root: Node): string[] {\n const t = engineOf(root).target;\n return Object.keys(t).filter((k) => {\n if (k.includes(\"*\") || k[0] === \"$\") return false;\n const d = Object.getOwnPropertyDescriptor(t, k)!;\n return d.get !== undefined || typeof d.value !== \"function\";\n });\n },\n \"read\"(root: Node, path: string, indexes?: number[]): unknown {\n const el = engineOf(root).element as any;\n let v: unknown;\n el.createState(\"readonly\", (s: any) => { v = s.$resolve(path, indexes ?? []); });\n return v;\n },\n \"write\"(root: Node, path: string, value: unknown, indexes?: number[]): void {\n const el = engineOf(root).element as any;\n el.createState(\"writable\", (s: any) => { s.$resolve(path, indexes ?? [], value); });\n },\n \"_setSink\"(next: Sink | null): void {\n const attached = sink === null && next !== null;\n sink = next;\n // detached: the ledgers go — an attach after it is told every binding there, and none of\n // their nodes is held meanwhile\n if (next === null) ledgers = new WeakMap();\n // what the add-ons notice ($watch fired / threw / cut, a path that does not resolve), with the\n // tree it came from (`stateElement`): built only while a DevTools is attached\n hooks.noticed = next && ((engine, event) => sink?.({ ...event, \"stateElement\": engine.element }));\n // a DevTools that attaches late sees the bindings there already\n if (attached) queueMicrotask(() => { for (const e of live) sync(e); });\n },\n };\n}\n\n// ---------------------------------------------------------------- the hooks\n\nconst wrapped = new WeakSet<Token>();\n\nfunction wrapTokens(engine: Engine): void {\n const wrap = (t: Token, kind: \"command\" | \"event\"): void => {\n if (wrapped.has(t)) return;\n wrapped.add(t);\n const emit = t.emit;\n t.emit = (...args: unknown[]) => {\n if (sink !== null) sink({ \"type\": \"state:token-emit\", \"kind\": kind, \"tokenName\": t.name, \"args\": args, \"subscriberCount\": t.size, \"stateElement\": engine.element });\n return emit.apply(t, args);\n };\n };\n for (const t of Object.values(engine.commands)) wrap(t, \"command\");\n for (const t of engine.events.values()) wrap(t, \"event\");\n}\n\nconst batches = new WeakMap<Engine, Set<unknown>>();\n\nexport function devtoolsElement(engine: Engine, phase: string): void {\n if (phase === \"mounting\" || phase === \"reset\") wrapTokens(engine);\n if (phase === \"connected\") {\n if (live.has(engine)) return;\n live.add(engine);\n sink?.({ \"type\": \"state:element-registered\", \"rootNode\": engine.root, \"element\": engine.element });\n sync(engine);\n } else if (phase === \"disconnected\") {\n live.delete(engine);\n sync(engine);\n sink?.({ \"type\": \"state:element-unregistered\", \"rootNode\": engine.root, \"element\": engine.element });\n }\n}\n\nexport function devtoolsWritten(engine: Engine, p: Pattern, row: StateRow | null, old: unknown, value: unknown, direct: boolean): void {\n if (sink === null) return;\n const a = address(engine, p, p.depth === 0 ? null : row);\n let batch = batches.get(engine);\n if (batch === undefined) batches.set(engine, (batch = new Set()));\n batch.add(a);\n if (direct) sink({ \"type\": \"state:write\", \"absoluteAddress\": a, \"value\": value, \"oldValue\": old, \"hasOldValue\": true });\n}\n\nexport function devtoolsDrained(engine: Engine): void {\n if (sink === null) return;\n const batch = batches.get(engine);\n batches.delete(engine);\n if (batch !== undefined) sink({ \"type\": \"state:update-batch\", \"addresses\": batch });\n sync(engine);\n}\n\nexport function devtoolsFailed(_engine: Engine, error: unknown, b: Binding): void {\n sink?.({ \"type\": \"state:binding-apply-error\", \"path\": b.pattern.path, \"bindingType\": b.typeName(), \"error\": error });\n}\n\nexport function registerSource(): void {\n if (typeof document === \"undefined\" || document.documentElement?.hasAttribute(\"data-wcs-server\")) return;\n const g = globalThis as any;\n const registry = g[HOOK] ?? (g[HOOK] = createRegistry());\n if (registry[\"version\"] !== PROTOCOL) console.warn(`[@wcstack/state] devtools hook registry version ${registry[\"version\"]}, expected ${PROTOCOL}: keeping the existing one.`);\n registry[\"register\"](createSource());\n}\n","/**\n * The DevTools add-on (@wcstack/state/features/devtools): `@wcstack/devtools` over the hook\n * protocol v2 — see src/devtools/devtools.ts.\n */\nimport { chain, hooks, type Feature } from \"../hooks\";\nimport { devtoolsDrained, devtoolsElement, devtoolsFailed, devtoolsWritten, registerSource } from \"../devtools/devtools\";\n\nexport const devtools: Feature = {\n name: \"devtools\",\n install(): void {\n hooks.element = chain(hooks.element, devtoolsElement);\n hooks.written = chain(hooks.written, devtoolsWritten);\n hooks.drained = chain(hooks.drained, devtoolsDrained);\n hooks.failed = chain(hooks.failed, devtoolsFailed);\n registerSource();\n },\n};\nexport default devtools;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import{b as e,c as t,h as n,j as a}from"../chunks/chunk-LTBR3OV5.js";import{a as i,d as s,f as r}from"../chunks/chunk-W5KT4PQ3.js";import{e as o}from"../chunks/chunk-2EGTC36Y.js";import"../chunks/chunk-SPWZUBQS.js";import{b as l}from"../chunks/chunk-ALVA5TQM.js";import{a as d,b as c,c as u,e as f,j as h}from"../chunks/chunk-V34ZHCK5.js";function $(e,t,n){if(Math.abs(e.length-t.length)>n)return n+1;let a=new Array(t.length+1),i=new Array(t.length+1);for(let e=0;e<=t.length;e++)a[e]=e;for(let n=1;n<=e.length;n++){i[0]=n;for(let s=1;s<=t.length;s++){let r=e[n-1]===t[s-1]?0:1;i[s]=Math.min(a[s]+1,i[s-1]+1,a[s-1]+r)}for(let e=0;e<=t.length;e++)a[e]=i[e]}return a[t.length]}function p(e,t){if(0===e.length)return"";let n=e.toLowerCase(),a=null,i=3;for(let e of t){let t=$(n,e.toLowerCase(),2);t<i&&(a=e,i=t)}return null!==a?` Did you mean "${a}"?`:""}var m=" Validate statically: npx @wcstack/lint <file>.",g=["","binding-syntax","template-syntax","binding-path-missing","binding-type-expectation","filter-unknown","filter-arity","getter-cycle","getter-depth-exceeded","index-arity","index-param-range","recursion-unsupported","token-misconfigured","token-undeclared","wildcard-rank","spread-no-bindable","declaration-alias","name-alias"],w=e=>{let t=g[e/100|0];return t?`[wcs/${t}] `:""},b=["enableMustache","sameValueGuard","enableDirectionalInitialSync"],y=(e,t)=>`<${e}${t.map((e,t)=>t%2?`="${e}"`:` ${e}`).join("")}>`,v="https://github.com/wcstack/wcstack/blob/main/docs/csp.md",k={1:()=>"$scan was removed (use $watch or $on)",2:e=>`"${e}" is a getter without a setter`,3:e=>`no row for "${e}"`,4:(e,t)=>`cannot write "${e}": its parent is ${t}`,5:e=>`"${e}" is not a method`,6:e=>`$getAll("${e}"): no loop level in common with the context`,7:e=>`$eqIndex("${e}") needs a list row scope.`,8:()=>"This state is readonly.",9:e=>`$setAll("${e}") needs indexes ([] for every match)`,10:(e,t)=>`$setAll("${e}", …, { spread: true }) needs an array of ${t} values`,11:()=>`updates did not settle after ${e} passes`,41:()=>`render chain depth limit exceeded (${t} drains that rendering itself started); bindings for this batch were not applied.`,12:(e,t)=>`binding "${e}: ${t}" failed to apply.`,13:(e,t)=>`failed to load "${e}": ${t}`,14:()=>"this <wcs-state> failed to initialize; create a new one",15:()=>"state is not initialized",16:e=>`no <script> with id "${e}"`,42:()=>`The inline <script> of <wcs-state> was blocked by Content-Security-Policy. Inline state is evaluated through a blob: URL: give the page's nonce to the <script> that loads @wcstack/state, or allow blob: in script-src. Moving the state into an external file (src="./state.js") needs neither. See ${v}`,43:e=>`Failed to evaluate the inline <script> of <wcs-state>: ${e}. If this page sets a Content-Security-Policy, see ${v}`,17:e=>`a subscriber of token "${e}" threw.`,18:e=>`${e} must be an array of strings.`,19:e=>`${e} entries must be non-empty strings.`,20:(e,t,n)=>`${e} entry "${t}" conflicts with the reserved namespace name "${n}".`,21:(e,t)=>`${e} entry "${t}" is duplicated.`,22:()=>"$on must be an object of handlers.",23:e=>`$on entry "${e}" is not declared in $eventTokens.`,24:e=>`$on entry "${e}" must be a function.`,25:e=>`view-transition naming-limit (${e}) reached.`,26:e=>`filter ${e} requires at least one option`,27:e=>`filter ${e} requires a number as option`,28:e=>`filter ${e} requires a number value`,29:e=>`filter ${e} requires a date value`,30:e=>`filter ${e} requires an array value`,31:()=>"init=/sync= modifiers require enableDirectionalInitialSync.",33:(e,t)=>`Unknown binding modifier "${e}" in "${t}".`,34:e=>`Binding modifier "${e}" may only be specified once.`,35:(e,t)=>`Invalid ${e} modifier value "${t}".`,36:()=>"Event bindings only allow init=none.",37:(e,t)=>`Binding type "${e}" does not support init=${t}.`,38:e=>`Property "${e}" is not declared by wcBindable.`,39:(e,t)=>`init=${e} is incompatible with wcBindable member "${t}".`,40:e=>`sync=connect requires observable property "${e}".`,44:(e,t)=>`${e}: "${t}" is not one of its options, or not of the option's type.${"bootstrapState"===e&&b.includes(t)?" 4.0 moved it to the state's $behavior.":""}`,45:()=>"a re-set state may not change $behavior: create the element again.",47:()=>'a second <wcs-state> on the same root: there is one state tree per root — graft a subtree with <wcs-state mount="path"> (v1\'s name="…" is gone: read the mounted state by its path).',48:e=>`the locale "${e}" (<html lang> or bootstrapState's locale) is not a language tag Intl takes (en-US, not en_US): the locale filters use "en".`,46:()=>'$features must be an array of add-on names (["temporal", "formats"]).',49:(e,...t)=>`${y(e,t)} failed to initialize.`,50:(e,...t)=>`${y(e,t)} $connectedCallback failed.`,51:(e,...t)=>`${y(e,t)} $disconnectedCallback failed.`,101:e=>`Invalid bindText: "${e}". Missing ':' separator between propPart and statePart.`,102:(e,t)=>`"${e}": "${t}" takes no modifiers or filters on its left side — write "${t}:".`,103:e=>`"${e}": "else" takes no value — write "else:".`,104:e=>`Invalid spread binding "${e}": spread target path is required.`,105:e=>`Invalid spread binding "${e}": filters are not allowed on spread targets.`,106:e=>`"${e}": a leading "." binds an element property by name — write a non-empty property that is not a namespace (class, attr, style, command, eventToken, state).`,107:(e,t)=>`unterminated ${e} quote in the filter arguments "(${t})". Close the quote.`,108:e=>`Invalid filter format: missing closing parenthesis in "${e}".`,109:e=>`Invalid filter format: missing opening parenthesis in "${e}".`,110:e=>`Invalid filter format: ")" comes before "(" in "${e}".`,111:(e,t)=>`"${e}": unexpected "${t}" after the filter's closing ")" — separate filters with "|" (write "${e.slice(0,e.lastIndexOf(")")+1)}|${t}").`,112:e=>`an empty filter in "${e}" — remove the extra "|" or name the filter.`,113:(e,t)=>`"${e}" is not a filter name: a modifier list "#${t}" comes before the input filters, not inside one`,114:e=>`"${e}" is not a filter name: "#" cannot appear in one.`,115:e=>`"${e}": a binding takes one modifier list after a single "#"`,116:e=>`"${e}": the left side of a binding must name a property — write "<property>: <path>" (modifiers and input filters come after the name).`,117:(e,t)=>`"${e}" has ${t} path segments — the limit is 512.`,32:e=>`"${e}": the "@name" selector was removed in v2 — there is a single state tree. Mount the named state onto the tree (<wcs-state mount="...">) and read it by its path prefix instead.`,120:e=>`"${e}": a state path cannot go through "__proto__" or "prototype" (it would reach every object's prototype).`,121:e=>`"${e}": "for:" takes no filters — a row is "<path>.<index>", so the rows of a filtered list would name other elements. Declare a getter that returns the filtered list and loop over it ("for: <getter>").`,119:e=>`"${e}": the right side of a binding must name a state path — write "<property>: <path>" (a path segment cannot be empty; "." alone and a leading "." are the loop-relative shorthand).`,201:e=>`Invalid bindText: "${e}". 'if', 'elseif', 'else', and 'for' bindings must be single binding.`,202:e=>`"${e}:" must follow an "if:" template`,204:e=>`a "${e}:" template at the top of inserted content was not rendered, as it would render beside itself out of the inserter's reach: wrap it in an element.`,203:e=>`"${e}:" replaces its element, so it cannot be used inside a "for" / "if" template (a row or branch keeps its nodes by position): bind innerHTML: on a wrapper element instead.`,301:e=>`Path "${e}" does not exist on the state tree.`,401:(e,t)=>`class.${e} needs a boolean, got ${t}.`,501:e=>`filter not found: ${e}.`,601:(e,t,n)=>`filter "${e}" requires at least ${t} argument(s) (${n} given).`,602:(e,t,n)=>`filter "${e}" accepts at most ${t} argument(s) (${n} given).`,701:e=>`"${e}" depends on itself`,801:e=>`"${e}"`,901:(e,t,n,a)=>`${e}("${t}") takes ${n} index(es), got ${a}.`,902:(e,t,n,a)=>`${e}("${t}") takes at most ${n} index(es), got ${a}.`,1001:e=>`"${e}": list index parameters run from $1 to $128.`,1101:e=>`"${e}" uses "**", which is not accepted here.`,1201:(e,t)=>`"${e}: ${t}": the right-hand side must be $command.<name>`,1202:(e,t)=>`<${e}> declares no static wcBindable (${t}).${!e.includes("-")&&t.startsWith("command.")?" A native element's command needs the add-on @wcstack/state/features/native-commands.":""}`,1203:(e,t)=>`<${e}> declares no command "${t}".`,1204:(e,t)=>`<${e}> declares no property "${t}".`,1205:(e,t,n)=>`<${e}> has no command "${t}" (a native <${e}>'s commands: ${n}).`,1301:e=>`eventToken "${e}" is not declared in $eventTokens.`,1302:e=>`"$command.${e}" is not declared in $commandTokens.`,1401:(e,t,n=0)=>`"${e}" needs ${t} enclosing loop level(s); the scope provides ${n}.`,1402:e=>`"${e}" is relative: it needs an enclosing "for" template`,1403:(e,t,n)=>`"${e}" ranges over the rows of "${t}", but the enclosing "for" template at that level renders "${n}".`,1501:(e,t)=>`<${e}> declares no static wcBindable (${t}).`,1601:(e,t)=>`${e} was removed: write ${t}.`,1701:(e,t)=>`${e} was removed: write ${t}.`};function x(e,t){let n=k[e];return void 0===n?`${w(e)}#${e} ${t.join(" ")}`:w(e)+n(...t)}var j=new Set(["binding-syntax","template-syntax","filter-unknown","filter-arity","index-arity","wildcard-rank","token-undeclared","binding-path-missing","index-param-range"]),T=[[/no loop level in common with the context/,"; pass indexes ([] for all)."],[/"([^"#]+)#([^"]*)" is not a filter name: a modifier list .* comes before the input filters/,' — write "<property>#$2|$1".'],[/\[wcs\/recursion-unsupported\]/," It is only meaningful in a $recursion declaration, in a recursive getter key, and in the path argument of $getAll / $setAll — and only when the state declares a $recursion anchor."],[/must be single binding/,' Put the structural binding alone in its own data-wcs (e.g. <template data-wcs="for: items">).'],[/\[wcs\/wildcard-rank\] .* needs \d+ enclosing/,' Wrap it in that many "for" templates, or use $resolve(path, indexes) to name the row explicitly.'],[/\[wcs\/wildcard-rank\] .* ranges over the rows of/,' A "*" in a binding is the row of the loop around it: read a row of another list in a getter, with $resolve(path, indexes).'],[/\[wcs\/binding-type-expectation\] class\.([^ ]+)/,' Write "class.$1: path|truthy" to toggle on truthiness.'],[/path segments — the limit/," Every prefix of a path is interned, so the cost grows with the square of the depth."],[/\[wcs\/index-arity\] \$resolve/,' $resolve takes one index per "*"; $getAll / $setAll take at most that many (fewer expands the rest).'],[/"([^"#]+)#[^"]*" is not a filter name: "#" cannot appear in one/,' Modifiers belong on the left side of the binding, before the ":" — write "$1" here.']],O={inc:"add",dec:"sub",fix:"toFixed",uc:"upper",lc:"lower",cap:"capitalize",rep:"repeat",rev:"reverse",pad:"padStart",null:"nullIfEmpty"};function S(e,t,n){let a=(void 0!==t&&e.includes("[wcs/filter-unknown]")?function(e){if("substr"===e)return' "substr" was removed in 4.0 — write slice(start, start + length): slice takes the end index, not a length.';let t=Object.hasOwn(O,e)?O[e]:null;return null===t?null:` "${e}" was renamed "${t}" in 3.2 and removed in 4.0 — write "${t}".`}(t):null)??(void 0!==t&&void 0!==n?p(t,n):"");for(let[t,n]of T){let i=t.exec(e);null!==i&&(a+=n.replace(/\$(\d)/g,(e,t)=>i[Number(t)]))}let i=/"([^"#]+)#([^"]+)": a binding takes one modifier list/.exec(e);null!==i&&(a+=` — write "${i[1]}#${i[2].split("#").join(",")}".`),e.includes("[wcs/filter-unknown]")&&(e.includes("formats add-on")?a+=' On a split auto page: features="formats" on the root, or "$features": ["formats"].':s.some(r)||(a+=' No formatting filters are installed — add the formats add-on: installFeatures([formats]) from "@wcstack/state/features/formats" (a split auto page: features="formats", or "$features").'));let o=/\[wcs\/([\w-]+)\]/.exec(e);return null!==o&&j.has(o[1])&&!/ path segments — the limit is |inserted content was not rendered|formats add-on/.test(e)&&(a+=m),a}var I=new WeakMap,M=new WeakMap,A=new WeakSet,P=new WeakSet;function W(e,t){for(let n=e;null!==n&&n!==Object.prototype;n=Object.getPrototypeOf(n)){let e=Object.getOwnPropertyDescriptor(n,t);if(void 0!==e)return e}}function q(e){let t=new Set;for(let n=e;null!==n&&n!==Object.prototype;n=Object.getPrototypeOf(n))for(let e of Object.getOwnPropertyNames(n))"$"!==e[0]&&"constructor"!==e&&t.add(e);return[...t]}function L(e,t){let n=[];for(let e=t;null!==e;e=e.d)n.unshift(e);let a=e.target,i=t=>null===t?null:function(e,t){let n=t.t.split("."),a=n.findIndex((e,t)=>t>0&&/^\d/.test(e));return a<0||n.indexOf("*",a)>=0||void 0!==W(e.target,t.t)?.get?t:e.I.jt(o(t.t).o)}(e,t);for(let t of n){if(null!=i(t)?.getter||null===a||"object"!=typeof a)return null;if("*"===t.s){if(!Array.isArray(a)||0===a.length)return null;a=a[0];continue}if(Array.isArray(a)&&/^\d+$/.test(t.s)){if(Number(t.s)>=a.length)return null;a=a[Number(t.s)];continue}let n=W(a,t.s);if(void 0===n&&null===t.d&&e.vt.has(t.s))return null;if(void 0===n){let n=q(a),s=i(t.d);for(let t of e.I.all())t.d===s&&null!==t.getter&&n.push(t.s);return{seg:t.s,names:n}}if(void 0!==n.get||void 0!==n.set)return null;a=n.value}return null}function C(e){A.has(e)||(A.add(e),setTimeout(()=>function(e){A.delete(e);let t=I.get(e);if(void 0===t)return;let n=M.get(e);void 0===n&&M.set(e,n=new Set);for(let[a,s]of t){if(n.has(a))continue;n.add(a);let t=L(e,a);if(null===t)continue;let r=[...e.root?.querySelectorAll(`${i.tagNames.state}[mount]`)??[]].find(e=>!P.has(e)&&(a.t+".").startsWith(e.getAttribute("mount")+"."));if(void 0!==r){n.delete(a),r.initializePromise.then(()=>{P.add(r),C(e)});continue}let[l,c]=s?["watch-path-missing","$watch path"]:["binding-path-missing","Bound path"];d.st?.(e,{type:"state:path-unresolved",source:s?"watch":"binding",path:a.t,missingSegment:t.seg});let u=e.I.jt(o(a.t).o),f="";if(void 0!==u&&u!==a&&null!==u.getter){let e=u.h.slice(1).map((e,t)=>`for: ${0===t?e.t:e.t.slice(u.h[t].t.length+2)}`);f=` The getter "${u.t}" is declared for the rows of ${e.join(" → ")}; a list named by an index has rows of its own.`}console.warn(`[@wcstack/state] [wcs/${l}] ${c} "${a.t}" does not resolve on the state tree: "${t.seg}" is not declared.${p(t.seg,t.names)}${f} Updates to this path will be silently dropped.${m}`)}}(e),0))}function B(e,t,n=!1){if("$"===t.t[0]||t.t.includes("#")||!n&&null===t.d)return;let a=I.get(e);void 0===a&&I.set(e,a=new Map),a.has(t)||a.set(t,n),C(e)}var D=e=>e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),z=!1;function H(e,t,i){let s="html"===i.name?"innerHTML":i.name;if(z||!(t instanceof TypeError)||!a(s)||!("trustedTypes"in globalThis))return;z=!0;let r="function"==typeof n()?.createHTML?"The injected policy's createHTML() did not return a TrustedHTML.":"No sanitizing policy is installed, and @wcstack/state deliberately does not pass state values through an identity policy — that would defeat the CSP.";console.error(`[@wcstack/state] Writing to "${s}" was blocked by Trusted Types (require-trusted-types-for 'script'). ${r}\nInstall a sanitizing policy before the first binding is applied:\n globalThis[Symbol.for("wcstack.trustedTypes.policy")] =\n trustedTypes.createPolicy("my-app", { createHTML: (s) => DOMPurify.sanitize(s) });\nOr bind the value as text instead of HTML. See docs/csp.md section 7.`,{element:i.a,property:s})}var N=new WeakMap;function E(e,t,n){let a=e[t],i=void 0===n?void 0===a?null:`the event carried no detail (undefined) while element.${t} is ${typeof a}`:null===n||"object"!=typeof n||!Object.prototype.hasOwnProperty.call(n,t)||null!==a&&"object"==typeof a?null:`the event's detail is an object with a "${t}" key while element.${t} is ${typeof a}`;if(null===i)return;let s=N.get(e);void 0===s&&N.set(e,s=new Set),!s.has(t)&&(s.add(t),console.warn(`[@wcstack/state] [wcs/default-getter-mismatch] <${e.localName}> "${t}": ${i}. With no getter, state receives e.detail as-is. Dispatch the value itself as detail, or declare getter (e.g. (e) => e.detail.${t}, or (e) => e.target.${t}) on that wcBindable property.`))}var U=[["$streams","$stream"],["$updatedCallback","$renderedCallback"]],R={$trackDependency:"$dependOn",$untrackDependency:"$untracked"},V={name:"diagnostics",install(){d.Lo=S,d.Bo=x,d.So=B,d.detail=E,d.Ke=c(d.Ke,H);let e=d.de;d.de=(t,n)=>{(function(e){void 0!==e.$scan&&l(1);for(let[t,n]of U)void 0!==e[t]&&l(1601,[t,n])})(n),e?.(t,n),function(e){let t=e.$recursion;if(null===t||"object"!=typeof t)return;let n=Object.entries(t);if(1!==n.length||"string"!=typeof n[0][1])return;let[a,i]=n[0];if(!a.endsWith(".*")||!i.endsWith(".*"))return;let s=a.slice(0,-2),r=i.slice(0,-2),o=`.${i}`,l=`${s}.**`,d=q(e),c=d.filter(e=>e.startsWith(l)).map(e=>e.slice(l.length)),u=e=>h(`[wcs/recursion-declaration-invalid] ${e}`);for(let e of c){(e===`.${r}`||e.startsWith(`.${r}.`))&&u(`"${l}${e}" names the recursion structure itself (the "${r}" lists): recursive getters compute values over the nodes.`);for(let t of c)t.length>e.length&&t.endsWith(e)&&new RegExp(`^(?:${D(o)})+$`).test(t.slice(0,t.length-e.length))&&u(`"${l}${e}" and "${l}${t}" expand to the same concrete path at different depths (they differ by whole repetitions of "${i}"). Rename one of them.`);let t=new RegExp(`^${D(a)}(?:${D(o)})*${D(e)}$`);for(let n of d)!n.includes("**")&&t.test(n)&&u(`"${n}" is already defined on the state, so the recursive getter "${l}${e}" cannot expand to it.`)}}(n),function(e){M.delete(e),I.has(e)&&C(e)}(t)},d.ot=u(f,d.ot,(e,t)=>Object.hasOwn(R,t)?l(1701,[t,R[t]]):void 0)}},_=V;export{_ as default,V as diagnostics};
|
|
1
|
+
import{b as e,c as t,h as n,j as a}from"../chunks/chunk-7AYOQHZH.js";import{a as i,d as s,f as r}from"../chunks/chunk-M5SODAAE.js";import{e as o}from"../chunks/chunk-ZN52NEIB.js";import"../chunks/chunk-NOPTR2L3.js";import{b as l}from"../chunks/chunk-EIMTT5I3.js";import{a as d,b as c,c as u,e as f,j as h}from"../chunks/chunk-4NJBYXIT.js";function $(e,t,n){if(Math.abs(e.length-t.length)>n)return n+1;let a=new Array(t.length+1),i=new Array(t.length+1);for(let e=0;e<=t.length;e++)a[e]=e;for(let n=1;n<=e.length;n++){i[0]=n;for(let s=1;s<=t.length;s++){let r=e[n-1]===t[s-1]?0:1;i[s]=Math.min(a[s]+1,i[s-1]+1,a[s-1]+r)}for(let e=0;e<=t.length;e++)a[e]=i[e]}return a[t.length]}function p(e,t){if(0===e.length)return"";let n=e.toLowerCase(),a=null,i=3;for(let e of t){let t=$(n,e.toLowerCase(),2);t<i&&(a=e,i=t)}return null!==a?` Did you mean "${a}"?`:""}var m=" Validate statically: npx @wcstack/lint <file>.",g=["","binding-syntax","template-syntax","binding-path-missing","binding-type-expectation","filter-unknown","filter-arity","getter-cycle","getter-depth-exceeded","index-arity","index-param-range","recursion-unsupported","token-misconfigured","token-undeclared","wildcard-rank","spread-no-bindable","declaration-alias","name-alias"],w=e=>{let t=g[e/100|0];return t?`[wcs/${t}] `:""},b=["enableMustache","sameValueGuard","enableDirectionalInitialSync"],y=(e,t)=>`<${e}${t.map((e,t)=>t%2?`="${e}"`:` ${e}`).join("")}>`,v="https://github.com/wcstack/wcstack/blob/main/docs/csp.md",k={1:()=>"$scan was removed (use $watch or $on)",2:e=>`"${e}" is a getter without a setter`,3:e=>`no row for "${e}"`,4:(e,t)=>`cannot write "${e}": its parent is ${t}`,5:e=>`"${e}" is not a method`,6:e=>`$getAll("${e}"): no loop level in common with the context`,7:e=>`$eqIndex("${e}") needs a list row scope.`,8:()=>"This state is readonly.",9:e=>`$setAll("${e}") needs indexes ([] for every match)`,10:(e,t)=>`$setAll("${e}", …, { spread: true }) needs an array of ${t} values`,11:()=>`updates did not settle after ${e} passes`,41:()=>`render chain depth limit exceeded (${t} drains that rendering itself started); bindings for this batch were not applied.`,12:(e,t)=>`binding "${e}: ${t}" failed to apply.`,13:(e,t)=>`failed to load "${e}": ${t}`,14:()=>"this <wcs-state> failed to initialize; create a new one",15:()=>"state is not initialized",16:e=>`no <script> with id "${e}"`,42:()=>`The inline <script> of <wcs-state> was blocked by Content-Security-Policy. Inline state is evaluated through a blob: URL: give the page's nonce to the <script> that loads @wcstack/state, or allow blob: in script-src. Moving the state into an external file (src="./state.js") needs neither. See ${v}`,43:e=>`Failed to evaluate the inline <script> of <wcs-state>: ${e}. If this page sets a Content-Security-Policy, see ${v}`,17:e=>`a subscriber of token "${e}" threw.`,18:e=>`${e} must be an array of strings.`,19:e=>`${e} entries must be non-empty strings.`,20:(e,t,n)=>`${e} entry "${t}" conflicts with the reserved namespace name "${n}".`,21:(e,t)=>`${e} entry "${t}" is duplicated.`,22:()=>"$on must be an object of handlers.",23:e=>`$on entry "${e}" is not declared in $eventTokens.`,24:e=>`$on entry "${e}" must be a function.`,25:e=>`view-transition naming-limit (${e}) reached.`,26:e=>`filter ${e} requires at least one option`,27:e=>`filter ${e} requires a number as option`,28:e=>`filter ${e} requires a number value`,29:e=>`filter ${e} requires a date value`,30:e=>`filter ${e} requires an array value`,31:()=>"init=/sync= modifiers require enableDirectionalInitialSync.",33:(e,t)=>`Unknown binding modifier "${e}" in "${t}".`,34:e=>`Binding modifier "${e}" may only be specified once.`,35:(e,t)=>`Invalid ${e} modifier value "${t}".`,36:()=>"Event bindings only allow init=none.",37:(e,t)=>`Binding type "${e}" does not support init=${t}.`,38:e=>`Property "${e}" is not declared by wcBindable.`,39:(e,t)=>`init=${e} is incompatible with wcBindable member "${t}".`,40:e=>`sync=connect requires observable property "${e}".`,44:(e,t)=>`${e}: "${t}" is not one of its options, or not of the option's type.${"bootstrapState"===e&&b.includes(t)?" 4.0 moved it to the state's $behavior.":""}`,45:()=>"a re-set state may not change $behavior: create the element again.",47:()=>'a second <wcs-state> on the same root: there is one state tree per root — graft a subtree with <wcs-state mount="path"> (v1\'s name="…" is gone: read the mounted state by its path).',48:e=>`the locale "${e}" (<html lang> or bootstrapState's locale) is not a language tag Intl takes (en-US, not en_US): the locale filters use "en".`,46:()=>'$features must be an array of add-on names (["temporal", "formats"]).',49:(e,...t)=>`${y(e,t)} failed to initialize.`,50:(e,...t)=>`${y(e,t)} $connectedCallback failed.`,51:(e,...t)=>`${y(e,t)} $disconnectedCallback failed.`,101:e=>`Invalid bindText: "${e}". Missing ':' separator between propPart and statePart.`,102:(e,t)=>`"${e}": "${t}" takes no modifiers or filters on its left side — write "${t}:".`,103:e=>`"${e}": "else" takes no value — write "else:".`,104:e=>`Invalid spread binding "${e}": spread target path is required.`,105:e=>`Invalid spread binding "${e}": filters are not allowed on spread targets.`,106:e=>`"${e}": a leading "." binds an element property by name — write a non-empty property that is not a namespace (class, attr, style, command, eventToken, state).`,107:(e,t)=>`unterminated ${e} quote in the filter arguments "(${t})". Close the quote.`,108:e=>`Invalid filter format: missing closing parenthesis in "${e}".`,109:e=>`Invalid filter format: missing opening parenthesis in "${e}".`,110:e=>`Invalid filter format: ")" comes before "(" in "${e}".`,111:(e,t)=>`"${e}": unexpected "${t}" after the filter's closing ")" — separate filters with "|" (write "${e.slice(0,e.lastIndexOf(")")+1)}|${t}").`,112:e=>`an empty filter in "${e}" — remove the extra "|" or name the filter.`,113:(e,t)=>`"${e}" is not a filter name: a modifier list "#${t}" comes before the input filters, not inside one`,114:e=>`"${e}" is not a filter name: "#" cannot appear in one.`,115:e=>`"${e}": a binding takes one modifier list after a single "#"`,116:e=>`"${e}": the left side of a binding must name a property — write "<property>: <path>" (modifiers and input filters come after the name).`,117:(e,t)=>`"${e}" has ${t} path segments — the limit is 512.`,32:e=>`"${e}": the "@name" selector was removed in v2 — there is a single state tree. Mount the named state onto the tree (<wcs-state mount="...">) and read it by its path prefix instead.`,120:e=>`"${e}": a state path cannot go through "__proto__" or "prototype" (it would reach every object's prototype).`,121:e=>`"${e}": "for:" takes no filters — a row is "<path>.<index>", so the rows of a filtered list would name other elements. Declare a getter that returns the filtered list and loop over it ("for: <getter>").`,119:e=>`"${e}": the right side of a binding must name a state path — write "<property>: <path>" (a path segment cannot be empty; "." alone and a leading "." are the loop-relative shorthand).`,201:e=>`Invalid bindText: "${e}". 'if', 'elseif', 'else', and 'for' bindings must be single binding.`,202:e=>`"${e}:" must follow an "if:" template`,204:e=>`a "${e}:" template at the top of inserted content was not rendered, as it would render beside itself out of the inserter's reach: wrap it in an element.`,203:e=>`"${e}:" replaces its element, so it cannot be used inside a "for" / "if" template (a row or branch keeps its nodes by position): bind innerHTML: on a wrapper element instead.`,301:e=>`Path "${e}" does not exist on the state tree.`,401:(e,t)=>`class.${e} needs a boolean, got ${t}.`,501:e=>`filter not found: ${e}.`,601:(e,t,n)=>`filter "${e}" requires at least ${t} argument(s) (${n} given).`,602:(e,t,n)=>`filter "${e}" accepts at most ${t} argument(s) (${n} given).`,701:e=>`"${e}" depends on itself`,801:e=>`"${e}"`,901:(e,t,n,a)=>`${e}("${t}") takes ${n} index(es), got ${a}.`,902:(e,t,n,a)=>`${e}("${t}") takes at most ${n} index(es), got ${a}.`,1001:e=>`"${e}": list index parameters run from $1 to $128.`,1101:e=>`"${e}" uses "**", which is not accepted here.`,1201:(e,t)=>`"${e}: ${t}": the right-hand side must be $command.<name>`,1202:(e,t)=>`<${e}> declares no static wcBindable (${t}).${!e.includes("-")&&t.startsWith("command.")?" A native element's command needs the add-on @wcstack/state/features/native-commands.":""}`,1203:(e,t)=>`<${e}> declares no command "${t}".`,1204:(e,t)=>`<${e}> declares no property "${t}".`,1205:(e,t,n)=>`<${e}> has no command "${t}" (a native <${e}>'s commands: ${n}).`,1301:e=>`eventToken "${e}" is not declared in $eventTokens.`,1302:e=>`"$command.${e}" is not declared in $commandTokens.`,1401:(e,t,n=0)=>`"${e}" needs ${t} enclosing loop level(s); the scope provides ${n}.`,1402:e=>`"${e}" is relative: it needs an enclosing "for" template`,1403:(e,t,n)=>`"${e}" ranges over the rows of "${t}", but the enclosing "for" template at that level renders "${n}".`,1501:(e,t)=>`<${e}> declares no static wcBindable (${t}).`,1601:(e,t)=>`${e} was removed: write ${t}.`,1701:(e,t)=>`${e} was removed: write ${t}.`};function x(e,t){let n=k[e];return void 0===n?`${w(e)}#${e} ${t.join(" ")}`:w(e)+n(...t)}var j=new Set(["binding-syntax","template-syntax","filter-unknown","filter-arity","index-arity","wildcard-rank","token-undeclared","binding-path-missing","index-param-range"]),T=[[/no loop level in common with the context/,"; pass indexes ([] for all)."],[/"([^"#]+)#([^"]*)" is not a filter name: a modifier list .* comes before the input filters/,' — write "<property>#$2|$1".'],[/\[wcs\/recursion-unsupported\]/," It is only meaningful in a $recursion declaration, in a recursive getter key, and in the path argument of $getAll / $setAll — and only when the state declares a $recursion anchor."],[/must be single binding/,' Put the structural binding alone in its own data-wcs (e.g. <template data-wcs="for: items">).'],[/\[wcs\/wildcard-rank\] .* needs \d+ enclosing/,' Wrap it in that many "for" templates, or use $resolve(path, indexes) to name the row explicitly.'],[/\[wcs\/wildcard-rank\] .* ranges over the rows of/,' A "*" in a binding is the row of the loop around it: read a row of another list in a getter, with $resolve(path, indexes).'],[/\[wcs\/binding-type-expectation\] class\.([^ ]+)/,' Write "class.$1: path|truthy" to toggle on truthiness.'],[/path segments — the limit/," Every prefix of a path is interned, so the cost grows with the square of the depth."],[/\[wcs\/index-arity\] \$resolve/,' $resolve takes one index per "*"; $getAll / $setAll take at most that many (fewer expands the rest).'],[/"([^"#]+)#[^"]*" is not a filter name: "#" cannot appear in one/,' Modifiers belong on the left side of the binding, before the ":" — write "$1" here.']],I={inc:"add",dec:"sub",fix:"toFixed",uc:"upper",lc:"lower",cap:"capitalize",rep:"repeat",rev:"reverse",pad:"padStart",null:"nullIfEmpty"};function O(e,t,n){let a=(void 0!==t&&e.includes("[wcs/filter-unknown]")?function(e){if("substr"===e)return' "substr" was removed in 4.0 — write slice(start, start + length): slice takes the end index, not a length.';let t=Object.hasOwn(I,e)?I[e]:null;return null===t?null:` "${e}" was renamed "${t}" in 3.2 and removed in 4.0 — write "${t}".`}(t):null)??(void 0!==t&&void 0!==n?p(t,n):"");for(let[t,n]of T){let i=t.exec(e);null!==i&&(a+=n.replace(/\$(\d)/g,(e,t)=>i[Number(t)]))}let i=/"([^"#]+)#([^"]+)": a binding takes one modifier list/.exec(e);null!==i&&(a+=` — write "${i[1]}#${i[2].split("#").join(",")}".`),e.includes("[wcs/filter-unknown]")&&(e.includes("formats add-on")?a+=' On a split auto page: features="formats" on the root, or "$features": ["formats"].':s.some(r)||(a+=' No formatting filters are installed — add the formats add-on: installFeatures([formats]) from "@wcstack/state/features/formats" (a split auto page: features="formats", or "$features").'));let o=/\[wcs\/([\w-]+)\]/.exec(e);return null!==o&&j.has(o[1])&&!/ path segments — the limit is |inserted content was not rendered|formats add-on/.test(e)&&(a+=m),a}var S=new WeakMap,M=new WeakMap,A=new WeakSet,P=new WeakSet;function W(e,t){for(let n=e;null!==n&&n!==Object.prototype;n=Object.getPrototypeOf(n)){let e=Object.getOwnPropertyDescriptor(n,t);if(void 0!==e)return e}}function q(e){let t=new Set;for(let n=e;null!==n&&n!==Object.prototype;n=Object.getPrototypeOf(n))for(let e of Object.getOwnPropertyNames(n))"$"!==e[0]&&"constructor"!==e&&t.add(e);return[...t]}function L(e,t){let n=[];for(let e=t;null!==e;e=e.d)n.unshift(e);let a=e.target,i=t=>null===t?null:function(e,t){let n=t.t.split("."),a=n.findIndex((e,t)=>t>0&&/^\d/.test(e));return a<0||n.indexOf("*",a)>=0||void 0!==W(e.target,t.t)?.get?t:e.I.jt(o(t.t).o)}(e,t);for(let t of n){if(null!=i(t)?.getter||null===a||"object"!=typeof a)return null;if("*"===t.s){if(!Array.isArray(a)||0===a.length)return null;a=a[0];continue}if(Array.isArray(a)&&/^\d+$/.test(t.s)){if(Number(t.s)>=a.length)return null;a=a[Number(t.s)];continue}let n=W(a,t.s);if(void 0===n&&null===t.d&&e.vt.has(t.s))return null;if(void 0===n){let n=q(a),s=i(t.d);for(let t of e.I.all())t.d===s&&null!==t.getter&&n.push(t.s);return{seg:t.s,names:n}}if(void 0!==n.get||void 0!==n.set)return null;a=n.value}return null}function N(e){A.has(e)||(A.add(e),setTimeout(()=>function(e){A.delete(e);let t=S.get(e);if(void 0===t)return;let n=M.get(e);void 0===n&&M.set(e,n=new Set);for(let[a,s]of t){if(n.has(a))continue;n.add(a);let t=L(e,a);if(null===t)continue;let r=[...e.root?.querySelectorAll(`${i.tagNames.state}[mount]`)??[]].find(e=>!P.has(e)&&(a.t+".").startsWith(e.getAttribute("mount")+"."));if(void 0!==r){n.delete(a),r.initializePromise.then(()=>{P.add(r),N(e)});continue}let[l,c]=s?["watch-path-missing","$watch path"]:["binding-path-missing","Bound path"];d.st?.(e,{type:"state:path-unresolved",source:s?"watch":"binding",path:a.t,missingSegment:t.seg});let u=e.I.jt(o(a.t).o),f="";if(void 0!==u&&u!==a&&null!==u.getter){let e=u.h.slice(1).map((e,t)=>`for: ${0===t?e.t:e.t.slice(u.h[t].t.length+2)}`);f=` The getter "${u.t}" is declared for the rows of ${e.join(" → ")}; a list named by an index has rows of its own.`}console.warn(`[@wcstack/state] [wcs/${l}] ${c} "${a.t}" does not resolve on the state tree: "${t.seg}" is not declared.${p(t.seg,t.names)}${f} Updates to this path will be silently dropped.${m}`)}}(e),0))}function B(e,t,n=!1){if("$"===t.t[0]||t.t.includes("#")||!n&&null===t.d)return;let a=S.get(e);void 0===a&&S.set(e,a=new Map),a.has(t)||a.set(t,n),N(e)}var C=e=>e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),D=!1;function E(e,t,i){let s="html"===i.name?"innerHTML":i.name;if(D||!(t instanceof TypeError)||!a(s)||!("trustedTypes"in globalThis))return;D=!0;let r="function"==typeof n()?.createHTML?"The injected policy's createHTML() did not return a TrustedHTML.":"No sanitizing policy is installed, and @wcstack/state deliberately does not pass state values through an identity policy — that would defeat the CSP.";console.error(`[@wcstack/state] Writing to "${s}" was blocked by Trusted Types (require-trusted-types-for 'script'). ${r}\nInstall a sanitizing policy before the first binding is applied:\n globalThis[Symbol.for("wcstack.trustedTypes.policy")] =\n trustedTypes.createPolicy("my-app", { createHTML: (s) => DOMPurify.sanitize(s) });\nOr bind the value as text instead of HTML. See docs/csp.md section 7.`,{element:i.a,property:s})}var H=new WeakMap;function z(e,t,n){let a=e[t],i=void 0===n?void 0===a?null:`the event carried no detail (undefined) while element.${t} is ${typeof a}`:null===n||"object"!=typeof n||!Object.prototype.hasOwnProperty.call(n,t)||null!==a&&"object"==typeof a?null:`the event's detail is an object with a "${t}" key while element.${t} is ${typeof a}`;if(null===i)return;let s=H.get(e);void 0===s&&H.set(e,s=new Set),!s.has(t)&&(s.add(t),console.warn(`[@wcstack/state] [wcs/default-getter-mismatch] <${e.localName}> "${t}": ${i}. With no getter, state receives e.detail as-is. Dispatch the value itself as detail, or declare getter (e.g. (e) => e.detail.${t}, or (e) => e.target.${t}) on that wcBindable property.`))}var R=[["$streams","$stream"],["$updatedCallback","$renderedCallback"]],U={$trackDependency:"$dependOn",$untrackDependency:"$untracked"},_={name:"diagnostics",install(){d.Lo=O,d.Bo=x,d.So=B,d.detail=z,d.Ke=c(d.Ke,E);let e=d.de;d.de=(t,n)=>{(function(e){void 0!==e.$scan&&l(1);for(let[t,n]of R)void 0!==e[t]&&l(1601,[t,n])})(n),e?.(t,n),function(e){let t=e.$recursion;if(null===t||"object"!=typeof t)return;let n=Object.entries(t);if(1!==n.length||"string"!=typeof n[0][1])return;let[a,i]=n[0];if(!a.endsWith(".*")||!i.endsWith(".*"))return;let s=a.slice(0,-2),r=i.slice(0,-2),o=`.${i}`,l=`${s}.**`,d=q(e),c=d.filter(e=>e.startsWith(l)).map(e=>e.slice(l.length)),u=e=>h(`[wcs/recursion-declaration-invalid] ${e}`);for(let e of c){(e===`.${r}`||e.startsWith(`.${r}.`))&&u(`"${l}${e}" names the recursion structure itself (the "${r}" lists): recursive getters compute values over the nodes.`);for(let t of c)t.length>e.length&&t.endsWith(e)&&new RegExp(`^(?:${C(o)})+$`).test(t.slice(0,t.length-e.length))&&u(`"${l}${e}" and "${l}${t}" expand to the same concrete path at different depths (they differ by whole repetitions of "${i}"). Rename one of them.`);let t=new RegExp(`^${C(a)}(?:${C(o)})*${C(e)}$`);for(let n of d)!n.includes("**")&&t.test(n)&&u(`"${n}" is already defined on the state, so the recursive getter "${l}${e}" cannot expand to it.`)}}(n),function(e){M.delete(e),S.has(e)&&N(e)}(t)},d.ot=u(f,d.ot,(e,t)=>Object.hasOwn(U,t)?l(1701,[t,U[t]]):void 0)}},F=_;export{F as default,_ as diagnostics};
|
|
2
|
+
//# sourceMappingURL=diagnostics.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["editDistance","a","b","max","Math","abs","length","prev","Array","curr","j","i","cost","min","didYouMean","input","candidates","folded","toLowerCase","best","bestDistance","candidate","distance","LINT_HINT","CODES","codeOf","id","c","MOVED","element","tag","at","map","join","CSP_GUIDE","SENTENCES","p","parent","name","n","MAX_DRAIN_PASSES","MAX_RENDER_CHAIN","type","src","status","detail","key","reserved","limit","fn","modifier","value","init","where","includes","l","t","keyword","prop","quote","args","f","trailing","slice","lastIndexOf","source","mods","given","api","depth","what","startsWith","method","allowed","over","loop","old","render","sentence","LINT_CODES","Set","GUIDES","RENAMED_FILTERS","inc","dec","fix","uc","lc","cap","rep","rev","pad","null","explain","message","subject","out","to","Object","hasOwn","removedFilter","re","text","m","exec","replace","_","Number","split","FORMATS_FILTER_NAMES","some","hasFilter","code","has","test","named","WeakMap","checked","due","WeakSet","settled","findDescriptor","o","x","prototype","getPrototypeOf","d","getOwnPropertyDescriptor","keysOf","k","getOwnPropertyNames","add","missing","engine","chain","q","unshift","v","target","segs","path","findIndex","s","indexOf","get","patterns","peek","parsePath","pattern","wildcardForm","getter","last","isArray","dropped","names","g","all","push","seg","set","schedule","setTimeout","delete","done","watch","root","querySelectorAll","config","tagNames","state","find","e","getAttribute","initializePromise","then","hooks","noticed","missingSegment","w","rowGetter","loops","lists","console","warn","check","declared","Map","esc","trustedTypesReported","failed","_engine","error","binding","TypeError","isHtmlSink","globalThis","cause","getTrustedTypesPolicy","createHTML","node","property","warnedDetail","el","reason","hasOwnProperty","call","said","localName","REMOVED_DECLARATIONS","REMOVED_APIS","$trackDependency","$untrackDependency","diagnostics","install","declare","$scan","raise","removedDeclarations","decl","$recursion","entries","anchor","repeat","endsWith","list","step","head","keys","families","filter","bad","why","raiseError","RegExp","checkRecursion","recheck","dollar","first","known","diagnostics_default"],"sources":["../../../src/diagnostics/guidance.ts","../../../src/diagnostics/messages.ts","../../../src/diagnostics/explain.ts","../../../src/features/diagnostics.ts"],"sourcesContent":["/**\n * diagnostics/guidance.ts — self-fix guidance for error messages, ported verbatim from\n * `@wcstack/state` (`errorGuidance.ts`). Only the diagnostics add-on uses it: the core's\n * messages state the fact, and the add-on appends this.\n *\n * The did-you-mean criteria (edit distance 2, ties go to the first candidate, case folded) are the\n * same as lint's suggestion, so the console, lint and the IDE never propose different names.\n */\n\n/** Insert / delete / substitute edit distance. Returns max + 1 early when the lengths differ by more than max. */\nfunction editDistance(a: string, b: string, max: number): number {\n if (Math.abs(a.length - b.length) > max) {\n return max + 1;\n }\n const prev: number[] = new Array(b.length + 1);\n const curr: number[] = new Array(b.length + 1);\n for (let j = 0; j <= b.length; j++) {\n prev[j] = j;\n }\n for (let i = 1; i <= a.length; i++) {\n curr[0] = i;\n for (let j = 1; j <= b.length; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1;\n curr[j] = Math.min(prev[j] + 1, curr[j - 1] + 1, prev[j - 1] + cost);\n }\n for (let j = 0; j <= b.length; j++) {\n prev[j] = curr[j];\n }\n }\n return prev[b.length];\n}\n\n/**\n * The nearest candidate within edit distance 2 as ` Did you mean \"<best>\"?`, or `\"\"` when there is\n * none. An empty input (a trailing `a|` pipe) gets no suggestion.\n */\nexport function didYouMean(input: string, candidates: Iterable<string>): string {\n if (input.length === 0) {\n return \"\";\n }\n const folded = input.toLowerCase();\n let best: string | null = null;\n let bestDistance = 3;\n for (const candidate of candidates) {\n const distance = editDistance(folded, candidate.toLowerCase(), 2);\n if (distance < bestDistance) {\n best = candidate;\n bestDistance = distance;\n }\n }\n return best !== null ? ` Did you mean \"${best}\"?` : \"\";\n}\n\n/**\n * The pointer to lint. Attach it **only where lint actually detects the case** — a hint that sends\n * the author to a lint run that comes back clean costs the loop its credibility.\n */\nexport const LINT_HINT = \" Validate statically: npx @wcstack/lint <file>.\";\n","/**\n * The sentences of the core's numbered messages (src/messages.ts), in the diagnostics add-on:\n * the core carries the number and the values, this renders what the core used to say. Each\n * sentence follows its `[wcs/<code>] ` (`codeOf`: the code the hundreds of the number name).\n * `Record<M, …>` makes a number without a sentence a type error.\n */\nimport { M } from \"../messages\";\nimport { MAX_DRAIN_PASSES, MAX_INDEX_PARAM, MAX_RENDER_CHAIN } from \"../engine\";\nimport { MAX_PATH_SEGMENTS, MODIFIER_SEPARATOR, RECURSION_WILDCARD } from \"../parser/define\";\n\ntype Sentence = (...a: any[]) => string;\n\n/**\n * The code of each hundred of message numbers (\"\" = none): the code lint and the VS Code extension\n * report for the same case. The core carried this up to 4.0.0-rc.3; without this add-on a message\n * now reads as its number and values alone.\n */\nexport const CODES = [\n \"\", \"binding-syntax\", \"template-syntax\", \"binding-path-missing\", \"binding-type-expectation\",\n \"filter-unknown\", \"filter-arity\", \"getter-cycle\", \"getter-depth-exceeded\", \"index-arity\",\n \"index-param-range\", \"recursion-unsupported\", \"token-misconfigured\", \"token-undeclared\",\n \"wildcard-rank\", \"spread-no-bindable\", \"declaration-alias\", \"name-alias\",\n];\n\n/** `[wcs/<code>] ` for a message number, or \"\" when it has none. */\nexport const codeOf = (id: M): string => {\n const c = CODES[(id / 100) | 0];\n return c ? `[wcs/${c}] ` : \"\";\n};\n\n/** The options 4.0 moved from `bootstrapState` to the state's `$behavior`. */\nconst MOVED = [\"enableMustache\", \"sameValueGuard\", \"enableDirectionalInitialSync\"];\n\n/** `<tag a=\"v\" …>` from the tag and its attributes' names and values. */\nconst element = (tag: string, at: string[]): string => `<${tag}${at.map((a, i) => (i % 2 ? `=\"${a}\"` : ` ${a}`)).join(\"\")}>`;\n\nconst CSP_GUIDE = \"https://github.com/wcstack/wcstack/blob/main/docs/csp.md\";\n\nexport const SENTENCES: Record<M, Sentence> = {\n [M.ScanRemoved]: () => \"$scan was removed (use $watch or $on)\",\n [M.GetterWithoutSetter]: (p) => `\"${p}\" is a getter without a setter`,\n [M.NoRow]: (p) => `no row for \"${p}\"`,\n [M.ParentNotObject]: (p, parent) => `cannot write \"${p}\": its parent is ${parent}`,\n [M.NotAMethod]: (name) => `\"${name}\" is not a method`,\n [M.GetAllNoCommonLevel]: (p) => `$getAll(\"${p}\"): no loop level in common with the context`,\n [M.EqIndexNoRow]: (p) => `$eqIndex(\"${p}\") needs a list row scope.`,\n [M.Readonly]: () => \"This state is readonly.\",\n [M.SetAllNeedsIndexes]: (p) => `$setAll(\"${p}\") needs indexes ([] for every match)`,\n [M.SetAllSpreadLength]: (p, n) => `$setAll(\"${p}\", …, { spread: true }) needs an array of ${n} values`,\n [M.DrainNotSettled]: () => `updates did not settle after ${MAX_DRAIN_PASSES} passes`,\n [M.RenderChain]: () => `render chain depth limit exceeded (${MAX_RENDER_CHAIN} drains that rendering itself started); bindings for this batch were not applied.`,\n [M.BindingFailed]: (type, p) => `binding \"${type}: ${p}\" failed to apply.`,\n [M.LoadFailed]: (src, status) => `failed to load \"${src}\": ${status}`,\n [M.ElementFailed]: () => \"this <wcs-state> failed to initialize; create a new one\",\n [M.NotInitialized]: () => \"state is not initialized\",\n [M.NoScript]: (id) => `no <script> with id \"${id}\"`,\n [M.InlineBlocked]: () => `The inline <script> of <wcs-state> was blocked by Content-Security-Policy. Inline state is evaluated through a blob: URL: give the page's nonce to the <script> that loads @wcstack/state, or allow blob: in script-src. Moving the state into an external file (src=\"./state.js\") needs neither. See ${CSP_GUIDE}`,\n [M.InlineFailed]: (detail) => `Failed to evaluate the inline <script> of <wcs-state>: ${detail}. If this page sets a Content-Security-Policy, see ${CSP_GUIDE}`,\n [M.TokenSubscriberThrew]: (name) => `a subscriber of token \"${name}\" threw.`,\n [M.TokenListNotArray]: (key) => `${key} must be an array of strings.`,\n [M.TokenEntryEmpty]: (key) => `${key} entries must be non-empty strings.`,\n [M.TokenEntryReserved]: (key, name, reserved) => `${key} entry \"${name}\" conflicts with the reserved namespace name \"${reserved}\".`,\n [M.TokenEntryDuplicated]: (key, name) => `${key} entry \"${name}\" is duplicated.`,\n [M.OnNotObject]: () => \"$on must be an object of handlers.\",\n [M.OnEntryUndeclared]: (name) => `$on entry \"${name}\" is not declared in $eventTokens.`,\n [M.OnEntryNotFunction]: (name) => `$on entry \"${name}\" must be a function.`,\n [M.NamingLimit]: (limit) => `view-transition naming-limit (${limit}) reached.`,\n [M.FilterOptionsRequired]: (fn) => `filter ${fn} requires at least one option`,\n [M.FilterOptionNotNumber]: (fn) => `filter ${fn} requires a number as option`,\n [M.FilterValueNotNumber]: (fn) => `filter ${fn} requires a number value`,\n [M.FilterValueNotDate]: (fn) => `filter ${fn} requires a date value`,\n [M.FilterValueNotArray]: (fn) => `filter ${fn} requires an array value`,\n [M.DirectionalSyncDisabled]: () => \"init=/sync= modifiers require enableDirectionalInitialSync.\",\n [M.ModifierUnknown]: (key, modifier) => `Unknown binding modifier \"${key}\" in \"${modifier}\".`,\n [M.ModifierTwice]: (key) => `Binding modifier \"${key}\" may only be specified once.`,\n [M.ModifierValue]: (key, value) => `Invalid ${key} modifier value \"${value}\".`,\n [M.EventInitNone]: () => \"Event bindings only allow init=none.\",\n [M.InitUnsupported]: (type, init) => `Binding type \"${type}\" does not support init=${init}.`,\n [M.MemberUndeclared]: (name) => `Property \"${name}\" is not declared by wcBindable.`,\n [M.InitIncompatible]: (init, name) => `init=${init} is incompatible with wcBindable member \"${name}\".`,\n [M.SyncConnectNeedsOutput]: (name) => `sync=connect requires observable property \"${name}\".`,\n [M.OptionInvalid]: (where, key) => `${where}: \"${key}\" is not one of its options, or not of the option's type.${where === \"bootstrapState\" && MOVED.includes(key) ? \" 4.0 moved it to the state's $behavior.\" : \"\"}`,\n [M.BehaviorChanged]: () => \"a re-set state may not change $behavior: create the element again.\",\n [M.SecondRoot]: () => \"a second <wcs-state> on the same root: there is one state tree per root — graft a subtree with <wcs-state mount=\\\"path\\\"> (v1's name=\\\"…\\\" is gone: read the mounted state by its path).\",\n [M.LocaleInvalid]: (l) => `the locale \"${l}\" (<html lang> or bootstrapState's locale) is not a language tag Intl takes (en-US, not en_US): the locale filters use \"en\".`,\n [M.FeaturesNotArray]: () => '$features must be an array of add-on names ([\"temporal\", \"formats\"]).',\n [M.InitFailed]: (tag, ...at) => `${element(tag, at)} failed to initialize.`,\n [M.ConnectedFailed]: (tag, ...at) => `${element(tag, at)} $connectedCallback failed.`,\n [M.DisconnectedFailed]: (tag, ...at) => `${element(tag, at)} $disconnectedCallback failed.`,\n\n [M.BindTextNoColon]: (t) => `Invalid bindText: \"${t}\". Missing ':' separator between propPart and statePart.`,\n [M.StructuralTakesNoModifiers]: (t, keyword) => `\"${t}\": \"${keyword}\" takes no modifiers or filters on its left side — write \"${keyword}:\".`,\n [M.ElseTakesNoValue]: (t) => `\"${t}\": \"else\" takes no value — write \"else:\".`,\n [M.SpreadNoPath]: (t) => `Invalid spread binding \"${t}\": spread target path is required.`,\n [M.SpreadNoFilters]: (t) => `Invalid spread binding \"${t}\": filters are not allowed on spread targets.`,\n [M.LeadingDotNamespace]: (prop) => `\"${prop}\": a leading \".\" binds an element property by name — write a non-empty property that is not a namespace (class, attr, style, command, eventToken, state).`,\n [M.UnterminatedQuote]: (quote, args) => `unterminated ${quote} quote in the filter arguments \"(${args})\". Close the quote.`,\n [M.FilterUnclosed]: (f) => `Invalid filter format: missing closing parenthesis in \"${f}\".`,\n [M.FilterUnopened]: (f) => `Invalid filter format: missing opening parenthesis in \"${f}\".`,\n [M.FilterParenOrder]: (f) => `Invalid filter format: \")\" comes before \"(\" in \"${f}\".`,\n [M.FilterTrailing]: (f, trailing) => `\"${f}\": unexpected \"${trailing}\" after the filter's closing \")\" — separate filters with \"|\" (write \"${f.slice(0, f.lastIndexOf(\")\") + 1)}|${trailing}\").`,\n [M.FilterEmpty]: (source) => `an empty filter in \"${source}\" — remove the extra \"|\" or name the filter.`,\n [M.FilterNameHasModifiersInput]: (name, mods) => `\"${name}\" is not a filter name: a modifier list \"${MODIFIER_SEPARATOR}${mods}\" comes before the input filters, not inside one`,\n [M.FilterNameHasModifiersOutput]: (name) => `\"${name}\" is not a filter name: \"${MODIFIER_SEPARATOR}\" cannot appear in one.`,\n [M.OneModifierList]: (prop) => `\"${prop}\": a binding takes one modifier list after a single \"#\"`,\n [M.NoPropertyName]: (prop) => `\"${prop}\": the left side of a binding must name a property — write \"<property>: <path>\" (modifiers and input filters come after the name).`,\n [M.TooManySegments]: (p, n) => `\"${p}\" has ${n} path segments — the limit is ${MAX_PATH_SEGMENTS}.`,\n [M.SelectorRemoved]: (t) => `\"${t}\": the \"@name\" selector was removed in v2 — there is a single state tree. Mount the named state onto the tree (<wcs-state mount=\"...\">) and read it by its path prefix instead.`,\n [M.UnsafeSegment]: (p) => `\"${p}\": a state path cannot go through \"__proto__\" or \"prototype\" (it would reach every object's prototype).`,\n [M.ForNoFilters]: (t) => `\"${t}\": \"for:\" takes no filters — a row is \"<path>.<index>\", so the rows of a filtered list would name other elements. Declare a getter that returns the filtered list and loop over it (\"for: <getter>\").`,\n [M.EmptySegment]: (t) => `\"${t}\": the right side of a binding must name a state path — write \"<property>: <path>\" (a path segment cannot be empty; \".\" alone and a leading \".\" are the loop-relative shorthand).`,\n\n [M.StructuralNotSingle]: (t) => `Invalid bindText: \"${t}\". 'if', 'elseif', 'else', and 'for' bindings must be single binding.`,\n [M.ElseWithoutIf]: (type) => `\"${type}:\" must follow an \"if:\" template`,\n [M.TemplateHandedOver]: (type) => `a \"${type}:\" template at the top of inserted content was not rendered, as it would render beside itself out of the inserter's reach: wrap it in an element.`,\n [M.OuterInTemplate]: (name) => `\"${name}:\" replaces its element, so it cannot be used inside a \"for\" / \"if\" template (a row or branch keeps its nodes by position): bind innerHTML: on a wrapper element instead.`,\n\n [M.PathMissing]: (p) => `Path \"${p}\" does not exist on the state tree.`,\n\n [M.ClassNeedsBoolean]: (name, type) => `class.${name} needs a boolean, got ${type}.`,\n\n [M.FilterUnknown]: (name) => `filter not found: ${name}.`,\n\n [M.FilterTooFewArgs]: (name, min, given) => `filter \"${name}\" requires at least ${min} argument(s) (${given} given).`,\n [M.FilterTooManyArgs]: (name, max, given) => `filter \"${name}\" accepts at most ${max} argument(s) (${given} given).`,\n\n [M.GetterCycle]: (p) => `\"${p}\" depends on itself`,\n\n [M.GetterDepth]: (p) => `\"${p}\"`,\n\n [M.IndexArityExact]: (api, p, depth, n) => `${api}(\"${p}\") takes ${depth} index(es), got ${n}.`,\n [M.IndexArityAtMost]: (api, p, depth, n) => `${api}(\"${p}\") takes at most ${depth} index(es), got ${n}.`,\n\n [M.IndexParamRange]: (key) => `\"${key}\": list index parameters run from $1 to $${MAX_INDEX_PARAM}.`,\n\n [M.RecursionUnsupported]: (p) => `\"${p}\" uses \"${RECURSION_WILDCARD}\", which is not accepted here.`,\n\n [M.CommandRightSide]: (prop, p) => `\"${prop}: ${p}\": the right-hand side must be $command.<name>`,\n // a native element's command (no hyphen: never a custom element) is the native-commands add-on's\n [M.NoBindable]: (tag, what) => `<${tag}> declares no static wcBindable (${what}).${\n !tag.includes(\"-\") && what.startsWith(\"command.\") ? \" A native element's command needs the add-on @wcstack/state/features/native-commands.\" : \"\"}`,\n [M.NoCommand]: (tag, method) => `<${tag}> declares no command \"${method}\".`,\n [M.NoProperty]: (tag, prop) => `<${tag}> declares no property \"${prop}\".`,\n [M.NativeNoCommand]: (tag, method, allowed) => `<${tag}> has no command \"${method}\" (a native <${tag}>'s commands: ${allowed}).`,\n\n [M.EventTokenUndeclared]: (name) => `eventToken \"${name}\" is not declared in $eventTokens.`,\n [M.CommandTokenUndeclared]: (name) => `\"$command.${name}\" is not declared in $commandTokens.`,\n\n [M.WildcardNoLoop]: (p, depth, n = 0) => `\"${p}\" needs ${depth} enclosing loop level(s); the scope provides ${n}.`,\n [M.WildcardRelative]: (p) => `\"${p}\" is relative: it needs an enclosing \"for\" template`,\n [M.WildcardOtherList]: (p, over, loop) => `\"${p}\" ranges over the rows of \"${over}\", but the enclosing \"for\" template at that level renders \"${loop}\".`,\n\n [M.SpreadNoBindable]: (tag, what) => `<${tag}> declares no static wcBindable (${what}).`,\n\n [M.DeclarationRemoved]: (old, name) => `${old} was removed: write ${name}.`,\n\n [M.ApiRemoved]: (old, name) => `${old} was removed: write ${name}.`,\n};\n","/**\n * The diagnostics add-on's sentences and guidance: a numbered core message rendered as its\n * sentence (src/diagnostics/messages.ts), then how to fix it, the nearest name and the lint\n * pointer. The add-on installs these; so does `@wcstack/state/parser`, a bundle of its own.\n */\nimport { didYouMean, LINT_HINT } from \"./guidance\";\nimport { FORMATS_FILTER_NAMES, hasFilter } from \"../filters/registry\";\nimport type { M } from \"../messages\";\nimport { codeOf, SENTENCES } from \"./messages\";\n\n/** A numbered core message as its sentence (the number and the values if it is not known here). */\nexport function render(id: number, args: readonly unknown[]): string {\n const sentence = SENTENCES[id as M];\n return sentence === undefined ? `${codeOf(id)}#${id} ${args.join(\" \")}` : codeOf(id) + sentence(...args);\n}\n\n/** Codes lint detects statically: only these point the author to a lint run. */\nconst LINT_CODES = new Set([\n \"binding-syntax\", \"template-syntax\", \"filter-unknown\", \"filter-arity\", \"index-arity\",\n \"wildcard-rank\", \"token-undeclared\", \"binding-path-missing\", \"index-param-range\",\n]);\n\n/** How to fix it, by what the message says. */\nconst GUIDES: [RegExp, string][] = [\n [/no loop level in common with the context/, \"; pass indexes ([] for all).\"],\n [/\"([^\"#]+)#([^\"]*)\" is not a filter name: a modifier list .* comes before the input filters/, ' — write \"<property>#$2|$1\".'],\n [/\\[wcs\\/recursion-unsupported\\]/, \" It is only meaningful in a $recursion declaration, in a recursive getter key, and in the path argument of $getAll / $setAll — and only when the state declares a $recursion anchor.\"],\n [/must be single binding/, ' Put the structural binding alone in its own data-wcs (e.g. <template data-wcs=\"for: items\">).'],\n [/\\[wcs\\/wildcard-rank\\] .* needs \\d+ enclosing/, ' Wrap it in that many \"for\" templates, or use $resolve(path, indexes) to name the row explicitly.'],\n [/\\[wcs\\/wildcard-rank\\] .* ranges over the rows of/, ' A \"*\" in a binding is the row of the loop around it: read a row of another list in a getter, with $resolve(path, indexes).'],\n [/\\[wcs\\/binding-type-expectation\\] class\\.([^ ]+)/, ' Write \"class.$1: path|truthy\" to toggle on truthiness.'],\n [/path segments — the limit/, \" Every prefix of a path is interned, so the cost grows with the square of the depth.\"],\n [/\\[wcs\\/index-arity\\] \\$resolve/, \" $resolve takes one index per \\\"*\\\"; $getAll / $setAll take at most that many (fewer expands the rest).\"],\n [/\"([^\"#]+)#[^\"]*\" is not a filter name: \"#\" cannot appear in one/, ' Modifiers belong on the left side of the binding, before the \":\" — write \"$1\" here.'],\n];\n\n/**\n * The filter names 3.2 renamed, which 3.x kept as aliases and 4.0 removed (3.x's `filterAliases`;\n * lint has the same table). Their message names the replacement, not the nearest name: for these\n * that is an unrelated filter (`dec` → `eq`, `fix` → `div`), and following it changes the meaning.\n */\nexport const RENAMED_FILTERS: Readonly<Record<string, string>> = {\n inc: \"add\", dec: \"sub\", fix: \"toFixed\", uc: \"upper\", lc: \"lower\", cap: \"capitalize\", rep: \"repeat\", rev: \"reverse\", pad: \"padStart\", null: \"nullIfEmpty\",\n};\n\n/** How to write a filter 4.0 removed, or null. */\nfunction removedFilter(name: string): string | null {\n // 4.0 folded substr(start, length) into slice(start, end): the second argument changes meaning\n if (name === \"substr\") return ' \"substr\" was removed in 4.0 — write slice(start, start + length): slice takes the end index, not a length.';\n const to = Object.hasOwn(RENAMED_FILTERS, name) ? RENAMED_FILTERS[name] : null;\n return to === null ? null : ` \"${name}\" was renamed \"${to}\" in 3.2 and removed in 4.0 — write \"${to}\".`;\n}\n\nexport function explain(message: string, subject?: string, candidates?: Iterable<string>): string {\n const removed = subject !== undefined && message.includes(\"[wcs/filter-unknown]\") ? removedFilter(subject) : null;\n let out = removed ?? (subject !== undefined && candidates !== undefined ? didYouMean(subject, candidates) : \"\");\n for (const [re, text] of GUIDES) {\n const m = re.exec(message);\n if (m !== null) out += text.replace(/\\$(\\d)/g, (_, i: string) => m[Number(i)]);\n }\n // \"value#ro#wo\": one modifier list — the fix joins them\n const mods = /\"([^\"#]+)#([^\"]+)\": a binding takes one modifier list/.exec(message);\n if (mods !== null) out += ` — write \"${mods[1]}#${mods[2].split(\"#\").join(\",\")}\".`;\n // a formatting filter on a page without the formats add-on (the core names installFeatures), or a\n // typo on a page with no formatting filters at all: the formats add-on may be what is missing\n if (message.includes(\"[wcs/filter-unknown]\")) {\n if (message.includes(\"formats add-on\")) out += ` On a split auto page: features=\"formats\" on the root, or \"$features\": [\"formats\"].`;\n else if (!FORMATS_FILTER_NAMES.some(hasFilter)) {\n out += ` No formatting filters are installed — add the formats add-on: installFeatures([formats]) from \"@wcstack/state/features/formats\" (a split auto page: features=\"formats\", or \"$features\").`;\n }\n }\n const code = /\\[wcs\\/([\\w-]+)\\]/.exec(message);\n // (not something lint reports: the path-length limit is a runtime cost, a template handed over at\n // the top of inserted content (#204) is the page's order of loading, not its markup, and lint's\n // manifest knows the formatting filters — one missing because the formats add-on is not installed\n // is the page's. A row of another list (#1403) and an `outerHTML:` in a template (#203) lint does\n // report, as of its 4.0 parser)\n if (code !== null && LINT_CODES.has(code[1]) && !/ path segments — the limit is |inserted content was not rendered|formats add-on/.test(message)) out += LINT_HINT;\n return out;\n}\n","/**\n * The diagnostics add-on (@wcstack/state/features/diagnostics): the sentences and the self-fix\n * guidance of error messages. The core states the message number and the values\n * (`#901 \"$resolve\" \"m.*.*\" 2 1`); with this installed, the message is the code shared with lint\n * and the sentence (`[wcs/index-arity] $resolve(\"m.*.*\") takes 2 index(es), got 1.`), followed by the\n * nearest name (did-you-mean, the same rule as lint), how to fix it, and a pointer to lint where\n * lint really detects the case. The full `auto` bundle installs it.\n */\nimport { chain, first, hooks, known, type Feature } from \"../hooks\";\nimport type { Engine } from \"../engine\";\nimport { parsePath, type Pattern } from \"../pattern\";\nimport { raiseError } from \"../parser/raiseError\";\nimport { config } from \"../config\";\nimport type { WcsState } from \"../element\";\nimport type { Binding } from \"../dom/view\";\nimport { getTrustedTypesPolicy, isHtmlSink } from \"../trustedTypes\";\nimport { didYouMean, LINT_HINT } from \"../diagnostics/guidance\";\nimport { explain, render } from \"../diagnostics/explain\";\nimport { raise, M } from \"../messages\";\n\n// ---------------------------------------------------------------- paths that do not resolve\n\n/** Paths bindings and `$watch` keys named, by engine: checked one macrotask later (and after a re-set). */\nconst named = new WeakMap<Engine, Map<Pattern, boolean>>();\nconst checked = new WeakMap<Engine, Set<Pattern>>();\nconst due = new WeakSet<Engine>();\n/** Volumes (`<wcs-state mount>`) whose loading settled: the paths under them are checked from then on. */\nconst settled = new WeakSet<Element>();\n\nfunction findDescriptor(o: object, key: string): PropertyDescriptor | undefined {\n for (let x: object | null = o; x !== null && x !== Object.prototype; x = Object.getPrototypeOf(x)) {\n const d = Object.getOwnPropertyDescriptor(x, key);\n if (d !== undefined) return d;\n }\n return undefined;\n}\n\nfunction keysOf(o: object): string[] {\n const out = new Set<string>();\n for (let x: object | null = o; x !== null && x !== Object.prototype; x = Object.getPrototypeOf(x)) {\n for (const k of Object.getOwnPropertyNames(x)) if (k[0] !== \"$\" && k !== \"constructor\") out.add(k);\n }\n return [...out];\n}\n\n/**\n * The pattern a path with an explicit index reads through: an index with no `*` after it\n * (`items.0.x`) has an accessor of its own (Engine.markupAccessor), so whether it reads a getter\n * is the question of the pattern it names (`items.*.x`). A `*` after the index (`groups.0.items.*.x`,\n * a row of `for: groups.0.items`) reads its row's own item: the pattern itself. So does a path the\n * author declared a getter under (`get \"groups.0.items\"()`): that getter is what it reads (#388).\n */\nfunction wildcardForm(engine: Engine, q: Pattern): Pattern | undefined {\n const segs = q.path.split(\".\");\n // (a leading numeric segment is a root key, not an index: parsePath)\n const i = segs.findIndex((s, j) => j > 0 && /^\\d/.test(s));\n return i < 0 || segs.indexOf(\"*\", i) >= 0 || findDescriptor(engine.target, q.path)?.get !== undefined\n ? q : engine.patterns.peek(parsePath(q.path).pattern);\n}\n\n/**\n * The segment of `p` that certainly does not exist, with the names that do at its level; null\n * when the path exists or it cannot be told without evaluating a getter (a getter on the way, a\n * null or primitive on the way, a list with no row to look into).\n */\nfunction missing(engine: Engine, p: Pattern): { seg: string; names: string[] } | null {\n const chain: Pattern[] = [];\n for (let q: Pattern | null = p; q !== null; q = q.parent) chain.unshift(q);\n let v: any = engine.target;\n const named = (q: Pattern | null): Pattern | null | undefined => (q === null ? null : wildcardForm(engine, q));\n for (const q of chain) {\n if (named(q)?.getter != null) return null;\n if (v === null || typeof v !== \"object\") return null;\n if (q.last === \"*\") {\n if (!Array.isArray(v) || v.length === 0) return null;\n v = v[0];\n continue;\n }\n if (Array.isArray(v) && /^\\d+$/.test(q.last)) {\n // an explicit index: only a row that is there can be looked into\n if (Number(q.last) >= v.length) return null;\n v = v[Number(q.last)];\n continue;\n }\n const d = findDescriptor(v, q.last);\n // a top-level key a re-set dropped is declared: it reads undefined, and a write fills it\n if (d === undefined && q.parent === null && engine.dropped.has(q.last)) return null;\n if (d === undefined) {\n const names = keysOf(v);\n // getters declared one level under the same parent (`items.*.subtotal`)\n const parent = named(q.parent);\n for (const g of engine.patterns.all()) if (g.parent === parent && g.getter !== null) names.push(g.last);\n return { seg: q.last, names };\n }\n if (d.get !== undefined || d.set !== undefined) return null;\n v = d.value;\n }\n return null;\n}\n\nfunction check(engine: Engine): void {\n due.delete(engine);\n const map = named.get(engine);\n if (map === undefined) return;\n let done = checked.get(engine);\n if (done === undefined) checked.set(engine, (done = new Set()));\n for (const [p, watch] of map) {\n if (done.has(p)) continue;\n done.add(p);\n const m = missing(engine, p);\n if (m === null) continue;\n // under the mount path of a volume on the page still loading: checked again once it settles (3.x D22)\n const v = [...((engine.root as ParentNode | null)?.querySelectorAll(`${config.tagNames.state}[mount]`) ?? [])]\n .find((e) => !settled.has(e) && (p.path + \".\").startsWith(e.getAttribute(\"mount\") + \".\"));\n if (v !== undefined) {\n done.delete(p);\n void (v as WcsState).initializePromise.then(() => {\n settled.add(v);\n schedule(engine);\n });\n continue;\n }\n const [code, subject] = watch ? [\"watch-path-missing\", \"$watch path\"] : [\"binding-path-missing\", \"Bound path\"];\n hooks.noticed?.(engine, { \"type\": \"state:path-unresolved\", \"source\": watch ? \"watch\" : \"binding\", \"path\": p.path, \"missingSegment\": m.seg });\n // a row of `for: groups.0.items` with a row getter declared on `groups.*.items.*` (#388)\n const w = engine.patterns.peek(parsePath(p.path).pattern);\n let rowGetter = \"\";\n if (w !== undefined && w !== p && w.getter !== null) {\n const loops = w.lists.slice(1).map((l, k) => `for: ${k === 0 ? l!.path : l!.path.slice(w.lists[k]!.path.length + 2)}`);\n rowGetter = ` The getter \"${w.path}\" is declared for the rows of ${loops.join(\" → \")}; a list named by an index has rows of its own.`;\n }\n console.warn(`[@wcstack/state] [wcs/${code}] ${subject} \"${p.path}\" does not resolve on the state tree: \"${m.seg}\" is not declared.${didYouMean(m.seg, m.names)}${rowGetter} Updates to this path will be silently dropped.${LINT_HINT}`);\n }\n}\n\nfunction schedule(engine: Engine): void {\n if (due.has(engine)) return;\n due.add(engine);\n setTimeout(() => check(engine), 0);\n}\n\n/** The `declared` hook: a path a binding or a `$watch` key names. */\nfunction declared(engine: Engine, p: Pattern, watch = false): void {\n // a missing top-level key already fails the binding's read (the core's error)\n if (p.path[0] === \"$\" || p.path.includes(\"#\") || (!watch && p.parent === null)) return;\n let map = named.get(engine);\n if (map === undefined) named.set(engine, (map = new Map()));\n if (!map.has(p)) map.set(p, watch);\n schedule(engine);\n}\n\n/** A re-set: every path is checked again against the new state. */\nfunction recheck(engine: Engine): void {\n checked.delete(engine);\n if (named.has(engine)) schedule(engine);\n}\n\n// ---------------------------------------------------------------- recursion's static checks\n\n/**\n * `$recursion` families that can never work (approved simplification: these checks moved out of\n * the core): a suffix naming the recursion structure itself, two families one of which is the\n * other a few repeats deeper, and a concrete key that one of the families expands to.\n */\nfunction checkRecursion(target: Record<string, any>): void {\n const decl = target.$recursion;\n if (decl === null || typeof decl !== \"object\") return;\n const entries = Object.entries(decl);\n if (entries.length !== 1 || typeof entries[0][1] !== \"string\") return;\n const [anchor, repeat] = entries[0] as [string, string];\n if (!anchor.endsWith(\".*\") || !repeat.endsWith(\".*\")) return;\n const list = anchor.slice(0, -2);\n const key = repeat.slice(0, -2);\n const step = `.${repeat}`;\n const head = `${list}.**`;\n const keys = keysOf(target);\n const families = keys.filter((k) => k.startsWith(head)).map((k) => k.slice(head.length));\n const bad = (why: string): never => raiseError(`[wcs/recursion-declaration-invalid] ${why}`);\n for (const s of families) {\n if (s === `.${key}` || s.startsWith(`.${key}.`)) {\n bad(`\"${head}${s}\" names the recursion structure itself (the \"${key}\" lists): recursive getters compute values over the nodes.`);\n }\n for (const t of families) {\n if (t.length > s.length && t.endsWith(s) && new RegExp(`^(?:${esc(step)})+$`).test(t.slice(0, t.length - s.length))) {\n bad(`\"${head}${s}\" and \"${head}${t}\" expand to the same concrete path at different depths (they differ by whole repetitions of \"${repeat}\"). Rename one of them.`);\n }\n }\n const re = new RegExp(`^${esc(anchor)}(?:${esc(step)})*${esc(s)}$`);\n for (const k of keys) {\n if (!k.includes(\"**\") && re.test(k)) bad(`\"${k}\" is already defined on the state, so the recursive getter \"${head}${s}\" cannot expand to it.`);\n }\n }\n}\n\nconst esc = (s: string): string => s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n\nlet trustedTypesReported = false;\n\n/**\n * An HTML sink write Trusted Types blocked: the browser's message names no fix, so say once\n * per page what to install (the same report as @wcstack/state 3.3).\n */\nfunction failed(_engine: Engine, error: unknown, binding: Binding): void {\n const prop = binding.name === \"html\" ? \"innerHTML\" : binding.name;\n if (trustedTypesReported || !(error instanceof TypeError) || !isHtmlSink(prop) || !(\"trustedTypes\" in globalThis)) return;\n trustedTypesReported = true;\n const cause = typeof getTrustedTypesPolicy()?.createHTML === \"function\"\n ? \"The injected policy's createHTML() did not return a TrustedHTML.\"\n : \"No sanitizing policy is installed, and @wcstack/state deliberately does not pass state values through an identity policy — that would defeat the CSP.\";\n console.error(\n `[@wcstack/state] Writing to \"${prop}\" was blocked by Trusted Types (require-trusted-types-for 'script'). ${cause}\\n`\n + `Install a sanitizing policy before the first binding is applied:\\n`\n + ` globalThis[Symbol.for(\"wcstack.trustedTypes.policy\")] =\\n`\n + ` trustedTypes.createPolicy(\"my-app\", { createHTML: (s) => DOMPurify.sanitize(s) });\\n`\n + `Or bind the value as text instead of HTML. See docs/csp.md section 7.`,\n { element: binding.node, property: prop },\n );\n}\n\n// ---------------------------------------------------------------- the default getter\n\nconst warnedDetail = new WeakMap<Element, Set<string>>();\n\n/**\n * A wc-bindable property's event read with the default getter (`e.detail`): warns once per\n * element and property about the two shapes that cannot be what the element meant (README\n * \"What the element writes back\", as @wcstack/state 3.3). The write is applied as it is.\n * (a) no detail while the element's property has a value — a plain Event, or a forgotten detail;\n * (b) a detail object with a `<name>` key while the property is not an object — a wrapper.\n */\nfunction detail(el: Element, name: string, v: unknown): void {\n const prop = (el as any)[name];\n const reason = v === undefined\n ? prop === undefined ? null : `the event carried no detail (undefined) while element.${name} is ${typeof prop}`\n : v !== null && typeof v === \"object\" && Object.prototype.hasOwnProperty.call(v, name) && (prop === null || typeof prop !== \"object\")\n ? `the event's detail is an object with a \"${name}\" key while element.${name} is ${typeof prop}`\n : null;\n if (reason === null) return;\n let said = warnedDetail.get(el);\n if (said === undefined) warnedDetail.set(el, (said = new Set()));\n if (said.has(name)) return;\n said.add(name);\n console.warn(\n `[@wcstack/state] [wcs/default-getter-mismatch] <${el.localName}> \"${name}\": ${reason}. `\n + \"With no getter, state receives e.detail as-is. Dispatch the value itself as detail, or declare \"\n + `getter (e.g. (e) => e.detail.${name}, or (e) => e.target.${name}) on that wcBindable property.`,\n );\n}\n\n// ---------------------------------------------------------------- 3.x names 4.0 removed\n\n/**\n * Declarations 3.2 renamed, whose old names 4.0 removed: a declaration under one would do nothing.\n * (The core detected these and the two APIs below up to 4.0.0-rc.3; without this add-on they are\n * ignored like any other unknown `$` key.)\n */\nconst REMOVED_DECLARATIONS: [string, string][] = [[\"$streams\", \"$stream\"], [\"$updatedCallback\", \"$renderedCallback\"]];\n/** APIs 3.2 renamed, whose old names 4.0 removed: reading one fails with the name to write. */\nconst REMOVED_APIS: Readonly<Record<string, string>> = { \"$trackDependency\": \"$dependOn\", \"$untrackDependency\": \"$untracked\" };\n\n/** A state that declares a 3.x name 4.0 removed (`$scan` has no successor: $watch or $on). */\nfunction removedDeclarations(target: Record<string, any>): void {\n if (target.$scan !== undefined) raise(M.ScanRemoved);\n for (const [old, name] of REMOVED_DECLARATIONS) if (target[old] !== undefined) raise(M.DeclarationRemoved, [old, name]);\n}\n\nexport const diagnostics: Feature = {\n name: \"diagnostics\",\n install(): void {\n hooks.explain = explain;\n hooks.render = render;\n hooks.declared = declared;\n hooks.detail = detail;\n hooks.failed = chain(hooks.failed, failed);\n // the removed names first, before what is installed (the core checked them before it took the\n // state in): a refused state never reaches the other add-ons' runtimes\n const prev = hooks.declare;\n hooks.declare = (engine, target) => {\n removedDeclarations(target);\n prev?.(engine, target);\n checkRecursion(target);\n recheck(engine);\n };\n hooks.dollar = first(known, hooks.dollar, (_engine, key) => (Object.hasOwn(REMOVED_APIS, key) ? raise(M.ApiRemoved, [key, REMOVED_APIS[key]]) : undefined));\n },\n};\nexport default diagnostics;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
import{a as t,b as r,c as e,d as a,e as n,f as o,g as i,h as l,i as c}from"../chunks/chunk-
|
|
1
|
+
import{a as t,b as r,c as e,d as a,e as n,f as o,g as i,h as l,i as c}from"../chunks/chunk-W4KOY6GT.js";import{a as y,e as u}from"../chunks/chunk-M5SODAAE.js";import{a as s}from"../chunks/chunk-EIMTT5I3.js";import"../chunks/chunk-4NJBYXIT.js";var f,p=t=>r=>{let e=t(r);return t=>null==t?t:e(t)},d="en";function m(){if(y.locale!==f){f=y.locale;try{d=Intl.getCanonicalLocales(f)[0]}catch{console.warn(`[@wcstack/state] ${s(48,[f])}`),d="en"}}return d}var{eq:g,ne:S,not:h,lt:b,le:M,gt:$,ge:k,falsy:j,truthy:D,boolean:w}=c,x={toFixed:{factory:t=>{let e=n(t?.[0]??"0","toFixed");return t=>("number"!=typeof t&&r("toFixed"),t.toFixed(e))},arity:[0,1]},locale:{factory:t=>{let e=t?.[0];return t=>("number"!=typeof t&&r("locale"),t.toLocaleString(e??m()))},arity:[0,1]},upper:{factory:p(()=>t=>String(t).toUpperCase()),arity:[0,0]},lower:{factory:p(()=>t=>String(t).toLowerCase()),arity:[0,0]},capitalize:{factory:p(()=>t=>{let r=String(t);return 0===r.length?r:1===r.length?r.toUpperCase():r.charAt(0).toUpperCase()+r.slice(1)}),arity:[0,0]},trim:{factory:p(()=>t=>String(t).trim()),arity:[0,0]},slice:{factory:p(t=>{let r=[o(t,0,"slice")],e=t?.[1];return typeof e<"u"&&r.push(n(e,"slice")),t=>String(t).slice(...r)}),arity:[1,2]},padStart:{factory:p(t=>{let r=o(t,0,"padStart"),e=t?.[1]??"0";return t=>String(t).padStart(r,e)}),arity:[1,2]},padEnd:{factory:p(t=>{let r=o(t,0,"padEnd"),e=t?.[1]??" ";return t=>String(t).padEnd(r,e)}),arity:[1,2]},repeat:{factory:p(t=>{let r=o(t,0,"repeat");return t=>String(t).repeat(r)}),arity:[1,1]},reverse:{factory:p(()=>t=>String(t).split("").reverse().join("")),arity:[0,0]},truncate:{factory:p(t=>{let r=o(t,0,"truncate"),e=t?.[1]??"…";return t=>{let a=String(t);return a.length<=r?a:a.slice(0,r)+e}}),arity:[1,2]},join:{factory:t=>{let r=t?.[0]??", ";return t=>(Array.isArray(t)||a("join"),t.join(r))},arity:[0,1]},round:{factory:t=>{let e=Math.pow(10,n(t?.[0]??"0","round"));return t=>("number"!=typeof t&&r("round"),Math.round(t*e)/e)},arity:[0,1]},floor:{factory:t=>{let e=Math.pow(10,n(t?.[0]??"0","floor"));return t=>("number"!=typeof t&&r("floor"),Math.floor(t*e)/e)},arity:[0,1]},ceil:{factory:t=>{let e=Math.pow(10,n(t?.[0]??"0","ceil"));return t=>("number"!=typeof t&&r("ceil"),Math.ceil(t*e)/e)},arity:[0,1]},percent:{factory:t=>{let e=n(t?.[0]??"0","percent");return t=>("number"!=typeof t&&r("percent"),`${(100*t).toFixed(e)}%`)},arity:[0,1]},unit:{factory:p(r=>{let e=r?.[0]??t("unit");return t=>String(t)+e}),arity:[1,1]},date:{factory:t=>{let r=t?.[0];return t=>(t instanceof Date||e("date"),t.toLocaleDateString(r??m()))},arity:[0,1]},time:{factory:t=>{let r=t?.[0];return t=>(t instanceof Date||e("time"),t.toLocaleTimeString(r??m()))},arity:[0,1]},datetime:{factory:t=>{let r=t?.[0];return t=>(t instanceof Date||e("datetime"),t.toLocaleString(r??m()))},arity:[0,1]},ymd:{factory:t=>{let r=t?.[0]??"-";return t=>{t instanceof Date||e("ymd");let a=t.getFullYear().toString(),n=(t.getMonth()+1).toString().padStart(2,"0"),o=t.getDate().toString().padStart(2,"0");return`${a}${r}${n}${r}${o}`}},arity:[0,1]},hms:{factory:t=>{let r=t?.[0]??":";return t=>{t instanceof Date||e("hms");let a=t.getHours().toString().padStart(2,"0"),n=t.getMinutes().toString().padStart(2,"0"),o=t.getSeconds().toString().padStart(2,"0");return`${a}${r}${n}${r}${o}`}},arity:[0,1]},eq:g,ne:S,not:h,lt:b,le:M,gt:$,ge:k,add:l("add",(t,r)=>t+r),sub:l("sub",(t,r)=>t-r),mul:l("mul",(t,r)=>t*r),div:l("div",(t,r)=>t/r),mod:l("mod",(t,r)=>t%r),abs:{factory:()=>t=>("number"!=typeof t&&r("abs"),Math.abs(t)),arity:[0,0]},clamp:{factory:t=>{let e=o(t,0,"clamp"),a=o(t,1,"clamp");return t=>("number"!=typeof t&&r("clamp"),Math.min(Math.max(t,e),a))},arity:[2,2]},int:{factory:()=>t=>parseInt(String(t),10),arity:[0,0]},float:{factory:()=>t=>parseFloat(String(t)),arity:[0,0]},falsy:j,truthy:D,defaults:{factory:(r,e)=>{let a=r?.[0]??t("defaults"),n=i(a,e);return t=>t||n},arity:[1,1]},coalesce:{factory:(r,e)=>{let a=r?.[0]??t("coalesce"),n=i(a,e);return t=>t??n},arity:[1,1]},boolean:w,number:{factory:()=>t=>Number(t),arity:[0,0]},string:{factory:()=>t=>String(t),arity:[0,0]},nullIfEmpty:{factory:()=>t=>""===t?null:t,arity:[0,0]}},F=!1,v={name:"formats",install:function(){F||(F=!0,u(x))}},E=v;export{E as default,v as formats};
|
|
2
|
+
//# sourceMappingURL=formats.js.map
|