@reactive-vscode/reactivity 0.2.0-beta.1 → 0.2.0-beta.2
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/dist/index.d.ts +780 -0
- package/dist/index.js +1753 -0
- package/package.json +11 -11
- package/shim.d.ts +0 -4
- package/src/apiWatch.ts +0 -415
- package/src/enums.ts +0 -4
- package/src/errorHandling.ts +0 -120
- package/src/index.ts +0 -5
- package/src/scheduler.ts +0 -211
- package/src/warning.ts +0 -13
- package/tsconfig.json +0 -3
package/src/scheduler.ts
DELETED
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
import { ErrorCodes, callWithErrorHandling, handleError } from './errorHandling'
|
|
2
|
-
import { type Awaited, NOOP, isArray } from '@vue/shared'
|
|
3
|
-
|
|
4
|
-
export interface SchedulerJob extends Function {
|
|
5
|
-
id?: number
|
|
6
|
-
pre?: boolean
|
|
7
|
-
active?: boolean
|
|
8
|
-
computed?: boolean
|
|
9
|
-
/**
|
|
10
|
-
* Indicates whether the effect is allowed to recursively trigger itself
|
|
11
|
-
* when managed by the scheduler.
|
|
12
|
-
*
|
|
13
|
-
* By default, a job cannot trigger itself because some built-in method calls,
|
|
14
|
-
* e.g. Array.prototype.push actually performs reads as well (#1740) which
|
|
15
|
-
* can lead to confusing infinite loops.
|
|
16
|
-
* The allowed cases are component update functions and watch callbacks.
|
|
17
|
-
* Component update functions may update child component props, which in turn
|
|
18
|
-
* trigger flush: "pre" watch callbacks that mutates state that the parent
|
|
19
|
-
* relies on (#1801). Watch callbacks doesn't track its dependencies so if it
|
|
20
|
-
* triggers itself again, it's likely intentional and it is the user's
|
|
21
|
-
* responsibility to perform recursive state mutation that eventually
|
|
22
|
-
* stabilizes (#1727).
|
|
23
|
-
*/
|
|
24
|
-
allowRecurse?: boolean
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export type SchedulerJobs = SchedulerJob | SchedulerJob[]
|
|
28
|
-
|
|
29
|
-
let isFlushing = false
|
|
30
|
-
let isFlushPending = false
|
|
31
|
-
|
|
32
|
-
const queue: SchedulerJob[] = []
|
|
33
|
-
let flushIndex = 0
|
|
34
|
-
|
|
35
|
-
const resolvedPromise = /*#__PURE__*/ Promise.resolve() as Promise<any>
|
|
36
|
-
let currentFlushPromise: Promise<void> | null = null
|
|
37
|
-
|
|
38
|
-
const RECURSION_LIMIT = 100
|
|
39
|
-
type CountMap = Map<SchedulerJob, number>
|
|
40
|
-
|
|
41
|
-
export function nextTick<T = void, R = void>(
|
|
42
|
-
this: T,
|
|
43
|
-
fn?: (this: T) => R,
|
|
44
|
-
): Promise<Awaited<R>> {
|
|
45
|
-
const p = currentFlushPromise || resolvedPromise
|
|
46
|
-
return fn ? p.then(this ? fn.bind(this) : fn) : p
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
// #2768
|
|
50
|
-
// Use binary-search to find a suitable position in the queue,
|
|
51
|
-
// so that the queue maintains the increasing order of job's id,
|
|
52
|
-
// which can prevent the job from being skipped and also can avoid repeated patching.
|
|
53
|
-
function findInsertionIndex(id: number) {
|
|
54
|
-
// the start index should be `flushIndex + 1`
|
|
55
|
-
let start = flushIndex + 1
|
|
56
|
-
let end = queue.length
|
|
57
|
-
|
|
58
|
-
while (start < end) {
|
|
59
|
-
const middle = (start + end) >>> 1
|
|
60
|
-
const middleJob = queue[middle]
|
|
61
|
-
const middleJobId = getId(middleJob)
|
|
62
|
-
if (middleJobId < id || (middleJobId === id && middleJob.pre)) {
|
|
63
|
-
start = middle + 1
|
|
64
|
-
} else {
|
|
65
|
-
end = middle
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return start
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export function queueJob(job: SchedulerJob) {
|
|
73
|
-
// the dedupe search uses the startIndex argument of Array.includes()
|
|
74
|
-
// by default the search index includes the current job that is being run
|
|
75
|
-
// so it cannot recursively trigger itself again.
|
|
76
|
-
// if the job is a watch() callback, the search will start with a +1 index to
|
|
77
|
-
// allow it recursively trigger itself - it is the user's responsibility to
|
|
78
|
-
// ensure it doesn't end up in an infinite loop.
|
|
79
|
-
if (
|
|
80
|
-
!queue.length ||
|
|
81
|
-
!queue.includes(
|
|
82
|
-
job,
|
|
83
|
-
isFlushing && job.allowRecurse ? flushIndex + 1 : flushIndex,
|
|
84
|
-
)
|
|
85
|
-
) {
|
|
86
|
-
if (job.id == null) {
|
|
87
|
-
queue.push(job)
|
|
88
|
-
} else {
|
|
89
|
-
queue.splice(findInsertionIndex(job.id), 0, job)
|
|
90
|
-
}
|
|
91
|
-
queueFlush()
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function queueFlush() {
|
|
96
|
-
if (!isFlushing && !isFlushPending) {
|
|
97
|
-
isFlushPending = true
|
|
98
|
-
currentFlushPromise = resolvedPromise.then(flushJobs)
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export function invalidateJob(job: SchedulerJob) {
|
|
103
|
-
const i = queue.indexOf(job)
|
|
104
|
-
if (i > flushIndex) {
|
|
105
|
-
queue.splice(i, 1)
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export function flushPreFlushCbs(
|
|
110
|
-
seen?: CountMap,
|
|
111
|
-
// if currently flushing, skip the current job itself
|
|
112
|
-
i = isFlushing ? flushIndex + 1 : 0,
|
|
113
|
-
) {
|
|
114
|
-
if (__DEV__) {
|
|
115
|
-
seen = seen || new Map()
|
|
116
|
-
}
|
|
117
|
-
for (; i < queue.length; i++) {
|
|
118
|
-
const cb = queue[i]
|
|
119
|
-
if (cb && cb.pre) {
|
|
120
|
-
if (__DEV__ && checkRecursiveUpdates(seen!, cb)) {
|
|
121
|
-
continue
|
|
122
|
-
}
|
|
123
|
-
queue.splice(i, 1)
|
|
124
|
-
i--
|
|
125
|
-
cb()
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const getId = (job: SchedulerJob): number =>
|
|
131
|
-
job.id == null ? Infinity : job.id
|
|
132
|
-
|
|
133
|
-
const comparator = (a: SchedulerJob, b: SchedulerJob): number => {
|
|
134
|
-
const diff = getId(a) - getId(b)
|
|
135
|
-
if (diff === 0) {
|
|
136
|
-
if (a.pre && !b.pre) return -1
|
|
137
|
-
if (b.pre && !a.pre) return 1
|
|
138
|
-
}
|
|
139
|
-
return diff
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function flushJobs(seen?: CountMap) {
|
|
143
|
-
isFlushPending = false
|
|
144
|
-
isFlushing = true
|
|
145
|
-
if (__DEV__) {
|
|
146
|
-
seen = seen || new Map()
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Sort queue before flush.
|
|
150
|
-
// This ensures that:
|
|
151
|
-
// 1. Components are updated from parent to child. (because parent is always
|
|
152
|
-
// created before the child so its render effect will have smaller
|
|
153
|
-
// priority number)
|
|
154
|
-
// 2. If a component is unmounted during a parent component's update,
|
|
155
|
-
// its update can be skipped.
|
|
156
|
-
queue.sort(comparator)
|
|
157
|
-
|
|
158
|
-
// conditional usage of checkRecursiveUpdate must be determined out of
|
|
159
|
-
// try ... catch block since Rollup by default de-optimizes treeshaking
|
|
160
|
-
// inside try-catch. This can leave all warning code unshaked. Although
|
|
161
|
-
// they would get eventually shaken by a minifier like terser, some minifiers
|
|
162
|
-
// would fail to do that (e.g. https://github.com/evanw/esbuild/issues/1610)
|
|
163
|
-
const check = __DEV__
|
|
164
|
-
? (job: SchedulerJob) => checkRecursiveUpdates(seen!, job)
|
|
165
|
-
: NOOP
|
|
166
|
-
|
|
167
|
-
try {
|
|
168
|
-
for (flushIndex = 0; flushIndex < queue.length; flushIndex++) {
|
|
169
|
-
const job = queue[flushIndex]
|
|
170
|
-
if (job && job.active !== false) {
|
|
171
|
-
if (__DEV__ && check(job)) {
|
|
172
|
-
continue
|
|
173
|
-
}
|
|
174
|
-
callWithErrorHandling(job, null, ErrorCodes.SCHEDULER)
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
} finally {
|
|
178
|
-
flushIndex = 0
|
|
179
|
-
queue.length = 0
|
|
180
|
-
|
|
181
|
-
isFlushing = false
|
|
182
|
-
currentFlushPromise = null
|
|
183
|
-
// some postFlushCb queued jobs!
|
|
184
|
-
// keep flushing until it drains.
|
|
185
|
-
if (queue.length) {
|
|
186
|
-
flushJobs(seen)
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function checkRecursiveUpdates(seen: CountMap, fn: SchedulerJob) {
|
|
192
|
-
if (!seen.has(fn)) {
|
|
193
|
-
seen.set(fn, 1)
|
|
194
|
-
} else {
|
|
195
|
-
const count = seen.get(fn)!
|
|
196
|
-
if (count > RECURSION_LIMIT) {
|
|
197
|
-
handleError(
|
|
198
|
-
`Maximum recursive updates exceeded. ` +
|
|
199
|
-
`This means you have a reactive effect that is mutating its own ` +
|
|
200
|
-
`dependencies and thus recursively triggering itself. Possible sources ` +
|
|
201
|
-
`include component template, render function, updated hook or ` +
|
|
202
|
-
`watcher source function.`,
|
|
203
|
-
null,
|
|
204
|
-
ErrorCodes.APP_ERROR_HANDLER,
|
|
205
|
-
)
|
|
206
|
-
return true
|
|
207
|
-
} else {
|
|
208
|
-
seen.set(fn, count + 1)
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
}
|
package/src/warning.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { pauseTracking, resetTracking } from '@vue/reactivity'
|
|
2
|
-
|
|
3
|
-
export function warn(msg: string, ...args: any[]) {
|
|
4
|
-
// avoid props formatting or warn handler tracking deps that might be mutated
|
|
5
|
-
// during patch, leading to infinite recursion.
|
|
6
|
-
pauseTracking()
|
|
7
|
-
|
|
8
|
-
const warnArgs = [`[Vue warn]: ${msg}`, ...args]
|
|
9
|
-
/* istanbul ignore if */
|
|
10
|
-
console.warn(...warnArgs)
|
|
11
|
-
|
|
12
|
-
resetTracking()
|
|
13
|
-
}
|
package/tsconfig.json
DELETED