@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/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reactive-vscode/reactivity",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.2.0-beta.
|
|
4
|
+
"version": "0.2.0-beta.2",
|
|
5
5
|
"description": "Full Vue Reactivity API without DOM",
|
|
6
6
|
"author": "_Kerman <kermanx@qq.com>",
|
|
7
7
|
"license": "MIT",
|
|
@@ -18,25 +18,25 @@
|
|
|
18
18
|
"sideEffects": false,
|
|
19
19
|
"exports": {
|
|
20
20
|
".": {
|
|
21
|
-
"types": "./
|
|
22
|
-
"import": "./
|
|
21
|
+
"types": "./dist/index.d.ts",
|
|
22
|
+
"import": "./dist/index.js"
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
|
-
"main": "./
|
|
26
|
-
"types": "./
|
|
25
|
+
"main": "./dist/index.js",
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
27
|
"files": [
|
|
28
28
|
"README.md",
|
|
29
|
-
"
|
|
30
|
-
"src",
|
|
31
|
-
"tsconfig.json"
|
|
29
|
+
"dist"
|
|
32
30
|
],
|
|
33
|
-
"dependencies": {},
|
|
34
31
|
"devDependencies": {
|
|
35
32
|
"@vue/reactivity": "^3.4.27",
|
|
36
33
|
"@vue/shared": "^3.4.27",
|
|
37
|
-
"typescript": "^5.4.5"
|
|
34
|
+
"typescript": "^5.4.5",
|
|
35
|
+
"vite": "^5.2.12",
|
|
36
|
+
"vite-plugin-dts": "^3.9.1"
|
|
38
37
|
},
|
|
39
38
|
"scripts": {
|
|
40
|
-
"typecheck": "tsc --noEmit"
|
|
39
|
+
"typecheck": "tsc --noEmit",
|
|
40
|
+
"build": "vite build"
|
|
41
41
|
}
|
|
42
42
|
}
|
package/shim.d.ts
DELETED
package/src/apiWatch.ts
DELETED
|
@@ -1,415 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
type ComputedRef,
|
|
3
|
-
type DebuggerOptions,
|
|
4
|
-
type EffectScheduler,
|
|
5
|
-
ReactiveEffect,
|
|
6
|
-
ReactiveFlags,
|
|
7
|
-
type Ref,
|
|
8
|
-
getCurrentScope,
|
|
9
|
-
isReactive,
|
|
10
|
-
isRef,
|
|
11
|
-
isShallow,
|
|
12
|
-
} from '@vue/reactivity'
|
|
13
|
-
import { type SchedulerJob, queueJob } from './scheduler'
|
|
14
|
-
import {
|
|
15
|
-
EMPTY_OBJ,
|
|
16
|
-
NOOP,
|
|
17
|
-
extend,
|
|
18
|
-
hasChanged,
|
|
19
|
-
isArray,
|
|
20
|
-
isFunction,
|
|
21
|
-
isMap,
|
|
22
|
-
isObject,
|
|
23
|
-
isPlainObject,
|
|
24
|
-
isSet,
|
|
25
|
-
remove,
|
|
26
|
-
} from '@vue/shared'
|
|
27
|
-
import {
|
|
28
|
-
ErrorCodes,
|
|
29
|
-
callWithAsyncErrorHandling,
|
|
30
|
-
callWithErrorHandling,
|
|
31
|
-
} from './errorHandling'
|
|
32
|
-
import { warn } from './warning'
|
|
33
|
-
|
|
34
|
-
export type WatchEffect = (onCleanup: OnCleanup) => void
|
|
35
|
-
|
|
36
|
-
export type WatchSource<T = any> = Ref<T> | ComputedRef<T> | (() => T)
|
|
37
|
-
|
|
38
|
-
export type WatchCallback<V = any, OV = any> = (
|
|
39
|
-
value: V,
|
|
40
|
-
oldValue: OV,
|
|
41
|
-
onCleanup: OnCleanup,
|
|
42
|
-
) => any
|
|
43
|
-
|
|
44
|
-
type MapSources<T, Immediate> = {
|
|
45
|
-
[K in keyof T]: T[K] extends WatchSource<infer V>
|
|
46
|
-
? Immediate extends true
|
|
47
|
-
? V | undefined
|
|
48
|
-
: V
|
|
49
|
-
: T[K] extends object
|
|
50
|
-
? Immediate extends true
|
|
51
|
-
? T[K] | undefined
|
|
52
|
-
: T[K]
|
|
53
|
-
: never
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export type OnCleanup = (cleanupFn: () => void) => void
|
|
57
|
-
|
|
58
|
-
export interface WatchOptionsBase extends DebuggerOptions {
|
|
59
|
-
flush?: 'pre' | 'post' | 'sync'
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export interface WatchOptions<Immediate = boolean> extends WatchOptionsBase {
|
|
63
|
-
immediate?: Immediate
|
|
64
|
-
deep?: boolean
|
|
65
|
-
once?: boolean
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export type WatchStopHandle = () => void
|
|
69
|
-
|
|
70
|
-
// Simple effect.
|
|
71
|
-
export function watchEffect(
|
|
72
|
-
effect: WatchEffect,
|
|
73
|
-
options?: WatchOptionsBase,
|
|
74
|
-
): WatchStopHandle {
|
|
75
|
-
return doWatch(effect, null, options)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export function watchPostEffect(
|
|
79
|
-
effect: WatchEffect,
|
|
80
|
-
options?: DebuggerOptions,
|
|
81
|
-
) {
|
|
82
|
-
return doWatch(
|
|
83
|
-
effect,
|
|
84
|
-
null,
|
|
85
|
-
__DEV__ ? extend({}, options as any, { flush: 'post' }) : { flush: 'post' },
|
|
86
|
-
)
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
export function watchSyncEffect(
|
|
90
|
-
effect: WatchEffect,
|
|
91
|
-
options?: DebuggerOptions,
|
|
92
|
-
) {
|
|
93
|
-
return doWatch(
|
|
94
|
-
effect,
|
|
95
|
-
null,
|
|
96
|
-
__DEV__ ? extend({}, options as any, { flush: 'sync' }) : { flush: 'sync' },
|
|
97
|
-
)
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// initial value for watchers to trigger on undefined initial values
|
|
101
|
-
const INITIAL_WATCHER_VALUE = {}
|
|
102
|
-
|
|
103
|
-
type MultiWatchSources = (WatchSource<unknown> | object)[]
|
|
104
|
-
|
|
105
|
-
// overload: single source + cb
|
|
106
|
-
export function watch<T, Immediate extends Readonly<boolean> = false>(
|
|
107
|
-
source: WatchSource<T>,
|
|
108
|
-
cb: WatchCallback<T, Immediate extends true ? T | undefined : T>,
|
|
109
|
-
options?: WatchOptions<Immediate>,
|
|
110
|
-
): WatchStopHandle
|
|
111
|
-
|
|
112
|
-
// overload: array of multiple sources + cb
|
|
113
|
-
export function watch<
|
|
114
|
-
T extends MultiWatchSources,
|
|
115
|
-
Immediate extends Readonly<boolean> = false,
|
|
116
|
-
>(
|
|
117
|
-
sources: [...T],
|
|
118
|
-
cb: WatchCallback<MapSources<T, false>, MapSources<T, Immediate>>,
|
|
119
|
-
options?: WatchOptions<Immediate>,
|
|
120
|
-
): WatchStopHandle
|
|
121
|
-
|
|
122
|
-
// overload: multiple sources w/ `as const`
|
|
123
|
-
// watch([foo, bar] as const, () => {})
|
|
124
|
-
// somehow [...T] breaks when the type is readonly
|
|
125
|
-
export function watch<
|
|
126
|
-
T extends Readonly<MultiWatchSources>,
|
|
127
|
-
Immediate extends Readonly<boolean> = false,
|
|
128
|
-
>(
|
|
129
|
-
source: T,
|
|
130
|
-
cb: WatchCallback<MapSources<T, false>, MapSources<T, Immediate>>,
|
|
131
|
-
options?: WatchOptions<Immediate>,
|
|
132
|
-
): WatchStopHandle
|
|
133
|
-
|
|
134
|
-
// overload: watching reactive object w/ cb
|
|
135
|
-
export function watch<
|
|
136
|
-
T extends object,
|
|
137
|
-
Immediate extends Readonly<boolean> = false,
|
|
138
|
-
>(
|
|
139
|
-
source: T,
|
|
140
|
-
cb: WatchCallback<T, Immediate extends true ? T | undefined : T>,
|
|
141
|
-
options?: WatchOptions<Immediate>,
|
|
142
|
-
): WatchStopHandle
|
|
143
|
-
|
|
144
|
-
// implementation
|
|
145
|
-
export function watch<T = any, Immediate extends Readonly<boolean> = false>(
|
|
146
|
-
source: T | WatchSource<T>,
|
|
147
|
-
cb: any,
|
|
148
|
-
options?: WatchOptions<Immediate>,
|
|
149
|
-
): WatchStopHandle {
|
|
150
|
-
if (__DEV__ && !isFunction(cb)) {
|
|
151
|
-
warn(
|
|
152
|
-
`\`watch(fn, options?)\` signature has been moved to a separate API. ` +
|
|
153
|
-
`Use \`watchEffect(fn, options?)\` instead. \`watch\` now only ` +
|
|
154
|
-
`supports \`watch(source, cb, options?) signature.`,
|
|
155
|
-
)
|
|
156
|
-
}
|
|
157
|
-
return doWatch(source as any, cb, options)
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function doWatch(
|
|
161
|
-
source: WatchSource | WatchSource[] | WatchEffect | object,
|
|
162
|
-
cb: WatchCallback | null,
|
|
163
|
-
{
|
|
164
|
-
immediate,
|
|
165
|
-
deep,
|
|
166
|
-
flush,
|
|
167
|
-
once,
|
|
168
|
-
onTrack,
|
|
169
|
-
onTrigger,
|
|
170
|
-
}: WatchOptions = EMPTY_OBJ,
|
|
171
|
-
): WatchStopHandle {
|
|
172
|
-
if (cb && once) {
|
|
173
|
-
const _cb = cb
|
|
174
|
-
cb = (...args) => {
|
|
175
|
-
_cb(...args)
|
|
176
|
-
unwatch()
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// TODO remove in 3.5
|
|
181
|
-
if (__DEV__ && deep !== void 0 && typeof deep === 'number') {
|
|
182
|
-
warn(
|
|
183
|
-
`watch() "deep" option with number value will be used as watch depth in future versions. ` +
|
|
184
|
-
`Please use a boolean instead to avoid potential breakage.`,
|
|
185
|
-
)
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
if (__DEV__ && !cb) {
|
|
189
|
-
if (immediate !== undefined) {
|
|
190
|
-
warn(
|
|
191
|
-
`watch() "immediate" option is only respected when using the ` +
|
|
192
|
-
`watch(source, callback, options?) signature.`,
|
|
193
|
-
)
|
|
194
|
-
}
|
|
195
|
-
if (deep !== undefined) {
|
|
196
|
-
warn(
|
|
197
|
-
`watch() "deep" option is only respected when using the ` +
|
|
198
|
-
`watch(source, callback, options?) signature.`,
|
|
199
|
-
)
|
|
200
|
-
}
|
|
201
|
-
if (once !== undefined) {
|
|
202
|
-
warn(
|
|
203
|
-
`watch() "once" option is only respected when using the ` +
|
|
204
|
-
`watch(source, callback, options?) signature.`,
|
|
205
|
-
)
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
const warnInvalidSource = (s: unknown) => {
|
|
210
|
-
warn(
|
|
211
|
-
`Invalid watch source: `,
|
|
212
|
-
s,
|
|
213
|
-
`A watch source can only be a getter/effect function, a ref, ` +
|
|
214
|
-
`a reactive object, or an array of these types.`,
|
|
215
|
-
)
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
const instance = null
|
|
219
|
-
const reactiveGetter = (source: object) =>
|
|
220
|
-
deep === true
|
|
221
|
-
? source // traverse will happen in wrapped getter below
|
|
222
|
-
: // for deep: false, only traverse root-level properties
|
|
223
|
-
traverse(source, deep === false ? 1 : undefined)
|
|
224
|
-
|
|
225
|
-
let getter: () => any
|
|
226
|
-
let forceTrigger = false
|
|
227
|
-
let isMultiSource = false
|
|
228
|
-
|
|
229
|
-
if (isRef(source)) {
|
|
230
|
-
getter = () => source.value
|
|
231
|
-
forceTrigger = isShallow(source)
|
|
232
|
-
} else if (isReactive(source)) {
|
|
233
|
-
getter = () => reactiveGetter(source)
|
|
234
|
-
forceTrigger = true
|
|
235
|
-
} else if (isArray(source)) {
|
|
236
|
-
isMultiSource = true
|
|
237
|
-
forceTrigger = source.some(s => isReactive(s) || isShallow(s))
|
|
238
|
-
getter = () =>
|
|
239
|
-
source.map(s => {
|
|
240
|
-
if (isRef(s)) {
|
|
241
|
-
return s.value
|
|
242
|
-
} else if (isReactive(s)) {
|
|
243
|
-
return reactiveGetter(s)
|
|
244
|
-
} else if (isFunction(s)) {
|
|
245
|
-
return callWithErrorHandling(s, instance, ErrorCodes.WATCH_GETTER)
|
|
246
|
-
} else {
|
|
247
|
-
__DEV__ && warnInvalidSource(s)
|
|
248
|
-
}
|
|
249
|
-
})
|
|
250
|
-
} else if (isFunction(source)) {
|
|
251
|
-
if (cb) {
|
|
252
|
-
// getter with cb
|
|
253
|
-
getter = () =>
|
|
254
|
-
callWithErrorHandling(source, instance, ErrorCodes.WATCH_GETTER)
|
|
255
|
-
} else {
|
|
256
|
-
// no cb -> simple effect
|
|
257
|
-
getter = () => {
|
|
258
|
-
if (cleanup) {
|
|
259
|
-
cleanup()
|
|
260
|
-
}
|
|
261
|
-
return callWithAsyncErrorHandling(
|
|
262
|
-
source,
|
|
263
|
-
instance,
|
|
264
|
-
ErrorCodes.WATCH_CALLBACK,
|
|
265
|
-
[onCleanup],
|
|
266
|
-
)
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
} else {
|
|
270
|
-
getter = NOOP
|
|
271
|
-
__DEV__ && warnInvalidSource(source)
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
if (cb && deep) {
|
|
275
|
-
const baseGetter = getter
|
|
276
|
-
getter = () => traverse(baseGetter())
|
|
277
|
-
}
|
|
278
|
-
|
|
279
|
-
let cleanup: (() => void) | undefined
|
|
280
|
-
let onCleanup: OnCleanup = (fn: () => void) => {
|
|
281
|
-
cleanup = effect.onStop = () => {
|
|
282
|
-
callWithErrorHandling(fn, instance, ErrorCodes.WATCH_CLEANUP)
|
|
283
|
-
cleanup = effect.onStop = undefined
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
let oldValue: any = isMultiSource
|
|
288
|
-
? new Array((source as []).length).fill(INITIAL_WATCHER_VALUE)
|
|
289
|
-
: INITIAL_WATCHER_VALUE
|
|
290
|
-
const job: SchedulerJob = () => {
|
|
291
|
-
if (!effect.active || !effect.dirty) {
|
|
292
|
-
return
|
|
293
|
-
}
|
|
294
|
-
if (cb) {
|
|
295
|
-
// watch(source, cb)
|
|
296
|
-
const newValue = effect.run()
|
|
297
|
-
if (
|
|
298
|
-
deep ||
|
|
299
|
-
forceTrigger ||
|
|
300
|
-
(isMultiSource
|
|
301
|
-
? (newValue as any[]).some((v, i) => hasChanged(v, oldValue[i]))
|
|
302
|
-
: hasChanged(newValue, oldValue))
|
|
303
|
-
) {
|
|
304
|
-
// cleanup before running cb again
|
|
305
|
-
if (cleanup) {
|
|
306
|
-
cleanup()
|
|
307
|
-
}
|
|
308
|
-
callWithAsyncErrorHandling(cb, instance, ErrorCodes.WATCH_CALLBACK, [
|
|
309
|
-
newValue,
|
|
310
|
-
// pass undefined as the old value when it's changed for the first time
|
|
311
|
-
oldValue === INITIAL_WATCHER_VALUE
|
|
312
|
-
? undefined
|
|
313
|
-
: isMultiSource && oldValue[0] === INITIAL_WATCHER_VALUE
|
|
314
|
-
? []
|
|
315
|
-
: oldValue,
|
|
316
|
-
onCleanup,
|
|
317
|
-
])
|
|
318
|
-
oldValue = newValue
|
|
319
|
-
}
|
|
320
|
-
} else {
|
|
321
|
-
// watchEffect
|
|
322
|
-
effect.run()
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
// important: mark the job as a watcher callback so that scheduler knows
|
|
327
|
-
// it is allowed to self-trigger (#1727)
|
|
328
|
-
job.allowRecurse = !!cb
|
|
329
|
-
|
|
330
|
-
let scheduler: EffectScheduler
|
|
331
|
-
if (flush === 'sync') {
|
|
332
|
-
scheduler = job as any // the scheduler function gets called directly
|
|
333
|
-
} else {
|
|
334
|
-
// default: 'pre'
|
|
335
|
-
job.pre = true
|
|
336
|
-
scheduler = () => queueJob(job)
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
const effect = new ReactiveEffect(getter, NOOP, scheduler)
|
|
340
|
-
|
|
341
|
-
const scope = getCurrentScope()
|
|
342
|
-
const unwatch = () => {
|
|
343
|
-
effect.stop()
|
|
344
|
-
if (scope) {
|
|
345
|
-
// @ts-ignore for internal use
|
|
346
|
-
remove(scope.effects, effect)
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
if (__DEV__) {
|
|
351
|
-
effect.onTrack = onTrack
|
|
352
|
-
effect.onTrigger = onTrigger
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
// initial run
|
|
356
|
-
if (cb) {
|
|
357
|
-
if (immediate) {
|
|
358
|
-
job()
|
|
359
|
-
} else {
|
|
360
|
-
oldValue = effect.run()
|
|
361
|
-
}
|
|
362
|
-
} else {
|
|
363
|
-
effect.run()
|
|
364
|
-
}
|
|
365
|
-
return unwatch
|
|
366
|
-
}
|
|
367
|
-
|
|
368
|
-
export function createPathGetter(ctx: any, path: string) {
|
|
369
|
-
const segments = path.split('.')
|
|
370
|
-
return () => {
|
|
371
|
-
let cur = ctx
|
|
372
|
-
for (let i = 0; i < segments.length && cur; i++) {
|
|
373
|
-
cur = cur[segments[i]]
|
|
374
|
-
}
|
|
375
|
-
return cur
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
export function traverse(
|
|
380
|
-
value: unknown,
|
|
381
|
-
depth = Infinity,
|
|
382
|
-
seen?: Set<unknown>,
|
|
383
|
-
) {
|
|
384
|
-
if (depth <= 0 || !isObject(value) || (value as any)[ReactiveFlags.SKIP]) {
|
|
385
|
-
return value
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
seen = seen || new Set()
|
|
389
|
-
if (seen.has(value)) {
|
|
390
|
-
return value
|
|
391
|
-
}
|
|
392
|
-
seen.add(value)
|
|
393
|
-
depth--
|
|
394
|
-
if (isRef(value)) {
|
|
395
|
-
traverse(value.value, depth, seen)
|
|
396
|
-
} else if (isArray(value)) {
|
|
397
|
-
for (let i = 0; i < value.length; i++) {
|
|
398
|
-
traverse(value[i], depth, seen)
|
|
399
|
-
}
|
|
400
|
-
} else if (isSet(value) || isMap(value)) {
|
|
401
|
-
value.forEach((v: any) => {
|
|
402
|
-
traverse(v, depth, seen)
|
|
403
|
-
})
|
|
404
|
-
} else if (isPlainObject(value)) {
|
|
405
|
-
for (const key in value) {
|
|
406
|
-
traverse(value[key], depth, seen)
|
|
407
|
-
}
|
|
408
|
-
for (const key of Object.getOwnPropertySymbols(value)) {
|
|
409
|
-
if (Object.prototype.propertyIsEnumerable.call(value, key)) {
|
|
410
|
-
traverse(value[key as any], depth, seen)
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
}
|
|
414
|
-
return value
|
|
415
|
-
}
|
package/src/enums.ts
DELETED
package/src/errorHandling.ts
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import { warn } from './warning'
|
|
2
|
-
import { isArray, isFunction, isPromise } from '@vue/shared'
|
|
3
|
-
import { LifecycleHooks } from './enums'
|
|
4
|
-
|
|
5
|
-
// contexts where user provided function may be executed, in addition to
|
|
6
|
-
// lifecycle hooks.
|
|
7
|
-
export enum ErrorCodes {
|
|
8
|
-
SETUP_FUNCTION,
|
|
9
|
-
RENDER_FUNCTION,
|
|
10
|
-
WATCH_GETTER,
|
|
11
|
-
WATCH_CALLBACK,
|
|
12
|
-
WATCH_CLEANUP,
|
|
13
|
-
NATIVE_EVENT_HANDLER,
|
|
14
|
-
COMPONENT_EVENT_HANDLER,
|
|
15
|
-
VNODE_HOOK,
|
|
16
|
-
DIRECTIVE_HOOK,
|
|
17
|
-
TRANSITION_HOOK,
|
|
18
|
-
APP_ERROR_HANDLER,
|
|
19
|
-
APP_WARN_HANDLER,
|
|
20
|
-
FUNCTION_REF,
|
|
21
|
-
ASYNC_COMPONENT_LOADER,
|
|
22
|
-
SCHEDULER,
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export const ErrorTypeStrings: Record<LifecycleHooks | ErrorCodes, string> = {
|
|
26
|
-
[LifecycleHooks.ACTIVATED]: 'activated hook',
|
|
27
|
-
[LifecycleHooks.DEACTIVATED]: 'deactivated hook',
|
|
28
|
-
[ErrorCodes.SETUP_FUNCTION]: 'setup function',
|
|
29
|
-
[ErrorCodes.RENDER_FUNCTION]: 'render function',
|
|
30
|
-
[ErrorCodes.WATCH_GETTER]: 'watcher getter',
|
|
31
|
-
[ErrorCodes.WATCH_CALLBACK]: 'watcher callback',
|
|
32
|
-
[ErrorCodes.WATCH_CLEANUP]: 'watcher cleanup function',
|
|
33
|
-
[ErrorCodes.NATIVE_EVENT_HANDLER]: 'native event handler',
|
|
34
|
-
[ErrorCodes.COMPONENT_EVENT_HANDLER]: 'component event handler',
|
|
35
|
-
[ErrorCodes.VNODE_HOOK]: 'vnode hook',
|
|
36
|
-
[ErrorCodes.DIRECTIVE_HOOK]: 'directive hook',
|
|
37
|
-
[ErrorCodes.TRANSITION_HOOK]: 'transition hook',
|
|
38
|
-
[ErrorCodes.APP_ERROR_HANDLER]: 'app errorHandler',
|
|
39
|
-
[ErrorCodes.APP_WARN_HANDLER]: 'app warnHandler',
|
|
40
|
-
[ErrorCodes.FUNCTION_REF]: 'ref function',
|
|
41
|
-
[ErrorCodes.ASYNC_COMPONENT_LOADER]: 'async component loader',
|
|
42
|
-
[ErrorCodes.SCHEDULER]:
|
|
43
|
-
'scheduler flush. This is likely a Vue internals bug. ' +
|
|
44
|
-
'Please open an issue at https://github.com/vuejs/core .',
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export type ErrorTypes = LifecycleHooks | ErrorCodes
|
|
48
|
-
|
|
49
|
-
export function callWithErrorHandling(
|
|
50
|
-
fn: Function,
|
|
51
|
-
instance: null,
|
|
52
|
-
type: ErrorTypes,
|
|
53
|
-
args?: unknown[],
|
|
54
|
-
) {
|
|
55
|
-
try {
|
|
56
|
-
return args ? fn(...args) : fn()
|
|
57
|
-
} catch (err) {
|
|
58
|
-
handleError(err, instance, type)
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
export function callWithAsyncErrorHandling(
|
|
63
|
-
fn: Function | Function[],
|
|
64
|
-
instance: null,
|
|
65
|
-
type: ErrorTypes,
|
|
66
|
-
args?: unknown[],
|
|
67
|
-
): any {
|
|
68
|
-
if (isFunction(fn)) {
|
|
69
|
-
const res = callWithErrorHandling(fn, instance, type, args)
|
|
70
|
-
if (res && isPromise(res)) {
|
|
71
|
-
res.catch(err => {
|
|
72
|
-
handleError(err, instance, type)
|
|
73
|
-
})
|
|
74
|
-
}
|
|
75
|
-
return res
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (isArray(fn)) {
|
|
79
|
-
const values = []
|
|
80
|
-
for (let i = 0; i < fn.length; i++) {
|
|
81
|
-
values.push(callWithAsyncErrorHandling(fn[i], instance, type, args))
|
|
82
|
-
}
|
|
83
|
-
return values
|
|
84
|
-
} else if (__DEV__) {
|
|
85
|
-
warn(
|
|
86
|
-
`Invalid value type passed to callWithAsyncErrorHandling(): ${typeof fn}`,
|
|
87
|
-
)
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export function handleError(
|
|
92
|
-
err: unknown,
|
|
93
|
-
instance: null,
|
|
94
|
-
type: ErrorTypes,
|
|
95
|
-
throwInDev = true,
|
|
96
|
-
) {
|
|
97
|
-
const contextVNode = null
|
|
98
|
-
logError(err, type, contextVNode, throwInDev)
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
function logError(
|
|
102
|
-
err: unknown,
|
|
103
|
-
type: ErrorTypes,
|
|
104
|
-
contextVNode: null,
|
|
105
|
-
throwInDev = true,
|
|
106
|
-
) {
|
|
107
|
-
if (__DEV__) {
|
|
108
|
-
const info = ErrorTypeStrings[type]
|
|
109
|
-
warn(`Unhandled error${info ? ` during execution of ${info}` : ``}`)
|
|
110
|
-
// crash in dev by default so it's more noticeable
|
|
111
|
-
if (throwInDev) {
|
|
112
|
-
throw err
|
|
113
|
-
} else {
|
|
114
|
-
console.error(err)
|
|
115
|
-
}
|
|
116
|
-
} else {
|
|
117
|
-
// recover in prod to reduce the impact on end-user
|
|
118
|
-
console.error(err)
|
|
119
|
-
}
|
|
120
|
-
}
|
package/src/index.ts
DELETED