Pārlūkot izejas kodu

fix(reactivity): fix currentScope loss when running detached effect scope (#5575)

Wei 4 gadi atpakaļ
vecāks
revīzija
0a301d4dab

+ 15 - 1
packages/reactivity/__tests__/effectScope.spec.ts

@@ -6,7 +6,8 @@ import {
   onScopeDispose,
   onScopeDispose,
   computed,
   computed,
   ref,
   ref,
-  ComputedRef
+  ComputedRef,
+  getCurrentScope
 } from '../src'
 } from '../src'
 
 
 describe('reactivity/effect/scope', () => {
 describe('reactivity/effect/scope', () => {
@@ -263,4 +264,17 @@ describe('reactivity/effect/scope', () => {
     expect(watchSpy).toHaveBeenCalledTimes(1)
     expect(watchSpy).toHaveBeenCalledTimes(1)
     expect(watchEffectSpy).toHaveBeenCalledTimes(2)
     expect(watchEffectSpy).toHaveBeenCalledTimes(2)
   })
   })
+
+  it('getCurrentScope() stays valid when running a detached nested EffectScope', () => {
+    const parentScope = new EffectScope()
+
+    parentScope.run(() => {
+      const currentScope = getCurrentScope()
+      expect(currentScope).toBeDefined()
+      const detachedScope = new EffectScope(true)
+      detachedScope.run(() => {})
+
+      expect(getCurrentScope()).toBe(currentScope)
+    })
+  })
 })
 })

+ 8 - 1
packages/reactivity/src/effectScope.ts

@@ -8,7 +8,13 @@ export class EffectScope {
   effects: ReactiveEffect[] = []
   effects: ReactiveEffect[] = []
   cleanups: (() => void)[] = []
   cleanups: (() => void)[] = []
 
 
+  /**
+   * only assinged by undetached scope
+   */
   parent: EffectScope | undefined
   parent: EffectScope | undefined
+  /**
+   * record undetached scopes
+   */
   scopes: EffectScope[] | undefined
   scopes: EffectScope[] | undefined
   /**
   /**
    * track a child scope's index in its parent's scopes array for optimized
    * track a child scope's index in its parent's scopes array for optimized
@@ -28,11 +34,12 @@ export class EffectScope {
 
 
   run<T>(fn: () => T): T | undefined {
   run<T>(fn: () => T): T | undefined {
     if (this.active) {
     if (this.active) {
+      const currentEffectScope = activeEffectScope
       try {
       try {
         activeEffectScope = this
         activeEffectScope = this
         return fn()
         return fn()
       } finally {
       } finally {
-        activeEffectScope = this.parent
+        activeEffectScope = currentEffectScope
       }
       }
     } else if (__DEV__) {
     } else if (__DEV__) {
       warn(`cannot run an inactive effect scope.`)
       warn(`cannot run an inactive effect scope.`)