mutts 1.0.7 → 1.0.9
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 +72 -17
- package/dist/browser.cjs +3111 -0
- package/dist/browser.cjs.map +1 -0
- package/dist/browser.d.ts +1391 -1
- package/dist/browser.esm.js +264 -35
- package/dist/browser.esm.js.map +1 -1
- package/dist/chunks/async-browser-lvzLOCgk.cjs +297 -0
- package/dist/chunks/async-browser-lvzLOCgk.cjs.map +1 -0
- package/dist/chunks/async-core-CRLKP3l-.cjs +29 -0
- package/dist/chunks/async-core-CRLKP3l-.cjs.map +1 -0
- package/dist/chunks/async-node-C3DeIb0y.cjs +96 -0
- package/dist/chunks/async-node-C3DeIb0y.cjs.map +1 -0
- package/dist/chunks/index-2vea86wD.esm.js +3011 -0
- package/dist/chunks/index-2vea86wD.esm.js.map +1 -0
- package/dist/chunks/index-CtA2AWl3.esm.js +4376 -0
- package/dist/chunks/index-CtA2AWl3.esm.js.map +1 -0
- package/dist/chunks/index-VTO-b2vR.cjs +4461 -0
- package/dist/chunks/index-VTO-b2vR.cjs.map +1 -0
- package/dist/debug/debug.d.ts +122 -0
- package/dist/debug/debug.d.ts.map +1 -0
- package/dist/debug/index.d.ts +4 -0
- package/dist/debug/index.d.ts.map +1 -0
- package/dist/debug/lineage-panel.d.ts +5 -0
- package/dist/debug/lineage-panel.d.ts.map +1 -0
- package/dist/debug/lineage.d.ts +79 -0
- package/dist/debug/lineage.d.ts.map +1 -0
- package/dist/debug.cjs +35 -0
- package/dist/debug.cjs.map +1 -0
- package/dist/debug.d.ts +209 -0
- package/dist/debug.esm.js +2 -0
- package/dist/debug.esm.js.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/index.d.ts +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 +107 -0
- package/dist/node.cjs.map +1 -0
- package/dist/node.d.ts +2 -2
- package/dist/node.esm.js +86 -33
- package/dist/node.esm.js.map +1 -1
- package/dist/src/async/browser.d.ts +2 -0
- package/dist/src/async/browser.d.ts.map +1 -0
- package/dist/src/async/index.d.ts +19 -0
- package/dist/src/async/index.d.ts.map +1 -0
- package/dist/src/async/node.d.ts +2 -0
- package/dist/src/async/node.d.ts.map +1 -0
- package/dist/src/decorator.d.ts +106 -0
- package/dist/src/decorator.d.ts.map +1 -0
- package/dist/src/destroyable.d.ts +87 -0
- package/dist/src/destroyable.d.ts.map +1 -0
- package/dist/src/entry-browser.d.ts +3 -0
- package/dist/src/entry-browser.d.ts.map +1 -0
- package/dist/src/entry-node.d.ts +3 -0
- package/dist/src/entry-node.d.ts.map +1 -0
- package/dist/src/eventful.d.ts +20 -0
- package/dist/src/eventful.d.ts.map +1 -0
- package/dist/src/flavored.d.ts +33 -0
- package/dist/src/flavored.d.ts.map +1 -0
- package/dist/src/index.d.ts +14 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/indexable.d.ts +243 -0
- package/dist/src/indexable.d.ts.map +1 -0
- package/dist/src/introspection.d.ts +27 -0
- package/dist/src/introspection.d.ts.map +1 -0
- package/dist/src/iterableWeak.d.ts +53 -0
- package/dist/src/iterableWeak.d.ts.map +1 -0
- package/dist/src/mixins.d.ts +25 -0
- package/dist/src/mixins.d.ts.map +1 -0
- package/dist/src/promiseChain.d.ts +20 -0
- package/dist/src/promiseChain.d.ts.map +1 -0
- package/dist/src/reactive/array.d.ts +48 -0
- package/dist/src/reactive/array.d.ts.map +1 -0
- package/dist/src/reactive/buffer.d.ts +120 -0
- package/dist/src/reactive/buffer.d.ts.map +1 -0
- package/dist/src/reactive/change.d.ts +29 -0
- package/dist/src/reactive/change.d.ts.map +1 -0
- package/dist/src/reactive/deep-touch.d.ts +28 -0
- package/dist/src/reactive/deep-touch.d.ts.map +1 -0
- package/dist/src/reactive/deep-watch-state.d.ts +25 -0
- package/dist/src/reactive/deep-watch-state.d.ts.map +1 -0
- package/dist/src/reactive/deep-watch.d.ts +20 -0
- package/dist/src/reactive/deep-watch.d.ts.map +1 -0
- package/dist/src/reactive/describe.d.ts +12 -0
- package/dist/src/reactive/describe.d.ts.map +1 -0
- package/dist/src/reactive/effect-context.d.ts +34 -0
- package/dist/src/reactive/effect-context.d.ts.map +1 -0
- package/dist/src/reactive/effects.d.ts +164 -0
- package/dist/src/reactive/effects.d.ts.map +1 -0
- package/dist/src/reactive/index.d.ts +19 -0
- package/dist/src/reactive/index.d.ts.map +1 -0
- package/dist/src/reactive/map.d.ts +28 -0
- package/dist/src/reactive/map.d.ts.map +1 -0
- package/dist/src/reactive/memoize.d.ts +28 -0
- package/dist/src/reactive/memoize.d.ts.map +1 -0
- package/dist/src/reactive/non-reactive-state.d.ts +9 -0
- package/dist/src/reactive/non-reactive-state.d.ts.map +1 -0
- package/dist/src/reactive/non-reactive.d.ts +11 -0
- package/dist/src/reactive/non-reactive.d.ts.map +1 -0
- package/dist/src/reactive/project.d.ts +40 -0
- package/dist/src/reactive/project.d.ts.map +1 -0
- package/dist/src/reactive/proxy-state.d.ts +8 -0
- package/dist/src/reactive/proxy-state.d.ts.map +1 -0
- package/dist/src/reactive/proxy.d.ts +23 -0
- package/dist/src/reactive/proxy.d.ts.map +1 -0
- package/dist/src/reactive/record.d.ts +115 -0
- package/dist/src/reactive/record.d.ts.map +1 -0
- package/dist/src/reactive/register.d.ts +125 -0
- package/dist/src/reactive/register.d.ts.map +1 -0
- package/dist/src/reactive/registry.d.ts +21 -0
- package/dist/src/reactive/registry.d.ts.map +1 -0
- package/dist/src/reactive/set.d.ts +26 -0
- package/dist/src/reactive/set.d.ts.map +1 -0
- package/dist/src/reactive/tracking.d.ts +7 -0
- package/dist/src/reactive/tracking.d.ts.map +1 -0
- package/dist/src/reactive/types.d.ts +424 -0
- package/dist/src/reactive/types.d.ts.map +1 -0
- package/dist/src/reactive/watch.d.ts +48 -0
- package/dist/src/reactive/watch.d.ts.map +1 -0
- package/dist/src/std-decorators.d.ts +45 -0
- package/dist/src/std-decorators.d.ts.map +1 -0
- package/dist/src/utils.d.ts +49 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/zone.d.ts +40 -0
- package/dist/src/zone.d.ts.map +1 -0
- package/dist/types-DaHFfhlN.d.ts +414 -0
- package/docs/ai/api-reference.md +1 -1
- package/docs/ai/manual.md +443 -17
- package/docs/events.md +57 -2
- package/docs/flavored.md +210 -0
- package/docs/reactive/advanced.md +2 -3
- package/docs/reactive/attend.md +143 -0
- package/docs/reactive/collections.md +55 -0
- package/docs/reactive/core.md +120 -4
- package/docs/reactive/debugging.md +8 -10
- package/docs/reactive/describe.md +85 -0
- package/docs/reactive/error-handling.md +121 -0
- package/docs/reactive/project.md +1 -1
- package/docs/reactive/scan.md +215 -0
- package/docs/reactive.md +2 -0
- package/docs/std-decorators.md +171 -52
- package/docs/zone.md +9 -6
- package/package.json +44 -27
- package/src/async/browser.ts +277 -41
- package/src/async/index.ts +23 -4
- package/src/async/node.ts +78 -32
- package/src/entry-browser.ts +5 -0
- package/src/entry-node.ts +5 -0
- package/src/eventful.ts +82 -49
- package/src/flavored.ts +106 -0
- package/src/index.d.ts +12 -9
- package/src/index.ts +2 -1
- package/src/introspection.ts +1 -1
- package/src/reactive/array.ts +160 -80
- package/src/reactive/buffer.ts +187 -27
- package/src/reactive/change.ts +16 -23
- package/src/reactive/deep-touch.ts +19 -14
- package/src/reactive/deep-watch-state.ts +3 -3
- package/src/reactive/deep-watch.ts +7 -4
- package/src/reactive/describe.ts +39 -0
- package/src/reactive/effect-context.ts +71 -6
- package/src/reactive/effects.ts +445 -393
- package/src/reactive/index.ts +12 -14
- package/src/reactive/map.ts +8 -24
- package/src/reactive/memoize.ts +26 -3
- package/src/reactive/project.md +107 -0
- package/src/reactive/project.ts +48 -71
- package/src/reactive/proxy.ts +21 -3
- package/src/reactive/record.ts +30 -45
- package/src/reactive/register.ts +138 -19
- package/src/reactive/registry.ts +22 -9
- package/src/reactive/set.ts +7 -20
- package/src/reactive/tracking.ts +9 -12
- package/src/reactive/types.ts +104 -24
- package/src/reactive/{interface.ts → watch.ts} +29 -59
- package/src/std-decorators.ts +56 -17
- package/src/utils.ts +3 -4
- package/src/zone.ts +43 -28
- package/dist/browser.js +0 -161
- package/dist/browser.js.map +0 -1
- package/dist/chunks/index-BFYK02LG.js +0 -6378
- package/dist/chunks/index-BFYK02LG.js.map +0 -1
- package/dist/chunks/index-CNR6QRUl.esm.js +0 -6291
- 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/reactive/debug.ts +0 -517
package/src/flavored.ts
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a flavored (extensible) version of a function with chainable property modifiers.
|
|
3
|
+
*
|
|
4
|
+
* Each property defined in `flavors` returns a new flavored function that transforms
|
|
5
|
+
* how the original function is called. This enables a fluent API where properties
|
|
6
|
+
* create specialized variants of the base function.
|
|
7
|
+
*
|
|
8
|
+
* @param fn - The base function to flavor
|
|
9
|
+
* @param flavors - Object defining the flavor properties (getters or methods)
|
|
10
|
+
* @returns A proxy of the function with the flavor properties attached
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* function greet(name: string, options?: { loud?: boolean }) {
|
|
15
|
+
* const greeting = `Hello, ${name}!`
|
|
16
|
+
* return options?.loud ? greeting.toUpperCase() : greeting
|
|
17
|
+
* }
|
|
18
|
+
*
|
|
19
|
+
* const flavoredGreet = flavored(greet, {
|
|
20
|
+
* get loud() {
|
|
21
|
+
* return createFlavor(this, (name, opts) => [name, { ...opts, loud: true }])
|
|
22
|
+
* }
|
|
23
|
+
* })
|
|
24
|
+
*
|
|
25
|
+
* flavoredGreet('World') // "Hello, World!"
|
|
26
|
+
* flavoredGreet.loud('World') // "HELLO, WORLD!"
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
import { named } from './utils'
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Creates a flavored (extensible) version of a function with chainable property modifiers.
|
|
33
|
+
*/
|
|
34
|
+
export function flavored<T extends (...args: any[]) => any, F extends Record<string, any>>(
|
|
35
|
+
fn: T,
|
|
36
|
+
flavors: F
|
|
37
|
+
): T & F {
|
|
38
|
+
// Store flavors for recursive flavoring
|
|
39
|
+
;(fn as any).flavors = flavors
|
|
40
|
+
|
|
41
|
+
return new Proxy(fn, {
|
|
42
|
+
get(target, prop, receiver) {
|
|
43
|
+
if (prop in flavors) {
|
|
44
|
+
return Reflect.get(flavors, prop, receiver)
|
|
45
|
+
}
|
|
46
|
+
return (target as any)[prop]
|
|
47
|
+
},
|
|
48
|
+
}) as T & F
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Creates a new flavored function that transforms arguments before calling the base.
|
|
53
|
+
*
|
|
54
|
+
* @param fn - The base flavored function
|
|
55
|
+
* @param transform - Function that receives the original arguments and returns transformed arguments
|
|
56
|
+
* @returns A new flavored function with the transformation applied
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* const loudGreet = createFlavor(greet, (name, opts) => [name, { ...opts, loud: true }])
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export function createFlavor<T extends (...args: any[]) => any>(
|
|
64
|
+
fn: T,
|
|
65
|
+
transform: (...args: Parameters<T>) => Parameters<T>,
|
|
66
|
+
name?: string
|
|
67
|
+
): T {
|
|
68
|
+
const fct = function flavorWrapper(this: any, ...args: Parameters<T>) {
|
|
69
|
+
return fn.apply(this, transform(...args))
|
|
70
|
+
}
|
|
71
|
+
if (name) named(name, fct)
|
|
72
|
+
|
|
73
|
+
return flavored(fct as any as T, (fn as any).flavors || {})
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Creates a new flavored function that merges options objects.
|
|
78
|
+
* Useful when the last argument is an options object that should be merged.
|
|
79
|
+
*
|
|
80
|
+
* @param fn - The base flavored function
|
|
81
|
+
* @param defaultOptions - Options to merge with the provided options
|
|
82
|
+
* @returns A new flavored function with merged options
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```typescript
|
|
86
|
+
* const opaqueEffect = flavorOptions(effect, { opaque: true })
|
|
87
|
+
* const namedEffect = flavorOptions(effect, { name: 'myEffect' })
|
|
88
|
+
* ```
|
|
89
|
+
*/
|
|
90
|
+
export function flavorOptions<T extends (...args: any[]) => any>(
|
|
91
|
+
fn: T,
|
|
92
|
+
defaultOptions: Record<string, any>,
|
|
93
|
+
name?: string
|
|
94
|
+
): T {
|
|
95
|
+
const fct = function flavorOptionsWrapper(this: any, ...args: any[]) {
|
|
96
|
+
const lastArg = args[args.length - 1]
|
|
97
|
+
const mergedArgs =
|
|
98
|
+
lastArg !== undefined && typeof lastArg === 'object'
|
|
99
|
+
? [...args.slice(0, -1), { ...defaultOptions, ...lastArg }]
|
|
100
|
+
: [...args, defaultOptions]
|
|
101
|
+
return fn.apply(this, mergedArgs)
|
|
102
|
+
}
|
|
103
|
+
if (name) named(name, fct)
|
|
104
|
+
|
|
105
|
+
return flavored(fct as any as T, (fn as any).flavors || {})
|
|
106
|
+
}
|
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
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
export * from './async'
|
|
1
2
|
export * from './decorator'
|
|
2
3
|
export * from './destroyable'
|
|
3
4
|
export * from './eventful'
|
|
5
|
+
export * from './flavored'
|
|
4
6
|
export * from './indexable'
|
|
5
7
|
export * from './iterableWeak'
|
|
6
8
|
export * from './mixins'
|
|
@@ -30,7 +32,6 @@ if (globalScope) {
|
|
|
30
32
|
let source = 'mutts/index'
|
|
31
33
|
const viteEval = eval
|
|
32
34
|
try {
|
|
33
|
-
// @ts-ignore
|
|
34
35
|
if (typeof __filename !== 'undefined') source = __filename
|
|
35
36
|
else {
|
|
36
37
|
// Using eval to avoid SyntaxError in CJS environments where import.meta is not allowed
|
package/src/introspection.ts
CHANGED
package/src/reactive/array.ts
CHANGED
|
@@ -25,29 +25,18 @@ export abstract class Indexer extends Array {
|
|
|
25
25
|
dependant(this, i)
|
|
26
26
|
return reactive(this[i])
|
|
27
27
|
}
|
|
28
|
+
// Returns undefined intentionally: signals the proxy handler that notifications
|
|
29
|
+
// were already dispatched via touched(), preventing double notification
|
|
28
30
|
set(i: number, value: any) {
|
|
29
31
|
const added = i >= this.length
|
|
30
32
|
this[i] = value
|
|
31
33
|
touched(this, { type: 'set', prop: i }, index(i, { length: added }))
|
|
32
34
|
}
|
|
33
|
-
getLength() {
|
|
34
|
-
dependant(this, 'length')
|
|
35
|
-
return this.length
|
|
36
|
-
}
|
|
37
|
-
setLength(value: number) {
|
|
38
|
-
const oldLength = this.length
|
|
39
|
-
try {
|
|
40
|
-
this.length = value
|
|
41
|
-
} finally {
|
|
42
|
-
touched(this, { type: 'set', prop: 'length' }, range(oldLength, value, { length: true }))
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
35
|
}
|
|
46
36
|
const indexLess = { get: FoolProof.get, set: FoolProof.set }
|
|
47
37
|
Object.assign(FoolProof, {
|
|
48
38
|
get(obj: any, prop: any, receiver: any) {
|
|
49
39
|
if (obj instanceof Array && typeof prop === 'string') {
|
|
50
|
-
if (prop === 'length') return Indexer.prototype.getLength.call(obj)
|
|
51
40
|
const index = parseInt(prop)
|
|
52
41
|
if (!Number.isNaN(index)) return Indexer.prototype.get.call(obj, index)
|
|
53
42
|
}
|
|
@@ -55,7 +44,6 @@ Object.assign(FoolProof, {
|
|
|
55
44
|
},
|
|
56
45
|
set(obj: any, prop: any, value: any, receiver: any) {
|
|
57
46
|
if (obj instanceof Array && typeof prop === 'string') {
|
|
58
|
-
if (prop === 'length') return Indexer.prototype.setLength.call(obj, value)
|
|
59
47
|
const index = parseInt(prop)
|
|
60
48
|
if (!Number.isNaN(index)) return Indexer.prototype.set.call(obj, index, value)
|
|
61
49
|
}
|
|
@@ -67,13 +55,24 @@ export abstract class ReactiveArray extends Array {
|
|
|
67
55
|
toJSON() {
|
|
68
56
|
return this
|
|
69
57
|
}
|
|
70
|
-
get
|
|
71
|
-
|
|
58
|
+
get length(): number {
|
|
59
|
+
dependant(this, 'length')
|
|
60
|
+
return this.length
|
|
61
|
+
}
|
|
62
|
+
set length(value: number) {
|
|
63
|
+
const oldLength = this.length
|
|
64
|
+
if (oldLength === value) return
|
|
65
|
+
try {
|
|
66
|
+
this.length = value
|
|
67
|
+
} finally {
|
|
68
|
+
touched(this, { type: 'set', prop: 'length' }, range(oldLength, value, { length: true }))
|
|
69
|
+
}
|
|
72
70
|
}
|
|
73
71
|
// Safe array access with negative indices
|
|
74
72
|
at(index: number): any {
|
|
75
73
|
const actualIndex = index < 0 ? this.length + index : index
|
|
76
74
|
dependant(this, actualIndex)
|
|
75
|
+
if (index < 0) dependant(this, 'length')
|
|
77
76
|
if (actualIndex < 0 || actualIndex >= this.length) return undefined
|
|
78
77
|
return reactive(this[actualIndex])
|
|
79
78
|
}
|
|
@@ -102,17 +101,17 @@ export abstract class ReactiveArray extends Array {
|
|
|
102
101
|
}
|
|
103
102
|
|
|
104
103
|
// Iterator methods with reactivity tracking
|
|
105
|
-
entries() {
|
|
104
|
+
entries(): any {
|
|
106
105
|
dependant(this)
|
|
107
106
|
return makeReactiveEntriesIterator(this.entries())
|
|
108
107
|
}
|
|
109
108
|
|
|
110
|
-
keys() {
|
|
109
|
+
keys(): any {
|
|
111
110
|
dependant(this, 'length')
|
|
112
111
|
return this.keys()
|
|
113
112
|
}
|
|
114
113
|
|
|
115
|
-
values() {
|
|
114
|
+
values(): any {
|
|
116
115
|
dependant(this)
|
|
117
116
|
return makeReactiveIterator(this.values())
|
|
118
117
|
}
|
|
@@ -136,36 +135,57 @@ export abstract class ReactiveArray extends Array {
|
|
|
136
135
|
}
|
|
137
136
|
|
|
138
137
|
indexOf(searchElement: any, fromIndex?: number): number {
|
|
139
|
-
|
|
138
|
+
const length = this.length
|
|
139
|
+
let i = fromIndex === undefined ? 0 : fromIndex
|
|
140
|
+
if (i < 0) i = Math.max(length + i, 0)
|
|
141
|
+
|
|
140
142
|
const unwrappedSearch = unwrap(searchElement)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
143
|
+
|
|
144
|
+
for (; i < length; i++) {
|
|
145
|
+
dependant(this, i)
|
|
146
|
+
const item = this[i]
|
|
147
|
+
if (item === searchElement || item === unwrappedSearch || unwrap(item) === unwrappedSearch) {
|
|
148
|
+
return i
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
dependant(this, 'length')
|
|
153
|
+
return -1
|
|
146
154
|
}
|
|
147
155
|
|
|
148
156
|
lastIndexOf(searchElement: any, fromIndex?: number): number {
|
|
149
|
-
|
|
157
|
+
const length = this.length
|
|
158
|
+
let i = fromIndex === undefined ? length - 1 : fromIndex
|
|
159
|
+
if (i >= length) i = length - 1
|
|
160
|
+
if (i < 0) i = Math.max(length + i, -1) // -1 ensures loop condition i >= 0 works correctly
|
|
161
|
+
|
|
150
162
|
const unwrappedSearch = unwrap(searchElement)
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
163
|
+
|
|
164
|
+
for (; i >= 0; i--) {
|
|
165
|
+
dependant(this, i)
|
|
166
|
+
const item = this[i]
|
|
167
|
+
if (item === searchElement || item === unwrappedSearch || unwrap(item) === unwrappedSearch) {
|
|
168
|
+
return i
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// If we scanned the whole relevant part and didn't find it, we depend on length
|
|
173
|
+
// (because adding elements might shift indices or add the element)
|
|
174
|
+
// Actually for lastIndexOf, if we start from end, length dependency is implicit in the start index calculation?
|
|
175
|
+
// But if we return -1, it means we didn't find it.
|
|
176
|
+
// If we push an element, should lastIndexOf update?
|
|
177
|
+
// Yes, if the new element is the one we are looking for.
|
|
178
|
+
dependant(this, 'length')
|
|
179
|
+
return -1
|
|
156
180
|
}
|
|
157
181
|
|
|
158
182
|
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)
|
|
183
|
+
return this.indexOf(searchElement, fromIndex) !== -1
|
|
163
184
|
}
|
|
164
185
|
|
|
165
186
|
find(predicate: (this: any, value: any, index: number, obj: any[]) => boolean, thisArg?: any): any
|
|
166
187
|
find(searchElement: any, fromIndex?: number): any
|
|
167
188
|
find(predicateOrElement: any, thisArg?: any): any {
|
|
168
|
-
dependant(this)
|
|
169
189
|
if (typeof predicateOrElement === 'function') {
|
|
170
190
|
const predicate = predicateOrElement as (
|
|
171
191
|
this: any,
|
|
@@ -173,12 +193,18 @@ export abstract class ReactiveArray extends Array {
|
|
|
173
193
|
index: number,
|
|
174
194
|
obj: any[]
|
|
175
195
|
) => boolean
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
)
|
|
181
|
-
|
|
196
|
+
const length = this.length
|
|
197
|
+
|
|
198
|
+
for (let i = 0; i < length; i++) {
|
|
199
|
+
dependant(this, i)
|
|
200
|
+
const val = reactive(this[i])
|
|
201
|
+
if (predicate.call(thisArg, val, i, this)) {
|
|
202
|
+
return val
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
dependant(this, 'length')
|
|
207
|
+
return undefined
|
|
182
208
|
}
|
|
183
209
|
const fromIndex = typeof thisArg === 'number' ? thisArg : undefined
|
|
184
210
|
const index = this.indexOf(predicateOrElement, fromIndex)
|
|
@@ -192,7 +218,6 @@ export abstract class ReactiveArray extends Array {
|
|
|
192
218
|
): number
|
|
193
219
|
findIndex(searchElement: any, fromIndex?: number): number
|
|
194
220
|
findIndex(predicateOrElement: any, thisArg?: any): number {
|
|
195
|
-
dependant(this)
|
|
196
221
|
if (typeof predicateOrElement === 'function') {
|
|
197
222
|
const predicate = predicateOrElement as (
|
|
198
223
|
this: any,
|
|
@@ -200,10 +225,18 @@ export abstract class ReactiveArray extends Array {
|
|
|
200
225
|
index: number,
|
|
201
226
|
obj: any[]
|
|
202
227
|
) => boolean
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
228
|
+
const length = this.length
|
|
229
|
+
|
|
230
|
+
for (let i = 0; i < length; i++) {
|
|
231
|
+
dependant(this, i)
|
|
232
|
+
const val = reactive(this[i])
|
|
233
|
+
if (predicate.call(thisArg, val, i, this)) {
|
|
234
|
+
return i
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
dependant(this, 'length')
|
|
239
|
+
return -1
|
|
207
240
|
}
|
|
208
241
|
const fromIndex = typeof thisArg === 'number' ? thisArg : undefined
|
|
209
242
|
return this.indexOf(predicateOrElement, fromIndex)
|
|
@@ -291,7 +324,6 @@ export abstract class ReactiveArray extends Array {
|
|
|
291
324
|
})
|
|
292
325
|
}
|
|
293
326
|
|
|
294
|
-
// TODO: re-implement for fun dependencies? (eg - every only check the first ones until it find some),
|
|
295
327
|
// no need to make it dependant on indexes after the found one
|
|
296
328
|
every<S>(
|
|
297
329
|
predicate: (value: any, index: number, array: any[]) => value is S,
|
|
@@ -299,21 +331,34 @@ export abstract class ReactiveArray extends Array {
|
|
|
299
331
|
): this is S[]
|
|
300
332
|
every(callbackfn: (value: any, index: number, array: any[]) => boolean, thisArg?: any): boolean
|
|
301
333
|
every(callbackfn: (value: any, index: number, array: any[]) => boolean, thisArg?: any): boolean {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
334
|
+
const length = this.length
|
|
335
|
+
|
|
336
|
+
for (let i = 0; i < length; i++) {
|
|
337
|
+
dependant(this, i)
|
|
338
|
+
if (!callbackfn.call(thisArg, reactive(this[i]), i, this)) {
|
|
339
|
+
return false
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
dependant(this, 'length')
|
|
344
|
+
return true
|
|
307
345
|
}
|
|
346
|
+
|
|
308
347
|
some(callbackfn: (value: any, index: number, array: any[]) => boolean, thisArg?: any): boolean {
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
348
|
+
const length = this.length
|
|
349
|
+
|
|
350
|
+
for (let i = 0; i < length; i++) {
|
|
351
|
+
dependant(this, i)
|
|
352
|
+
if (callbackfn.call(thisArg, reactive(this[i]), i, this)) {
|
|
353
|
+
return true
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
dependant(this, 'length')
|
|
358
|
+
return false
|
|
314
359
|
}
|
|
315
360
|
// Side-effectful
|
|
316
|
-
push(...items: any[]) {
|
|
361
|
+
push(...items: any[]): number {
|
|
317
362
|
const oldLength = this.length
|
|
318
363
|
try {
|
|
319
364
|
return this.push(...items)
|
|
@@ -326,7 +371,7 @@ export abstract class ReactiveArray extends Array {
|
|
|
326
371
|
}
|
|
327
372
|
}
|
|
328
373
|
|
|
329
|
-
pop() {
|
|
374
|
+
pop(): any {
|
|
330
375
|
if (this.length === 0) return undefined
|
|
331
376
|
try {
|
|
332
377
|
return reactive(this.pop())
|
|
@@ -335,7 +380,7 @@ export abstract class ReactiveArray extends Array {
|
|
|
335
380
|
}
|
|
336
381
|
}
|
|
337
382
|
|
|
338
|
-
shift() {
|
|
383
|
+
shift(): any {
|
|
339
384
|
if (this.length === 0) return undefined
|
|
340
385
|
try {
|
|
341
386
|
return reactive(this.shift())
|
|
@@ -344,7 +389,7 @@ export abstract class ReactiveArray extends Array {
|
|
|
344
389
|
}
|
|
345
390
|
}
|
|
346
391
|
|
|
347
|
-
unshift(...items: any[]) {
|
|
392
|
+
unshift(...items: any[]): number {
|
|
348
393
|
try {
|
|
349
394
|
return this.unshift(...items)
|
|
350
395
|
} finally {
|
|
@@ -356,9 +401,22 @@ export abstract class ReactiveArray extends Array {
|
|
|
356
401
|
}
|
|
357
402
|
}
|
|
358
403
|
|
|
359
|
-
splice(start: number, deleteCount?: number, ...items: any[]) {
|
|
404
|
+
splice(start: number, deleteCount?: number, ...items: any[]): any[] {
|
|
360
405
|
const oldLength = this.length
|
|
361
|
-
|
|
406
|
+
|
|
407
|
+
// Normalize start index
|
|
408
|
+
let actualStart = start
|
|
409
|
+
if (actualStart < 0) actualStart = Math.max(oldLength + actualStart, 0)
|
|
410
|
+
else actualStart = Math.min(actualStart, oldLength)
|
|
411
|
+
|
|
412
|
+
// Normalize deleteCount
|
|
413
|
+
let actualDeleteCount = deleteCount
|
|
414
|
+
if (actualDeleteCount === undefined) {
|
|
415
|
+
actualDeleteCount = oldLength - actualStart
|
|
416
|
+
} else {
|
|
417
|
+
actualDeleteCount = Math.max(0, Math.min(actualDeleteCount, oldLength - actualStart))
|
|
418
|
+
}
|
|
419
|
+
|
|
362
420
|
try {
|
|
363
421
|
if (deleteCount === undefined) return reactive(this.splice(start))
|
|
364
422
|
return reactive(this.splice(start, deleteCount, ...items))
|
|
@@ -366,17 +424,16 @@ export abstract class ReactiveArray extends Array {
|
|
|
366
424
|
touched(
|
|
367
425
|
this,
|
|
368
426
|
{ type: 'bunch', method: 'splice' },
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
: range(start, oldLength + Math.max(items.length - deleteCount, 0), {
|
|
427
|
+
actualDeleteCount === items.length
|
|
428
|
+
? range(actualStart, actualStart + actualDeleteCount - 1)
|
|
429
|
+
: range(actualStart, oldLength + Math.max(items.length - actualDeleteCount, 0), {
|
|
373
430
|
length: true,
|
|
374
431
|
})
|
|
375
432
|
)
|
|
376
433
|
}
|
|
377
434
|
}
|
|
378
435
|
|
|
379
|
-
reverse() {
|
|
436
|
+
reverse(): any[] {
|
|
380
437
|
try {
|
|
381
438
|
return this.reverse()
|
|
382
439
|
} finally {
|
|
@@ -384,7 +441,7 @@ export abstract class ReactiveArray extends Array {
|
|
|
384
441
|
}
|
|
385
442
|
}
|
|
386
443
|
|
|
387
|
-
sort(compareFn?: (a: any, b: any) => number) {
|
|
444
|
+
sort(compareFn?: (a: any, b: any) => number): this {
|
|
388
445
|
compareFn = compareFn || ((a, b) => a.toString().localeCompare(b.toString()))
|
|
389
446
|
try {
|
|
390
447
|
return this.sort((a, b) => compareFn(reactive(a), reactive(b))) as any
|
|
@@ -393,28 +450,51 @@ export abstract class ReactiveArray extends Array {
|
|
|
393
450
|
}
|
|
394
451
|
}
|
|
395
452
|
|
|
396
|
-
fill(value: any, start?: number, end?: number) {
|
|
453
|
+
fill(value: any, start?: number, end?: number): this {
|
|
454
|
+
const len = this.length
|
|
455
|
+
let k = start === undefined ? 0 : start
|
|
456
|
+
if (k < 0) k = Math.max(len + k, 0)
|
|
457
|
+
else k = Math.min(k, len)
|
|
458
|
+
|
|
459
|
+
let final = end === undefined ? len : end
|
|
460
|
+
if (final < 0) final = Math.max(len + final, 0)
|
|
461
|
+
else final = Math.min(final, len)
|
|
462
|
+
|
|
397
463
|
try {
|
|
398
464
|
if (start === undefined) return this.fill(value) as any
|
|
399
465
|
if (end === undefined) return this.fill(value, start) as any
|
|
400
466
|
return this.fill(value, start, end) as any
|
|
401
467
|
} finally {
|
|
402
|
-
|
|
468
|
+
if (final > k) {
|
|
469
|
+
touched(this, { type: 'bunch', method: 'fill' }, range(k, final - 1))
|
|
470
|
+
}
|
|
403
471
|
}
|
|
404
472
|
}
|
|
405
473
|
|
|
406
|
-
copyWithin(target: number, start: number, end?: number) {
|
|
474
|
+
copyWithin(target: number, start: number, end?: number): this {
|
|
407
475
|
try {
|
|
408
476
|
if (end === undefined) return this.copyWithin(target, start) as any
|
|
409
477
|
return this.copyWithin(target, start, end) as any
|
|
410
478
|
} finally {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
479
|
+
const len = this.length
|
|
480
|
+
|
|
481
|
+
let to = target
|
|
482
|
+
if (to < 0) to = Math.max(len + to, 0)
|
|
483
|
+
else if (to >= len) to = len
|
|
484
|
+
|
|
485
|
+
let from = start
|
|
486
|
+
if (from < 0) from = Math.max(len + from, 0)
|
|
487
|
+
else if (from >= len) from = len
|
|
488
|
+
|
|
489
|
+
let final = end === undefined ? len : end
|
|
490
|
+
if (final < 0) final = Math.max(len + final, 0)
|
|
491
|
+
else if (final >= len) final = len
|
|
492
|
+
|
|
493
|
+
const count = Math.min(final - from, len - to)
|
|
494
|
+
|
|
495
|
+
if (count > 0) {
|
|
496
|
+
touched(this, { type: 'bunch', method: 'copyWithin' }, range(to, to + count - 1))
|
|
497
|
+
}
|
|
417
498
|
}
|
|
418
|
-
// Touch all affected indices with a single allProps call
|
|
419
499
|
}
|
|
420
500
|
}
|