Skip to content

Commit

Permalink
Database once() should only fire once (#4864)
Browse files Browse the repository at this point in the history
  • Loading branch information
schmidt-sebastian authored May 11, 2021
1 parent 3cd42d4 commit 5b202f8
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 2 deletions.
5 changes: 5 additions & 0 deletions .changeset/many-turtles-try.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@firebase/database": patch
---

Fixed an issue that could cause `once()` to fire more than once if the value was modified inside its callback.
2 changes: 1 addition & 1 deletion packages/database/src/api/Reference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -326,7 +326,7 @@ export class Query implements Compat<ExpQuery> {
validateCallback('Query.once', 'callback', callback, true);

const ret = Query.getCancelAndContextArgs_(
'Query.on',
'Query.once',
failureCallbackOrContext,
context
);
Expand Down
2 changes: 1 addition & 1 deletion packages/database/src/exp/Reference_impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -959,8 +959,8 @@ function addEventListener(
if (options && options.onlyOnce) {
const userCallback = callback;
const onceCallback: UserCallback = (dataSnapshot, previousChildName) => {
userCallback(dataSnapshot, previousChildName);
repoRemoveEventCallbackForQuery(query._repo, query, container);
userCallback(dataSnapshot, previousChildName);
};
onceCallback.userCallback = callback.userCallback;
onceCallback.context = callback.context;
Expand Down
17 changes: 17 additions & 0 deletions packages/database/test/helpers/EventAccumulator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,23 @@ export const EventAccumulatorFactory = {
count++;
});
return ea;
},
waitsForExactCount: maxCount => {
let count = 0;
const condition = () => {
if (count > maxCount) {
throw new Error('Received more events than expected');
}
return count === maxCount;
};
const ea = new EventAccumulator(condition);
ea.onReset(() => {
count = 0;
});
ea.onEvent(() => {
count++;
});
return ea;
}
};

Expand Down
26 changes: 26 additions & 0 deletions packages/database/test/query.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2330,6 +2330,32 @@ describe('Query Tests', () => {
await ea.promise;
});

it('Query.once() only fires once', async () => {
const node = getRandomNode() as Reference;

let count = 1;
node.set(count);

const valueEvent = EventAccumulatorFactory.waitsForCount(3);
node.on('value', () => {
if (count < 3) {
++count;
node.set(count);
}
valueEvent.addEvent();
});

const onceEvent = EventAccumulatorFactory.waitsForExactCount(1);
node.once('value', () => {
++count;
node.set(count);
onceEvent.addEvent();
});

await valueEvent.promise;
await onceEvent.promise;
});

it('Ensure on() returns callback function.', () => {
const node = getRandomNode() as Reference;
const callback = function () {};
Expand Down

0 comments on commit 5b202f8

Please sign in to comment.