ctx-core 2.4.0 → 3.1.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/all/be_/index.js CHANGED
@@ -1,12 +1,5 @@
1
1
  import { globalThis__prop__ensure } from '../globalThis__prop__ensure/index.js'
2
- import { isArray } from '../isArray/index.js'
3
- let proto_ = Object.getPrototypeOf
4
- let string_proto = proto_('')
5
- let _null = null
6
- let pending_sym = Symbol.for('pending')
7
- let be_M_is_source_ = globalThis__prop__ensure(
8
- Symbol.for('be_M_is_source_'),
9
- ()=>new WeakMap())
2
+ let be_M_is_source_ = globalThis.be_M_is_source_ ||= new WeakMap()
10
3
  /** @typedef {import('./index.d.ts').Be}Be */
11
4
  /** @typedef {import('./index.d.ts').Ctx}Ctx */
12
5
  /** @typedef {import('./index.d.ts').MapCtx}MapCtx */
@@ -51,69 +44,60 @@ export function globalThis__be_(
51
44
  export function be_(
52
45
  id_OR_val__new,
53
46
  val__new_OR_be__params,
54
- be__params = {}
47
+ be__params
55
48
  ) {
56
49
  /** @type {string} */
57
- let id =
58
- proto_(id_OR_val__new) === string_proto
59
- ? id_OR_val__new
60
- : _null
50
+ let id
61
51
  /** @type {be__val__T} */
62
- let val__new =
63
- proto_(id_OR_val__new) === string_proto
64
- ? val__new_OR_be__params || (()=>null)
65
- : id_OR_val__new
66
- be__params =
67
- proto_(id_OR_val__new) === string_proto
68
- ? be__params
69
- : val__new_OR_be__params
70
- let is_source_ =
71
- be__params
72
- ? be__params.is_source_
73
- : _null
74
- let expired_ =
75
- be__params
76
- ? be__params.expired_
77
- : ()=>0
78
- let be = (argv__ctx, params = {})=>{
52
+ let val__new
53
+ /** @type {is_source__T} */
54
+ let is_source_
55
+ /** @type {expired__T} */
56
+ let expired_
57
+ if (typeof id_OR_val__new === 'string') {
58
+ val__new = val__new_OR_be__params
59
+ id = id_OR_val__new
60
+ } else {
61
+ val__new = id_OR_val__new
62
+ be__params = val__new_OR_be__params
63
+ }
64
+ if (be__params) {
65
+ is_source_ = be__params.is_source_
66
+ expired_ = be__params.expired_
67
+ }
68
+ let be = (argv__ctx, params)=>{
79
69
  if (!argv__ctx) {
80
- throw new Error(`be must have a Ctx passed as an argument`)
70
+ throw new Error(`be: no Ctx`)
81
71
  }
82
72
  let saved__val = be__val_(be, argv__ctx)
83
73
  if (
84
- be__has_(be, argv__ctx)
85
- && !params.force
86
- && (!expired_ || !expired_(argv__ctx))
74
+ !params?.force
75
+ && be__has_(be, argv__ctx)
76
+ && !expired_?.(argv__ctx)
87
77
  ) {
88
78
  return saved__val
89
79
  }
90
80
  let ctx = source__map_ctx_(argv__ctx, is_source_)
91
81
  if (!ctx) {
92
82
  throw new Error(
93
- `be: ${
94
- String(id)
95
- }: is_source_ must be true for at least one Ctx`)
83
+ `be: ${String(id)}: no is_source_ returns true`)
96
84
  }
97
- let pending = ctx.get(pending_sym)
85
+ let pending = ctx.get(Symbol.for('pending'))
98
86
  if (!pending) {
99
- pending = new Map()
100
- ctx.set(pending_sym, pending)
87
+ pending = new Map
88
+ ctx.set(Symbol.for('pending'), pending)
101
89
  }
102
90
  if (pending.get(be)) {
103
- let pending_value_a = []
104
- for (let value of pending.values()) {
105
- pending_value_a.push(value)
106
- }
107
91
  throw new Error(
108
92
  `be_: ${
109
93
  String(id)
110
- }: circular dependency:\n${pending_value_a.map(pending_value=>
111
- typeof pending_value === 'function'
112
- ? 'Function'
113
- : pending_value).join('\n')}`)
94
+ }: circular:\n${pending.values().map(pending_value=>
95
+ typeof pending_value === 'string'
96
+ ? pending_value
97
+ : 'Function').join('\n')}`)
114
98
  }
115
99
  pending.set(be, id || be)
116
- let val = val__new(argv__ctx, be, params)
100
+ let val = val__new ? val__new(argv__ctx, be, params) : null
117
101
  ctx.set(be, val)
118
102
  if (id) {
119
103
  ctx.set(id, val)
@@ -162,7 +146,6 @@ export function ctx__set(
162
146
  val,
163
147
  is_source_
164
148
  ) {
165
- if (!is_source_) is_source_ = ()=>true
166
149
  let source__map_ctx = source__map_ctx_(ctx, is_source_)
167
150
  if (source__map_ctx) {
168
151
  source__map_ctx.set(be_OR_id, val)
@@ -189,25 +172,18 @@ export function ctx__delete(
189
172
  ctx,
190
173
  be_OR_id,
191
174
  ) {
192
- const is_source_ =
193
- be__is_source__(be_OR_id)
194
- || (()=>true)
195
- if (isArray(ctx)) {
196
- for (let i = 0; i < ctx.length; i++) {
197
- if (is_source_(ctx[i], ctx)) {
198
- ctx__delete(ctx[i], be_OR_id)
199
- }
175
+ if (Array.isArray(ctx)) {
176
+ for (let _ctx of ctx) {
177
+ ctx__delete(_ctx, be_OR_id)
200
178
  }
201
179
  } else {
202
180
  /** @type {MapCtx} */
203
181
  let map_ctx = /** @type {any} */ctx
204
- if (is_source_(map_ctx, ctx)) {
205
- let { id } = be_OR_id
206
- if (id) {
207
- map_ctx.delete(id)
208
- }
209
- map_ctx.delete(be_OR_id)
182
+ let { id } = be_OR_id
183
+ if (id) {
184
+ map_ctx.delete(id)
210
185
  }
186
+ map_ctx.delete(be_OR_id)
211
187
  }
212
188
  }
213
189
  /**
@@ -217,7 +193,7 @@ export function ctx__delete(
217
193
  * @private
218
194
  */
219
195
  export function be__has_(be_or_id, argv__ctx) {
220
- return !!be__has__ctx_(be_or_id, argv__ctx)
196
+ return Boolean(be__has__ctx_(be_or_id, argv__ctx))
221
197
  }
222
198
  /**
223
199
  * @param {Be|string}be_or_id
@@ -226,7 +202,7 @@ export function be__has_(be_or_id, argv__ctx) {
226
202
  * @private
227
203
  */
228
204
  export function be__has__ctx_(be_or_id, argv__ctx) {
229
- if (isArray(argv__ctx)) {
205
+ if (Array.isArray(argv__ctx)) {
230
206
  for (let i = 0; i < argv__ctx.length; i++) {
231
207
  const be__has__ctx = be__has__ctx_(be_or_id, argv__ctx[i])
232
208
  if (be__has__ctx) return be__has__ctx
@@ -243,7 +219,7 @@ export function be__has__ctx_(be_or_id, argv__ctx) {
243
219
  * @private
244
220
  */
245
221
  export function be__val_(be_or_id, argv__ctx) {
246
- if (isArray(argv__ctx)) {
222
+ if (Array.isArray(argv__ctx)) {
247
223
  for (let i = 0; i < argv__ctx.length; i++) {
248
224
  let ctx = argv__ctx[i]
249
225
  const be__has__ctx = be__has__ctx_(be_or_id, ctx)
@@ -260,7 +236,7 @@ export function be__val_(be_or_id, argv__ctx) {
260
236
  * @private
261
237
  */
262
238
  export function source__map_ctx_(ctx, is_source_) {
263
- if (isArray(ctx)) {
239
+ if (Array.isArray(ctx)) {
264
240
  for (let i = 0; i < ctx.length; i++) {
265
241
  let i_ctx = ctx[i]
266
242
  let source__map_ctx = source__map_ctx_(i_ctx, is_source_)
@@ -0,0 +1,18 @@
1
+ export declare function rmemo_<val_T>(
2
+ def:rmemo_def_T<val_T>,
3
+ ...subscriber_a:rmemo_subscriber_T<val_T>[]
4
+ ):rmemo_T<val_T>
5
+ export declare function rsig_<val_T>(
6
+ init_val:val_T,
7
+ ...subscriber_a:rmemo_subscriber_T<val_T>[]
8
+ ):rmemo_T<val_T>
9
+ export type rmemo_T<val_T> = ((val?:val_T)=>val_T)&rmemo_o_T<val_T>
10
+ export type rmemo_def_T<val_T> = (rmemo:rmemo_T<val_T>)=>val_T
11
+ export type rmemo_subscriber_T<val_T> = (rmemo:rmemo_T<val_T>)=>unknown
12
+ export type rmemo_o_T<val_T> = {
13
+ _:val_T
14
+ readonly val:val_T
15
+ go():unknown
16
+ onset(val:val_T):unknown
17
+ refresh():val_T
18
+ }
@@ -0,0 +1,88 @@
1
+ /** @typedef {import('./index.d.ts').rmemo_T} */
2
+ /** @typedef {import('./index.d.ts').rmemo_subscriber_T} */
3
+ /** @type {(()=>unknown)[]} */
4
+ let queue = []
5
+ /** @type {WeakRef<rmemo_T>} */
6
+ let cur_ref
7
+ /**
8
+ * @param {(rmemo:rmemo_T<unknown>)=>unknown}_f
9
+ * @param {rmemo_subscriber_T<unknown>[]}subscriber_a
10
+ * @returns {rmemo_T}
11
+ * @private
12
+ */
13
+ export function rmemo_(_f, ...subscriber_a) {
14
+ let rmemo$ = (...arg_a)=>arg_a.length ? rmemo$._ = arg_a[0] : rmemo$._
15
+ let _a = []
16
+ let _r = new WeakRef(()=>rmemo$.refresh(_f(rmemo$)))
17
+ _r.l = 0
18
+ rmemo$._a = _a
19
+ rmemo$._f = _f
20
+ rmemo$._r = _r
21
+ rmemo$._rS = new Set
22
+ rmemo$.go = ()=>(rmemo$(), rmemo$)
23
+ rmemo$.onset = ()=>0
24
+ Object.defineProperty(rmemo$, '_', {
25
+ get() {
26
+ if (!_a.length) {
27
+ let prev_ref = cur_ref
28
+ cur_ref = _r
29
+ try {
30
+ _a[0] = _f(rmemo$)
31
+ } finally {
32
+ cur_ref = prev_ref
33
+ }
34
+ }
35
+ // allow self-referencing
36
+ if (cur_ref && cur_ref !== _r) {
37
+ // Math.max: bitwise is much faster on chrome
38
+ // https://measurethat.net/Benchmarks/Show/28483/0/mathmax-vs-bitwise
39
+ cur_ref.l = cur_ref.l ^ ((cur_ref.l ^ _r.l + 1) & -(cur_ref.l < _r.l + 1))
40
+ rmemo$._rS.add(cur_ref)
41
+ }
42
+ return _a[0]
43
+ },
44
+ set(val) {
45
+ if (!_a.length || val !== _a[0]) {
46
+ rmemo$.refresh(val)
47
+ }
48
+ return val
49
+ }
50
+ })
51
+ rmemo$.refresh = val=>{
52
+ let length = _a.length
53
+ _a[0] = val
54
+ rmemo$.onset(val)
55
+ if (length) {
56
+ let run_queue = !queue[0]
57
+ for (let ref of rmemo$._rS) {
58
+ if (!~queue.indexOf(ref)) queue.push(ref)
59
+ }
60
+ if (run_queue) {
61
+ for (let ref; ref = queue.shift();) {
62
+ if (queue.some(_ref=>ref.l > _ref.l)) {
63
+ queue.push(ref)
64
+ } else {
65
+ (ref.deref() || rmemo$._rS.delete)(ref)
66
+ }
67
+ }
68
+ }
69
+ }
70
+ return rmemo$
71
+ }
72
+ rmemo$._sa = subscriber_a.map(subscriber=>
73
+ rmemo_(()=>subscriber(rmemo$)).go())
74
+ return rmemo$
75
+ }
76
+ /**
77
+ * @param {unknown}init_val
78
+ * @param {rmemo_subscriber_T[]}subscriber_a
79
+ * @returns {rmemo_T}
80
+ * @private
81
+ */
82
+ export function rsig_(init_val, ...subscriber_a) {
83
+ let signal$ =
84
+ rmemo_(signal$=>signal$._v, ...subscriber_a)
85
+ signal$.onset = val=>signal$._v = val
86
+ signal$._v = init_val
87
+ return signal$
88
+ }
@@ -1,33 +1,43 @@
1
1
  import { deepStrictEqual } from 'node:assert'
2
- import { clock } from 'sinon'
3
2
  import { test } from 'uvu'
4
3
  import { equal } from 'uvu/assert'
5
4
  import { sleep } from '../sleep/index.js'
6
- import { rememo_, signal_ } from './index.js'
7
- test('rememo_|static value', ()=>{
5
+ import { rmemo_, rmemo_T, rsig_ } from './index.js'
6
+ test('rmemo_|static value', ()=>{
8
7
  let count = 0
9
- let rememo$ = rememo_(rememo=>{
8
+ let rmemo$ = rmemo_(rmemo=>{
10
9
  count++
11
- return 'rememo-value'
10
+ return 'rmemo-value'
12
11
  })
13
12
  equal(count, 0)
14
- equal(rememo$(), 'rememo-value')
13
+ equal(rmemo$(), 'rmemo-value')
15
14
  equal(count, 1)
16
- equal(rememo$(), 'rememo-value')
15
+ equal(rmemo$(), 'rmemo-value')
17
16
  equal(count, 1)
18
17
  })
19
- test('signal_', ()=>{
20
- let signal$ = signal_('val0')
21
- equal(signal$(), 'val0')
22
- signal$('val1')
23
- equal(signal$(), 'val1')
18
+ test('rsig_', ()=>{
19
+ let rsig$ = rsig_('val0')
20
+ equal(rsig$(), 'val0')
21
+ rsig$('val1')
22
+ equal(rsig$(), 'val1')
24
23
  })
25
- test('rememo_|async subsubscriber', async ()=>{
24
+ test('rmemo_|def function|rmemo$ argument', ()=>{
25
+ let rsig$ = rsig_('val0')
26
+ let rmemo$:rmemo_T<string>&{custom?:string} = rmemo_<string>((_rmemo$:rmemo_T<string>&{custom?:string})=>
27
+ `${_rmemo$.custom}-${rsig$()}`)
28
+ rmemo$.custom = 'custom_val0'
29
+ equal(rmemo$(), 'custom_val0-val0')
30
+ rmemo$.custom = 'custom_val1'
31
+ equal(rmemo$(), 'custom_val0-val0')
32
+ rsig$('val1')
33
+ equal(rmemo$(), 'custom_val1-val1')
34
+ })
35
+ test('rsig_|async subsubscriber|case 1', async ()=>{
26
36
  let resolve:(user:{ id:string })=>void
27
37
  let user0 = { id: 'id-0' }
28
38
  let user1 = { id: 'id-1' }
29
- let id$ = signal_('id-0')
30
- let user$ = signal_<{ id:string }|null>(
39
+ let id$ = rsig_('id-0')
40
+ let user$ = rsig_<{ id:string }|null>(
31
41
  null,
32
42
  async (_user$)=>{
33
43
  id$()
@@ -43,13 +53,46 @@ test('rememo_|async subsubscriber', async ()=>{
43
53
  resolve!(user1)
44
54
  await sleep(0)
45
55
  })
46
- test('rememo_+signal_|simple graph', ()=>{
47
- let base$ = signal_('base0')
48
- let dep0$ = rememo_(()=>base$() + '-dep0')
49
- let dep1$ = rememo_(()=>dep0$() + '-dep1')
50
- let dep2$ = rememo_(()=>dep1$() + '-dep2')
51
- let dep3$ = rememo_(()=>dep2$() + '-dep3')
52
- let dep4$ = rememo_(()=>dep3$() + '-dep4')
56
+ test('rsig_|async subsubscriber|case 2', async ()=>{
57
+ let a$ = rsig_(1)
58
+ let b$ = rsig_(2)
59
+ let sleepCycles = 5
60
+ let taskArgumentsCalls:number[][] = []
61
+ let sum$ = rsig_<null|number>(null,
62
+ async sum$=>{
63
+ taskArgumentsCalls.push([a$(), b$()])
64
+ for (let i = 0; i < sleepCycles; i++) {
65
+ await Promise.resolve()
66
+ }
67
+ sum$(a$() + b$())
68
+ })
69
+ equal(sum$(), null)
70
+ deepStrictEqual(taskArgumentsCalls, [[1, 2]])
71
+ a$(10)
72
+ b$(20)
73
+ for (let i = 0; i < sleepCycles; i++) {
74
+ equal(sum$(), null)
75
+ await Promise.resolve()
76
+ deepStrictEqual(taskArgumentsCalls, [
77
+ [1, 2],
78
+ [10, 2],
79
+ [10, 20]
80
+ ])
81
+ }
82
+ equal(sum$(), 30)
83
+ deepStrictEqual(taskArgumentsCalls, [
84
+ [1, 2],
85
+ [10, 2],
86
+ [10, 20]
87
+ ])
88
+ })
89
+ test('rmemo_+rsig_|simple graph', ()=>{
90
+ let base$ = rsig_('base0')
91
+ let dep0$ = rmemo_(()=>base$() + '-dep0')
92
+ let dep1$ = rmemo_(()=>dep0$() + '-dep1')
93
+ let dep2$ = rmemo_(()=>dep1$() + '-dep2')
94
+ let dep3$ = rmemo_(()=>dep2$() + '-dep3')
95
+ let dep4$ = rmemo_(()=>dep3$() + '-dep4')
53
96
  equal(dep4$(), 'base0-dep0-dep1-dep2-dep3-dep4')
54
97
  equal(dep3$(), 'base0-dep0-dep1-dep2-dep3')
55
98
  equal(dep2$(), 'base0-dep0-dep1-dep2')
@@ -65,13 +108,13 @@ test('rememo_+signal_|simple graph', ()=>{
65
108
  equal(dep4$(), 'base1-dep0-dep1-dep2-dep3-dep4')
66
109
  })
67
110
  test('prevents diamond dependency problem 1', ()=>{
68
- let store$ = signal_(0)
111
+ let store$ = rsig_(0)
69
112
  let values:string[] = []
70
- let a$ = rememo_(()=>`a${store$()}`)
71
- let b$ = rememo_(()=>a$().replace('a', 'b'))
72
- let c$ = rememo_(()=>a$().replace('a', 'c'))
73
- let d$ = rememo_(()=>a$().replace('a', 'd'))
74
- let combined$ = rememo_(()=>`${b$()}${c$()}${d$()}`,
113
+ let a$ = rmemo_(()=>`a${store$()}`)
114
+ let b$ = rmemo_(()=>a$().replace('a', 'b'))
115
+ let c$ = rmemo_(()=>a$().replace('a', 'c'))
116
+ let d$ = rmemo_(()=>a$().replace('a', 'd'))
117
+ let combined$ = rmemo_(()=>`${b$()}${c$()}${d$()}`,
75
118
  combined$=>
76
119
  values.push(combined$()))
77
120
  deepStrictEqual(values, ['b0c0d0'])
@@ -80,14 +123,14 @@ test('prevents diamond dependency problem 1', ()=>{
80
123
  deepStrictEqual(values, ['b0c0d0', 'b1c1d1', 'b2c2d2'])
81
124
  })
82
125
  test('prevents diamond dependency problem 2', ()=>{
83
- let store$ = signal_(0)
126
+ let store$ = rsig_(0)
84
127
  let values:string[] = []
85
- let a$ = rememo_(()=>`a${store$()}`)
86
- let b$ = rememo_(()=>a$().replace('a', 'b'))
87
- let c$ = rememo_(()=>b$().replace('b', 'c'))
88
- let d$ = rememo_(()=>c$().replace('c', 'd'))
89
- let e$ = rememo_(()=>d$().replace('d', 'e'))
90
- let combined$ = rememo_<string>(
128
+ let a$ = rmemo_(()=>`a${store$()}`)
129
+ let b$ = rmemo_(()=>a$().replace('a', 'b'))
130
+ let c$ = rmemo_(()=>b$().replace('b', 'c'))
131
+ let d$ = rmemo_(()=>c$().replace('c', 'd'))
132
+ let e$ = rmemo_(()=>d$().replace('d', 'e'))
133
+ let combined$ = rmemo_<string>(
91
134
  ()=>[a$(), e$()].join(''),
92
135
  combined$=>values.push(combined$()))
93
136
  deepStrictEqual(values, ['a0e0'])
@@ -95,13 +138,13 @@ test('prevents diamond dependency problem 2', ()=>{
95
138
  deepStrictEqual(values, ['a0e0', 'a1e1'])
96
139
  })
97
140
  test('prevents diamond dependency problem 3', ()=>{
98
- let store$ = signal_(0)
141
+ let store$ = rsig_(0)
99
142
  let values:string[] = []
100
- let a$ = rememo_(()=>`a${store$()}`)
101
- let b$ = rememo_(()=>a$().replace('a', 'b'))
102
- let c$ = rememo_(()=>b$().replace('b', 'c'))
103
- let d$ = rememo_(()=>c$().replace('c', 'd'))
104
- rememo_<string>(
143
+ let a$ = rmemo_(()=>`a${store$()}`)
144
+ let b$ = rmemo_(()=>a$().replace('a', 'b'))
145
+ let c$ = rmemo_(()=>b$().replace('b', 'c'))
146
+ let d$ = rmemo_(()=>c$().replace('c', 'd'))
147
+ rmemo_<string>(
105
148
  ()=>`${a$()}${b$()}${c$()}${d$()}`,
106
149
  combined$=>values.push(combined$()))
107
150
  deepStrictEqual(values, ['a0b0c0d0'])
@@ -109,24 +152,24 @@ test('prevents diamond dependency problem 3', ()=>{
109
152
  deepStrictEqual(values, ['a0b0c0d0', 'a1b1c1d1'])
110
153
  })
111
154
  test('autosubscribe: prevents diamond dependency problem 4 (complex)', ()=>{
112
- let store1$ = signal_(0)
113
- let store2$ = signal_(0)
155
+ let store1$ = rsig_(0)
156
+ let store2$ = rsig_(0)
114
157
  let values:string[] = []
115
158
  let fn =
116
159
  (name:string)=>
117
160
  (...v:(number|string)[])=>
118
161
  `${name}${v.join('')}`
119
- let a$ = rememo_(()=>`a${store1$()}`)
120
- let b$ = rememo_(()=>`b${store2$()}`)
121
- let c$ = rememo_(()=>`c${a$()}${b$()}`)
122
- let d$ = rememo_(()=>`d${a$()}`)
123
- let e$ = rememo_(()=>`e${c$()}${d$()}`)
124
- let f$ = rememo_(()=>`f${e$()}`)
125
- let g$ = rememo_(()=>`g${f$()}`)
126
- rememo_(
162
+ let a$ = rmemo_(()=>`a${store1$()}`)
163
+ let b$ = rmemo_(()=>`b${store2$()}`)
164
+ let c$ = rmemo_(()=>`c${a$()}${b$()}`)
165
+ let d$ = rmemo_(()=>`d${a$()}`)
166
+ let e$ = rmemo_(()=>`e${c$()}${d$()}`)
167
+ let f$ = rmemo_(()=>`f${e$()}`)
168
+ let g$ = rmemo_(()=>`g${f$()}`)
169
+ rmemo_(
127
170
  ()=>e$(),
128
171
  combined1$=>values.push(combined1$()))
129
- rememo_(
172
+ rmemo_(
130
173
  ()=>[e$(), g$()].join(''),
131
174
  combined2$=>values.push(combined2$()))
132
175
  deepStrictEqual(values, ['eca0b0da0', 'eca0b0da0gfeca0b0da0'])
@@ -143,17 +186,17 @@ test('autosubscribe: prevents diamond dependency problem 4 (complex)', ()=>{
143
186
  })
144
187
  test('prevents diamond dependency problem 5', ()=>{
145
188
  let events = ''
146
- let firstName$ = signal_('John')
147
- let lastName$ = signal_('Doe')
148
- let fullName$ = rememo_(()=>{
189
+ let firstName$ = rsig_('John')
190
+ let lastName$ = rsig_('Doe')
191
+ let fullName$ = rmemo_(()=>{
149
192
  events += 'full '
150
193
  return `${firstName$()} ${lastName$()}`
151
194
  })
152
- let isFirstShort$ = rememo_(()=>{
195
+ let isFirstShort$ = rmemo_(()=>{
153
196
  events += 'short '
154
197
  return firstName$().length < 10
155
198
  })
156
- let displayName$ = rememo_(
199
+ let displayName$ = rmemo_(
157
200
  ()=>{
158
201
  events += 'display '
159
202
  return isFirstShort$() ? fullName$() : firstName$()
@@ -170,13 +213,13 @@ test('prevents diamond dependency problem 5', ()=>{
170
213
  equal(events, 'display short full short full display short full display ')
171
214
  })
172
215
  test('prevents diamond dependency problem 6', ()=>{
173
- let store1$ = signal_(0)
174
- let store2$ = signal_(0)
216
+ let store1$ = rsig_(0)
217
+ let store2$ = rsig_(0)
175
218
  let values:string[] = []
176
- let a$ = rememo_(()=>`a${store1$()}`)
177
- let b$ = rememo_(()=>`b${store2$()}`)
178
- let c$ = rememo_(()=>b$().replace('b', 'c'))
179
- rememo_(
219
+ let a$ = rmemo_(()=>`a${store1$()}`)
220
+ let b$ = rmemo_(()=>`b${store2$()}`)
221
+ let c$ = rmemo_(()=>b$().replace('b', 'c'))
222
+ rmemo_(
180
223
  ()=>`${a$()}${c$()}`,
181
224
  combined$=>values.push(combined$()))
182
225
  deepStrictEqual(values, ['a0c0'])
@@ -184,12 +227,12 @@ test('prevents diamond dependency problem 6', ()=>{
184
227
  deepStrictEqual(values, ['a0c0', 'a1c0'])
185
228
  })
186
229
  test('prevents dependency listeners from being out of order', ()=>{
187
- let base$ = signal_(0)
188
- let a$ = rememo_(()=>{
230
+ let base$ = rsig_(0)
231
+ let a$ = rmemo_(()=>{
189
232
  return `${base$()}a`
190
233
  })
191
234
  let values:string[] = []
192
- let b$ = rememo_(()=>{
235
+ let b$ = rmemo_(()=>{
193
236
  return `${a$()}b`
194
237
  }, b$=>values.push(b$()))
195
238
  equal(b$(), '0ab')
@@ -199,43 +242,9 @@ test('prevents dependency listeners from being out of order', ()=>{
199
242
  deepStrictEqual(values, ['0ab', '1ab'])
200
243
  })
201
244
  test('computes initial value when argument is undefined', ()=>{
202
- let one$ = signal_<string|undefined>(undefined)
203
- let two$ = rememo_(()=>!!one$())
245
+ let one$ = rsig_<string|undefined>(undefined)
246
+ let two$ = rmemo_(()=>!!one$())
204
247
  equal(one$(), undefined)
205
248
  equal(two$(), false)
206
249
  })
207
- test('async computed using task', async ()=>{
208
- let a$ = signal_(1)
209
- let b$ = signal_(2)
210
- let sleepCycles = 5
211
- let taskArgumentsCalls:number[][] = []
212
- let sum$ = signal_<null|number>(null,
213
- async sum$=>{
214
- taskArgumentsCalls.push([a$(), b$()])
215
- for (let i = 0; i < sleepCycles; i++) {
216
- await Promise.resolve()
217
- }
218
- sum$(a$() + b$())
219
- })
220
- equal(sum$(), null)
221
- deepStrictEqual(taskArgumentsCalls, [[1, 2]])
222
- // sleepCycles = 0
223
- a$(10)
224
- b$(20)
225
- for (let i = 0; i < sleepCycles; i++) {
226
- equal(sum$(), null)
227
- await Promise.resolve()
228
- deepStrictEqual(taskArgumentsCalls, [
229
- [1, 2],
230
- [10, 2],
231
- [10, 20]
232
- ])
233
- }
234
- equal(sum$(), 30)
235
- deepStrictEqual(taskArgumentsCalls, [
236
- [1, 2],
237
- [10, 2],
238
- [10, 20]
239
- ])
240
- })
241
250
  test.run()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ctx-core",
3
- "version": "2.4.0",
3
+ "version": "3.1.0",
4
4
  "description": "ctx-core core library",
5
5
  "keywords": [
6
6
  "ctx-core",
@@ -53,7 +53,7 @@
53
53
  "queue",
54
54
  "random",
55
55
  "regex",
56
- "rememo",
56
+ "rmemo",
57
57
  "set",
58
58
  "sleep",
59
59
  "string",
@@ -94,7 +94,7 @@
94
94
  "./queue": "./queue/index.js",
95
95
  "./random": "./random/index.js",
96
96
  "./regex": "./regex/index.js",
97
- "./rememo": "./rememo/index.js",
97
+ "./rmemo": "./rmemo/index.js",
98
98
  "./set": "./set/index.js",
99
99
  "./sleep": "./sleep/index.js",
100
100
  "./string": "./string/index.js",
@@ -129,21 +129,21 @@
129
129
  "import": {
130
130
  "./be": "{ be_ }"
131
131
  },
132
- "limit": "600 B"
132
+ "limit": "465 B"
133
133
  },
134
134
  {
135
- "name": "rememo",
135
+ "name": "rmemo",
136
136
  "import": {
137
- "./rememo": "{ rememo_ }"
137
+ "./rmemo": "{ rmemo_ }"
138
138
  },
139
- "limit": "358 B"
139
+ "limit": "351 B"
140
140
  },
141
141
  {
142
- "name": "rememo signal",
142
+ "name": "rmemo signal",
143
143
  "import": {
144
- "./rememo": "{ signal_ }"
144
+ "./rmemo": "{ rsig_ }"
145
145
  },
146
- "limit": "385 B"
146
+ "limit": "377 B"
147
147
  }
148
148
  ],
149
149
  "scripts": {
@@ -0,0 +1 @@
1
+ export * from '../all/rmemo/index.js'
package/rmemo/index.js ADDED
@@ -0,0 +1 @@
1
+ export * from '../all/rmemo/index.js'
@@ -1,20 +0,0 @@
1
- export declare function rememo_<val_T>(
2
- def:(rememo:rememo__T<val_T>)=>val_T,
3
- ...subscriber_a:rememo_subscriber_T<val_T>[]
4
- ):rememo_T<val_T>
5
- export declare function signal_<val_T>(
6
- init_val:val_T,
7
- ...subscriber_a:rememo_subscriber_T<val_T>[]
8
- ):rememo_T<val_T>
9
- export type rememo__T<val_T> =
10
- (def:rememo_def_T<val_T>, ...subscriber_a:rememo_subscriber_T<val_T>[])=>val_T
11
- export type rememo_T<val_T> = ((val?:val_T)=>val_T)&rememo_o_T<val_T>
12
- export type rememo_def_T<val_T> = (rememo:rememo__T<val>)=>val_T
13
- export type rememo_subscriber_T<val_T> = (rememo:rememo_T<val_T>)=>unknown
14
- export type rememo_o_T<val_T> = {
15
- _:val_T
16
- readonly val:val_T
17
- init():unknown
18
- onset(val:val_T):unknown
19
- refresh():val_T
20
- }
@@ -1,82 +0,0 @@
1
- /** @typedef {import('./index.d.ts').rememo_T} */
2
- /** @typedef {import('./index.d.ts').rememo_subscriber_T} */
3
- /** @type {(()=>unknown)[]} */
4
- let queue = []
5
- /** @type {WeakRef<rememo_T>} */
6
- let cur_ref
7
- /**
8
- * @param {(rememo:rememo_T<unknown>)=>unknown}_f
9
- * @param {rememo_subscriber_T<unknown>[]}subscriber_a
10
- * @returns {rememo_T}
11
- * @private
12
- */
13
- export function rememo_(_f, ...subscriber_a) {
14
- let _a = []
15
- let _rS = new Set
16
- let rememo$ = (...arg_a)=>arg_a.length ? rememo$._ = arg_a[0] : rememo$._
17
- rememo$._a = _a
18
- rememo$._f = _f
19
- rememo$._rS = _rS
20
- rememo$._r = new WeakRef(()=>rememo$.refresh(_f(rememo$)))
21
- rememo$.onset = ()=>0
22
- rememo$._r.l = 0
23
- rememo$.init = ()=>(rememo$(), rememo$)
24
- Object.defineProperty(rememo$, '_', {
25
- get() {
26
- // allow self-referencing
27
- if (!_a.length) {
28
- let prev_ref = cur_ref
29
- cur_ref = rememo$._r
30
- try {
31
- _a[0] = _f(rememo$)
32
- } finally {
33
- cur_ref = prev_ref
34
- }
35
- }
36
- if (cur_ref && cur_ref !== rememo$._r) {
37
- cur_ref.l = Math.max(rememo$._r.l + 1, cur_ref.l)
38
- _rS.add(cur_ref)
39
- }
40
- return _a[0]
41
- },
42
- set(val) {
43
- if (!_a.length || val !== _a[0]) {
44
- rememo$.refresh(val)
45
- }
46
- return val
47
- }
48
- })
49
- rememo$.refresh = val=>{
50
- let { length } = _a
51
- _a[0] = val
52
- rememo$.onset(val)
53
- if (length) {
54
- let run_queue = !queue[0]
55
- for (let ref of _rS) {
56
- if (!~queue.indexOf(ref)) queue.push(ref)
57
- }
58
- if (run_queue) {
59
- for (let ref; ref = queue.shift();) {
60
- queue.some(_ref=>ref.l > _ref.l) ? queue.push(ref) : ref.deref()?.() ?? _rS.delete(ref)
61
- }
62
- }
63
- }
64
- return rememo$
65
- }
66
- rememo$._sa = subscriber_a.map(subscriber=>
67
- rememo_(()=>subscriber(rememo$)).init())
68
- return rememo$
69
- }
70
- /**
71
- * @param {unknown}init_val
72
- * @param {rememo_subscriber_T[]}subscriber_a
73
- * @returns {rememo_T}
74
- * @private
75
- */
76
- export function signal_(init_val, ...subscriber_a) {
77
- let signal$ =
78
- rememo_(signal$=>signal$._v, ...subscriber_a)
79
- signal$.onset = val=>signal$._v = val
80
- signal$._v = init_val
81
- return signal$
82
- }
package/rememo/index.d.ts DELETED
@@ -1 +0,0 @@
1
- export * from '../all/rememo/index.js'
package/rememo/index.js DELETED
@@ -1 +0,0 @@
1
- export * from '../all/rememo/index.js'