@vidact/runtime 0.2.0-beta.0 → 0.2.0-beta.11

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.
Files changed (244) hide show
  1. package/CHANGELOG.md +73 -0
  2. package/README.md +1 -1
  3. package/dist/actions.d.ts +32 -30
  4. package/dist/actions.d.ts.map +1 -1
  5. package/dist/actions.js +251 -266
  6. package/dist/actions.js.map +1 -1
  7. package/dist/async.d.ts +20 -17
  8. package/dist/async.d.ts.map +1 -1
  9. package/dist/async.js +18 -17
  10. package/dist/async.js.map +1 -1
  11. package/dist/compiled/async-resource.d.ts +9 -6
  12. package/dist/compiled/async-resource.d.ts.map +1 -1
  13. package/dist/compiled/async-resource.js +69 -77
  14. package/dist/compiled/async-resource.js.map +1 -1
  15. package/dist/compiled/core.d.ts +148 -147
  16. package/dist/compiled/core.d.ts.map +1 -1
  17. package/dist/compiled/core.js +3064 -2987
  18. package/dist/compiled/core.js.map +1 -1
  19. package/dist/compiled/types.d.ts +44 -56
  20. package/dist/compiled/types.d.ts.map +1 -1
  21. package/dist/compiled/types.js +10 -6
  22. package/dist/compiled/types.js.map +1 -1
  23. package/dist/compiled/validation.d.ts +4 -1
  24. package/dist/compiled/validation.d.ts.map +1 -1
  25. package/dist/compiled/validation.js +17 -20
  26. package/dist/compiled/validation.js.map +1 -1
  27. package/dist/component-spread.d.ts +5 -3
  28. package/dist/component-spread.d.ts.map +1 -1
  29. package/dist/component-spread.js +49 -67
  30. package/dist/component-spread.js.map +1 -1
  31. package/dist/concurrent.d.ts +20 -18
  32. package/dist/concurrent.d.ts.map +1 -1
  33. package/dist/concurrent.js +191 -210
  34. package/dist/concurrent.js.map +1 -1
  35. package/dist/direct-dom.d.ts +17 -12
  36. package/dist/direct-dom.d.ts.map +1 -1
  37. package/dist/direct-dom.js +279 -222
  38. package/dist/direct-dom.js.map +1 -1
  39. package/dist/dom/attributes.d.ts +9 -6
  40. package/dist/dom/attributes.d.ts.map +1 -1
  41. package/dist/dom/attributes.js +65 -47
  42. package/dist/dom/attributes.js.map +1 -1
  43. package/dist/dom/events.d.ts +8 -2
  44. package/dist/dom/events.d.ts.map +1 -1
  45. package/dist/dom/events.js +118 -65
  46. package/dist/dom/events.js.map +1 -1
  47. package/dist/dom/forms.d.ts +9 -6
  48. package/dist/dom/forms.d.ts.map +1 -1
  49. package/dist/dom/forms.js +152 -198
  50. package/dist/dom/forms.js.map +1 -1
  51. package/dist/dom/intrinsic.d.ts +17 -15
  52. package/dist/dom/intrinsic.d.ts.map +1 -1
  53. package/dist/dom/intrinsic.js +48 -50
  54. package/dist/dom/intrinsic.js.map +1 -1
  55. package/dist/dom/namespace.d.ts +4 -1
  56. package/dist/dom/namespace.d.ts.map +1 -1
  57. package/dist/dom/namespace.js +25 -28
  58. package/dist/dom/namespace.js.map +1 -1
  59. package/dist/dom/namespaces.d.ts +11 -8
  60. package/dist/dom/namespaces.d.ts.map +1 -1
  61. package/dist/dom/namespaces.js +14 -12
  62. package/dist/dom/namespaces.js.map +1 -1
  63. package/dist/dom/properties.d.ts +18 -16
  64. package/dist/dom/properties.d.ts.map +1 -1
  65. package/dist/dom/properties.js +273 -296
  66. package/dist/dom/properties.js.map +1 -1
  67. package/dist/dom/style-properties.d.ts +4 -1
  68. package/dist/dom/style-properties.d.ts.map +1 -1
  69. package/dist/dom/style-properties.js +49 -45
  70. package/dist/dom/style-properties.js.map +1 -1
  71. package/dist/dom/styles.d.ts +5 -2
  72. package/dist/dom/styles.d.ts.map +1 -1
  73. package/dist/dom/styles.js +47 -67
  74. package/dist/dom/styles.js.map +1 -1
  75. package/dist/dom-forms.d.ts +4 -1
  76. package/dist/dom-forms.d.ts.map +1 -1
  77. package/dist/dom-forms.js +16 -13
  78. package/dist/dom-forms.js.map +1 -1
  79. package/dist/dom-styles.d.ts +4 -1
  80. package/dist/dom-styles.d.ts.map +1 -1
  81. package/dist/dom-styles.js +10 -7
  82. package/dist/dom-styles.js.map +1 -1
  83. package/dist/framework-hydrate.d.ts +20 -17
  84. package/dist/framework-hydrate.d.ts.map +1 -1
  85. package/dist/framework-hydrate.js +128 -146
  86. package/dist/framework-hydrate.js.map +1 -1
  87. package/dist/framework-protocol.d.ts +27 -25
  88. package/dist/framework-protocol.d.ts.map +1 -1
  89. package/dist/framework-protocol.js +173 -211
  90. package/dist/framework-protocol.js.map +1 -1
  91. package/dist/framework.d.ts +34 -32
  92. package/dist/framework.d.ts.map +1 -1
  93. package/dist/framework.js +74 -93
  94. package/dist/framework.js.map +1 -1
  95. package/dist/hydrate.d.ts +11 -8
  96. package/dist/hydrate.d.ts.map +1 -1
  97. package/dist/hydrate.js +13 -9
  98. package/dist/hydrate.js.map +1 -1
  99. package/dist/hydration-bridge.d.ts +70 -58
  100. package/dist/hydration-bridge.d.ts.map +1 -1
  101. package/dist/hydration-bridge.js +77 -66
  102. package/dist/hydration-bridge.js.map +1 -1
  103. package/dist/hydration.d.ts +54 -28
  104. package/dist/hydration.d.ts.map +1 -1
  105. package/dist/hydration.js +450 -463
  106. package/dist/hydration.js.map +1 -1
  107. package/dist/index.d.ts +13 -13
  108. package/dist/index.js +11 -13
  109. package/dist/indexed-list.d.ts +8 -5
  110. package/dist/indexed-list.d.ts.map +1 -1
  111. package/dist/indexed-list.js +14 -7
  112. package/dist/indexed-list.js.map +1 -1
  113. package/dist/jsx-runtime.d.ts +10 -8
  114. package/dist/jsx-runtime.d.ts.map +1 -1
  115. package/dist/jsx-runtime.js +28 -23
  116. package/dist/jsx-runtime.js.map +1 -1
  117. package/dist/keyed-list.d.ts +17 -14
  118. package/dist/keyed-list.d.ts.map +1 -1
  119. package/dist/keyed-list.js +244 -161
  120. package/dist/keyed-list.js.map +1 -1
  121. package/dist/metadata.d.ts +6 -3
  122. package/dist/metadata.d.ts.map +1 -1
  123. package/dist/metadata.js +131 -164
  124. package/dist/metadata.js.map +1 -1
  125. package/dist/nested-prop.d.ts +4 -2
  126. package/dist/nested-prop.d.ts.map +1 -1
  127. package/dist/nested-prop.js +17 -16
  128. package/dist/nested-prop.js.map +1 -1
  129. package/dist/profiling.d.ts +11 -8
  130. package/dist/profiling.d.ts.map +1 -1
  131. package/dist/profiling.js +17 -17
  132. package/dist/profiling.js.map +1 -1
  133. package/dist/protocol.d.ts +5 -2
  134. package/dist/protocol.d.ts.map +1 -1
  135. package/dist/protocol.js +8 -5
  136. package/dist/protocol.js.map +1 -1
  137. package/dist/raw-html.d.ts +5 -2
  138. package/dist/raw-html.d.ts.map +1 -1
  139. package/dist/raw-html.js +86 -146
  140. package/dist/raw-html.js.map +1 -1
  141. package/dist/ref.d.ts +8 -3
  142. package/dist/ref.d.ts.map +1 -1
  143. package/dist/ref.js +10 -2
  144. package/dist/ref.js.map +1 -1
  145. package/dist/renderable-protocol.d.ts +26 -8
  146. package/dist/renderable-protocol.d.ts.map +1 -1
  147. package/dist/renderable-protocol.js +30 -9
  148. package/dist/renderable-protocol.js.map +1 -1
  149. package/dist/renderable.d.ts +28 -22
  150. package/dist/renderable.d.ts.map +1 -1
  151. package/dist/renderable.js +152 -133
  152. package/dist/renderable.js.map +1 -1
  153. package/dist/retained-ui.d.ts +9 -6
  154. package/dist/retained-ui.d.ts.map +1 -1
  155. package/dist/retained-ui.js +12 -10
  156. package/dist/retained-ui.js.map +1 -1
  157. package/dist/root.d.ts +18 -15
  158. package/dist/root.d.ts.map +1 -1
  159. package/dist/root.js +73 -85
  160. package/dist/root.js.map +1 -1
  161. package/dist/scheduler.d.ts +10 -8
  162. package/dist/scheduler.d.ts.map +1 -1
  163. package/dist/scheduler.js +97 -105
  164. package/dist/scheduler.js.map +1 -1
  165. package/dist/server-framework.d.ts +45 -42
  166. package/dist/server-framework.d.ts.map +1 -1
  167. package/dist/server-framework.js +209 -217
  168. package/dist/server-framework.js.map +1 -1
  169. package/dist/server.d.ts +130 -128
  170. package/dist/server.d.ts.map +1 -1
  171. package/dist/server.js +603 -710
  172. package/dist/server.js.map +1 -1
  173. package/dist/shared/promise.d.ts +6 -3
  174. package/dist/shared/promise.d.ts.map +1 -1
  175. package/dist/shared/promise.js +21 -19
  176. package/dist/shared/promise.js.map +1 -1
  177. package/dist/source-mask.d.ts +10 -6
  178. package/dist/source-mask.d.ts.map +1 -1
  179. package/dist/source-mask.js +60 -63
  180. package/dist/source-mask.js.map +1 -1
  181. package/dist/spread.d.ts +5 -2
  182. package/dist/spread.d.ts.map +1 -1
  183. package/dist/spread.js +79 -99
  184. package/dist/spread.js.map +1 -1
  185. package/dist/state-slot.d.ts +29 -15
  186. package/dist/state-slot.d.ts.map +1 -1
  187. package/dist/state-slot.js +73 -42
  188. package/dist/state-slot.js.map +1 -1
  189. package/dist/testing.d.ts +9 -6
  190. package/dist/testing.d.ts.map +1 -1
  191. package/dist/testing.js +16 -12
  192. package/dist/testing.js.map +1 -1
  193. package/package.json +8 -7
  194. package/src/actions.ts +415 -0
  195. package/src/async.ts +78 -0
  196. package/src/compiled/async-resource.ts +113 -0
  197. package/src/compiled/core.ts +4647 -0
  198. package/src/compiled/types.ts +96 -0
  199. package/src/compiled/validation.ts +23 -0
  200. package/src/component-spread.ts +86 -0
  201. package/src/concurrent.ts +310 -0
  202. package/src/direct-dom.ts +491 -0
  203. package/src/dom/attributes.ts +55 -0
  204. package/src/dom/events.ts +179 -0
  205. package/src/dom/forms.ts +220 -0
  206. package/src/dom/intrinsic.ts +94 -0
  207. package/src/dom/namespace.ts +30 -0
  208. package/src/dom/namespaces.ts +14 -0
  209. package/src/dom/properties.ts +355 -0
  210. package/src/dom/style-properties.ts +46 -0
  211. package/src/dom/styles.ts +86 -0
  212. package/src/dom-forms.ts +23 -0
  213. package/src/dom-styles.ts +11 -0
  214. package/src/env.d.ts +6 -0
  215. package/src/framework-hydrate.ts +224 -0
  216. package/src/framework-protocol.ts +335 -0
  217. package/src/framework.ts +161 -0
  218. package/src/hydrate.ts +38 -0
  219. package/src/hydration-bridge.ts +202 -0
  220. package/src/hydration.ts +644 -0
  221. package/src/index.ts +94 -0
  222. package/src/indexed-list.ts +20 -0
  223. package/src/jsx-runtime.ts +55 -0
  224. package/src/keyed-list.ts +379 -0
  225. package/src/metadata.ts +212 -0
  226. package/src/nested-prop.ts +27 -0
  227. package/src/profiling.ts +43 -0
  228. package/src/protocol.ts +8 -0
  229. package/src/raw-html.ts +206 -0
  230. package/src/ref.ts +13 -0
  231. package/src/renderable-protocol.ts +63 -0
  232. package/src/renderable.ts +313 -0
  233. package/src/retained-ui.ts +19 -0
  234. package/src/root.ts +122 -0
  235. package/src/scheduler.ts +136 -0
  236. package/src/server-framework.ts +397 -0
  237. package/src/server.ts +1160 -0
  238. package/src/shared/promise.ts +28 -0
  239. package/src/source-mask.ts +103 -0
  240. package/src/spread.ts +131 -0
  241. package/src/state-slot.ts +132 -0
  242. package/src/testing.ts +27 -0
  243. package/dist/index.d.ts.map +0 -1
  244. package/dist/index.js.map +0 -1
