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

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 +71 -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,28 @@
1
+ export function abortReason(signal: AbortSignal): unknown {
2
+ return signal.reason ?? new DOMException('The operation was aborted', 'AbortError')
3
+ }
4
+
5
+ export function isPromiseLike<Value>(value: unknown): value is PromiseLike<Value> {
6
+ return (
7
+ ((typeof value === 'object' && value !== null) || typeof value === 'function') &&
8
+ typeof (value as PromiseLike<Value>).then === 'function'
9
+ )
10
+ }
11
+
12
+ export function withAbort<Value>(operation: Promise<Value>, signal: AbortSignal): Promise<Value> {
13
+ if (signal.aborted) return Promise.reject(abortReason(signal))
14
+ return new Promise((resolve, reject) => {
15
+ const onAbort = (): void => reject(abortReason(signal))
16
+ signal.addEventListener('abort', onAbort, { once: true })
17
+ void operation.then(
18
+ (value) => {
19
+ signal.removeEventListener('abort', onAbort)
20
+ resolve(value)
21
+ },
22
+ (error: unknown) => {
23
+ signal.removeEventListener('abort', onAbort)
24
+ reject(error)
25
+ },
26
+ )
27
+ })
28
+ }
@@ -0,0 +1,103 @@
1
+ const BITS_PER_WORD = 32
2
+ const DEV = typeof __VIDACT_DEV__ === 'undefined' || __VIDACT_DEV__
3
+
4
+ export type SourceMask = number | Uint32Array
5
+
6
+ export function source(index: number): SourceMask {
7
+ if (!Number.isSafeInteger(index) || index < 0) {
8
+ throw new RangeError(
9
+ DEV ? `source index must be a non-negative safe integer, received ${index}` : 'V701',
10
+ )
11
+ }
12
+
13
+ const word = Math.floor(index / BITS_PER_WORD)
14
+ const bit = (1 << (index % BITS_PER_WORD)) >>> 0
15
+ if (word === 0) return bit
16
+
17
+ const words = new Uint32Array(word + 1)
18
+ words[word] = bit
19
+ return words
20
+ }
21
+
22
+ export function combineSources(...masks: readonly SourceMask[]): SourceMask {
23
+ const length = masks.reduce<number>((maximum, mask) => Math.max(maximum, wordLength(mask)), 1)
24
+ if (length === 1) {
25
+ let combined = 0
26
+ for (const mask of masks) combined = (combined | wordAt(mask, 0)) >>> 0
27
+ return combined
28
+ }
29
+
30
+ const combined = new Uint32Array(length)
31
+ for (const mask of masks) {
32
+ for (let index = 0; index < wordLength(mask); index += 1) {
33
+ combined[index] = ((combined[index] ?? 0) | wordAt(mask, index)) >>> 0
34
+ }
35
+ }
36
+ return combined
37
+ }
38
+
39
+ export function intersectsSources(left: SourceMask, right: SourceMask): boolean {
40
+ if (typeof left === 'number' && typeof right === 'number') {
41
+ return (left & right) >>> 0 !== 0
42
+ }
43
+
44
+ const leftLength = wordLength(left)
45
+ const rightLength = wordLength(right)
46
+ const length = Math.min(leftLength, rightLength)
47
+ for (let index = 0; index < length; index += 1) {
48
+ if ((wordAt(left, index) & wordAt(right, index)) >>> 0 !== 0) return true
49
+ }
50
+ return false
51
+ }
52
+
53
+ export function forEachSource(mask: SourceMask, visit: (index: number) => void): void {
54
+ if (typeof mask === 'number') {
55
+ visitWordSources(mask, 0, visit)
56
+ return
57
+ }
58
+
59
+ for (let word = 0; word < mask.length; word += 1) {
60
+ visitWordSources(mask[word] ?? 0, word * BITS_PER_WORD, visit)
61
+ }
62
+ }
63
+
64
+ export function isEmptySources(mask: SourceMask): boolean {
65
+ if (typeof mask === 'number') return mask === 0
66
+ for (const word of mask) {
67
+ if (word !== 0) return false
68
+ }
69
+ return true
70
+ }
71
+
72
+ export function unionSources(left: SourceMask, right: SourceMask): SourceMask {
73
+ if (typeof left === 'number' && typeof right === 'number') {
74
+ return (left | right) >>> 0
75
+ }
76
+
77
+ const leftLength = wordLength(left)
78
+ const rightLength = wordLength(right)
79
+ const length = Math.max(leftLength, rightLength)
80
+ const words = new Uint32Array(length)
81
+ for (let index = 0; index < length; index += 1) {
82
+ words[index] = (wordAt(left, index) | wordAt(right, index)) >>> 0
83
+ }
84
+ return words
85
+ }
86
+
87
+ function wordAt(mask: SourceMask, index: number): number {
88
+ if (typeof mask === 'number') return index === 0 ? mask : 0
89
+ return mask[index] ?? 0
90
+ }
91
+
92
+ function visitWordSources(word: number, offset: number, visit: (index: number) => void): void {
93
+ let remaining = word >>> 0
94
+ while (remaining !== 0) {
95
+ const bit = 31 - Math.clz32(remaining)
96
+ visit(offset + bit)
97
+ remaining = (remaining & ~(1 << bit)) >>> 0
98
+ }
99
+ }
100
+
101
+ function wordLength(mask: SourceMask): number {
102
+ return typeof mask === 'number' ? 1 : mask.length
103
+ }
package/src/spread.ts ADDED
@@ -0,0 +1,131 @@
1
+ import {
2
+ binding as createBinding,
3
+ mountCompiledPropTransition,
4
+ mountCompiledRef,
5
+ registerCompiledCleanup,
6
+ } from './compiled/core.ts'
7
+ import type { CompiledBinding } from './compiled/types.ts'
8
+ import { attachEventProp, isEventProp } from './dom/events.ts'
9
+ import { INTERNAL_NAMESPACE_PROP } from './dom/intrinsic.ts'
10
+ import {
11
+ applyDomProp,
12
+ ensureControlledFormRestoration,
13
+ isControlledFormProp,
14
+ } from './dom/properties.ts'
15
+
16
+ const DEV = typeof __VIDACT_DEV__ === 'undefined' || __VIDACT_DEV__
17
+ let spreadId = 0
18
+
19
+ export function compiledSpread(
20
+ binding: CompiledBinding<unknown>,
21
+ overriddenNames: readonly string[],
22
+ ): Record<string, (element: Element) => boolean> {
23
+ return {
24
+ [`__vidactSpread${spreadId++}`]: (element) =>
25
+ mountReactiveSpread(element, binding, overriddenNames),
26
+ }
27
+ }
28
+
29
+ function mountReactiveSpread(
30
+ element: Element,
31
+ binding: CompiledBinding<unknown>,
32
+ overriddenNames: readonly string[],
33
+ ): boolean {
34
+ const overrides = new Set(overriddenNames)
35
+ const cleanups = new Map<string, () => void>()
36
+ let controlledCleanup: (() => void) | undefined
37
+ let restoreAfterChildren = false
38
+ const active = (value: unknown): Record<string, unknown> => {
39
+ if (value === null || value === undefined) return {}
40
+ if (typeof value !== 'object' || Array.isArray(value)) {
41
+ throw new TypeError(DEV ? 'reactive JSX spread value must be an object or nullish' : 'V105')
42
+ }
43
+ return value as Record<string, unknown>
44
+ }
45
+ if (!overrides.has('ref')) {
46
+ mountCompiledRef(
47
+ element,
48
+ createBinding(binding[2], binding[3], () => active(binding[1]()).ref, binding[4], binding[5]),
49
+ )
50
+ overrides.add('ref')
51
+ }
52
+ const apply = (name: string, value: unknown): (() => void) => {
53
+ if (
54
+ name === 'children' ||
55
+ name === 'key' ||
56
+ name === 'dangerouslySetInnerHTML' ||
57
+ name === INTERNAL_NAMESPACE_PROP
58
+ ) {
59
+ throw new TypeError(
60
+ DEV
61
+ ? `reactive JSX spread property ${name} requires dedicated ownership semantics`
62
+ : 'V105',
63
+ )
64
+ }
65
+ if (isControlledFormProp(element, name) && controlledCleanup === undefined) {
66
+ controlledCleanup = ensureControlledFormRestoration(element)
67
+ }
68
+ if (name === 'value' && element instanceof HTMLSelectElement) restoreAfterChildren = true
69
+ if (isEventProp(name)) return attachEventProp(element, name, value)
70
+ applyDomProp(element, name, value)
71
+ return () => {}
72
+ }
73
+ const visibleEntries = (value: Record<string, unknown>): Array<[string, unknown]> =>
74
+ Object.entries(value).filter(([name]) => !overrides.has(name))
75
+
76
+ mountCompiledPropTransition(
77
+ binding,
78
+ (initial) => {
79
+ for (const [name, value] of visibleEntries(active(initial))) {
80
+ cleanups.set(name, apply(name, value))
81
+ }
82
+ },
83
+ (nextValue, previousValue) => {
84
+ const next = active(nextValue)
85
+ const previous = active(previousValue)
86
+ const names = new Set([...Object.keys(previous), ...Object.keys(next)])
87
+ const changes = [...names]
88
+ .filter((name) => !overrides.has(name) && !Object.is(next[name], previous[name]))
89
+ .map((name) => ({ name, next: next[name], previous: previous[name] }))
90
+ const undo: Array<() => void> = []
91
+ return [
92
+ () => {
93
+ for (const change of changes) {
94
+ const previousCleanup = cleanups.get(change.name)
95
+ let nextCleanup: () => void
96
+ try {
97
+ nextCleanup = apply(change.name, change.next)
98
+ } catch (error) {
99
+ try {
100
+ apply(change.name, change.previous)
101
+ } catch {
102
+ // Preserve the spread property error that aborted publication.
103
+ }
104
+ throw error
105
+ }
106
+ try {
107
+ previousCleanup?.()
108
+ } catch (error) {
109
+ nextCleanup()
110
+ throw error
111
+ }
112
+ cleanups.set(change.name, nextCleanup)
113
+ undo.push(() => {
114
+ nextCleanup()
115
+ cleanups.set(change.name, apply(change.name, change.previous))
116
+ })
117
+ }
118
+ },
119
+ () => {
120
+ for (let index = undo.length - 1; index >= 0; index -= 1) undo[index]?.()
121
+ undo.length = 0
122
+ },
123
+ ]
124
+ },
125
+ )
126
+ registerCompiledCleanup(() => {
127
+ controlledCleanup?.()
128
+ for (const cleanup of cleanups.values()) cleanup()
129
+ })
130
+ return restoreAfterChildren
131
+ }
@@ -0,0 +1,132 @@
1
+ import type { SourceMask } from './source-mask.ts'
2
+
3
+ export type StateUpdate<T> = T | ((previous: T) => T)
4
+
5
+ export interface DeferredStateWrite<T> {
6
+ readonly slot: object
7
+ readonly revision: number
8
+ readonly update: StateUpdate<T>
9
+ readonly commit: (update: StateUpdate<T>) => void
10
+ readonly currentRevision: () => number
11
+ }
12
+
13
+ export type StateWriteInterceptor = <T>(write: DeferredStateWrite<T>) => boolean
14
+
15
+ let stateWriteInterceptor: StateWriteInterceptor | undefined
16
+
17
+ export function installStateWriteInterceptor(interceptor: StateWriteInterceptor): void {
18
+ stateWriteInterceptor = interceptor
19
+ }
20
+
21
+ export interface StateSlot<T> {
22
+ readonly get: () => T
23
+ readonly set: (update: StateUpdate<T>) => void
24
+ readonly replace: (value: T) => void
25
+ }
26
+
27
+ export interface ReadOnlyStateInvalidationTarget {
28
+ readonly [1]: (sources: SourceMask) => void
29
+ }
30
+
31
+ export interface ReadOnlyStateCell<T> extends Pick<StateSlot<T>, 'get'> {
32
+ value: T
33
+ revision?: number
34
+ readonly invalidationTarget: ReadOnlyStateInvalidationTarget
35
+ readonly source: SourceMask
36
+ }
37
+
38
+ export function createReadOnlyStateSlot<T>(
39
+ invalidationTarget: ReadOnlyStateInvalidationTarget,
40
+ source: SourceMask,
41
+ initialValue: T,
42
+ ): ReadOnlyStateCell<T> {
43
+ return {
44
+ value: initialValue,
45
+ invalidationTarget,
46
+ source,
47
+ get: readReadOnlyState,
48
+ }
49
+ }
50
+
51
+ function readReadOnlyState<T>(this: ReadOnlyStateCell<T>): T {
52
+ return this.value
53
+ }
54
+
55
+ export function replaceReadOnlyStateSlot<T>(cell: ReadOnlyStateCell<T>, replacement: T): void {
56
+ if (Object.is(cell.value, replacement)) return
57
+ const revision = cell.revision ?? 0
58
+ if (
59
+ stateWriteInterceptor?.({
60
+ slot: cell,
61
+ revision,
62
+ update: replacement,
63
+ commit: (pending) => applyReadOnlyState(cell, pending as T),
64
+ currentRevision: () => cell.revision ?? 0,
65
+ })
66
+ ) {
67
+ cell.revision ??= revision
68
+ return
69
+ }
70
+ applyReadOnlyState(cell, replacement)
71
+ }
72
+
73
+ function applyReadOnlyState<T>(cell: ReadOnlyStateCell<T>, next: T): void {
74
+ if (Object.is(cell.value, next)) return
75
+ cell.value = next
76
+ if (cell.revision !== undefined) cell.revision += 1
77
+ cell.invalidationTarget[1](cell.source)
78
+ }
79
+
80
+ export function createStateSlot<T>(
81
+ invalidate: (sources: SourceMask) => void,
82
+ source: SourceMask,
83
+ initialValue: T,
84
+ assertWritable?: () => void,
85
+ ): StateSlot<T> {
86
+ let value = initialValue
87
+ let revision = 0
88
+ let token: object | undefined
89
+
90
+ const apply = (next: T): void => {
91
+ if (Object.is(value, next)) return
92
+
93
+ value = next
94
+ revision += 1
95
+ invalidate(source)
96
+ }
97
+
98
+ return {
99
+ get: () => value,
100
+ set: (update) => {
101
+ assertWritable?.()
102
+ if (
103
+ stateWriteInterceptor?.({
104
+ slot: (token ??= {}),
105
+ revision,
106
+ update,
107
+ commit: (pending) =>
108
+ apply(typeof pending === 'function' ? (pending as (previous: T) => T)(value) : pending),
109
+ currentRevision: () => revision,
110
+ })
111
+ ) {
112
+ return
113
+ }
114
+ apply(typeof update === 'function' ? (update as (previous: T) => T)(value) : update)
115
+ },
116
+ replace: (replacement) => {
117
+ assertWritable?.()
118
+ if (
119
+ stateWriteInterceptor?.({
120
+ slot: (token ??= {}),
121
+ revision,
122
+ update: replacement,
123
+ commit: (pending) => apply(pending as T),
124
+ currentRevision: () => revision,
125
+ })
126
+ ) {
127
+ return
128
+ }
129
+ apply(replacement)
130
+ },
131
+ }
132
+ }
package/src/testing.ts ADDED
@@ -0,0 +1,27 @@
1
+ import { readCompiledOwnerMetrics as readOwnerMetrics } from './compiled/core.ts'
2
+ import {
3
+ beginActScope as beginSchedulerActScope,
4
+ endActScope as endSchedulerActScope,
5
+ flushScheduledTasks as flushSchedulerTasks,
6
+ hasScheduledTasks as schedulerHasTasks,
7
+ } from './scheduler.ts'
8
+
9
+ export function beginActScope(): void {
10
+ beginSchedulerActScope()
11
+ }
12
+
13
+ export function endActScope(): void {
14
+ endSchedulerActScope()
15
+ }
16
+
17
+ export function flushScheduledTasks(): number {
18
+ return flushSchedulerTasks()
19
+ }
20
+
21
+ export function hasScheduledTasks(): boolean {
22
+ return schedulerHasTasks()
23
+ }
24
+
25
+ export function readCompiledOwnerMetrics(): ReturnType<typeof readOwnerMetrics> {
26
+ return readOwnerMetrics()
27
+ }
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,OAAO,EACP,MAAM,EACN,aAAa,EACb,cAAc,EACd,wBAAwB,EACxB,uBAAuB,EACvB,oBAAoB,EACpB,YAAY,EACZ,qBAAqB,EACrB,yBAAyB,EACzB,2BAA2B,EAC3B,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,yBAAyB,EACzB,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,OAAO,EACP,KAAK,EACL,aAAa,EACb,gBAAgB,EAChB,GAAG,EACH,WAAW,EACX,UAAU,EACV,SAAS,EACT,cAAc,EACd,KAAK,EACL,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,OAAO,EACP,oBAAoB,EACpB,IAAI,EACJ,KAAK,UAAU,EACf,KAAK,oBAAoB,GAC1B,MAAM,oBAAoB,CAAA;AAC3B,YAAY,EACV,eAAe,EACf,uBAAuB,EACvB,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,aAAa,EACb,UAAU,EACV,iBAAiB,GAClB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AAC/D,OAAO,EACL,aAAa,EACb,QAAQ,EACR,CAAC,EACD,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,WAAW,GACjB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAA;AAC9E,OAAO,EAAE,MAAM,EAAE,KAAK,UAAU,EAAE,MAAM,UAAU,CAAA;AAClD,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,kBAAkB,EAClB,gBAAgB,EAChB,yBAAyB,EACzB,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,GAC1B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,KAAK,YAAY,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAA;AACxF,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7F,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5C,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAA"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,2HAA2H;AAC3H,mCAAmC;AAEnC,OAAO,EACL,OAAO,EACP,MAAM,EACN,aAAa,EACb,cAAc,EACd,wBAAwB,EACxB,uBAAuB,EACvB,oBAAoB,EACpB,YAAY,EACZ,qBAAqB,EACrB,yBAAyB,EACzB,2BAA2B,EAC3B,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,yBAAyB,EACzB,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,aAAa,EACb,OAAO,EACP,KAAK,EACL,aAAa,EACb,gBAAgB,EAChB,GAAG,EACH,WAAW,EACX,UAAU,EACV,SAAS,EACT,cAAc,EACd,KAAK,EACL,mBAAmB,EACnB,kBAAkB,EAClB,eAAe,EACf,OAAO,EACP,oBAAoB,EACpB,IAAI,GAGL,MAAM,oBAAoB,CAAA;AAW3B,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AAC/D,OAAO,EACL,aAAa,EACb,QAAQ,EACR,CAAC,GAIF,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAC7C,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAA;AAC9E,OAAO,EAAE,MAAM,EAAmB,MAAM,UAAU,CAAA;AAClD,OAAO,EACL,eAAe,EACf,wBAAwB,EACxB,kBAAkB,EAClB,gBAAgB,EAChB,yBAAyB,EACzB,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,iBAAiB,GAGlB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,UAAU,EAAE,YAAY,EAAsC,MAAM,WAAW,CAAA;AACxF,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,MAAM,EAAmB,MAAM,kBAAkB,CAAA;AAC7F,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA"}