mutts 1.0.7 → 1.0.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/README.md +61 -23
- package/dist/async/browser.d.ts +2 -0
- package/dist/async/browser.d.ts.map +1 -0
- package/dist/async/index.d.ts +18 -0
- package/dist/async/index.d.ts.map +1 -0
- package/dist/async/node.d.ts +2 -0
- package/dist/async/node.d.ts.map +1 -0
- package/dist/{chunks/index-BFYK02LG.js → browser.cjs} +169 -60
- package/dist/browser.cjs.map +1 -0
- package/dist/browser.d.ts +1654 -1
- package/dist/browser.esm.js +260 -25
- package/dist/browser.esm.js.map +1 -1
- package/dist/chunks/async-browser-CA0jPWIi.cjs +304 -0
- package/dist/chunks/async-browser-CA0jPWIi.cjs.map +1 -0
- package/dist/chunks/async-core-UqHzvJ-S.cjs +25 -0
- package/dist/chunks/async-core-UqHzvJ-S.cjs.map +1 -0
- package/dist/chunks/async-node-BYHuGTni.cjs +103 -0
- package/dist/chunks/async-node-BYHuGTni.cjs.map +1 -0
- package/dist/chunks/{index-CNR6QRUl.esm.js → index-DhaOVusv.esm.js} +173 -53
- package/dist/chunks/index-DhaOVusv.esm.js.map +1 -0
- package/dist/decorator.d.ts +106 -0
- package/dist/decorator.d.ts.map +1 -0
- package/dist/destroyable.d.ts +87 -0
- package/dist/destroyable.d.ts.map +1 -0
- package/dist/devtools/devtool/devtools.d.ts +1 -0
- package/dist/devtools/devtool/devtools.d.ts.map +1 -0
- package/dist/devtools/devtool/panel.d.ts +2 -0
- package/dist/devtools/devtool/panel.d.ts.map +1 -0
- package/dist/entry-browser.d.ts +3 -0
- package/dist/entry-browser.d.ts.map +1 -0
- package/dist/entry-node.d.ts +3 -0
- package/dist/entry-node.d.ts.map +1 -0
- package/dist/eventful.d.ts +18 -0
- package/dist/eventful.d.ts.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/indexable.d.ts +243 -0
- package/dist/indexable.d.ts.map +1 -0
- package/dist/introspection.d.ts +27 -0
- package/dist/introspection.d.ts.map +1 -0
- package/dist/iterableWeak.d.ts +53 -0
- package/dist/iterableWeak.d.ts.map +1 -0
- package/dist/mixins.d.ts +25 -0
- package/dist/mixins.d.ts.map +1 -0
- package/dist/mutts.umd.js +1 -1
- package/dist/mutts.umd.js.map +1 -1
- package/dist/mutts.umd.min.js +1 -1
- package/dist/mutts.umd.min.js.map +1 -1
- package/dist/node.cjs +105 -0
- package/dist/node.cjs.map +1 -0
- package/dist/node.d.ts +1 -2
- package/dist/node.esm.js +91 -32
- package/dist/node.esm.js.map +1 -1
- package/dist/promiseChain.d.ts +20 -0
- package/dist/promiseChain.d.ts.map +1 -0
- package/dist/reactive/array.d.ts +49 -0
- package/dist/reactive/array.d.ts.map +1 -0
- package/dist/reactive/buffer.d.ts +44 -0
- package/dist/reactive/buffer.d.ts.map +1 -0
- package/dist/reactive/change.d.ts +29 -0
- package/dist/reactive/change.d.ts.map +1 -0
- package/dist/reactive/debug.d.ts +111 -0
- package/dist/reactive/debug.d.ts.map +1 -0
- package/dist/reactive/deep-touch.d.ts +28 -0
- package/dist/reactive/deep-touch.d.ts.map +1 -0
- package/dist/reactive/deep-watch-state.d.ts +25 -0
- package/dist/reactive/deep-watch-state.d.ts.map +1 -0
- package/dist/reactive/deep-watch.d.ts +19 -0
- package/dist/reactive/deep-watch.d.ts.map +1 -0
- package/dist/reactive/effect-context.d.ts +7 -0
- package/dist/reactive/effect-context.d.ts.map +1 -0
- package/dist/reactive/effects.d.ts +151 -0
- package/dist/reactive/effects.d.ts.map +1 -0
- package/dist/reactive/index.d.ts +20 -0
- package/dist/reactive/index.d.ts.map +1 -0
- package/dist/reactive/interface.d.ts +64 -0
- package/dist/reactive/interface.d.ts.map +1 -0
- package/dist/reactive/map.d.ts +30 -0
- package/dist/reactive/map.d.ts.map +1 -0
- package/dist/reactive/memoize.d.ts +5 -0
- package/dist/reactive/memoize.d.ts.map +1 -0
- package/dist/reactive/non-reactive-state.d.ts +9 -0
- package/dist/reactive/non-reactive-state.d.ts.map +1 -0
- package/dist/reactive/non-reactive.d.ts +11 -0
- package/dist/reactive/non-reactive.d.ts.map +1 -0
- package/dist/reactive/project.d.ts +41 -0
- package/dist/reactive/project.d.ts.map +1 -0
- package/dist/reactive/proxy-state.d.ts +8 -0
- package/dist/reactive/proxy-state.d.ts.map +1 -0
- package/dist/reactive/proxy.d.ts +23 -0
- package/dist/reactive/proxy.d.ts.map +1 -0
- package/dist/reactive/record.d.ts +116 -0
- package/dist/reactive/record.d.ts.map +1 -0
- package/dist/reactive/register.d.ts +64 -0
- package/dist/reactive/register.d.ts.map +1 -0
- package/dist/reactive/registry.d.ts +20 -0
- package/dist/reactive/registry.d.ts.map +1 -0
- package/dist/reactive/set.d.ts +28 -0
- package/dist/reactive/set.d.ts.map +1 -0
- package/dist/reactive/tracking.d.ts +7 -0
- package/dist/reactive/tracking.d.ts.map +1 -0
- package/dist/reactive/types.d.ts +376 -0
- package/dist/reactive/types.d.ts.map +1 -0
- package/dist/std-decorators.d.ts +50 -0
- package/dist/std-decorators.d.ts.map +1 -0
- package/dist/utils.d.ts +49 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/zone.d.ts +40 -0
- package/dist/zone.d.ts.map +1 -0
- package/docs/std-decorators.md +69 -1
- package/docs/zone.md +7 -0
- package/package.json +39 -27
- package/src/async/browser.ts +266 -34
- package/src/async/index.ts +17 -2
- package/src/async/node.ts +89 -31
- package/src/entry-browser.ts +5 -0
- package/src/entry-node.ts +5 -0
- package/src/index.d.ts +12 -9
- package/src/index.ts +1 -0
- package/src/reactive/array.ts +139 -52
- package/src/reactive/effect-context.ts +3 -3
- package/src/reactive/index.ts +2 -1
- package/src/reactive/map.ts +1 -1
- package/src/reactive/set.ts +1 -1
- package/src/utils.ts +1 -1
- package/src/zone.ts +19 -8
- package/dist/browser.js +0 -161
- package/dist/browser.js.map +0 -1
- package/dist/chunks/index-BFYK02LG.js.map +0 -1
- package/dist/chunks/index-CNR6QRUl.esm.js.map +0 -1
- package/dist/node.js +0 -136
- package/dist/node.js.map +0 -1
package/src/async/node.ts
CHANGED
|
@@ -1,46 +1,104 @@
|
|
|
1
1
|
import { createHook } from 'node:async_hooks'
|
|
2
2
|
import { Hook, Restorer, asyncHooks } from '.'
|
|
3
3
|
|
|
4
|
+
// 1. Generic async_hooks implementation for Hooks
|
|
5
|
+
// This maintains support for 'asyncHooks.addHook' for generic use cases.
|
|
6
|
+
|
|
4
7
|
const hooks = new Set<Hook>()
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
asyncHooks.addHook = function (hook: Hook) {
|
|
9
|
+
hooks.add(hook)
|
|
10
|
+
return () => {
|
|
11
|
+
hooks.delete(hook)
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const contexts = new Map<number, Restorer[]>()
|
|
16
|
+
const activeUndoers = new Map<number, (() => void)[]>()
|
|
17
|
+
|
|
18
|
+
// Helper to capture current hooks state
|
|
19
|
+
function captureRestorers() {
|
|
20
|
+
if (hooks.size === 0) return []
|
|
21
|
+
const restorers: Restorer[] = []
|
|
22
|
+
for (const h of hooks) {
|
|
23
|
+
const r = h()
|
|
24
|
+
if (r) restorers.push(r)
|
|
25
|
+
}
|
|
26
|
+
return restorers
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Manual Wrap function to handle Promise callbacks
|
|
30
|
+
function wrap<Args extends any[], R>(fn: ((...args: Args) => R) | null | undefined) {
|
|
31
|
+
if (typeof fn !== 'function') return fn
|
|
32
|
+
const restorers = captureRestorers()
|
|
33
|
+
if (restorers.length === 0) return fn
|
|
34
|
+
|
|
35
|
+
return function (this: any, ...args: Args) {
|
|
36
|
+
const undoers: (() => void)[] = []
|
|
37
|
+
for (const restore of restorers) {
|
|
38
|
+
const u = restore()
|
|
39
|
+
if (u) undoers.push(u)
|
|
40
|
+
}
|
|
41
|
+
try {
|
|
42
|
+
return fn.apply(this, args)
|
|
43
|
+
} finally {
|
|
44
|
+
for (let i = undoers.length - 1; i >= 0; i--) undoers[i]()
|
|
13
45
|
}
|
|
14
|
-
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const hook = createHook({
|
|
50
|
+
init(asyncId, type, triggerId, resource) {
|
|
51
|
+
// Used for native resources like Timers
|
|
52
|
+
const restorers = captureRestorers()
|
|
53
|
+
if (restorers.length > 0) contexts.set(asyncId, restorers)
|
|
15
54
|
},
|
|
16
55
|
before(asyncId) {
|
|
17
|
-
const restorers =
|
|
18
|
-
if (restorers)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
undoersPerAsyncId.set(asyncId, undoers)
|
|
56
|
+
const restorers = contexts.get(asyncId)
|
|
57
|
+
if (!restorers) return
|
|
58
|
+
const undoers: (() => void)[] = []
|
|
59
|
+
for (const restore of restorers) {
|
|
60
|
+
const u = restore()
|
|
61
|
+
if (u) undoers.push(u)
|
|
24
62
|
}
|
|
63
|
+
if (undoers.length > 0) activeUndoers.set(asyncId, undoers)
|
|
25
64
|
},
|
|
26
65
|
after(asyncId) {
|
|
27
|
-
const undoers =
|
|
28
|
-
if (undoers)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
66
|
+
const undoers = activeUndoers.get(asyncId)
|
|
67
|
+
if (!undoers) return
|
|
68
|
+
for (let i = undoers.length - 1; i >= 0; i--) undoers[i]()
|
|
69
|
+
activeUndoers.delete(asyncId)
|
|
32
70
|
},
|
|
33
71
|
destroy(asyncId) {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
})
|
|
72
|
+
contexts.delete(asyncId)
|
|
73
|
+
activeUndoers.delete(asyncId)
|
|
74
|
+
},
|
|
75
|
+
})
|
|
76
|
+
hook.enable()
|
|
38
77
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
78
|
+
// 2. Shadow Promise Implementation
|
|
79
|
+
// Ensures V8 await resumptions are visible as .then callbacks, wrapping them to restore context.
|
|
80
|
+
|
|
81
|
+
const OriginalPromise = globalThis.Promise
|
|
82
|
+
const originalMethods = {
|
|
83
|
+
then: OriginalPromise.prototype.then,
|
|
84
|
+
catch: OriginalPromise.prototype.catch,
|
|
85
|
+
finally: OriginalPromise.prototype.finally,
|
|
86
|
+
resolve: OriginalPromise.resolve,
|
|
87
|
+
reject: OriginalPromise.reject,
|
|
88
|
+
all: OriginalPromise.all,
|
|
44
89
|
}
|
|
45
90
|
|
|
46
|
-
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
// Patch prototype
|
|
94
|
+
OriginalPromise.prototype.then = function(onFulfilled, onRejected) {
|
|
95
|
+
return originalMethods.then.call(this, wrap(onFulfilled), wrap(onRejected))
|
|
96
|
+
} as any
|
|
97
|
+
OriginalPromise.prototype.catch = function(onRejected) {
|
|
98
|
+
return originalMethods.catch.call(this, wrap(onRejected))
|
|
99
|
+
} as any
|
|
100
|
+
OriginalPromise.prototype.finally = function(onFinally) {
|
|
101
|
+
return originalMethods.finally.call(this, wrap(onFinally))
|
|
102
|
+
} as any
|
|
103
|
+
|
|
104
|
+
|
package/src/index.d.ts
CHANGED
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
export * from './decorator';
|
|
2
|
+
export * from './destroyable';
|
|
3
|
+
export * from './eventful';
|
|
4
|
+
export * from './indexable';
|
|
5
|
+
export * from './iterableWeak';
|
|
6
|
+
export * from './mixins';
|
|
7
|
+
export * from './promiseChain';
|
|
8
|
+
export * from './reactive';
|
|
9
|
+
export * from './std-decorators';
|
|
10
|
+
export * from './utils';
|
|
11
|
+
export * from './zone';
|
|
12
|
+
export * from './async';
|
package/src/index.ts
CHANGED
package/src/reactive/array.ts
CHANGED
|
@@ -74,6 +74,7 @@ export abstract class ReactiveArray extends Array {
|
|
|
74
74
|
at(index: number): any {
|
|
75
75
|
const actualIndex = index < 0 ? this.length + index : index
|
|
76
76
|
dependant(this, actualIndex)
|
|
77
|
+
if (index < 0) dependant(this, 'length')
|
|
77
78
|
if (actualIndex < 0 || actualIndex >= this.length) return undefined
|
|
78
79
|
return reactive(this[actualIndex])
|
|
79
80
|
}
|
|
@@ -136,36 +137,57 @@ export abstract class ReactiveArray extends Array {
|
|
|
136
137
|
}
|
|
137
138
|
|
|
138
139
|
indexOf(searchElement: any, fromIndex?: number): number {
|
|
139
|
-
|
|
140
|
+
const length = this.length
|
|
141
|
+
let i = fromIndex === undefined ? 0 : fromIndex
|
|
142
|
+
if (i < 0) i = Math.max(length + i, 0)
|
|
143
|
+
|
|
140
144
|
const unwrappedSearch = unwrap(searchElement)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
145
|
+
|
|
146
|
+
for (; i < length; i++) {
|
|
147
|
+
dependant(this, i)
|
|
148
|
+
const item = this[i]
|
|
149
|
+
if (item === searchElement || item === unwrappedSearch || unwrap(item) === unwrappedSearch) {
|
|
150
|
+
return i
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
dependant(this, 'length')
|
|
155
|
+
return -1
|
|
146
156
|
}
|
|
147
157
|
|
|
148
158
|
lastIndexOf(searchElement: any, fromIndex?: number): number {
|
|
149
|
-
|
|
159
|
+
const length = this.length
|
|
160
|
+
let i = fromIndex === undefined ? length - 1 : fromIndex
|
|
161
|
+
if (i >= length) i = length - 1
|
|
162
|
+
if (i < 0) i = Math.max(length + i, -1) // -1 ensures loop condition i >= 0 works correctly
|
|
163
|
+
|
|
150
164
|
const unwrappedSearch = unwrap(searchElement)
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
165
|
+
|
|
166
|
+
for (; i >= 0; i--) {
|
|
167
|
+
dependant(this, i)
|
|
168
|
+
const item = this[i]
|
|
169
|
+
if (item === searchElement || item === unwrappedSearch || unwrap(item) === unwrappedSearch) {
|
|
170
|
+
return i
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// If we scanned the whole relevant part and didn't find it, we depend on length
|
|
175
|
+
// (because adding elements might shift indices or add the element)
|
|
176
|
+
// Actually for lastIndexOf, if we start from end, length dependency is implicit in the start index calculation?
|
|
177
|
+
// But if we return -1, it means we didn't find it.
|
|
178
|
+
// If we push an element, should lastIndexOf update?
|
|
179
|
+
// Yes, if the new element is the one we are looking for.
|
|
180
|
+
dependant(this, 'length')
|
|
181
|
+
return -1
|
|
156
182
|
}
|
|
157
183
|
|
|
158
184
|
includes(searchElement: any, fromIndex?: number): boolean {
|
|
159
|
-
|
|
160
|
-
const unwrappedSearch = unwrap(searchElement)
|
|
161
|
-
// Check both wrapped and unwrapped versions since array may contain either
|
|
162
|
-
return this.includes(unwrappedSearch, fromIndex) || this.includes(searchElement, fromIndex)
|
|
185
|
+
return this.indexOf(searchElement, fromIndex) !== -1
|
|
163
186
|
}
|
|
164
187
|
|
|
165
188
|
find(predicate: (this: any, value: any, index: number, obj: any[]) => boolean, thisArg?: any): any
|
|
166
189
|
find(searchElement: any, fromIndex?: number): any
|
|
167
190
|
find(predicateOrElement: any, thisArg?: any): any {
|
|
168
|
-
dependant(this)
|
|
169
191
|
if (typeof predicateOrElement === 'function') {
|
|
170
192
|
const predicate = predicateOrElement as (
|
|
171
193
|
this: any,
|
|
@@ -173,12 +195,18 @@ export abstract class ReactiveArray extends Array {
|
|
|
173
195
|
index: number,
|
|
174
196
|
obj: any[]
|
|
175
197
|
) => boolean
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
)
|
|
181
|
-
|
|
198
|
+
const length = this.length
|
|
199
|
+
|
|
200
|
+
for (let i = 0; i < length; i++) {
|
|
201
|
+
dependant(this, i)
|
|
202
|
+
const val = reactive(this[i])
|
|
203
|
+
if (predicate.call(thisArg, val, i, this)) {
|
|
204
|
+
return val
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
dependant(this, 'length')
|
|
209
|
+
return undefined
|
|
182
210
|
}
|
|
183
211
|
const fromIndex = typeof thisArg === 'number' ? thisArg : undefined
|
|
184
212
|
const index = this.indexOf(predicateOrElement, fromIndex)
|
|
@@ -192,7 +220,6 @@ export abstract class ReactiveArray extends Array {
|
|
|
192
220
|
): number
|
|
193
221
|
findIndex(searchElement: any, fromIndex?: number): number
|
|
194
222
|
findIndex(predicateOrElement: any, thisArg?: any): number {
|
|
195
|
-
dependant(this)
|
|
196
223
|
if (typeof predicateOrElement === 'function') {
|
|
197
224
|
const predicate = predicateOrElement as (
|
|
198
225
|
this: any,
|
|
@@ -200,10 +227,18 @@ export abstract class ReactiveArray extends Array {
|
|
|
200
227
|
index: number,
|
|
201
228
|
obj: any[]
|
|
202
229
|
) => boolean
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
230
|
+
const length = this.length
|
|
231
|
+
|
|
232
|
+
for (let i = 0; i < length; i++) {
|
|
233
|
+
dependant(this, i)
|
|
234
|
+
const val = reactive(this[i])
|
|
235
|
+
if (predicate.call(thisArg, val, i, this)) {
|
|
236
|
+
return i
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
dependant(this, 'length')
|
|
241
|
+
return -1
|
|
207
242
|
}
|
|
208
243
|
const fromIndex = typeof thisArg === 'number' ? thisArg : undefined
|
|
209
244
|
return this.indexOf(predicateOrElement, fromIndex)
|
|
@@ -291,7 +326,6 @@ export abstract class ReactiveArray extends Array {
|
|
|
291
326
|
})
|
|
292
327
|
}
|
|
293
328
|
|
|
294
|
-
// TODO: re-implement for fun dependencies? (eg - every only check the first ones until it find some),
|
|
295
329
|
// no need to make it dependant on indexes after the found one
|
|
296
330
|
every<S>(
|
|
297
331
|
predicate: (value: any, index: number, array: any[]) => value is S,
|
|
@@ -299,18 +333,31 @@ export abstract class ReactiveArray extends Array {
|
|
|
299
333
|
): this is S[]
|
|
300
334
|
every(callbackfn: (value: any, index: number, array: any[]) => boolean, thisArg?: any): boolean
|
|
301
335
|
every(callbackfn: (value: any, index: number, array: any[]) => boolean, thisArg?: any): boolean {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
336
|
+
const length = this.length
|
|
337
|
+
|
|
338
|
+
for (let i = 0; i < length; i++) {
|
|
339
|
+
dependant(this, i)
|
|
340
|
+
if (!callbackfn.call(thisArg, reactive(this[i]), i, this)) {
|
|
341
|
+
return false
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
dependant(this, 'length')
|
|
346
|
+
return true
|
|
307
347
|
}
|
|
348
|
+
|
|
308
349
|
some(callbackfn: (value: any, index: number, array: any[]) => boolean, thisArg?: any): boolean {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
350
|
+
const length = this.length
|
|
351
|
+
|
|
352
|
+
for (let i = 0; i < length; i++) {
|
|
353
|
+
dependant(this, i)
|
|
354
|
+
if (callbackfn.call(thisArg, reactive(this[i]), i, this)) {
|
|
355
|
+
return true
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
dependant(this, 'length')
|
|
360
|
+
return false
|
|
314
361
|
}
|
|
315
362
|
// Side-effectful
|
|
316
363
|
push(...items: any[]) {
|
|
@@ -358,7 +405,20 @@ export abstract class ReactiveArray extends Array {
|
|
|
358
405
|
|
|
359
406
|
splice(start: number, deleteCount?: number, ...items: any[]) {
|
|
360
407
|
const oldLength = this.length
|
|
361
|
-
|
|
408
|
+
|
|
409
|
+
// Normalize start index
|
|
410
|
+
let actualStart = start
|
|
411
|
+
if (actualStart < 0) actualStart = Math.max(oldLength + actualStart, 0)
|
|
412
|
+
else actualStart = Math.min(actualStart, oldLength)
|
|
413
|
+
|
|
414
|
+
// Normalize deleteCount
|
|
415
|
+
let actualDeleteCount = deleteCount
|
|
416
|
+
if (actualDeleteCount === undefined) {
|
|
417
|
+
actualDeleteCount = oldLength - actualStart
|
|
418
|
+
} else {
|
|
419
|
+
actualDeleteCount = Math.max(0, Math.min(actualDeleteCount, oldLength - actualStart))
|
|
420
|
+
}
|
|
421
|
+
|
|
362
422
|
try {
|
|
363
423
|
if (deleteCount === undefined) return reactive(this.splice(start))
|
|
364
424
|
return reactive(this.splice(start, deleteCount, ...items))
|
|
@@ -366,10 +426,9 @@ export abstract class ReactiveArray extends Array {
|
|
|
366
426
|
touched(
|
|
367
427
|
this,
|
|
368
428
|
{ type: 'bunch', method: 'splice' },
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
: range(start, oldLength + Math.max(items.length - deleteCount, 0), {
|
|
429
|
+
actualDeleteCount === items.length
|
|
430
|
+
? range(actualStart, actualStart + actualDeleteCount - 1)
|
|
431
|
+
: range(actualStart, oldLength + Math.max(items.length - actualDeleteCount, 0), {
|
|
373
432
|
length: true,
|
|
374
433
|
})
|
|
375
434
|
)
|
|
@@ -394,12 +453,23 @@ export abstract class ReactiveArray extends Array {
|
|
|
394
453
|
}
|
|
395
454
|
|
|
396
455
|
fill(value: any, start?: number, end?: number) {
|
|
456
|
+
const len = this.length
|
|
457
|
+
let k = start === undefined ? 0 : start
|
|
458
|
+
if (k < 0) k = Math.max(len + k, 0)
|
|
459
|
+
else k = Math.min(k, len)
|
|
460
|
+
|
|
461
|
+
let final = end === undefined ? len : end
|
|
462
|
+
if (final < 0) final = Math.max(len + final, 0)
|
|
463
|
+
else final = Math.min(final, len)
|
|
464
|
+
|
|
397
465
|
try {
|
|
398
466
|
if (start === undefined) return this.fill(value) as any
|
|
399
467
|
if (end === undefined) return this.fill(value, start) as any
|
|
400
468
|
return this.fill(value, start, end) as any
|
|
401
469
|
} finally {
|
|
402
|
-
|
|
470
|
+
if (final > k) {
|
|
471
|
+
touched(this, { type: 'bunch', method: 'fill' }, range(k, final - 1))
|
|
472
|
+
}
|
|
403
473
|
}
|
|
404
474
|
}
|
|
405
475
|
|
|
@@ -408,13 +478,30 @@ export abstract class ReactiveArray extends Array {
|
|
|
408
478
|
if (end === undefined) return this.copyWithin(target, start) as any
|
|
409
479
|
return this.copyWithin(target, start, end) as any
|
|
410
480
|
} finally {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
481
|
+
const len = this.length
|
|
482
|
+
|
|
483
|
+
let to = target
|
|
484
|
+
if (to < 0) to = Math.max(len + to, 0)
|
|
485
|
+
else if (to >= len) to = len
|
|
486
|
+
|
|
487
|
+
let from = start
|
|
488
|
+
if (from < 0) from = Math.max(len + from, 0)
|
|
489
|
+
else if (from >= len) from = len
|
|
490
|
+
|
|
491
|
+
let final = end === undefined ? len : end
|
|
492
|
+
if (final < 0) final = Math.max(len + final, 0)
|
|
493
|
+
else if (final >= len) final = len
|
|
494
|
+
|
|
495
|
+
const count = Math.min(final - from, len - to)
|
|
496
|
+
|
|
497
|
+
if (count > 0) {
|
|
498
|
+
touched(
|
|
499
|
+
this,
|
|
500
|
+
{ type: 'bunch', method: 'copyWithin' },
|
|
501
|
+
range(to, to + count - 1)
|
|
502
|
+
)
|
|
503
|
+
}
|
|
504
|
+
|
|
417
505
|
}
|
|
418
|
-
// Touch all affected indices with a single allProps call
|
|
419
506
|
}
|
|
420
507
|
}
|
|
@@ -3,10 +3,10 @@ import { asyncZone, ZoneAggregator, ZoneHistory } from '../zone'
|
|
|
3
3
|
import { getRoot } from './registry'
|
|
4
4
|
import { type ScopedCallback } from './types'
|
|
5
5
|
|
|
6
|
-
export const effectHistory = tag(new ZoneHistory<ScopedCallback>()
|
|
7
|
-
tag(effectHistory.present,
|
|
6
|
+
export const effectHistory = tag('effectHistory', new ZoneHistory<ScopedCallback>())
|
|
7
|
+
tag('effectHistory.present', effectHistory.present)
|
|
8
8
|
asyncZone.add(effectHistory)
|
|
9
|
-
export const effectAggregator = tag(new ZoneAggregator(effectHistory.present)
|
|
9
|
+
export const effectAggregator = tag('effectAggregator', new ZoneAggregator(effectHistory.present))
|
|
10
10
|
|
|
11
11
|
export function isRunning(effect: ScopedCallback): boolean {
|
|
12
12
|
const root = getRoot(effect)
|
package/src/reactive/index.ts
CHANGED
|
@@ -27,8 +27,9 @@ export { immutables, isNonReactive, registerNativeReactivity } from './non-react
|
|
|
27
27
|
export { getActiveProjection, project } from './project'
|
|
28
28
|
export { isReactive, ReactiveBase, reactive, unwrap } from './proxy'
|
|
29
29
|
export { organize, organized } from './record'
|
|
30
|
-
export { scan, type ScanResult } from './buffer'
|
|
30
|
+
export { scan, type ScanResult, resolve } from './buffer'
|
|
31
31
|
export { Register, register } from './register'
|
|
32
|
+
export { getActiveEffect, effectAggregator } from './effect-context'
|
|
32
33
|
export {
|
|
33
34
|
type DependencyAccess,
|
|
34
35
|
type Evolution,
|
package/src/reactive/map.ts
CHANGED
package/src/reactive/set.ts
CHANGED
package/src/utils.ts
CHANGED
|
@@ -275,7 +275,7 @@ export function contentRef(container: object) {
|
|
|
275
275
|
return contentRefs.get(container)
|
|
276
276
|
}
|
|
277
277
|
|
|
278
|
-
export function tag<T extends object>(
|
|
278
|
+
export function tag<T extends object>(name: string, obj: T): T {
|
|
279
279
|
Object.defineProperties(obj, {
|
|
280
280
|
[Symbol.toStringTag]: {
|
|
281
281
|
value: name,
|
package/src/zone.ts
CHANGED
|
@@ -1,23 +1,34 @@
|
|
|
1
1
|
import { asyncHooks } from "./async"
|
|
2
2
|
import { named, tag } from "./utils"
|
|
3
3
|
|
|
4
|
+
interface InternalZoneUse<T> {
|
|
5
|
+
enter(value?: T): unknown
|
|
6
|
+
leave(entered: unknown): void
|
|
7
|
+
}
|
|
8
|
+
function isu<T>(z: AZone<T> | InternalZoneUse<T>): InternalZoneUse<T> {
|
|
9
|
+
return z as InternalZoneUse<T>
|
|
10
|
+
}
|
|
4
11
|
export abstract class AZone<T> {
|
|
5
12
|
abstract active?: T
|
|
6
|
-
enter(value?: T): unknown {
|
|
13
|
+
protected enter(value?: T): unknown {
|
|
7
14
|
const prev = this.active
|
|
8
15
|
this.active = value
|
|
9
16
|
return prev
|
|
10
17
|
}
|
|
11
|
-
leave(entered: unknown): void {
|
|
18
|
+
protected leave(entered: unknown): void {
|
|
12
19
|
this.active = entered as T | undefined
|
|
13
20
|
}
|
|
14
21
|
with<R>(value: T, fn: () => R): R {
|
|
15
22
|
const entered = this.enter(value)
|
|
23
|
+
let res: R;
|
|
16
24
|
try {
|
|
17
|
-
|
|
25
|
+
res = fn()
|
|
18
26
|
} finally {
|
|
19
27
|
this.leave(entered)
|
|
20
28
|
}
|
|
29
|
+
// [HACK]: Sanitization
|
|
30
|
+
// See BROWSER_ASYNC_POLYFILL.md
|
|
31
|
+
return asyncHooks.sanitizePromise(res) as R
|
|
21
32
|
}
|
|
22
33
|
root<R>(fn: () => R): R {
|
|
23
34
|
let prev = this.enter()
|
|
@@ -61,11 +72,11 @@ export class ZoneHistory<T> extends AZone<HistoryValue<T>> {
|
|
|
61
72
|
enter(value?: T) {
|
|
62
73
|
if(value && self.history.has(value)) throw new Error('ZoneHistory: re-entering historical zone')
|
|
63
74
|
if(value !== undefined) self.history.add(value)
|
|
64
|
-
return { added: value, entered: controlled.enter(value) }
|
|
75
|
+
return { added: value, entered: isu(controlled).enter(value) }
|
|
65
76
|
},
|
|
66
77
|
leave(entered: { added: T | undefined, entered: unknown }) {
|
|
67
78
|
if(entered.added !== undefined) self.history.delete(entered.added)
|
|
68
|
-
return controlled.leave(entered.entered)
|
|
79
|
+
return isu(controlled).leave(entered.entered)
|
|
69
80
|
}
|
|
70
81
|
})
|
|
71
82
|
)
|
|
@@ -98,12 +109,12 @@ export class ZoneAggregator extends AZone<Map<AZone<unknown>, unknown>> {
|
|
|
98
109
|
const entered = new Map<AZone<unknown>, unknown>()
|
|
99
110
|
for (const z of this.#zones) {
|
|
100
111
|
const v = value?.get(z)
|
|
101
|
-
entered.set(z, z.enter(v))
|
|
112
|
+
entered.set(z, isu(z).enter(v))
|
|
102
113
|
}
|
|
103
114
|
return entered
|
|
104
115
|
}
|
|
105
116
|
leave(entered: Map<AZone<unknown>, unknown>): void {
|
|
106
|
-
for (const z of this.#zones) z.leave(entered.get(z))
|
|
117
|
+
for (const z of this.#zones) isu(z).leave(entered.get(z))
|
|
107
118
|
}
|
|
108
119
|
add(z: AZone<unknown>) {
|
|
109
120
|
this.#zones.add(z)
|
|
@@ -116,7 +127,7 @@ export class ZoneAggregator extends AZone<Map<AZone<unknown>, unknown>> {
|
|
|
116
127
|
}
|
|
117
128
|
}
|
|
118
129
|
|
|
119
|
-
export const asyncZone = tag(new ZoneAggregator()
|
|
130
|
+
export const asyncZone = tag('async', new ZoneAggregator())
|
|
120
131
|
asyncHooks.addHook(() => {
|
|
121
132
|
const zone = asyncZone.active
|
|
122
133
|
return () => {
|