@@ -0,0 +1,313 @@
1
+ import { binding, isCompiledBinding } from './compiled/core.ts'
2
+ import type { CompiledBinding, CompiledRenderValue, CompiledScope } from './compiled/types.ts'
3
+ import { compiledComponentSpread } from './component-spread.ts'
4
+ import { Fragment, h, type DirectComponent } from './direct-dom.ts'
5
+ import {
6
+ installRenderableClone,
7
+ isRenderableProtocol,
8
+ RENDERABLE,
9
+ type RenderableClone,
10
+ } from './renderable-protocol.ts'
11
+ import type { SourceMask } from './source-mask.ts'
12
+ import { unionSources } from './source-mask.ts'
13
+ import { compiledSpread } from './spread.ts'
14
+
15
+ const DEV = typeof __VIDACT_DEV__ === 'undefined' || __VIDACT_DEV__
16
+ const SPECIAL_PROPS = new Set(['children', 'key', 'ref'])
17
+
18
+ type Props = Record<string, unknown>
19
+ export type RenderablePropsInput = Props | CompiledBinding<Props>
20
+
21
+ type RenderableInternals = {
22
+ readonly identity: unknown
23
+ readonly input: RenderablePropsInput
24
+ readonly reconcile: boolean
25
+ readonly construct: (input: RenderablePropsInput) => CompiledRenderValue
26
+ }
27
+
28
+ export interface CompiledRenderable {
29
+ readonly props: Props
30
+ readonly [RENDERABLE]: RenderableInternals
31
+ }
32
+
33
+ export function createRenderable(
34
+ input: RenderablePropsInput,
35
+ construct: (input: RenderablePropsInput) => CompiledRenderValue,
36
+ identity: unknown = construct,
37
+ reconcile = false,
38
+ ): CompiledRenderable {
39
+ installRenderableClone(cloneRenderable as RenderableClone)
40
+ readPropsInput(input)
41
+ const capability = {
42
+ props: propsView(input),
43
+ } as CompiledRenderable
44
+ Object.defineProperty(capability, RENDERABLE, {
45
+ configurable: false,
46
+ enumerable: false,
47
+ value: { identity, input, reconcile, construct } satisfies RenderableInternals,
48
+ })
49
+ return capability
50
+ }
51
+
52
+ export function createComponentRenderable(
53
+ type: DirectComponent,
54
+ input: RenderablePropsInput,
55
+ identity: unknown = type,
56
+ ): CompiledRenderable {
57
+ return createRenderable(
58
+ input,
59
+ (currentInput) =>
60
+ h(
61
+ type,
62
+ { ...renderableComponentProps(currentInput), ref: renderableRef(currentInput) },
63
+ renderableChildren(currentInput),
64
+ ),
65
+ identity,
66
+ true,
67
+ )
68
+ }
69
+
70
+ function renderableComponentProps(input: RenderablePropsInput): Record<string, unknown> {
71
+ const ordinary = projectInput<Record<string, unknown>>(input, (props) =>
72
+ Object.fromEntries(
73
+ Reflect.ownKeys(props)
74
+ .filter((name) => typeof name !== 'string' || !SPECIAL_PROPS.has(name))
75
+ .map((name) => [name, Reflect.get(props, name)]),
76
+ ),
77
+ )
78
+ return isCompiledBinding(ordinary) ? compiledComponentSpread(ordinary, []) : ordinary
79
+ }
80
+
81
+ export function isRenderable(value: unknown): value is CompiledRenderable {
82
+ return isRenderableProtocol(value)
83
+ }
84
+
85
+ export function createReactElement(
86
+ type: string | typeof Fragment | DirectComponent | CompiledRenderable,
87
+ props: Props | null,
88
+ ...children: CompiledRenderValue[]
89
+ ): CompiledRenderable {
90
+ const input: Props = { ...props }
91
+ if (children.length === 1) input.children = children[0]
92
+ else if (children.length > 1) input.children = children
93
+
94
+ if (typeof type === 'string') return createIntrinsicRenderable(type, input)
95
+
96
+ return createRenderable(
97
+ input,
98
+ (currentInput) => {
99
+ if (isRenderable(type)) return cloneRenderable(type, currentInput)
100
+ const resolved = readPropsInput(currentInput)
101
+ const { children: currentChildren, key: _key, ...currentProps } = resolved
102
+ return Object.hasOwn(resolved, 'children')
103
+ ? h(type, currentProps, currentChildren as CompiledRenderValue)
104
+ : h(type, currentProps)
105
+ },
106
+ type,
107
+ false,
108
+ )
109
+ }
110
+
111
+ export function renderableToArray(value: unknown): [CompiledRenderable] {
112
+ if (!isRenderable(value)) {
113
+ throw new TypeError(
114
+ DEV ? 'Children.toArray requires one compiled renderable capability' : 'V107',
115
+ )
116
+ }
117
+ return [value]
118
+ }
119
+
120
+ export function renderableMarker(value: unknown): undefined {
121
+ if (!isRenderable(value)) {
122
+ throw new TypeError(
123
+ DEV ? 'React element metadata requires a compiled renderable capability' : 'V107',
124
+ )
125
+ }
126
+ return undefined
127
+ }
128
+
129
+ export function cloneRenderable(
130
+ value: unknown,
131
+ overrides?: RenderablePropsInput | null,
132
+ childrenOverride?: CompiledRenderValue | CompiledBinding<CompiledRenderValue>,
133
+ ): CompiledRenderValue {
134
+ if (!isRenderable(value)) {
135
+ throw new TypeError(DEV ? 'cloneRenderable requires a compiled renderable capability' : 'V107')
136
+ }
137
+ const internals = value[RENDERABLE]
138
+ let input = mergeInputs(internals.input, overrides)
139
+ if (arguments.length >= 3) input = mergeInputs(input, childrenInput(childrenOverride))
140
+ return createRenderable(
141
+ input,
142
+ internals.construct,
143
+ internals.identity,
144
+ internals.reconcile,
145
+ ) as unknown as CompiledRenderValue
146
+ }
147
+
148
+ export function cloneRenderableComponent(props: Record<string, unknown>): CompiledRenderValue {
149
+ const value = isCompiledBinding(props.value) ? props.value[1]() : props.value
150
+ if (Object.hasOwn(props, 'childrenOverride')) {
151
+ return cloneRenderable(
152
+ value,
153
+ props.overrides as RenderablePropsInput | null | undefined,
154
+ props.childrenOverride as CompiledRenderValue | CompiledBinding<CompiledRenderValue>,
155
+ )
156
+ }
157
+ return cloneRenderable(value, props.overrides as RenderablePropsInput | null | undefined)
158
+ }
159
+
160
+ export function keyedFragmentComponent(props: Record<string, unknown>): CompiledRenderValue {
161
+ return props.children as CompiledRenderValue
162
+ }
163
+
164
+ export function renderableProps(input: RenderablePropsInput): Record<string, unknown> {
165
+ const ordinary = projectInput(input, (props) =>
166
+ Object.fromEntries(
167
+ Reflect.ownKeys(props)
168
+ .filter((name) => typeof name !== 'string' || !SPECIAL_PROPS.has(name))
169
+ .map((name) => [name, Reflect.get(props, name)]),
170
+ ),
171
+ )
172
+ return isCompiledBinding(ordinary) ? compiledSpread(ordinary, []) : ordinary
173
+ }
174
+
175
+ export function renderableChildren(input: RenderablePropsInput): CompiledRenderValue {
176
+ return projectInput(input, (props) => props.children) as CompiledRenderValue
177
+ }
178
+
179
+ export function renderableRef(input: RenderablePropsInput): unknown {
180
+ return projectInput(input, (props) => props.ref)
181
+ }
182
+
183
+ export function forwardedRef(props: Record<string, unknown>): unknown {
184
+ return props.ref
185
+ }
186
+
187
+ export function dynamicIntrinsicComponent(props: Record<string, unknown>): CompiledRenderValue {
188
+ const tag = isCompiledBinding(props.tag) ? props.tag[1]() : props.tag
189
+ if (typeof tag !== 'string') {
190
+ throw new TypeError(DEV ? 'dynamic intrinsic construction requires a string tag' : 'V107')
191
+ }
192
+ let input = props.props as RenderablePropsInput
193
+ if (Object.hasOwn(props, 'childrenOverride')) {
194
+ input = mergeInputs(
195
+ input,
196
+ childrenInput(
197
+ props.childrenOverride as CompiledRenderValue | CompiledBinding<CompiledRenderValue>,
198
+ ),
199
+ )
200
+ }
201
+ return createIntrinsicRenderable(tag, input) as unknown as CompiledRenderValue
202
+ }
203
+
204
+ function createIntrinsicRenderable(tag: string, input: RenderablePropsInput): CompiledRenderable {
205
+ return createRenderable(
206
+ input,
207
+ (currentInput) =>
208
+ h(
209
+ tag,
210
+ { ...renderableProps(currentInput), ref: renderableRef(currentInput) },
211
+ renderableChildren(currentInput),
212
+ ),
213
+ tag,
214
+ true,
215
+ )
216
+ }
217
+
218
+ function propsView(input: RenderablePropsInput): Props {
219
+ return new Proxy(
220
+ {},
221
+ {
222
+ get(_target, property) {
223
+ const value = Reflect.get(readPropsInput(input), property)
224
+ return isCompiledBinding(value) ? value[1]() : value
225
+ },
226
+ getOwnPropertyDescriptor(_target, property) {
227
+ return Object.hasOwn(readPropsInput(input), property)
228
+ ? { configurable: true, enumerable: true }
229
+ : undefined
230
+ },
231
+ has(_target, property) {
232
+ return Reflect.has(readPropsInput(input), property)
233
+ },
234
+ ownKeys() {
235
+ return Reflect.ownKeys(readPropsInput(input))
236
+ },
237
+ },
238
+ )
239
+ }
240
+
241
+ function childrenInput(
242
+ value: CompiledRenderValue | CompiledBinding<CompiledRenderValue> | undefined,
243
+ ): RenderablePropsInput {
244
+ if (!isCompiledBinding(value)) return { children: value }
245
+ return binding(value[2], value[3], () => ({ children: value[1]() }), value[4], value[5])
246
+ }
247
+
248
+ function mergeInputs(
249
+ authored: RenderablePropsInput,
250
+ overrides: RenderablePropsInput | null | undefined,
251
+ ): RenderablePropsInput {
252
+ if (overrides == null) return authored
253
+ if (!isCompiledBinding(authored) && !isCompiledBinding(overrides)) {
254
+ return { ...readPropsInput(authored), ...readPropsInput(overrides) }
255
+ }
256
+ const inputs = [authored, overrides]
257
+ const subscriptions = collectSubscriptions(inputs)
258
+ const evaluate = (): Props => ({
259
+ ...readPropsInput(authored),
260
+ ...readPropsInput(overrides),
261
+ })
262
+ return binding(
263
+ subscriptions[0]![0],
264
+ subscriptions[0]![1],
265
+ evaluate,
266
+ subscriptions[1]?.[0],
267
+ subscriptions[1]?.[1],
268
+ )
269
+ }
270
+
271
+ function projectInput<Value>(
272
+ input: RenderablePropsInput,
273
+ project: (props: Props) => Value,
274
+ ): Value | CompiledBinding<Value> {
275
+ if (!isCompiledBinding(input)) return project(readPropsInput(input))
276
+ return binding(input[2], input[3], () => project(readPropsInput(input)), input[4], input[5])
277
+ }
278
+
279
+ function collectSubscriptions(
280
+ inputs: readonly RenderablePropsInput[],
281
+ ): Array<[CompiledScope, SourceMask]> {
282
+ const subscriptions = new Map<CompiledScope, SourceMask>()
283
+ for (const input of inputs) {
284
+ if (!isCompiledBinding(input)) continue
285
+ addSubscription(subscriptions, input[2], input[3])
286
+ if (input[4] !== undefined && input[5] !== undefined) {
287
+ addSubscription(subscriptions, input[4], input[5])
288
+ }
289
+ }
290
+ if (subscriptions.size > 2) {
291
+ throw new TypeError(
292
+ DEV ? 'a compiled renderable can combine reactive props from at most two scopes' : 'V107',
293
+ )
294
+ }
295
+ return [...subscriptions]
296
+ }
297
+
298
+ function addSubscription(
299
+ subscriptions: Map<CompiledScope, SourceMask>,
300
+ scope: CompiledScope,
301
+ reads: SourceMask,
302
+ ): void {
303
+ const current = subscriptions.get(scope)
304
+ subscriptions.set(scope, current === undefined ? reads : unionSources(current, reads))
305
+ }
306
+
307
+ function readPropsInput(input: RenderablePropsInput): Props {
308
+ const value = isCompiledBinding(input) ? input[1]() : input
309
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
310
+ throw new TypeError(DEV ? 'compiled renderable props must evaluate to an object' : 'V107')
311
+ }
312
+ return value
313
+ }
@@ -0,0 +1,19 @@
1
+ import { enableRetainedUi, retainedActivity } from './compiled/core.ts'
2
+ import type { CompiledBinding, CompiledRenderValue, StructuralBinding } from './compiled/types.ts'
3
+ import { enableRetainedUiStyles } from './dom/styles.ts'
4
+
5
+ export interface ActivityProps {
6
+ readonly children?: (() => CompiledRenderValue) | readonly [() => CompiledRenderValue]
7
+ readonly mode: 'visible' | 'hidden' | CompiledBinding<'visible' | 'hidden'>
8
+ readonly name?: string
9
+ }
10
+
11
+ export function Activity(props: ActivityProps): StructuralBinding {
12
+ const render = Array.isArray(props.children) ? props.children[0] : props.children
13
+ if (typeof render !== 'function') {
14
+ throw new TypeError('Activity children must be a compiler-generated render function')
15
+ }
16
+ enableRetainedUi()
17
+ enableRetainedUiStyles()
18
+ return retainedActivity(props.mode, render)
19
+ }
package/src/root.ts ADDED
@@ -0,0 +1,122 @@
1
+ import { hydrateCompiled, mountCompiled, type MountCompiledOptions } from './compiled/core.ts'
2
+ import type { CompiledComponentResult } from './compiled/types.ts'
3
+
4
+ const DEV = typeof __VIDACT_DEV__ === 'undefined' || __VIDACT_DEV__
5
+
6
+ export interface CompiledRoot {
7
+ readonly mount: (application: () => CompiledComponentResult) => void
8
+ readonly replace: (application: () => CompiledComponentResult) => void
9
+ readonly unmount: () => void
10
+ }
11
+
12
+ export interface HotContext {
13
+ readonly data: Record<string, unknown>
14
+ readonly accept: () => void
15
+ readonly dispose: (callback: (data: Record<string, unknown>) => void) => void
16
+ readonly prune: (callback: () => void) => void
17
+ }
18
+
19
+ const HOT_ROOT = '__vidactHotRoot'
20
+
21
+ export function createRoot(host: ParentNode, options?: MountCompiledOptions): CompiledRoot {
22
+ let dispose: (() => void) | undefined
23
+ let terminal = false
24
+ return {
25
+ mount(application) {
26
+ if (terminal) throw new Error(DEV ? 'cannot mount an unmounted root' : 'V024')
27
+ if (dispose !== undefined) {
28
+ throw new Error(DEV ? 'compiled root already has a mounted application' : 'V025')
29
+ }
30
+ dispose = mountCompiled(application, host, options).dispose
31
+ },
32
+ replace(nextApplication) {
33
+ if (terminal) throw new Error(DEV ? 'cannot replace an unmounted root' : 'V030')
34
+ const previous = dispose
35
+ const next = mountCompiled(nextApplication, host, options).dispose
36
+ dispose = next
37
+ previous?.()
38
+ },
39
+ unmount() {
40
+ if (terminal) return
41
+ terminal = true
42
+ dispose?.()
43
+ dispose = undefined
44
+ },
45
+ }
46
+ }
47
+
48
+ export function hydrateRoot(
49
+ host: ParentNode,
50
+ application: () => CompiledComponentResult,
51
+ options?: MountCompiledOptions,
52
+ ): CompiledRoot {
53
+ let dispose: (() => void) | undefined = hydrateCompiled(application, host, options).dispose
54
+ let terminal = false
55
+ return {
56
+ mount() {
57
+ throw new Error(DEV ? 'hydration roots are mounted during creation' : 'V029')
58
+ },
59
+ replace(nextApplication) {
60
+ if (terminal) throw new Error(DEV ? 'cannot replace an unmounted root' : 'V030')
61
+ const previous = dispose
62
+ const next = mountCompiled(nextApplication, host, options).dispose
63
+ dispose = next
64
+ previous?.()
65
+ },
66
+ unmount() {
67
+ if (terminal) return
68
+ terminal = true
69
+ dispose?.()
70
+ dispose = undefined
71
+ },
72
+ }
73
+ }
74
+
75
+ export function mountHotRoot(
76
+ hot: HotContext,
77
+ host: ParentNode,
78
+ application: () => CompiledComponentResult,
79
+ options?: MountCompiledOptions,
80
+ ): CompiledRoot {
81
+ const previous = hot.data[HOT_ROOT]
82
+ const root = isCompiledRoot(previous) ? previous : createRoot(host, options)
83
+ if (isCompiledRoot(previous)) root.replace(application)
84
+ else root.mount(application)
85
+ registerHotRoot(hot, root)
86
+ return root
87
+ }
88
+
89
+ export function hydrateHotRoot(
90
+ hot: HotContext,
91
+ host: ParentNode,
92
+ application: () => CompiledComponentResult,
93
+ options?: MountCompiledOptions,
94
+ ): CompiledRoot {
95
+ const previous = hot.data[HOT_ROOT]
96
+ const root = isCompiledRoot(previous) ? previous : hydrateRoot(host, application, options)
97
+ if (isCompiledRoot(previous)) root.replace(application)
98
+ registerHotRoot(hot, root)
99
+ return root
100
+ }
101
+
102
+ function registerHotRoot(hot: HotContext, root: CompiledRoot): void {
103
+ hot.data[HOT_ROOT] = root
104
+ hot.accept()
105
+ hot.dispose((data) => {
106
+ data[HOT_ROOT] = root
107
+ })
108
+ hot.prune(() => {
109
+ if (hot.data[HOT_ROOT] !== root) return
110
+ delete hot.data[HOT_ROOT]
111
+ root.unmount()
112
+ })
113
+ }
114
+
115
+ function isCompiledRoot(value: unknown): value is CompiledRoot {
116
+ return (
117
+ typeof value === 'object' &&
118
+ value !== null &&
119
+ typeof Reflect.get(value, 'replace') === 'function' &&
120
+ typeof Reflect.get(value, 'unmount') === 'function'
121
+ )
122
+ }
@@ -0,0 +1,136 @@
1
+ type ScheduledTask = () => void
2
+ export type CancelScheduledTask = () => void
3
+
4
+ type DeferredTask = {
5
+ readonly run: ScheduledTask
6
+ canceled: boolean
7
+ }
8
+
9
+ let tasks: ScheduledTask[] = []
10
+ let deferredTasks: DeferredTask[] = []
11
+ let microtaskScheduled = false
12
+ let deferredTurnScheduled = false
13
+ let flushing = false
14
+ let actDepth = 0
15
+
16
+ export function scheduleTask(task: ScheduledTask): void {
17
+ tasks.push(task)
18
+ requestFlush()
19
+ }
20
+
21
+ export function scheduleDeferredTask(task: ScheduledTask): CancelScheduledTask {
22
+ const entry: DeferredTask = { run: task, canceled: false }
23
+ deferredTasks.push(entry)
24
+ requestDeferredTurn()
25
+ return () => {
26
+ entry.canceled = true
27
+ }
28
+ }
29
+
30
+ export function flushScheduledTasks(): number {
31
+ if (flushing) return 0
32
+ flushing = true
33
+ microtaskScheduled = false
34
+ let firstError: unknown
35
+ let failed = false
36
+ let count = 0
37
+ try {
38
+ const queued = tasks
39
+ const deferred = deferredTasks
40
+ tasks = []
41
+ deferredTasks = []
42
+ for (const task of queued) {
43
+ count += 1
44
+ try {
45
+ task()
46
+ } catch (error) {
47
+ if (!failed) {
48
+ firstError = error
49
+ failed = true
50
+ }
51
+ }
52
+ }
53
+ for (const task of deferred) {
54
+ if (task.canceled) continue
55
+ count += 1
56
+ try {
57
+ task.run()
58
+ } catch (error) {
59
+ if (!failed) {
60
+ firstError = error
61
+ failed = true
62
+ }
63
+ }
64
+ }
65
+ } finally {
66
+ flushing = false
67
+ requestFlush()
68
+ requestDeferredTurn()
69
+ }
70
+ if (failed) throw firstError
71
+ return count
72
+ }
73
+
74
+ export function hasScheduledTasks(): boolean {
75
+ return tasks.length > 0 || deferredTasks.some((task) => !task.canceled)
76
+ }
77
+
78
+ export function beginActScope(): void {
79
+ actDepth += 1
80
+ }
81
+
82
+ export function endActScope(): void {
83
+ actDepth -= 1
84
+ requestFlush()
85
+ requestDeferredTurn()
86
+ }
87
+
88
+ function requestFlush(): void {
89
+ if (tasks.length === 0 || microtaskScheduled || flushing || actDepth > 0) return
90
+ microtaskScheduled = true
91
+ queueMicrotask(() => {
92
+ microtaskScheduled = false
93
+ if (actDepth === 0) flushScheduledTasks()
94
+ })
95
+ }
96
+
97
+ function requestDeferredTurn(): void {
98
+ if (
99
+ deferredTasks.every((task) => task.canceled) ||
100
+ deferredTurnScheduled ||
101
+ flushing ||
102
+ actDepth > 0
103
+ ) {
104
+ return
105
+ }
106
+ deferredTurnScheduled = true
107
+ const channel = new MessageChannel()
108
+ channel.port1.addEventListener(
109
+ 'message',
110
+ () => {
111
+ channel.port1.close()
112
+ channel.port2.close()
113
+ deferredTurnScheduled = false
114
+ if (actDepth > 0 || flushing) {
115
+ requestDeferredTurn()
116
+ return
117
+ }
118
+ flushOneDeferredTask()
119
+ },
120
+ { once: true },
121
+ )
122
+ channel.port1.start()
123
+ channel.port2.postMessage(undefined)
124
+ }
125
+
126
+ function flushOneDeferredTask(): void {
127
+ let task: DeferredTask | undefined
128
+ while ((task = deferredTasks.shift()) !== undefined && task.canceled) {}
129
+ if (task === undefined) return
130
+ try {
131
+ task.run()
132
+ } finally {
133
+ requestFlush()
134
+ requestDeferredTurn()
135
+ }
136
+ }