diff --git a/services/web/frontend/js/features/ide-react/scope-value-store/react-scope-value-store.ts b/services/web/frontend/js/features/ide-react/scope-value-store/react-scope-value-store.ts index 3673af4721..4020119a56 100644 --- a/services/web/frontend/js/features/ide-react/scope-value-store/react-scope-value-store.ts +++ b/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(path, item.value, [watcher]) + // add this watcher to any existing watchers scheduled for this path + const { watchers } = this.watcherUpdates.get(path) ?? { watchers: [] } + this.scheduleWatcherUpdate(path, item.value, [...watchers, watcher]) } return () => { diff --git a/services/web/test/frontend/features/ide-react/unit/react-scope-value-store.test.ts b/services/web/test/frontend/features/ide-react/unit/react-scope-value-store.test.ts index 4b3be365ae..7f867ca850 100644 --- a/services/web/test/frontend/features/ide-react/unit/react-scope-value-store.test.ts +++ b/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