Skip to content

Commit 8dc6e83

Browse files
committed
[firestore] Fix FirestoreQuery/FirestoreQueryModifiers incorrectly mutating previous query instances when chaining (fixes invertase#2691)
1 parent 147ee63 commit 8dc6e83

File tree

3 files changed

+53
-8
lines changed

3 files changed

+53
-8
lines changed
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright (c) 2016-present Invertase Limited & Contributors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this library except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
describe('FirestoreQuery/FirestoreQueryModifiers', () => {
18+
it('should not mutate previous queries (#2691)', async () => {
19+
const queryBefore = firebase
20+
.firestore()
21+
.collection('users')
22+
.where('age', '>', 30);
23+
const queryAfter = queryBefore.orderBy('age');
24+
queryBefore._modifiers._orders.length.should.equal(0);
25+
queryBefore._modifiers._filters.length.should.equal(1);
26+
27+
queryAfter._modifiers._orders.length.should.equal(1);
28+
queryAfter._modifiers._filters.length.should.equal(1);
29+
});
30+
});

packages/firestore/lib/FirestoreQuery.js

+10-8
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ export default class FirestoreQuery {
3636
}
3737

3838
_handleQueryCursor(cursor, docOrField, fields) {
39+
const modifiers = this._modifiers._copy();
40+
3941
if (isUndefined(docOrField)) {
4042
throw new Error(
4143
`firebase.firestore().collection().${cursor}(*) Expected a DocumentSnapshot or list of field values but got undefined.`,
@@ -58,7 +60,7 @@ export default class FirestoreQuery {
5860
);
5961
}
6062

61-
const currentOrders = this._modifiers.orders;
63+
const currentOrders = modifiers.orders;
6264

6365
const values = [];
6466

@@ -77,14 +79,14 @@ export default class FirestoreQuery {
7779
values.push(value);
7880
}
7981

80-
this._modifiers._orders.push({
82+
modifiers._orders.push({
8183
fieldPath: '__name__',
8284
direction: 'ASCENDING',
8385
});
8486

8587
values.push(documentSnapshot.id);
8688

87-
return this._modifiers.setFieldsCursor(cursor, values);
89+
return modifiers.setFieldsCursor(cursor, values);
8890
}
8991

9092
/**
@@ -93,13 +95,13 @@ export default class FirestoreQuery {
9395

9496
const allFields = [docOrField].concat(fields);
9597

96-
if (allFields.length > this._modifiers.orders.length) {
98+
if (allFields.length > modifiers.orders.length) {
9799
throw new Error(
98100
`firebase.firestore().collection().${cursor}(*) Too many arguments provided. The number of arguments must be less than or equal to the number of orderBy() clauses.`,
99101
);
100102
}
101103

102-
return this._modifiers.setFieldsCursor(cursor, allFields);
104+
return modifiers.setFieldsCursor(cursor, allFields);
103105
}
104106

105107
endAt(docOrField, ...fields) {
@@ -187,7 +189,7 @@ export default class FirestoreQuery {
187189
);
188190
}
189191

190-
const modifiers = this._modifiers.limit(limit);
192+
const modifiers = this._modifiers._copy().limit(limit);
191193

192194
return new FirestoreQuery(this._firestore, this._collectionPath, modifiers);
193195
}
@@ -291,7 +293,7 @@ export default class FirestoreQuery {
291293
);
292294
}
293295

294-
const modifiers = this._modifiers.orderBy(path, directionStr);
296+
const modifiers = this._modifiers._copy().orderBy(path, directionStr);
295297

296298
try {
297299
modifiers.validateOrderBy();
@@ -355,7 +357,7 @@ export default class FirestoreQuery {
355357
);
356358
}
357359

358-
const modifiers = this._modifiers.where(path, opStr, value);
360+
const modifiers = this._modifiers._copy().where(path, opStr, value);
359361

360362
try {
361363
modifiers.validateWhere();

packages/firestore/lib/FirestoreQueryModifiers.js

+13
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,19 @@ export default class FirestoreQueryModifiers {
5252
this._endBefore = undefined;
5353
}
5454

55+
_copy() {
56+
const newInstance = new FirestoreQueryModifiers();
57+
newInstance._limit = this._limit;
58+
newInstance._filters = [...this._filters];
59+
newInstance._orders = [...this._orders];
60+
newInstance._type = this._type;
61+
newInstance._startAt = this._startAt;
62+
newInstance._startAfter = this._startAfter;
63+
newInstance._endAt = this._endAt;
64+
newInstance._endBefore = this._endBefore;
65+
return newInstance;
66+
}
67+
5568
get filters() {
5669
return this._filters;
5770
}

0 commit comments

Comments
 (0)