@@ -22,7 +22,7 @@ import {
22
22
} from './effect'
23
23
import { isReactive , isShallow } from './reactive'
24
24
import { type Ref , isRef } from './ref'
25
- import { getCurrentScope } from './effectScope '
25
+ import { type SchedulerJob , SchedulerJobFlags } from './scheduler '
26
26
27
27
// These errors were transferred from `packages/runtime-core/src/errorHandling.ts`
28
28
// along with baseWatch to maintain code compatibility. Hence,
@@ -33,32 +33,6 @@ export enum BaseWatchErrorCodes {
33
33
WATCH_CLEANUP ,
34
34
}
35
35
36
- // TODO move to a scheduler package
37
- export interface SchedulerJob extends Function {
38
- id ?: number
39
- // TODO refactor these boolean flags to a single bitwise flag
40
- pre ?: boolean
41
- active ?: boolean
42
- computed ?: boolean
43
- queued ?: boolean
44
- /**
45
- * Indicates whether the effect is allowed to recursively trigger itself
46
- * when managed by the scheduler.
47
- *
48
- * By default, a job cannot trigger itself because some built-in method calls,
49
- * e.g. Array.prototype.push actually performs reads as well (#1740) which
50
- * can lead to confusing infinite loops.
51
- * The allowed cases are component update functions and watch callbacks.
52
- * Component update functions may update child component props, which in turn
53
- * trigger flush: "pre" watch callbacks that mutates state that the parent
54
- * relies on (#1801). Watch callbacks doesn't track its dependencies so if it
55
- * triggers itself again, it's likely intentional and it is the user's
56
- * responsibility to perform recursive state mutation that eventually
57
- * stabilizes (#1727).
58
- */
59
- allowRecurse ?: boolean
60
- }
61
-
62
36
type WatchEffect = ( onCleanup : OnCleanup ) => void
63
37
type WatchSource < T = any > = Ref < T > | ComputedRef < T > | ( ( ) => T )
64
38
type WatchCallback < V = any , OV = any > = (
@@ -254,8 +228,11 @@ export function baseWatch(
254
228
let oldValue : any = isMultiSource
255
229
? new Array ( ( source as [ ] ) . length ) . fill ( INITIAL_WATCHER_VALUE )
256
230
: INITIAL_WATCHER_VALUE
257
- const job : SchedulerJob = ( ) => {
258
- if ( ! effect . active || ! effect . dirty ) {
231
+ const job : SchedulerJob = ( immediateFirstRun ?: boolean ) => {
232
+ if (
233
+ ! ( effect . flags & EffectFlags . ACTIVE ) ||
234
+ ( ! effect . dirty && ! immediateFirstRun )
235
+ ) {
259
236
return
260
237
}
261
238
if ( cb ) {
@@ -310,11 +287,10 @@ export function baseWatch(
310
287
311
288
// important: mark the job as a watcher callback so that scheduler knows
312
289
// it is allowed to self-trigger (#1727)
313
- job . allowRecurse = ! ! cb
314
-
315
- let effectScheduler : EffectScheduler = ( ) => scheduler ( job , effect , false )
290
+ if ( cb ) job . flags ! |= SchedulerJobFlags . ALLOW_RECURSE
316
291
317
- effect = new ReactiveEffect ( getter , NOOP , effectScheduler , scope )
292
+ effect = new ReactiveEffect ( getter )
293
+ effect . scheduler = ( ) => scheduler ( job , effect , false , ! ! cb )
318
294
319
295
cleanup = effect . onStop = ( ) => {
320
296
const cleanups = cleanupMap . get ( effect )
@@ -337,13 +313,14 @@ export function baseWatch(
337
313
338
314
// initial run
339
315
if ( cb ) {
316
+ scheduler ( job , effect , true , ! ! cb )
340
317
if ( immediate ) {
341
- job ( )
318
+ job ( true )
342
319
} else {
343
320
oldValue = effect . run ( )
344
321
}
345
322
} else {
346
- scheduler ( job , effect , true )
323
+ scheduler ( job , effect , true , ! ! cb )
347
324
}
348
325
349
326
return effect
0 commit comments