sygnal 7.0.0 → 7.2.0-preview.0
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/CHANGELOG.md +632 -0
- package/dist/agent-ui.cjs.js +592 -0
- package/dist/agent-ui.cjs.js.map +1 -0
- package/dist/agent-ui.esm.js +582 -0
- package/dist/agent-ui.esm.js.map +1 -0
- package/dist/api.cjs.js +63 -0
- package/dist/api.cjs.js.map +1 -0
- package/dist/api.esm.js +2 -0
- package/dist/api.esm.js.map +1 -0
- package/dist/astro/index.cjs.js +968 -4
- package/dist/astro/index.cjs.js.map +1 -1
- package/dist/astro/index.mjs +968 -4
- package/dist/astro/index.mjs.map +1 -1
- package/dist/astro/server.cjs.js +73 -45
- package/dist/astro/server.cjs.js.map +1 -1
- package/dist/astro/server.mjs +73 -45
- package/dist/astro/server.mjs.map +1 -1
- package/dist/canvas.cjs.js +2919 -0
- package/dist/canvas.cjs.js.map +1 -0
- package/dist/canvas.esm.js +2866 -0
- package/dist/canvas.esm.js.map +1 -0
- package/dist/devtools.cjs.js +38 -6
- package/dist/devtools.cjs.js.map +1 -1
- package/dist/devtools.esm.js +38 -6
- package/dist/devtools.esm.js.map +1 -1
- package/dist/diagnostics.cjs.js +224 -20
- package/dist/diagnostics.cjs.js.map +1 -1
- package/dist/diagnostics.esm.js +224 -20
- package/dist/diagnostics.esm.js.map +1 -1
- package/dist/guide/accessibility.md +1 -1
- package/dist/guide/ai-compose.md +150 -0
- package/dist/guide/behaviors.md +2 -1
- package/dist/guide/collaborative-state.md +265 -0
- package/dist/guide/element-commands.md +36 -2
- package/dist/guide/forms-reference.md +5 -5
- package/dist/guide/forms.md +3 -2
- package/dist/guide/http.md +28 -1
- package/dist/guide/islands.md +240 -0
- package/dist/guide/recipes/code-editor.md +1 -1
- package/dist/guide/renderers/agent-ui.md +138 -0
- package/dist/guide/renderers/custom-targets.md +126 -0
- package/dist/guide/renderers/overview.md +120 -0
- package/dist/guide/renderers/react-native.md +128 -0
- package/dist/guide/renderers/terminal.md +306 -0
- package/dist/guide/renderers/three.md +332 -0
- package/dist/guide/renderers/write-once.md +137 -0
- package/dist/guide/resources.md +2 -0
- package/dist/guide/sandboxed-components.md +223 -0
- package/dist/guide/timers.md +32 -5
- package/dist/guide/typed-apis.md +442 -0
- package/dist/guide/ui/accordion.md +11 -0
- package/dist/guide/ui/combobox.md +112 -8
- package/dist/guide/ui/dialog.md +96 -20
- package/dist/guide/ui/menu.md +57 -5
- package/dist/guide/ui/overview.md +8 -4
- package/dist/guide/ui/popover.md +69 -9
- package/dist/guide/ui/select.md +54 -4
- package/dist/guide/ui/tabs.md +1 -1
- package/dist/guide/ui/tooltip.md +7 -5
- package/dist/guide/virtual-collections.md +3 -0
- package/dist/guide/widgets.md +90 -1
- package/dist/host.cjs.js +2181 -0
- package/dist/host.cjs.js.map +1 -0
- package/dist/host.esm.js +2146 -0
- package/dist/host.esm.js.map +1 -0
- package/dist/index.cjs.js +3948 -586
- package/dist/index.cjs.js.map +1 -1
- package/dist/index.d.ts +584 -44
- package/dist/index.esm.js +3918 -586
- package/dist/index.esm.js.map +1 -1
- package/dist/primitives.cjs.js +143 -0
- package/dist/primitives.cjs.js.map +1 -0
- package/dist/primitives.esm.js +133 -0
- package/dist/primitives.esm.js.map +1 -0
- package/dist/react-native.cjs.js +248 -0
- package/dist/react-native.cjs.js.map +1 -0
- package/dist/react-native.esm.js +244 -0
- package/dist/react-native.esm.js.map +1 -0
- package/dist/replay.cjs.js +39 -0
- package/dist/replay.cjs.js.map +1 -0
- package/dist/replay.esm.js +2 -0
- package/dist/replay.esm.js.map +1 -0
- package/dist/sandbox-build.cjs.js +140 -0
- package/dist/sandbox-build.cjs.js.map +1 -0
- package/dist/sandbox-build.esm.js +137 -0
- package/dist/sandbox-build.esm.js.map +1 -0
- package/dist/sandbox-kernel.esm.js +212 -0
- package/dist/sandbox-kernel.esm.js.map +1 -0
- package/dist/sandbox-worker.cjs.js +857 -0
- package/dist/sandbox-worker.cjs.js.map +1 -0
- package/dist/sandbox-worker.esm.js +854 -0
- package/dist/sandbox-worker.esm.js.map +1 -0
- package/dist/sandbox.cjs.js +1425 -0
- package/dist/sandbox.cjs.js.map +1 -0
- package/dist/sandbox.esm.js +1406 -0
- package/dist/sandbox.esm.js.map +1 -0
- package/dist/sygnal.min.js +1 -1
- package/dist/sygnal.min.js.map +1 -1
- package/dist/terminal.cjs.js +1314 -0
- package/dist/terminal.cjs.js.map +1 -0
- package/dist/terminal.esm.js +1304 -0
- package/dist/terminal.esm.js.map +1 -0
- package/dist/three.cjs.js +1111 -0
- package/dist/three.cjs.js.map +1 -0
- package/dist/three.esm.js +1079 -0
- package/dist/three.esm.js.map +1 -0
- package/dist/ui-combobox.cjs.js +256 -18
- package/dist/ui-combobox.cjs.js.map +1 -1
- package/dist/ui-combobox.esm.js +256 -18
- package/dist/ui-combobox.esm.js.map +1 -1
- package/dist/ui-menu.cjs.js +150 -16
- package/dist/ui-menu.cjs.js.map +1 -1
- package/dist/ui-menu.esm.js +151 -17
- package/dist/ui-menu.esm.js.map +1 -1
- package/dist/ui-select.cjs.js +95 -9
- package/dist/ui-select.cjs.js.map +1 -1
- package/dist/ui-select.esm.js +95 -9
- package/dist/ui-select.esm.js.map +1 -1
- package/dist/ui.cjs.js +679 -173
- package/dist/ui.cjs.js.map +1 -1
- package/dist/ui.esm.js +679 -175
- package/dist/ui.esm.js.map +1 -1
- package/dist/vike/config/package.json +1 -1
- package/dist/vite/plugin.cjs.js +968 -4
- package/dist/vite/plugin.cjs.js.map +1 -1
- package/dist/vite/plugin.mjs +968 -4
- package/dist/vite/plugin.mjs.map +1 -1
- package/dist/worker-page.cjs.js +669 -0
- package/dist/worker-page.cjs.js.map +1 -0
- package/dist/worker-page.esm.js +665 -0
- package/dist/worker-page.esm.js.map +1 -0
- package/dist/worker.cjs.js +377 -0
- package/dist/worker.cjs.js.map +1 -0
- package/dist/worker.esm.js +374 -0
- package/dist/worker.esm.js.map +1 -0
- package/dist/yjs-testing.cjs.js +98 -0
- package/dist/yjs-testing.cjs.js.map +1 -0
- package/dist/yjs-testing.esm.js +77 -0
- package/dist/yjs-testing.esm.js.map +1 -0
- package/dist/yjs.cjs.js +923 -0
- package/dist/yjs.cjs.js.map +1 -0
- package/dist/yjs.esm.js +900 -0
- package/dist/yjs.esm.js.map +1 -0
- package/dist/zag.cjs.js +11 -1
- package/dist/zag.cjs.js.map +1 -1
- package/dist/zag.esm.js +11 -1
- package/dist/zag.esm.js.map +1 -1
- package/llms/ai.md +65 -0
- package/llms/collaboration.md +5 -0
- package/llms/graphics.md +10 -0
- package/llms/renderers.md +7 -0
- package/llms/replay.md +5 -0
- package/llms/sandbox.md +5 -0
- package/llms/typed-apis.md +5 -0
- package/llms/ui.md +10 -0
- package/llms-full.txt +444 -0
- package/llms.txt +37 -35
- package/package.json +139 -3
- package/src/agent-ui/mcp.ts +152 -0
- package/src/agent-ui/snapshot.ts +212 -0
- package/src/agent-ui.d.ts +106 -0
- package/src/agent-ui.ts +249 -0
- package/src/ai.d.ts +95 -2
- package/src/api.d.ts +303 -0
- package/src/api.ts +9 -0
- package/src/canvas/Canvas.ts +585 -0
- package/src/canvas/backend.ts +627 -0
- package/src/canvas/geometry.ts +187 -0
- package/src/canvas/gesture.ts +23 -0
- package/src/canvas/image.ts +197 -0
- package/src/canvas/kit.ts +130 -0
- package/src/canvas/paint.ts +260 -0
- package/src/canvas/pointer.ts +25 -0
- package/src/canvas/snap.ts +68 -0
- package/src/canvas/svg.ts +99 -0
- package/src/canvas.d.ts +373 -0
- package/src/canvas.ts +46 -0
- package/src/core/actions.ts +14 -3
- package/src/core/cell.ts +12 -4
- package/src/core/debug.ts +8 -3
- package/src/core/hooks.ts +16 -2
- package/src/core/hosts/collection.ts +1 -1
- package/src/core/hosts/switchable.ts +26 -8
- package/src/core/instance.ts +98 -45
- package/src/core/markers/portal.ts +4 -0
- package/src/core/registry.ts +4 -0
- package/src/core/runtime.ts +34 -25
- package/src/core/statics.ts +5 -5
- package/src/cycle/dom/EventDelegator.ts +37 -33
- package/src/cycle/dom/MainDOMSource.ts +16 -14
- package/src/cycle/dom/enrichEventStream.ts +13 -9
- package/src/cycle/dom/fromEvent.ts +6 -10
- package/src/cycle/dom/index.ts +11 -7
- package/src/cycle/dom/isolate.ts +13 -6
- package/src/cycle/dom/makeDOMDriver.ts +6 -2
- package/src/cycle/dom/utils.ts +9 -2
- package/src/cycle/run/adapt.ts +4 -12
- package/src/devtools.d.ts +9 -0
- package/src/devtools.ts +2 -1
- package/src/extra/ai/compose/catalog.ts +2 -1
- package/src/extra/ai/compose/decisions.ts +1 -2
- package/src/extra/ai/compose/generated.ts +234 -0
- package/src/extra/ai/compose/index.ts +6 -2
- package/src/extra/ai/compose/layout.ts +3 -1
- package/src/extra/ai/compose/llm.ts +7 -3
- package/src/extra/ai/compose/types.ts +2 -2
- package/src/extra/ai/transports/shared.ts +3 -1
- package/src/extra/api/contract.ts +485 -0
- package/src/extra/api/index.ts +26 -0
- package/src/extra/behaviors.ts +3 -3
- package/src/extra/controlled.ts +44 -0
- package/src/extra/copyAsTest.ts +22 -0
- package/src/extra/devtools.ts +5 -3
- package/src/extra/devtoolsActions.ts +8 -0
- package/src/extra/devtoolsNext.ts +1 -1
- package/src/extra/diagnostics/checks/actionLog.ts +8 -3
- package/src/extra/diagnostics/checks/behaviors.ts +25 -0
- package/src/extra/diagnostics/checks/elementCommands.ts +17 -5
- package/src/extra/diagnostics/checks/index.ts +1 -1
- package/src/extra/diagnostics/checks/next.ts +78 -4
- package/src/extra/diagnostics/checks/props.ts +6 -1
- package/src/extra/diagnostics/checks/replies.ts +11 -7
- package/src/extra/diagnostics/checks/timers.ts +8 -2
- package/src/extra/diagnostics/checks/virtual.ts +11 -0
- package/src/extra/diagnostics/codes.ts +51 -1
- package/src/extra/elementCommands.ts +20 -4
- package/src/extra/fetchDriver.ts +4 -1
- package/src/extra/fetchEventSource.ts +6 -2
- package/src/extra/field.ts +29 -0
- package/src/extra/form.ts +42 -16
- package/src/extra/frame.ts +54 -0
- package/src/extra/keymap.ts +41 -0
- package/src/extra/pager.ts +2 -0
- package/src/extra/persist.ts +2 -1
- package/src/extra/pointer.ts +262 -0
- package/src/extra/processForm.ts +34 -1
- package/src/extra/replay/address.ts +49 -0
- package/src/extra/replay/entropy.ts +99 -0
- package/src/extra/replay/format.ts +263 -0
- package/src/extra/replay/index.ts +8 -0
- package/src/extra/replay/inert.ts +22 -0
- package/src/extra/replay/recorder.ts +247 -0
- package/src/extra/replay/replayer.ts +234 -0
- package/src/extra/replay/report.ts +126 -0
- package/src/extra/replay/schema.ts +52 -0
- package/src/extra/replay/version.ts +3 -0
- package/src/extra/router.ts +7 -3
- package/src/extra/selection.ts +2 -0
- package/src/extra/socketDriver.ts +51 -6
- package/src/extra/ssr.ts +128 -42
- package/src/extra/testing.ts +295 -39
- package/src/extra/timers.ts +96 -7
- package/src/extra/undo.ts +2 -0
- package/src/extra/virtual.ts +25 -2
- package/src/extra/widget.ts +106 -17
- package/src/host/actions.ts +383 -0
- package/src/host/delegation.ts +101 -0
- package/src/host/dom.ts +553 -0
- package/src/host/driver.ts +185 -0
- package/src/host/selector.ts +119 -0
- package/src/host/style.ts +51 -0
- package/src/host.d.ts +298 -0
- package/src/host.ts +46 -0
- package/src/index.d.ts +302 -38
- package/src/index.ts +15 -3
- package/src/pragma/blocks.ts +211 -0
- package/src/pragma/index.ts +44 -10
- package/src/primitives.d.ts +54 -0
- package/src/primitives.ts +136 -0
- package/src/react-native.d.ts +57 -0
- package/src/react-native.ts +285 -0
- package/src/react-peers.d.ts +21 -3
- package/src/replay.d.ts +185 -0
- package/src/replay.ts +6 -0
- package/src/sandbox/build.ts +119 -0
- package/src/sandbox/create.ts +187 -0
- package/src/sandbox/engine.ts +267 -0
- package/src/sandbox/generated.ts +195 -0
- package/src/sandbox/kernel.ts +180 -0
- package/src/sandbox/mirror.ts +269 -0
- package/src/sandbox/protocol.ts +128 -0
- package/src/sandbox/quickjs.ts +74 -0
- package/src/sandbox/ssr.ts +41 -0
- package/src/sandbox/widget.ts +60 -0
- package/src/sandbox/worker-entry.ts +59 -0
- package/src/sandbox/worker.ts +137 -0
- package/src/sandbox-build.d.ts +12 -0
- package/src/sandbox-build.ts +6 -0
- package/src/sandbox.d.ts +299 -0
- package/src/sandbox.ts +25 -0
- package/src/shared.ts +12 -0
- package/src/terminal/paint.ts +712 -0
- package/src/terminal.d.ts +167 -0
- package/src/terminal.ts +530 -0
- package/src/three/assets.ts +170 -0
- package/src/three/host.ts +36 -0
- package/src/three/scene.ts +217 -0
- package/src/three/target.ts +252 -0
- package/src/three.d.ts +221 -0
- package/src/three.ts +30 -0
- package/src/ui/accordion.ts +21 -7
- package/src/ui/dialog.ts +192 -90
- package/src/ui/disclosure.ts +2 -0
- package/src/ui/dom.ts +30 -0
- package/src/ui/layers.ts +132 -0
- package/src/ui/popover.ts +120 -21
- package/src/ui/shared.ts +98 -12
- package/src/ui/stack.ts +18 -0
- package/src/ui/tabs.ts +2 -0
- package/src/ui/toaster.ts +16 -15
- package/src/ui/tooltip.ts +24 -8
- package/src/ui/tooltips.ts +26 -14
- package/src/ui/zag/combobox.ts +180 -13
- package/src/ui/zag/menu.ts +97 -17
- package/src/ui/zag/select.ts +15 -4
- package/src/ui/zag/shared.ts +60 -8
- package/src/ui-combobox.d.ts +16 -1
- package/src/ui-menu.d.ts +22 -7
- package/src/ui-zag-types.d.ts +13 -5
- package/src/ui.d.ts +62 -7
- package/src/ui.ts +2 -2
- package/src/vite/api.ts +186 -0
- package/src/vite/compile.ts +280 -0
- package/src/vite/plugin.d.ts +34 -0
- package/src/vite/plugin.ts +78 -4
- package/src/vite/sandbox.ts +16 -0
- package/src/worker/page.ts +396 -0
- package/src/worker/protocol.ts +48 -0
- package/src/worker/target.ts +282 -0
- package/src/worker-page.d.ts +42 -0
- package/src/worker-page.ts +12 -0
- package/src/worker.d.ts +65 -0
- package/src/worker.ts +16 -0
- package/src/yjs/driver.ts +253 -0
- package/src/yjs/mapping.ts +389 -0
- package/src/yjs/shared.ts +138 -0
- package/src/yjs/testing.ts +91 -0
- package/src/yjs-testing.d.ts +34 -0
- package/src/yjs-testing.ts +7 -0
- package/src/yjs.d.ts +109 -0
- package/src/yjs.ts +18 -0
- package/src/zag.d.ts +2 -0
- package/src/zag.ts +8 -1
package/src/core/instance.ts
CHANGED
|
@@ -21,7 +21,7 @@ import type {App} from './runtime'
|
|
|
21
21
|
import {tearDown, INST, SEED} from './teardown'
|
|
22
22
|
import {CoreDef, defOf, isObj} from './define'
|
|
23
23
|
import {Cell, CalcCell, calcCell, keyCell, lensCell, localCell, pathOf} from './cell'
|
|
24
|
-
import {hosts, posts, pres, resolvers} from './registry'
|
|
24
|
+
import {ext, hosts, posts, pres, resolvers} from './registry'
|
|
25
25
|
import {handle} from './actions'
|
|
26
26
|
import {viewOf} from './view'
|
|
27
27
|
import {makeCommandSource} from '../extra/command'
|
|
@@ -31,13 +31,22 @@ import {sameData} from '../cycle/dom/utils'
|
|
|
31
31
|
|
|
32
32
|
// v7: a known binding target joins key/id/path in the lifetime identity. Fresh equivalent
|
|
33
33
|
// byId helpers retain identity; opaque lenses need an explicit key for a new target.
|
|
34
|
-
function bindingChanged(a: any, b: any): boolean {
|
|
34
|
+
export function bindingChanged(a: any, b: any): boolean {
|
|
35
35
|
if (a === b) return false
|
|
36
36
|
const x = a?.[BINDING], y = b?.[BINDING]
|
|
37
37
|
return x && y ? !x.every((v: any, i: number) => Object.is(v, y[i]))
|
|
38
38
|
: !!(x || y || typeof a == 'string' || typeof b == 'string' || a === undefined || b === undefined)
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
+
/** a binding whose target is known (a key, a byId selection): its deletion ends the child */
|
|
42
|
+
export const known = (b: any) => typeof b == 'string' || b?.[BINDING]
|
|
43
|
+
/** F-3: `owner` watches child (or Switchable page) `k`'s target: notify() disposes it when deleted */
|
|
44
|
+
export function watch(owner: Inst, k: any) {
|
|
45
|
+
k.bs = bindingState(k)
|
|
46
|
+
;(owner.bound ||= new Set()).add(k)
|
|
47
|
+
owner.app.watchers.add(owner)
|
|
48
|
+
}
|
|
49
|
+
|
|
41
50
|
function bindingState(k: any): any {
|
|
42
51
|
const c = k.base || k.cell || k.arr
|
|
43
52
|
return c && (c.has?.() ?? c.get() !== undefined) ? (k.cell || k.arr).get() : undefined
|
|
@@ -118,6 +127,8 @@ let left = 0
|
|
|
118
127
|
export const sameTree = (a: any, b: any): boolean => (left = SAME_MAX, same(a, b))
|
|
119
128
|
function same(a: any, b: any): boolean {
|
|
120
129
|
if (a === b) return true
|
|
130
|
+
// CV-3: a compiled block (its inside is its hole values)
|
|
131
|
+
if (b?.$b) return !!a?.$b && ext.sb!(a, b)
|
|
121
132
|
if (--left < 0 || !a || !b || a.sel !== b.sel || a.key !== b.key || a.text !== b.text || b.data?.hook || !sameData(a.data, b.data)) return false
|
|
122
133
|
const x = a.children, y = b.children
|
|
123
134
|
if (x === y) return true
|
|
@@ -129,8 +140,23 @@ function same(a: any, b: any): boolean {
|
|
|
129
140
|
const EMPTY_CTX: any = Object.freeze({})
|
|
130
141
|
/** a view read every key (spread, Object.keys): any context change re-renders it */
|
|
131
142
|
const ALL = '\u0000all'
|
|
143
|
+
// D168 read-tracking: one handler for every view; each render's Proxy targets a holder of that
|
|
144
|
+
// render's context (c) and the instance's key set (k), so a read after the view returned (a
|
|
145
|
+
// closure the view made) still sees its own render's context
|
|
146
|
+
const track = (h: any, k: any) => (typeof k == 'string' && h.k.add(k), k)
|
|
147
|
+
const TRACK: ProxyHandler<any> = {
|
|
148
|
+
get: (h, k) => h.c[track(h, k)],
|
|
149
|
+
has: (h, k) => track(h, k) in h.c,
|
|
150
|
+
ownKeys: (h) => (h.k.add(ALL), Reflect.ownKeys(h.c)),
|
|
151
|
+
getOwnPropertyDescriptor: (h, k) => Reflect.getOwnPropertyDescriptor(h.c, k),
|
|
152
|
+
}
|
|
132
153
|
|
|
133
154
|
let IDS = 0
|
|
155
|
+
// shared defaults (one per module, not per instance): the first render's "last state", no
|
|
156
|
+
// slots, no tag children (reconcile() makes an instance its own Map on its first child)
|
|
157
|
+
const UNSET = {}
|
|
158
|
+
const NOSLOTS: Record<string, any[]> = Object.freeze({}) as any
|
|
159
|
+
const NOKIDS = new Map<string, any>()
|
|
134
160
|
|
|
135
161
|
/**
|
|
136
162
|
* a child that failed to instantiate: renders the owner's error fallback (SYG408). It keeps its
|
|
@@ -144,6 +170,31 @@ class Failed {
|
|
|
144
170
|
dispose() {}
|
|
145
171
|
}
|
|
146
172
|
|
|
173
|
+
/**
|
|
174
|
+
* The intent's sources: a Proxy whose own properties are the source names, in the table's order
|
|
175
|
+
* (spread, Object.keys, `in`, destructuring as on a plain object), each made when read; one
|
|
176
|
+
* handler for every instance (a property defined with Object.defineProperty per instance was
|
|
177
|
+
* ~1 µs of its creation). Its target holds the instance and what the intent adds
|
|
178
|
+
*/
|
|
179
|
+
const table = (t: any) => t[INST].app.srcDesc(!!t[INST].parent)
|
|
180
|
+
const tab = (t: any, k: any): any => typeof k == 'string' && table(t)[k]
|
|
181
|
+
const SRC: ProxyHandler<any> = {
|
|
182
|
+
get: (t, k) => { const g = tab(t, k); return g ? g(t[INST]) : t[k] },
|
|
183
|
+
has: (t, k) => !!tab(t, k) || k in t,
|
|
184
|
+
ownKeys: (t) => Object.keys(table(t)).concat(Reflect.ownKeys(t) as any),
|
|
185
|
+
getOwnPropertyDescriptor: (t, k) => { const g = tab(t, k); return g ? {value: g(t[INST]), enumerable: true, configurable: true} : Reflect.getOwnPropertyDescriptor(t, k) },
|
|
186
|
+
// a source is read-only, as the getter-only property it was: a write fails (a TypeError in strict code)
|
|
187
|
+
set: (t, k, v) => !tab(t, k) && ((t[k] = v), true),
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** an intent stream's listener: its action (an object, no closures per stream) */
|
|
191
|
+
class Listener {
|
|
192
|
+
constructor(public i: Inst, public t: string) {}
|
|
193
|
+
next(d: any) { const i = this.i; i.dying ? handle(i, this.t, d, 'intent') : i.app.dispatch(i, this.t, d, 'intent') }
|
|
194
|
+
// (no code of its own yet: R4's diagnostics may add one)
|
|
195
|
+
error(e: any) { const i = this.i; console.error(`[Sygnal] ${i.def.name}: intent stream '${this.t}' errored; it stops emitting`, e); i.app.appError(i, e, 'intent', this.t) }
|
|
196
|
+
}
|
|
197
|
+
|
|
147
198
|
export class Inst {
|
|
148
199
|
readonly id = IDS++
|
|
149
200
|
disposed = false
|
|
@@ -159,41 +210,47 @@ export class Inst {
|
|
|
159
210
|
children!: any[]
|
|
160
211
|
/** the children as the parent passed them (slots included) */
|
|
161
212
|
raw!: any[]
|
|
162
|
-
slots
|
|
163
|
-
kids =
|
|
213
|
+
slots = NOSLOTS
|
|
214
|
+
kids = NOKIDS
|
|
164
215
|
/** the children with a string / byId binding: the presence scan's (notify) */
|
|
165
216
|
bound?: Set<any>
|
|
166
217
|
uidBase: string
|
|
218
|
+
// (the fields most instances set are initialized here, so they are the object's own slots;
|
|
219
|
+
// the ones few instances use are left out until used)
|
|
167
220
|
/** the parent's view of this instance's output (last vnode / READY it injected) */
|
|
168
221
|
last: any; lr = true
|
|
169
222
|
outv: any
|
|
170
223
|
// the last render's inputs: state, props, children, context, the context keys its view read
|
|
171
|
-
ls: any =
|
|
224
|
+
ls: any = UNSET; lp: any; lc: any; lctx: any; keys: Set<string> | null = null; tmpl: any; forced = true
|
|
172
225
|
postSels: string[] | null = null
|
|
173
226
|
// context memo: the app's write version it was computed at, the value
|
|
174
227
|
cver = -1; cv: any
|
|
175
228
|
subs: any[] = []
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
229
|
+
/** a Collection item's key; the isolate memo (runtime scopeValue) */
|
|
230
|
+
k: any; $iso: any
|
|
231
|
+
/** canvas-three F2: a template node's last injected copy, by the node (its children array, `.r` the copy) */
|
|
232
|
+
ic?: WeakMap<any, any>
|
|
233
|
+
srcs?: Record<string, any>
|
|
234
|
+
fb?: Record<string, any>
|
|
235
|
+
ac?: AbortController | null
|
|
179
236
|
disp$: any
|
|
180
237
|
st$: any; stLast: any; stateSrc: any
|
|
181
238
|
props$: any; children$: any
|
|
182
239
|
/** CHILD.select listeners (the children's PARENT values) */
|
|
183
|
-
hub
|
|
240
|
+
hub?: Set<(e: any) => void> | null
|
|
184
241
|
wd: any; so: any; el: any
|
|
185
242
|
iv: any
|
|
186
243
|
cmds: any
|
|
187
244
|
/** the app's render epoch it last rendered at (G-311) */
|
|
188
245
|
ep = 0
|
|
189
246
|
/** pending next() timers (G-300) */
|
|
190
|
-
timers
|
|
247
|
+
timers?: Set<any> | null
|
|
191
248
|
// statics.ts: the [sink, static] pairs it declares, the last values sent, the state / shown
|
|
192
249
|
// flag they were computed from; its reply streams
|
|
193
|
-
st
|
|
194
|
-
sv
|
|
195
|
-
sS: any; sH: any
|
|
196
|
-
rep
|
|
250
|
+
st?: Array<[string, string]> | null
|
|
251
|
+
sv?: Record<string, any> | null
|
|
252
|
+
sS: any; sH: any; sC: any
|
|
253
|
+
rep?: any[] | null
|
|
197
254
|
|
|
198
255
|
constructor(
|
|
199
256
|
public app: App, public def: CoreDef, public parent: Inst | null, public base: Cell,
|
|
@@ -204,7 +261,8 @@ export class Inst {
|
|
|
204
261
|
this.setChildren(children)
|
|
205
262
|
this.uidBase = uidBase
|
|
206
263
|
this.ready = !def.ready
|
|
207
|
-
|
|
264
|
+
// (no calculated fields: the base cell itself)
|
|
265
|
+
this.cell = def.calculated || def.idle ? calcCell(base, def) : base as CalcCell
|
|
208
266
|
const H = app.hooks
|
|
209
267
|
// the initial state, synchronously (INITIALIZE at construction, D165): a root (or the state an
|
|
210
268
|
// HMR swap keeps), an isolated child's local state. D174: an isolated child bound to a slice
|
|
@@ -226,7 +284,7 @@ export class Inst {
|
|
|
226
284
|
if (reset || (!has && def.model)) app.dispatch(this, SEED, {v: init, r: reset, b}, 'built-in')
|
|
227
285
|
else if (has) H.onStateSeed?.(viewOf(this), b.get(), init)
|
|
228
286
|
}
|
|
229
|
-
} else if (def.idle && isObj(this.
|
|
287
|
+
} else if (def.idle && isObj(this.rawState()) && !parent) this.cell.set(this.rawState())
|
|
230
288
|
H.onCreate?.(viewOf(this))
|
|
231
289
|
dbg(this, () => 'Instantiated')
|
|
232
290
|
if (def.handlers.has('INITIALIZE')) app.dispatch(this, 'INITIALIZE', init, 'built-in')
|
|
@@ -245,6 +303,8 @@ export class Inst {
|
|
|
245
303
|
}
|
|
246
304
|
|
|
247
305
|
get name() { return this.def.name }
|
|
306
|
+
/** the state with calculated fields only as stored (STATE.stream) */
|
|
307
|
+
rawState() { return this.cell === this.base ? this.base.get() : this.cell.raw() }
|
|
248
308
|
|
|
249
309
|
// ---------------------------------------------------------------- sources (the stream edge)
|
|
250
310
|
subscribe() {
|
|
@@ -264,11 +324,7 @@ export class Inst {
|
|
|
264
324
|
const s = actions[type]
|
|
265
325
|
if (s == null) continue
|
|
266
326
|
if (typeof s.subscribe != 'function') fail('SYG603', this, `intent entry '${type}' is not a stream`, 'Return { ACTION: stream$ }')
|
|
267
|
-
this.subs.push(s.subscribe(
|
|
268
|
-
next: (d: any) => this.dying ? handle(this, type, d, 'intent') : app.dispatch(this, type, d, 'intent'),
|
|
269
|
-
// (no code of its own yet: R4's diagnostics may add one)
|
|
270
|
-
error: (e: any) => { console.error(`[Sygnal] ${def.name}: intent stream '${type}' errored; it stops emitting`, e); app.appError(this, e, 'intent', type) },
|
|
271
|
-
}))
|
|
327
|
+
this.subs.push(s.subscribe(new Listener(this, type)))
|
|
272
328
|
}
|
|
273
329
|
} catch (e) {
|
|
274
330
|
// a failed instance keeps no subscription (its parent renders the error fallback)
|
|
@@ -280,10 +336,7 @@ export class Inst {
|
|
|
280
336
|
}
|
|
281
337
|
|
|
282
338
|
sources() {
|
|
283
|
-
|
|
284
|
-
const so = this.so = Object.defineProperties({}, this.app.srcDesc(!!this.parent))
|
|
285
|
-
Object.defineProperty(so, INST, {value: this})
|
|
286
|
-
return so
|
|
339
|
+
return this.so ||= new Proxy({[INST]: this}, SRC)
|
|
287
340
|
}
|
|
288
341
|
/** a driver source isolated to this instance (the parent's, isolated to this scope; cached) */
|
|
289
342
|
src(n: string): any {
|
|
@@ -297,7 +350,7 @@ export class Inst {
|
|
|
297
350
|
stateSource() {
|
|
298
351
|
if (this.stateSrc) return this.stateSrc
|
|
299
352
|
this.st$ = xs.createWithMemory()
|
|
300
|
-
const v = this.stLast = this.
|
|
353
|
+
const v = this.stLast = this.rawState()
|
|
301
354
|
if (v !== undefined) this.st$.shamefullySendNext(v)
|
|
302
355
|
this.app.watchers.add(this)
|
|
303
356
|
return (this.stateSrc = new StateSource(this.st$, 'STATE', this.dispose$(), 1))
|
|
@@ -321,7 +374,7 @@ export class Inst {
|
|
|
321
374
|
}
|
|
322
375
|
}
|
|
323
376
|
if (this.st$) {
|
|
324
|
-
const v = this.
|
|
377
|
+
const v = this.rawState()
|
|
325
378
|
if (v !== this.stLast && v !== undefined) { this.stLast = v; this.st$.shamefullySendNext(v) }
|
|
326
379
|
}
|
|
327
380
|
}
|
|
@@ -342,9 +395,8 @@ export class Inst {
|
|
|
342
395
|
setChildren(children: any[]) {
|
|
343
396
|
// G-294: the raw children (before the slots are split out) decide whether the view re-runs
|
|
344
397
|
this.raw = children
|
|
345
|
-
|
|
346
|
-
this.children =
|
|
347
|
-
this.slots = slots
|
|
398
|
+
if (children.length) [this.children, this.slots] = extractSlots(children)
|
|
399
|
+
else this.children = children, this.slots = NOSLOTS
|
|
348
400
|
}
|
|
349
401
|
setProps(props: Record<string, any>, children: any[]) {
|
|
350
402
|
this.props = props
|
|
@@ -458,10 +510,11 @@ export class Inst {
|
|
|
458
510
|
if (v !== k.last || k.ready !== k.lr) { k.last = v; k.lr = k.ready; kidsDirty = true }
|
|
459
511
|
}
|
|
460
512
|
if (!viewDirty && !kidsDirty) return this.outv
|
|
461
|
-
|
|
513
|
+
// CV-3: hooks (dev checks, devtools, testing) see a compiled block's vnodes (ext.xb)
|
|
514
|
+
if (same && !kidsDirty) { this.app.hooks.onRender?.(viewOf(this), ext.xb ? ext.xb(this.tmpl) : this.tmpl); return this.outv }
|
|
462
515
|
let v = this.kids.size ? this.inject(this.tmpl, 'r') : this.tmpl
|
|
463
516
|
if (this.postSels) for (const s of this.postSels) v = posts[s](v, this)
|
|
464
|
-
this.app.hooks.onRender?.(viewOf(this), v)
|
|
517
|
+
this.app.hooks.onRender?.(viewOf(this), ext.xb ? ext.xb(v) : v)
|
|
465
518
|
return (this.outv = this.parent ? this.app.scopeValue(this.parent, 'DOM', v, this) : v)
|
|
466
519
|
}
|
|
467
520
|
|
|
@@ -478,12 +531,10 @@ export class Inst {
|
|
|
478
531
|
const def = this.def
|
|
479
532
|
let keys: Set<string> | null = null, context = ctx
|
|
480
533
|
if (ctx !== EMPTY_CTX) {
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
ownKeys: (t) => (ks.add(ALL), Reflect.ownKeys(t)),
|
|
486
|
-
})
|
|
534
|
+
// (the last render's set, read by ctxChanged before this call)
|
|
535
|
+
keys = this.keys || new Set<string>()
|
|
536
|
+
keys.clear()
|
|
537
|
+
context = new Proxy({c: ctx, k: keys}, TRACK)
|
|
487
538
|
}
|
|
488
539
|
try {
|
|
489
540
|
this.tmpl = def.view({...this.props, state, children: this.children, slots: this.slots, context, uid: this.uid})
|
|
@@ -536,12 +587,8 @@ export class Inst {
|
|
|
536
587
|
const binding = host && sel != 'switchable' ? 'from' : 'state'
|
|
537
588
|
if (k && (k.disposed || (view && k.def && k.def.view !== view) || bindingChanged(k.props?.[binding], props[binding]))) { k.dispose(); this.kids.delete(id); k = undefined }
|
|
538
589
|
if (k) k.setProps(props, children, n, id)
|
|
539
|
-
else this.kids.set(id, k = host ? this.host(host, props, children, id, n) : this.child(view, props, children, id, !!data.props?.resetState))
|
|
540
|
-
if (
|
|
541
|
-
k.bs = bindingState(k)
|
|
542
|
-
;(this.bound ||= new Set()).add(k)
|
|
543
|
-
this.app.watchers.add(this)
|
|
544
|
-
}
|
|
590
|
+
else (this.kids === NOKIDS ? this.kids = new Map() : this.kids).set(id, k = host ? this.host(host, props, children, id, n) : this.child(view, props, children, id, !!data.props?.resetState))
|
|
591
|
+
if (known(props[binding])) watch(this, k)
|
|
545
592
|
return
|
|
546
593
|
}
|
|
547
594
|
if (posts[sel] && !(ps ||= []).includes(sel)) ps.push(sel)
|
|
@@ -604,7 +651,13 @@ export class Inst {
|
|
|
604
651
|
const v = this.inject(c[i], path + '.' + i)
|
|
605
652
|
if (v !== c[i]) (out ||= c.slice())[i] = v
|
|
606
653
|
}
|
|
607
|
-
|
|
654
|
+
if (!out) return n
|
|
655
|
+
// canvas-three F2: the same children as this node's last injection: its last copy, so snabbdom
|
|
656
|
+
// skips an element (and its hooks: a widget's postpatch) above components that didn't change
|
|
657
|
+
const p = (this.ic ||= new WeakMap()).get(n)
|
|
658
|
+
if (p && p.length == out.length && p.every((x: any, i: number) => x === out[i])) return p.r
|
|
659
|
+
this.ic.set(n, out)
|
|
660
|
+
return out.r = {...n, children: out}
|
|
608
661
|
}
|
|
609
662
|
|
|
610
663
|
// ---------------------------------------------------------------- actions
|
|
@@ -33,6 +33,9 @@ function mount(st: PortalState, target: string): boolean {
|
|
|
33
33
|
container.appendChild(anchor)
|
|
34
34
|
st.pv = st.v.data._portalVnode = (patch ||= snabbdomInit(defaultModules))(anchor, box(st.kids))
|
|
35
35
|
st.c = st.v.data._portalContainer = container
|
|
36
|
+
// ui-sweep R4: the placeholder names its content, so ELEMENT commands and sygnal/ui parts find
|
|
37
|
+
// elements the component renders into the portal (extra/elementCommands.ts, ui/shared.ts)
|
|
38
|
+
if (st.v.elm) st.v.elm.__portal = st.pv.elm
|
|
36
39
|
return true
|
|
37
40
|
}
|
|
38
41
|
|
|
@@ -74,6 +77,7 @@ export function portalPlaceholder(target: string, children: any[]): any {
|
|
|
74
77
|
if (!st.pv) return
|
|
75
78
|
st.pv = newVnode.data._portalVnode = patch(st.pv, box(st.kids))
|
|
76
79
|
newVnode.data._portalContainer = st.c
|
|
80
|
+
if (newVnode.elm) newVnode.elm.__portal = st.pv.elm
|
|
77
81
|
},
|
|
78
82
|
destroy: (vnode: any) => {
|
|
79
83
|
const st: PortalState | undefined = vnode.data?._p
|
package/src/core/registry.ts
CHANGED
|
@@ -27,3 +27,7 @@ export const posts: Record<string, (vnode: any, owner: any) => any> = {}
|
|
|
27
27
|
export const resolvers: Array<(view: ComponentFn, owner: any) => ComponentFn | undefined> = []
|
|
28
28
|
/** definition time, every app: (src, view) -> src (behaviors, undo, selection, pager, persist, resources) */
|
|
29
29
|
export const defHooks: Array<(src: DefSource, view: ComponentFn) => DefSource | void> = []
|
|
30
|
+
/** CV-3 (compiled blocks, src/pragma/blocks.ts, registered by the first block): xb expands blocks
|
|
31
|
+
* into plain vnodes for a DOM driver that doesn't patch them (not `DOMDriver.blocks`); sb, the
|
|
32
|
+
* same-output check for two blocks */
|
|
33
|
+
export const ext: {xb?: (v: any) => any; sb?: (a: any, b: any) => boolean} = {}
|
package/src/core/runtime.ts
CHANGED
|
@@ -21,14 +21,16 @@ import xs from '../extra/xstreamCompat'
|
|
|
21
21
|
import {makeDOMDriver} from '../cycle/dom/index'
|
|
22
22
|
import eventBusDriver from '../extra/eventDriver'
|
|
23
23
|
import logDriver from '../extra/logDriver'
|
|
24
|
-
import {NOT_SINK, isAbort} from '../shared'
|
|
24
|
+
import {NOT_SINK, isAbort, delivering} from '../shared'
|
|
25
25
|
import {error as logError, callHook} from '../extra/diagnostics/legacy'
|
|
26
26
|
import type {ComponentFn, DefSource, Hooks, RuntimeAPI, ActionCause} from './hooks'
|
|
27
27
|
import {CoreDef, defOf, rootDef} from './define'
|
|
28
28
|
import {rootCell} from './cell'
|
|
29
29
|
import {Inst} from './instance'
|
|
30
|
+
import {seen} from './actions'
|
|
30
31
|
import {viewOf} from './view'
|
|
31
|
-
import {
|
|
32
|
+
import {ext} from './registry'
|
|
33
|
+
import {stopQueued, SET, SEED} from './teardown'
|
|
32
34
|
import {scanSources} from './statics'
|
|
33
35
|
// the public ClientOnly is a separate bundle (sygnal/vike/ClientOnly) with no core of its own, so
|
|
34
36
|
// its marker handler registers with the core (the other markers register from their modules)
|
|
@@ -56,6 +58,8 @@ export interface StartOptions {
|
|
|
56
58
|
__state?: any
|
|
57
59
|
/** internal: an HMR swap: the instances its first flush makes get no BOOTSTRAP (as today's `__hmr`) */
|
|
58
60
|
__swap?: boolean
|
|
61
|
+
/** internal: the handlers' now() / random() / uuid() (renderComponent's fixed clock, seeded random, ids) */
|
|
62
|
+
__entropy?: {now?: () => number; random?: () => number; uuid?: () => string}
|
|
59
63
|
/** internal: renderComponent's root (test intent, initial state, name) */
|
|
60
64
|
__override?: Partial<DefSource> & {name?: string; testActions?: string[]}
|
|
61
65
|
}
|
|
@@ -81,6 +85,8 @@ export class App {
|
|
|
81
85
|
last: any
|
|
82
86
|
/** P46-P: a view ran but kept its last vnode (the flush still emits, as when it changed) */
|
|
83
87
|
ran = false
|
|
88
|
+
/** CV-3: the DOM driver patches compiled blocks itself (makeDOMDriver's DOMDriver.blocks) */
|
|
89
|
+
bd = false
|
|
84
90
|
vdomL: any
|
|
85
91
|
vdom$: any
|
|
86
92
|
sources: Record<string, any> = {}
|
|
@@ -149,6 +155,8 @@ export class App {
|
|
|
149
155
|
/** `src`: for a reply, the source that delivered it (the action log's replySink) */
|
|
150
156
|
dispatch(inst: Inst, type: any, data: any, cause: ActionCause = 'intent', src?: string) {
|
|
151
157
|
if (this.disposed) return
|
|
158
|
+
// 7.2: at enqueue, with the DOM event being delivered (a string type: not setState / a seed)
|
|
159
|
+
typeof type == 'string' && this.hooks.onDispatch?.(viewOf(inst), type, data, cause, delivering)
|
|
152
160
|
this.queue.push(inst, type, data, cause, src)
|
|
153
161
|
if (!this.draining && !this.rendering) this.drain()
|
|
154
162
|
}
|
|
@@ -165,8 +173,9 @@ export class App {
|
|
|
165
173
|
if (q[i + 1] === SET) {
|
|
166
174
|
const f = q[i + 2], c = inst.cell
|
|
167
175
|
const v = typeof f == 'function' ? f(c.get()) : f
|
|
168
|
-
// (ABORT: no change, as from a reducer)
|
|
169
|
-
|
|
176
|
+
// (ABORT: no change, as from a reducer). 7.2: seen by onAction as a 'setState' action
|
|
177
|
+
// with the new state (false: dropped)
|
|
178
|
+
if (v !== c.get() && !isAbort(v) && seen(inst, 'setState', v, 'setState')) c.set(v)
|
|
170
179
|
} else if (q[i + 1] === SEED) {
|
|
171
180
|
// G-309: decided when it is applied: a parent write queued before it keeps the slice (D174)
|
|
172
181
|
const d = q[i + 2], b = d.b
|
|
@@ -283,8 +292,9 @@ export class App {
|
|
|
283
292
|
if (v !== this.last || this.ran) {
|
|
284
293
|
this.ran = false
|
|
285
294
|
this.last = v
|
|
286
|
-
this.hooks.onPatch?.(v)
|
|
287
|
-
|
|
295
|
+
this.hooks.onPatch?.(ext.xb ? ext.xb(v) : v)
|
|
296
|
+
// CV-3: compiled blocks are patched only by the browser DOM driver; any other gets their vnodes
|
|
297
|
+
this.vdomL?.next(ext.xb && !this.bd ? ext.xb(v ?? null) : v ?? null)
|
|
288
298
|
}
|
|
289
299
|
if (this.dq.length) this.stopLater()
|
|
290
300
|
} finally {
|
|
@@ -350,7 +360,7 @@ export class App {
|
|
|
350
360
|
scopeValue(parent: Inst, _: string, v: any, inst: Inst) {
|
|
351
361
|
const d = parent.dom
|
|
352
362
|
if (!d || inst.scope === undefined) return v
|
|
353
|
-
if (typeof d.isolateValue == 'function') return d.isolateValue(v, inst.scope)
|
|
363
|
+
if (typeof d.isolateValue == 'function') return d.isolateValue(v, inst.scope, inst)
|
|
354
364
|
let r: any
|
|
355
365
|
this.pipe(inst, '\u0000DOM', v, (s$) => d.isolateSink(s$, inst.scope), (x) => { r = x })
|
|
356
366
|
return r
|
|
@@ -376,22 +386,21 @@ export class App {
|
|
|
376
386
|
}
|
|
377
387
|
|
|
378
388
|
// ---------------------------------------------------------------- intent sources
|
|
379
|
-
/**
|
|
380
|
-
srcDesc(child: boolean) {
|
|
389
|
+
/** an instance's intent sources by name, each a getter of its instance (one table per app and kind; Inst SRC) */
|
|
390
|
+
srcDesc(child: boolean): Record<string, (i: Inst) => any> {
|
|
381
391
|
const k = +child
|
|
382
392
|
if (this.desc[k]) return this.desc[k]
|
|
383
|
-
const d: any =
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
d.
|
|
387
|
-
d.
|
|
388
|
-
d.
|
|
389
|
-
d.dispose$ = get(i => i.dispose$())
|
|
393
|
+
const d: any = Object.create(null)
|
|
394
|
+
for (const n in this.sources) if (n !== 'DOM') d[n] = (i: Inst) => i.src(n)
|
|
395
|
+
d.DOM = (i: Inst) => i.dom && (i.wd ||= wrapDOM(i.dom))
|
|
396
|
+
d.STATE = (i: Inst) => i.stateSource()
|
|
397
|
+
d.CHILD = (i: Inst) => i.childSource()
|
|
398
|
+
d.dispose$ = (i: Inst) => i.dispose$()
|
|
390
399
|
if (child) {
|
|
391
|
-
d.props$ =
|
|
392
|
-
d.children$ =
|
|
400
|
+
d.props$ = (i: Inst) => i.props$ || seeded(i, 'props$', i.props)
|
|
401
|
+
d.children$ = (i: Inst) => i.children$ || seeded(i, 'children$', i.children)
|
|
393
402
|
// a Command passed as a prop (createCommand): its messages, as today's `commands$`
|
|
394
|
-
d.commands$ =
|
|
403
|
+
d.commands$ = (i: Inst) => i.commands()
|
|
395
404
|
}
|
|
396
405
|
return (this.desc[k] = d)
|
|
397
406
|
}
|
|
@@ -437,9 +446,8 @@ export class App {
|
|
|
437
446
|
: k == 'wrapHandler' ? (i: any, t: any, s: any, f: any) => { const x = b(i, t, s, f) || f; return a(i, t, s, x) || x }
|
|
438
447
|
: k == 'wrapSources' ? (i: any, s: any) => { const x = b(i, s) || s; return a(i, x) || x }
|
|
439
448
|
: k == 'transformDef' ? (src: any, v: any) => { const x = b(src, v) || src; return a(x, v) || x }
|
|
440
|
-
//
|
|
441
|
-
:
|
|
442
|
-
: (...args: any[]) => { b(...args); a(...args) }
|
|
449
|
+
// false from either layer: onElementCommand (not run), onAction (dropped)
|
|
450
|
+
: (...args: any[]) => { const x = b(...args); return a(...args) === false || x === false ? false : undefined }
|
|
443
451
|
}
|
|
444
452
|
}
|
|
445
453
|
// D168's safety net (R4): a view context tracking skipped, offered for a re-run check
|
|
@@ -460,9 +468,9 @@ export class App {
|
|
|
460
468
|
}
|
|
461
469
|
}
|
|
462
470
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
471
|
+
// (one handler for every instance's DOM source)
|
|
472
|
+
const DOMH: ProxyHandler<any> = {get: (t, p, r) => (typeof p == 'symbol' || p in t ? Reflect.get(t, p, r) : (sel: any, o?: any) => t.select(sel).events(p, o))}
|
|
473
|
+
const wrapDOM = (dom: any) => new Proxy(dom, DOMH)
|
|
466
474
|
/** props$ / children$: a memory stream with the current value, fed by setProps */
|
|
467
475
|
function seeded(i: any, k: string, v: any) {
|
|
468
476
|
const s = xs.createWithMemory()
|
|
@@ -529,6 +537,7 @@ export function start(Root: ComponentFn, drivers: Record<string, any> = {}, opts
|
|
|
529
537
|
}
|
|
530
538
|
// the Cycle run loop, reduced: a proxy sink per driver, the driver's source, then the app's
|
|
531
539
|
// streams imitated (values reach a driver synchronously; the DOM gets one vnode per flush)
|
|
540
|
+
app.bd = !!all.DOM?.blocks
|
|
532
541
|
for (const n in all) {
|
|
533
542
|
const p = app.proxies[n] = xs.create()
|
|
534
543
|
const src = app.sources[n] = all[n](p, n)
|
package/src/core/statics.ts
CHANGED
|
@@ -76,17 +76,17 @@ const shownOf = (inst: Inst) => {
|
|
|
76
76
|
/** recompute the instance's declarations when its state or shown flag changed; send the changed ones */
|
|
77
77
|
export function checkStatics(inst: Inst) {
|
|
78
78
|
if (inst.disposed) return
|
|
79
|
-
const s = inst.cell.get(), shown = shownOf(inst)
|
|
79
|
+
const s = inst.cell.get(), shown = shownOf(inst), c = inst.context()
|
|
80
80
|
// no state yet: nothing declared (as the state stream, which skips undefined)
|
|
81
|
-
if (s === undefined || (s === inst.sS && shown === inst.sH)) return
|
|
82
|
-
inst.sS = s; inst.sH = shown
|
|
81
|
+
if (s === undefined || (s === inst.sS && shown === inst.sH && c === inst.sC)) return
|
|
82
|
+
inst.sS = s; inst.sH = shown; inst.sC = c
|
|
83
83
|
const view = inst.def.view, sv = inst.sv!
|
|
84
84
|
for (const [n, k] of inst.st!) {
|
|
85
85
|
const f = view[k]
|
|
86
86
|
let v: any = f
|
|
87
87
|
try {
|
|
88
|
-
if (typeof f == 'function') v = f(s)
|
|
89
|
-
else if (f && typeof f == 'object') { v = {}; for (const r in f) v[r] = f[r](s) }
|
|
88
|
+
if (typeof f == 'function') v = f(s, c)
|
|
89
|
+
else if (f && typeof f == 'object') { v = {}; for (const r in f) v[r] = f[r](s, c) }
|
|
90
90
|
} catch (e) {
|
|
91
91
|
// as today: nothing sent; the next value is sent even when equal to the last one
|
|
92
92
|
inst.app.caught(inst, 'SYG216', `${k} threw; nothing sent`, e, 'declaration')
|
|
@@ -7,6 +7,7 @@ import {EventsFnOptions} from './DOMSource';
|
|
|
7
7
|
import {Scope} from './isolate';
|
|
8
8
|
import SymbolTree from './SymbolTree';
|
|
9
9
|
import PriorityQueue from './PriorityQueue';
|
|
10
|
+
import {deliver} from '../../shared';
|
|
10
11
|
import {
|
|
11
12
|
fromEvent,
|
|
12
13
|
preventDefaultConditional,
|
|
@@ -382,46 +383,49 @@ export class EventDelegator {
|
|
|
382
383
|
passive: boolean,
|
|
383
384
|
bubbles = true
|
|
384
385
|
): void {
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
if (
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
eventType,
|
|
397
|
-
|
|
398
|
-
rootElement,
|
|
399
|
-
cycleEvent,
|
|
400
|
-
listeners,
|
|
401
|
-
namespace,
|
|
402
|
-
namespace.length - 1,
|
|
403
|
-
useCapture,
|
|
404
|
-
passive
|
|
405
|
-
);
|
|
406
|
-
phase(true);
|
|
407
|
-
phase(false);
|
|
408
|
-
} else {
|
|
409
|
-
const phase = (useCapture: boolean) => {
|
|
410
|
-
this.putNonBubblingListener(eventType, target, useCapture, passive);
|
|
411
|
-
this.doBubbleStep(
|
|
386
|
+
// 7.2: the event is recorded while it is delivered (the core's onDispatch hook)
|
|
387
|
+
deliver(event, () => {
|
|
388
|
+
const cycleEvent = this.patchEvent(event);
|
|
389
|
+
const target = event.target as Element;
|
|
390
|
+
const rootElement = this.isolateModule.getRootElement(target);
|
|
391
|
+
|
|
392
|
+
if (bubbles) {
|
|
393
|
+
const namespace = this.isolateModule.getNamespace(target);
|
|
394
|
+
if (!namespace) {
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
const listeners = this.getVirtualListeners(eventType, namespace);
|
|
398
|
+
const phase = (useCapture: boolean) => this.bubble(
|
|
412
399
|
eventType,
|
|
413
400
|
target,
|
|
414
401
|
rootElement,
|
|
415
402
|
cycleEvent,
|
|
416
|
-
|
|
403
|
+
listeners,
|
|
404
|
+
namespace,
|
|
405
|
+
namespace.length - 1,
|
|
417
406
|
useCapture,
|
|
418
407
|
passive
|
|
419
408
|
);
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
409
|
+
phase(true);
|
|
410
|
+
phase(false);
|
|
411
|
+
} else {
|
|
412
|
+
const phase = (useCapture: boolean) => {
|
|
413
|
+
this.putNonBubblingListener(eventType, target, useCapture, passive);
|
|
414
|
+
this.doBubbleStep(
|
|
415
|
+
eventType,
|
|
416
|
+
target,
|
|
417
|
+
rootElement,
|
|
418
|
+
cycleEvent,
|
|
419
|
+
this.virtualNonBubblingListener,
|
|
420
|
+
useCapture,
|
|
421
|
+
passive
|
|
422
|
+
);
|
|
423
|
+
};
|
|
424
|
+
phase(true);
|
|
425
|
+
phase(false);
|
|
426
|
+
event.stopPropagation();
|
|
427
|
+
}
|
|
428
|
+
});
|
|
425
429
|
}
|
|
426
430
|
|
|
427
431
|
private bubble(
|
|
@@ -28,19 +28,24 @@ export class MainDOMSource {
|
|
|
28
28
|
private _eventDelegator: EventDelegator,
|
|
29
29
|
private _name: string
|
|
30
30
|
) {
|
|
31
|
-
this.isolateSource = (source, scope) =>
|
|
32
|
-
new MainDOMSource(
|
|
33
|
-
source._rootElement$,
|
|
34
|
-
source._sanitation$,
|
|
35
|
-
source._namespace.concat(getScopeObj(scope)),
|
|
36
|
-
source._isolateModule,
|
|
37
|
-
source._eventDelegator,
|
|
38
|
-
source._name
|
|
39
|
-
);
|
|
40
|
-
this.isolateSink = makeIsolateSink(this._namespace) as any;
|
|
41
|
-
this.isolateValue = makeIsolateValue(this._namespace);
|
|
42
31
|
}
|
|
43
32
|
|
|
33
|
+
// (methods and lazily made functions, not closures per source: one source per instance)
|
|
34
|
+
public isolateSource(source: MainDOMSource, scope: string): MainDOMSource {
|
|
35
|
+
return new MainDOMSource(
|
|
36
|
+
source._rootElement$,
|
|
37
|
+
source._sanitation$,
|
|
38
|
+
source._namespace.concat(getScopeObj(scope)),
|
|
39
|
+
source._isolateModule,
|
|
40
|
+
source._eventDelegator,
|
|
41
|
+
source._name
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
private _is?: IsolateSink<VNode>;
|
|
45
|
+
private _iv?: (node: any, scope: string, memo?: any) => any;
|
|
46
|
+
get isolateSink(): IsolateSink<VNode> { return this._is ||= makeIsolateSink(this._namespace) as any }
|
|
47
|
+
get isolateValue(): (node: any, scope: string, memo?: any) => any { return this._iv ||= makeIsolateValue(this._namespace) }
|
|
48
|
+
|
|
44
49
|
private _elements(): Stream<Array<Element>> {
|
|
45
50
|
if (this._namespace.length === 0) {
|
|
46
51
|
return this._rootElement$.map(x => [x]);
|
|
@@ -148,7 +153,4 @@ export class MainDOMSource {
|
|
|
148
153
|
this._sanitation$.shamefullySendNext(null);
|
|
149
154
|
}
|
|
150
155
|
|
|
151
|
-
public isolateSource: (source: MainDOMSource, scope: string) => MainDOMSource;
|
|
152
|
-
public isolateSink: IsolateSink<VNode>;
|
|
153
|
-
public isolateValue: (node: any, scope: string) => any;
|
|
154
156
|
}
|