refactor(reactivity): use class for Link

This commit is contained in:
Evan You 2024-09-13 17:44:41 +08:00
parent 7fe6c795a1
commit 11eebcb4df
No known key found for this signature in database
GPG Key ID: 00E9AB7A6704CE0A
3 changed files with 47 additions and 49 deletions

View File

@ -3,14 +3,13 @@ import {
type DebuggerEvent,
type DebuggerOptions,
EffectFlags,
type Link,
type Subscriber,
activeSub,
refreshComputed,
} from './effect'
import type { Ref } from './ref'
import { warn } from './warning'
import { Dep, globalVersion } from './dep'
import { Dep, type Link, globalVersion } from './dep'
import { ReactiveFlags, TrackOpTypes } from './constants'
declare const ComputedRefSymbol: unique symbol

View File

@ -4,7 +4,7 @@ import { type TrackOpTypes, TriggerOpTypes } from './constants'
import {
type DebuggerEventExtraInfo,
EffectFlags,
type Link,
type Subscriber,
activeSub,
endBatch,
shouldTrack,
@ -18,6 +18,49 @@ import {
*/
export let globalVersion = 0
/**
* Represents a link between a source (Dep) and a subscriber (Effect or Computed).
* Deps and subs have a many-to-many relationship - each link between a
* dep and a sub is represented by a Link instance.
*
* A Link is also a node in two doubly-linked lists - one for the associated
* sub to track all its deps, and one for the associated dep to track all its
* subs.
*
* @internal
*/
export class Link {
/**
* - Before each effect run, all previous dep links' version are reset to -1
* - During the run, a link's version is synced with the source dep on access
* - After the run, links with version -1 (that were never used) are cleaned
* up
*/
version: number
/**
* Pointers for doubly-linked lists
*/
nextDep?: Link
prevDep?: Link
nextSub?: Link
prevSub?: Link
prevActiveLink?: Link
constructor(
public sub: Subscriber,
public dep: Dep,
) {
this.version = dep.version
this.nextDep =
this.prevDep =
this.nextSub =
this.prevSub =
this.prevActiveLink =
undefined
}
}
/**
* @internal
*/
@ -52,16 +95,7 @@ export class Dep {
let link = this.activeLink
if (link === undefined || link.sub !== activeSub) {
link = this.activeLink = {
dep: this,
sub: activeSub,
version: this.version,
nextDep: undefined,
prevDep: undefined,
nextSub: undefined,
prevSub: undefined,
prevActiveLink: undefined,
}
link = this.activeLink = new Link(activeSub, this)
// add the link to the activeEffect as a dep (as tail)
if (!activeSub.deps) {

View File

@ -1,7 +1,7 @@
import { extend, hasChanged } from '@vue/shared'
import type { ComputedRefImpl } from './computed'
import type { TrackOpTypes, TriggerOpTypes } from './constants'
import { type Dep, globalVersion } from './dep'
import { type Link, globalVersion } from './dep'
import { activeEffectScope } from './effectScope'
import { warn } from './warning'
@ -72,41 +72,6 @@ export interface Subscriber extends DebuggerOptions {
notify(): void
}
/**
* Represents a link between a source (Dep) and a subscriber (Effect or Computed).
* Deps and subs have a many-to-many relationship - each link between a
* dep and a sub is represented by a Link instance.
*
* A Link is also a node in two doubly-linked lists - one for the associated
* sub to track all its deps, and one for the associated dep to track all its
* subs.
*
* @internal
*/
export interface Link {
dep: Dep
sub: Subscriber
/**
* - Before each effect run, all previous dep links' version are reset to -1
* - During the run, a link's version is synced with the source dep on access
* - After the run, links with version -1 (that were never used) are cleaned
* up
*/
version: number
/**
* Pointers for doubly-linked lists
*/
nextDep?: Link
prevDep?: Link
nextSub?: Link
prevSub?: Link
prevActiveLink?: Link
}
const pausedQueueEffects = new WeakSet<ReactiveEffect>()
export class ReactiveEffect<T = any>