Selaa lähdekoodia

[ide-react] Preserve scope value update watchers on watcher add (#16729)

GitOrigin-RevId: 1168577364fef6e13a58d7d96afdf4ba685fc342
Alf Eaton 2 vuotta sitten
vanhempi
sitoutus
bb0da73a36

+ 3 - 1
services/web/frontend/js/features/ide-react/scope-value-store/react-scope-value-store.ts

@@ -273,7 +273,9 @@ export class ReactScopeValueStore implements ScopeValueStore {
     // useScopeValue, during which the value could change without being
     // observed
     if ('value' in item) {
-      this.scheduleWatcherUpdate<T>(path, item.value, [watcher])
+      // add this watcher to any existing watchers scheduled for this path
+      const { watchers } = this.watcherUpdates.get(path) ?? { watchers: [] }
+      this.scheduleWatcherUpdate<T>(path, item.value, [...watchers, watcher])
     }
 
     return () => {

+ 29 - 0
services/web/test/frontend/features/ide-react/unit/react-scope-value-store.test.ts

@@ -122,6 +122,35 @@ describe('ReactScopeValueStore', function () {
     expect(watcher).to.have.been.calledWith('wombat')
   })
 
+  it('handles multiple watchers for the same path added at the same time before the value is set', async function () {
+    const store = new ReactScopeValueStore()
+
+    const watcherOne = sinon.stub()
+    const watcherTwo = sinon.stub()
+    store.watch('test', watcherOne)
+    store.watch('test', watcherTwo)
+    await waitForWatchers(() => {
+      store.set('test', 'wombat')
+    })
+
+    expect(watcherOne).to.have.been.calledWith('wombat')
+    expect(watcherTwo).to.have.been.calledWith('wombat')
+  })
+
+  it('handles multiple watchers for the same path added at the same time after the value is set', async function () {
+    const store = new ReactScopeValueStore()
+    store.set('test', 'wombat')
+
+    const watcherOne = sinon.stub()
+    const watcherTwo = sinon.stub()
+    store.watch('test', watcherOne)
+    store.watch('test', watcherTwo)
+    store.flushUpdates()
+
+    expect(watcherOne).to.have.been.calledWith('wombat')
+    expect(watcherTwo).to.have.been.calledWith('wombat')
+  })
+
   it('throws an error when watching an unknown value', function () {
     const store = new ReactScopeValueStore()
     expect(() => store.watch('test', () => {})).to.throw