Skip to content

Commit d0bae02

Browse files
Tree-Shake Path (#4477)
1 parent c6eadf7 commit d0bae02

30 files changed

+622
-467
lines changed

packages/database/src/api/Database.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818
import { fatal } from '../core/util/util';
1919
import { parseRepoInfo } from '../core/util/libs/parser';
20-
import { Path } from '../core/util/Path';
20+
import { newEmptyPath } from '../core/util/Path';
2121
import { Reference } from './Reference';
2222
import { Repo } from '../core/Repo';
2323
import { RepoManager } from '../core/RepoManager';
@@ -79,7 +79,7 @@ export class Database implements FirebaseService {
7979

8080
get root_(): Reference {
8181
if (!this.rootInternal_) {
82-
this.rootInternal_ = new Reference(this.repo_, Path.Empty);
82+
this.rootInternal_ = new Reference(this.repo_, newEmptyPath());
8383
}
8484

8585
return this.rootInternal_;

packages/database/src/api/Query.ts

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,30 +17,35 @@
1717

1818
import {
1919
assert,
20+
Deferred,
2021
errorPrefix,
2122
validateArgCount,
2223
validateCallback,
23-
validateContextObject,
24-
Deferred
24+
validateContextObject
2525
} from '@firebase/util';
2626
import { KEY_INDEX } from '../core/snap/indexes/KeyIndex';
2727
import { PRIORITY_INDEX } from '../core/snap/indexes/PriorityIndex';
2828
import { VALUE_INDEX } from '../core/snap/indexes/ValueIndex';
2929
import { PathIndex } from '../core/snap/indexes/PathIndex';
30-
import { MIN_NAME, MAX_NAME, ObjectToUniqueKey } from '../core/util/util';
31-
import { Path } from '../core/util/Path';
30+
import { MAX_NAME, MIN_NAME, ObjectToUniqueKey } from '../core/util/util';
31+
import {
32+
Path,
33+
pathEquals,
34+
pathIsEmpty,
35+
pathToUrlEncodedString
36+
} from '../core/util/Path';
3237
import {
3338
isValidPriority,
3439
validateEventType,
35-
validatePathString,
3640
validateFirebaseDataArg,
37-
validateKey
41+
validateKey,
42+
validatePathString
3843
} from '../core/util/validation';
3944

4045
import {
41-
ValueEventRegistration,
4246
ChildEventRegistration,
43-
EventRegistration
47+
EventRegistration,
48+
ValueEventRegistration
4449
} from '../core/view/EventRegistration';
4550

4651
import { Repo } from '../core/Repo';
@@ -405,7 +410,7 @@ export class Query {
405410
validatePathString('Query.orderByChild', 1, path, false);
406411
this.validateNoPreviousOrderByCall_('Query.orderByChild');
407412
const parsedPath = new Path(path);
408-
if (parsedPath.isEmpty()) {
413+
if (pathIsEmpty(parsedPath)) {
409414
throw new Error(
410415
'Query.orderByChild: cannot pass in empty path. Use Query.orderByValue() instead.'
411416
);
@@ -569,7 +574,7 @@ export class Query {
569574
toString(): string {
570575
validateArgCount('Query.toString', 0, 0, arguments.length);
571576

572-
return this.repo.toString() + this.path.toUrlEncodedString();
577+
return this.repo.toString() + pathToUrlEncodedString(this.path);
573578
}
574579

575580
// Do not create public documentation. This is intended to make JSON serialization work but is otherwise unnecessary
@@ -605,7 +610,7 @@ export class Query {
605610
}
606611

607612
const sameRepo = this.repo === other.repo;
608-
const samePath = this.path.equals(other.path);
613+
const samePath = pathEquals(this.path, other.path);
609614
const sameQueryIdentifier =
610615
this.queryIdentifier() === other.queryIdentifier();
611616

packages/database/src/api/Reference.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,14 @@ import { warn } from '../core/util/util';
2121
import { nextPushId } from '../core/util/NextPushId';
2222
import { Query } from './Query';
2323
import { Repo } from '../core/Repo';
24-
import { Path } from '../core/util/Path';
24+
import {
25+
Path,
26+
pathChild,
27+
pathGetBack,
28+
pathGetFront,
29+
pathIsEmpty,
30+
pathParent
31+
} from '../core/util/Path';
2532
import { QueryParams } from '../core/view/QueryParams';
2633
import {
2734
validateBoolean,
@@ -68,10 +75,10 @@ export class Reference extends Query {
6875
getKey(): string | null {
6976
validateArgCount('Reference.key', 0, 0, arguments.length);
7077

71-
if (this.path.isEmpty()) {
78+
if (pathIsEmpty(this.path)) {
7279
return null;
7380
} else {
74-
return this.path.getBack();
81+
return pathGetBack(this.path);
7582
}
7683
}
7784

@@ -80,21 +87,21 @@ export class Reference extends Query {
8087
if (typeof pathString === 'number') {
8188
pathString = String(pathString);
8289
} else if (!(pathString instanceof Path)) {
83-
if (this.path.getFront() === null) {
90+
if (pathGetFront(this.path) === null) {
8491
validateRootPathString('Reference.child', 1, pathString, false);
8592
} else {
8693
validatePathString('Reference.child', 1, pathString, false);
8794
}
8895
}
8996

90-
return new Reference(this.repo, this.path.child(pathString));
97+
return new Reference(this.repo, pathChild(this.path, pathString));
9198
}
9299

93100
/** @return {?Reference} */
94101
getParent(): Reference | null {
95102
validateArgCount('Reference.parent', 0, 0, arguments.length);
96103

97-
const parentPath = this.path.parent();
104+
const parentPath = pathParent(this.path);
98105
return parentPath === null ? null : new Reference(this.repo, parentPath);
99106
}
100107

@@ -278,7 +285,7 @@ export class Reference extends Query {
278285

279286
const deferred = new Deferred();
280287
this.repo.setWithPriority(
281-
this.path.child('.priority'),
288+
pathChild(this.path, '.priority'),
282289
priority,
283290
null,
284291
deferred.wrapCallback(onComplete)

packages/database/src/core/CompoundWrite.ts

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,13 @@
1616
*/
1717

1818
import { ImmutableTree } from './util/ImmutableTree';
19-
import { Path } from './util/Path';
19+
import {
20+
newEmptyPath,
21+
newRelativePath,
22+
Path,
23+
pathChild,
24+
pathIsEmpty
25+
} from './util/Path';
2026
import { NamedNode, Node } from './snap/Node';
2127
import { PRIORITY_INDEX } from './snap/indexes/PriorityIndex';
2228
import { assert } from '@firebase/util';
@@ -42,14 +48,14 @@ export function compoundWriteAddWrite(
4248
path: Path,
4349
node: Node
4450
): CompoundWrite {
45-
if (path.isEmpty()) {
51+
if (pathIsEmpty(path)) {
4652
return new CompoundWrite(new ImmutableTree(node));
4753
} else {
4854
const rootmost = compoundWrite.writeTree_.findRootMostValueAndPath(path);
4955
if (rootmost != null) {
5056
const rootMostPath = rootmost.path;
5157
let value = rootmost.value;
52-
const relativePath = Path.relativePath(rootMostPath, path);
58+
const relativePath = newRelativePath(rootMostPath, path);
5359
value = value.updateChild(relativePath, node);
5460
return new CompoundWrite(
5561
compoundWrite.writeTree_.set(rootMostPath, value)
@@ -69,7 +75,7 @@ export function compoundWriteAddWrites(
6975
): CompoundWrite {
7076
let newWrite = compoundWrite;
7177
each(updates, (childKey: string, node: Node) => {
72-
newWrite = compoundWriteAddWrite(newWrite, path.child(childKey), node);
78+
newWrite = compoundWriteAddWrite(newWrite, pathChild(path, childKey), node);
7379
});
7480
return newWrite;
7581
}
@@ -86,7 +92,7 @@ export function compoundWriteRemoveWrite(
8692
compoundWrite: CompoundWrite,
8793
path: Path
8894
): CompoundWrite {
89-
if (path.isEmpty()) {
95+
if (pathIsEmpty(path)) {
9096
return CompoundWrite.empty();
9197
} else {
9298
const newWriteTree = compoundWrite.writeTree_.setTree(
@@ -128,7 +134,7 @@ export function compoundWriteGetCompleteNode(
128134
if (rootmost != null) {
129135
return compoundWrite.writeTree_
130136
.get(rootmost.path)
131-
.getChild(Path.relativePath(rootmost.path, path));
137+
.getChild(newRelativePath(rootmost.path, path));
132138
} else {
133139
return null;
134140
}
@@ -171,7 +177,7 @@ export function compoundWriteChildCompoundWrite(
171177
compoundWrite: CompoundWrite,
172178
path: Path
173179
): CompoundWrite {
174-
if (path.isEmpty()) {
180+
if (pathIsEmpty(path)) {
175181
return compoundWrite;
176182
} else {
177183
const shadowingNode = compoundWriteGetCompleteNode(compoundWrite, path);
@@ -201,7 +207,7 @@ export function compoundWriteApply(
201207
compoundWrite: CompoundWrite,
202208
node: Node
203209
): Node {
204-
return applySubtreeWrite(Path.Empty, compoundWrite.writeTree_, node);
210+
return applySubtreeWrite(newEmptyPath(), compoundWrite.writeTree_, node);
205211
}
206212

207213
function applySubtreeWrite(
@@ -224,12 +230,19 @@ function applySubtreeWrite(
224230
);
225231
priorityWrite = childTree.value;
226232
} else {
227-
node = applySubtreeWrite(relativePath.child(childKey), childTree, node);
233+
node = applySubtreeWrite(
234+
pathChild(relativePath, childKey),
235+
childTree,
236+
node
237+
);
228238
}
229239
});
230240
// If there was a priority write, we only apply it if the node is not empty
231241
if (!node.getChild(relativePath).isEmpty() && priorityWrite !== null) {
232-
node = node.updateChild(relativePath.child('.priority'), priorityWrite);
242+
node = node.updateChild(
243+
pathChild(relativePath, '.priority'),
244+
priorityWrite
245+
);
233246
}
234247
return node;
235248
}

packages/database/src/core/Repo.ts

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,14 @@ import {
2121
resolveDeferredValueTree
2222
} from './util/ServerValues';
2323
import { nodeFromJSON } from './snap/nodeFromJSON';
24-
import { Path } from './util/Path';
24+
import {
25+
newEmptyPath,
26+
newRelativePath,
27+
Path,
28+
pathChild,
29+
pathGetFront,
30+
pathPopFront
31+
} from './util/Path';
2532
import { SparseSnapshotTree } from './SparseSnapshotTree';
2633
import { SyncTree } from './SyncTree';
2734
import { SnapshotHolder } from './SnapshotHolder';
@@ -496,7 +503,7 @@ export class Repo {
496503
each(childrenToMerge, (changedKey: string, changedValue: unknown) => {
497504
empty = false;
498505
changedChildren[changedKey] = resolveDeferredValueTree(
499-
path.child(changedKey),
506+
pathChild(path, changedKey),
500507
nodeFromJSON(changedValue),
501508
this.serverSyncTree_,
502509
serverValues
@@ -536,7 +543,9 @@ export class Repo {
536543
);
537544

538545
each(childrenToMerge, (changedPath: string) => {
539-
const affectedPath = this.abortTransactions_(path.child(changedPath));
546+
const affectedPath = this.abortTransactions_(
547+
pathChild(path, changedPath)
548+
);
540549
this.rerunTransactions_(affectedPath);
541550
});
542551

@@ -556,7 +565,7 @@ export class Repo {
556565

557566
const serverValues = this.generateServerValues();
558567
const resolvedOnDisconnectTree = new SparseSnapshotTree();
559-
this.onDisconnect_.forEachTree(Path.Empty, (path, node) => {
568+
this.onDisconnect_.forEachTree(newEmptyPath(), (path, node) => {
560569
const resolved = resolveDeferredValueTree(
561570
path,
562571
node,
@@ -567,7 +576,7 @@ export class Repo {
567576
});
568577
let events: Event[] = [];
569578

570-
resolvedOnDisconnectTree.forEachTree(Path.Empty, (path, snap) => {
579+
resolvedOnDisconnectTree.forEachTree(newEmptyPath(), (path, snap) => {
571580
events = events.concat(
572581
this.serverSyncTree_.applyServerOverwrite(path, snap)
573582
);
@@ -576,7 +585,11 @@ export class Repo {
576585
});
577586

578587
this.onDisconnect_ = new SparseSnapshotTree();
579-
eventQueueRaiseEventsForChangedPath(this.eventQueue_, Path.Empty, events);
588+
eventQueueRaiseEventsForChangedPath(
589+
this.eventQueue_,
590+
newEmptyPath(),
591+
events
592+
);
580593
}
581594

582595
onDisconnectCancel(
@@ -648,7 +661,10 @@ export class Repo {
648661
if (status === 'ok') {
649662
each(childrenToMerge, (childName: string, childNode: unknown) => {
650663
const newChildNode = nodeFromJSON(childNode);
651-
this.onDisconnect_.remember(path.child(childName), newChildNode);
664+
this.onDisconnect_.remember(
665+
pathChild(path, childName),
666+
newChildNode
667+
);
652668
});
653669
}
654670
this.callOnCompleteCallback(onComplete, status, errorReason);
@@ -658,7 +674,7 @@ export class Repo {
658674

659675
addEventCallbackForQuery(query: Query, eventRegistration: EventRegistration) {
660676
let events;
661-
if (query.path.getFront() === '.info') {
677+
if (pathGetFront(query.path) === '.info') {
662678
events = this.infoSyncTree_.addEventRegistration(
663679
query,
664680
eventRegistration
@@ -679,7 +695,7 @@ export class Repo {
679695
// These are guaranteed not to raise events, since we're not passing in a cancelError. However, we can future-proof
680696
// a little bit by handling the return values anyways.
681697
let events;
682-
if (query.path.getFront() === '.info') {
698+
if (pathGetFront(query.path) === '.info') {
683699
events = this.infoSyncTree_.removeEventRegistration(
684700
query,
685701
eventRegistration
@@ -978,7 +994,7 @@ export class Repo {
978994
);
979995
txn.status = TransactionStatus.SENT;
980996
txn.retryCount++;
981-
const relativePath = Path.relativePath(path, txn.path);
997+
const relativePath = newRelativePath(path, txn.path);
982998
// If we've gotten to this point, the output snapshot must be defined.
983999
snapToSend = snapToSend.updateChild(
9841000
relativePath /** @type {!Node} */,
@@ -1112,7 +1128,7 @@ export class Repo {
11121128
});
11131129
for (let i = 0; i < queue.length; i++) {
11141130
const transaction = queue[i];
1115-
const relativePath = Path.relativePath(path, transaction.path);
1131+
const relativePath = newRelativePath(path, transaction.path);
11161132
let abortTransaction = false,
11171133
abortReason;
11181134
assert(
@@ -1258,11 +1274,11 @@ export class Repo {
12581274
// Start at the root and walk deeper into the tree towards path until we
12591275
// find a node with pending transactions.
12601276
let transactionNode = this.transactionQueueTree_;
1261-
front = path.getFront();
1277+
front = pathGetFront(path);
12621278
while (front !== null && transactionNode.getValue() === null) {
12631279
transactionNode = transactionNode.subTree(front);
1264-
path = path.popFront();
1265-
front = path.getFront();
1280+
path = pathPopFront(path);
1281+
front = pathGetFront(path);
12661282
}
12671283

12681284
return transactionNode;

packages/database/src/core/RepoManager.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ import {
3232
EmulatorAdminTokenProvider,
3333
FirebaseAuthTokenProvider
3434
} from './AuthTokenProvider';
35+
import { pathIsEmpty } from './util/Path';
3536

3637
/**
3738
* This variable is also defined in the firebase node.js admin SDK. Before
@@ -156,7 +157,7 @@ export class RepoManager {
156157
: new FirebaseAuthTokenProvider(app, authProvider);
157158

158159
validateUrl('Invalid Firebase Database URL', 1, parsedUrl);
159-
if (!parsedUrl.path.isEmpty()) {
160+
if (!pathIsEmpty(parsedUrl.path)) {
160161
fatal(
161162
'Database URL must point to the root of a Firebase Database ' +
162163
'(not including a child path).'

0 commit comments

Comments
 (0)