Skip to content

Commit f513922

Browse files
authored
Database tree-shake step: modularize CompoundWrite (#4444)
1 parent 05614aa commit f513922

File tree

3 files changed

+597
-277
lines changed

3 files changed

+597
-277
lines changed

packages/database/src/core/CompoundWrite.ts

Lines changed: 147 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -30,145 +30,178 @@ import { each } from './util/util';
3030
* to reflect the write added.
3131
*/
3232
export class CompoundWrite {
33-
constructor(private writeTree_: ImmutableTree<Node>) {}
33+
constructor(public writeTree_: ImmutableTree<Node>) {}
3434

3535
static empty(): CompoundWrite {
3636
return new CompoundWrite(new ImmutableTree(null));
3737
}
38+
}
3839

39-
addWrite(path: Path, node: Node): CompoundWrite {
40-
if (path.isEmpty()) {
41-
return new CompoundWrite(new ImmutableTree(node));
40+
export function compoundWriteAddWrite(
41+
compoundWrite: CompoundWrite,
42+
path: Path,
43+
node: Node
44+
): CompoundWrite {
45+
if (path.isEmpty()) {
46+
return new CompoundWrite(new ImmutableTree(node));
47+
} else {
48+
const rootmost = compoundWrite.writeTree_.findRootMostValueAndPath(path);
49+
if (rootmost != null) {
50+
const rootMostPath = rootmost.path;
51+
let value = rootmost.value;
52+
const relativePath = Path.relativePath(rootMostPath, path);
53+
value = value.updateChild(relativePath, node);
54+
return new CompoundWrite(
55+
compoundWrite.writeTree_.set(rootMostPath, value)
56+
);
4257
} else {
43-
const rootmost = this.writeTree_.findRootMostValueAndPath(path);
44-
if (rootmost != null) {
45-
const rootMostPath = rootmost.path;
46-
let value = rootmost.value;
47-
const relativePath = Path.relativePath(rootMostPath, path);
48-
value = value.updateChild(relativePath, node);
49-
return new CompoundWrite(this.writeTree_.set(rootMostPath, value));
50-
} else {
51-
const subtree = new ImmutableTree(node);
52-
const newWriteTree = this.writeTree_.setTree(path, subtree);
53-
return new CompoundWrite(newWriteTree);
54-
}
58+
const subtree = new ImmutableTree(node);
59+
const newWriteTree = compoundWrite.writeTree_.setTree(path, subtree);
60+
return new CompoundWrite(newWriteTree);
5561
}
5662
}
63+
}
5764

58-
addWrites(path: Path, updates: { [name: string]: Node }): CompoundWrite {
59-
let newWrite = this as CompoundWrite;
60-
each(updates, (childKey: string, node: Node) => {
61-
newWrite = newWrite.addWrite(path.child(childKey), node);
62-
});
63-
return newWrite;
64-
}
65+
export function compoundWriteAddWrites(
66+
compoundWrite: CompoundWrite,
67+
path: Path,
68+
updates: { [name: string]: Node }
69+
): CompoundWrite {
70+
let newWrite = compoundWrite;
71+
each(updates, (childKey: string, node: Node) => {
72+
newWrite = compoundWriteAddWrite(newWrite, path.child(childKey), node);
73+
});
74+
return newWrite;
75+
}
6576

66-
/**
67-
* Will remove a write at the given path and deeper paths. This will <em>not</em> modify a write at a higher
68-
* location, which must be removed by calling this method with that path.
69-
*
70-
* @param path The path at which a write and all deeper writes should be removed
71-
* @return The new CompoundWrite with the removed path
72-
*/
73-
removeWrite(path: Path): CompoundWrite {
74-
if (path.isEmpty()) {
75-
return CompoundWrite.empty();
76-
} else {
77-
const newWriteTree = this.writeTree_.setTree(
78-
path,
79-
new ImmutableTree<Node>(null)
80-
);
81-
return new CompoundWrite(newWriteTree);
82-
}
77+
/**
78+
* Will remove a write at the given path and deeper paths. This will <em>not</em> modify a write at a higher
79+
* location, which must be removed by calling this method with that path.
80+
*
81+
* @param compoundWrite The CompoundWrite to remove.
82+
* @param path The path at which a write and all deeper writes should be removed
83+
* @return The new CompoundWrite with the removed path
84+
*/
85+
export function compoundWriteRemoveWrite(
86+
compoundWrite: CompoundWrite,
87+
path: Path
88+
): CompoundWrite {
89+
if (path.isEmpty()) {
90+
return CompoundWrite.empty();
91+
} else {
92+
const newWriteTree = compoundWrite.writeTree_.setTree(
93+
path,
94+
new ImmutableTree<Node>(null)
95+
);
96+
return new CompoundWrite(newWriteTree);
8397
}
98+
}
8499

85-
/**
86-
* Returns whether this CompoundWrite will fully overwrite a node at a given location and can therefore be
87-
* considered "complete".
88-
*
89-
* @param path The path to check for
90-
* @return Whether there is a complete write at that path
91-
*/
92-
hasCompleteWrite(path: Path): boolean {
93-
return this.getCompleteNode(path) != null;
94-
}
100+
/**
101+
* Returns whether this CompoundWrite will fully overwrite a node at a given location and can therefore be
102+
* considered "complete".
103+
*
104+
* @param compoundWrite The CompoundWrite to check.
105+
* @param path The path to check for
106+
* @return Whether there is a complete write at that path
107+
*/
108+
export function compoundWriteHasCompleteWrite(
109+
compoundWrite: CompoundWrite,
110+
path: Path
111+
): boolean {
112+
return compoundWriteGetCompleteNode(compoundWrite, path) != null;
113+
}
95114

96-
/**
97-
* Returns a node for a path if and only if the node is a "complete" overwrite at that path. This will not aggregate
98-
* writes from deeper paths, but will return child nodes from a more shallow path.
99-
*
100-
* @param path The path to get a complete write
101-
* @return The node if complete at that path, or null otherwise.
102-
*/
103-
getCompleteNode(path: Path): Node | null {
104-
const rootmost = this.writeTree_.findRootMostValueAndPath(path);
105-
if (rootmost != null) {
106-
return this.writeTree_
107-
.get(rootmost.path)
108-
.getChild(Path.relativePath(rootmost.path, path));
109-
} else {
110-
return null;
111-
}
115+
/**
116+
* Returns a node for a path if and only if the node is a "complete" overwrite at that path. This will not aggregate
117+
* writes from deeper paths, but will return child nodes from a more shallow path.
118+
*
119+
* @param compoundWrite The CompoundWrite to get the node from.
120+
* @param path The path to get a complete write
121+
* @return The node if complete at that path, or null otherwise.
122+
*/
123+
export function compoundWriteGetCompleteNode(
124+
compoundWrite: CompoundWrite,
125+
path: Path
126+
): Node | null {
127+
const rootmost = compoundWrite.writeTree_.findRootMostValueAndPath(path);
128+
if (rootmost != null) {
129+
return compoundWrite.writeTree_
130+
.get(rootmost.path)
131+
.getChild(Path.relativePath(rootmost.path, path));
132+
} else {
133+
return null;
112134
}
135+
}
113136

114-
/**
115-
* Returns all children that are guaranteed to be a complete overwrite.
116-
*
117-
* @return A list of all complete children.
118-
*/
119-
getCompleteChildren(): NamedNode[] {
120-
const children: NamedNode[] = [];
121-
const node = this.writeTree_.value;
122-
if (node != null) {
123-
// If it's a leaf node, it has no children; so nothing to do.
124-
if (!node.isLeafNode()) {
125-
(node as ChildrenNode).forEachChild(
126-
PRIORITY_INDEX,
127-
(childName, childNode) => {
128-
children.push(new NamedNode(childName, childNode));
129-
}
130-
);
131-
}
132-
} else {
133-
this.writeTree_.children.inorderTraversal((childName, childTree) => {
137+
/**
138+
* Returns all children that are guaranteed to be a complete overwrite.
139+
*
140+
* @param compoundWrite The CompoundWrite to get children from.
141+
* @return A list of all complete children.
142+
*/
143+
export function compoundWriteGetCompleteChildren(
144+
compoundWrite: CompoundWrite
145+
): NamedNode[] {
146+
const children: NamedNode[] = [];
147+
const node = compoundWrite.writeTree_.value;
148+
if (node != null) {
149+
// If it's a leaf node, it has no children; so nothing to do.
150+
if (!node.isLeafNode()) {
151+
(node as ChildrenNode).forEachChild(
152+
PRIORITY_INDEX,
153+
(childName, childNode) => {
154+
children.push(new NamedNode(childName, childNode));
155+
}
156+
);
157+
}
158+
} else {
159+
compoundWrite.writeTree_.children.inorderTraversal(
160+
(childName, childTree) => {
134161
if (childTree.value != null) {
135162
children.push(new NamedNode(childName, childTree.value));
136163
}
137-
});
138-
}
139-
return children;
164+
}
165+
);
140166
}
167+
return children;
168+
}
141169

142-
childCompoundWrite(path: Path): CompoundWrite {
143-
if (path.isEmpty()) {
144-
return this;
170+
export function compoundWriteChildCompoundWrite(
171+
compoundWrite: CompoundWrite,
172+
path: Path
173+
): CompoundWrite {
174+
if (path.isEmpty()) {
175+
return compoundWrite;
176+
} else {
177+
const shadowingNode = compoundWriteGetCompleteNode(compoundWrite, path);
178+
if (shadowingNode != null) {
179+
return new CompoundWrite(new ImmutableTree(shadowingNode));
145180
} else {
146-
const shadowingNode = this.getCompleteNode(path);
147-
if (shadowingNode != null) {
148-
return new CompoundWrite(new ImmutableTree(shadowingNode));
149-
} else {
150-
return new CompoundWrite(this.writeTree_.subtree(path));
151-
}
181+
return new CompoundWrite(compoundWrite.writeTree_.subtree(path));
152182
}
153183
}
184+
}
154185

155-
/**
156-
* Returns true if this CompoundWrite is empty and therefore does not modify any nodes.
157-
* @return Whether this CompoundWrite is empty
158-
*/
159-
isEmpty(): boolean {
160-
return this.writeTree_.isEmpty();
161-
}
186+
/**
187+
* Returns true if this CompoundWrite is empty and therefore does not modify any nodes.
188+
* @return Whether this CompoundWrite is empty
189+
*/
190+
export function compoundWriteIsEmpty(compoundWrite: CompoundWrite): boolean {
191+
return compoundWrite.writeTree_.isEmpty();
192+
}
162193

163-
/**
164-
* Applies this CompoundWrite to a node. The node is returned with all writes from this CompoundWrite applied to the
165-
* node
166-
* @param node The node to apply this CompoundWrite to
167-
* @return The node with all writes applied
168-
*/
169-
apply(node: Node): Node {
170-
return applySubtreeWrite(Path.Empty, this.writeTree_, node);
171-
}
194+
/**
195+
* Applies this CompoundWrite to a node. The node is returned with all writes from this CompoundWrite applied to the
196+
* node
197+
* @param node The node to apply this CompoundWrite to
198+
* @return The node with all writes applied
199+
*/
200+
export function compoundWriteApply(
201+
compoundWrite: CompoundWrite,
202+
node: Node
203+
): Node {
204+
return applySubtreeWrite(Path.Empty, compoundWrite.writeTree_, node);
172205
}
173206

174207
function applySubtreeWrite(

0 commit comments

Comments
 (0)