@vidact/runtime 0.2.0-beta.7 → 0.2.0-beta.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/state-slot.ts CHANGED
@@ -24,6 +24,59 @@ export interface StateSlot<T> {
24
24
  readonly replace: (value: T) => void
25
25
  }
26
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
+
27
80
  export function createStateSlot<T>(
28
81
  invalidate: (sources: SourceMask) => void,
29
82
  source: SourceMask,
@@ -32,45 +85,48 @@ export function createStateSlot<T>(
32
85
  ): StateSlot<T> {
33
86
  let value = initialValue
34
87
  let revision = 0
35
- const token = {}
88
+ let token: object | undefined
36
89
 
37
- const commit = (next: T): void => {
90
+ const apply = (next: T): void => {
38
91
  if (Object.is(value, next)) return
39
92
 
40
93
  value = next
41
94
  revision += 1
42
95
  invalidate(source)
43
96
  }
44
- const commitUpdate = (update: StateUpdate<T>): void => {
45
- const next = typeof update === 'function' ? (update as (previous: T) => T)(value) : update
46
- commit(next)
47
- }
48
- const commitReplacement = (replacement: StateUpdate<T>): void => commit(replacement as T)
49
- const write = (update: StateUpdate<T>, commitWrite: (update: StateUpdate<T>) => void): void => {
50
- if (
51
- stateWriteInterceptor?.({
52
- slot: token,
53
- revision,
54
- update,
55
- commit: commitWrite,
56
- currentRevision: () => revision,
57
- })
58
- ) {
59
- return
60
- }
61
- commitWrite(update)
62
- }
63
- const replace = (next: T): void => {
64
- assertWritable?.()
65
- write(next, commitReplacement)
66
- }
67
97
 
68
98
  return {
69
99
  get: () => value,
70
100
  set: (update) => {
71
101
  assertWritable?.()
72
- write(update, commitUpdate)
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)
73
130
  },
74
- replace,
75
131
  }
76
132
  }