Skip to content

Commit 95f20f0

Browse files
committed
refactor(project): Fix HashTree tests
1 parent 85626f8 commit 95f20f0

5 files changed

Lines changed: 316 additions & 329 deletions

File tree

packages/project/lib/build/cache/index/HashTree.js

Lines changed: 0 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -711,80 +711,4 @@ export default class HashTree {
711711
traverse(this.root, "/");
712712
return paths.sort();
713713
}
714-
715-
/**
716-
* For a tree derived from a base tree, get the list of resource nodes
717-
* that were added compared to the base tree.
718-
*
719-
* @param {HashTree} rootTree - The base tree to compare against
720-
* @returns {Array<ResourceMetadata>}
721-
* Array of added resource metadata
722-
*/
723-
getAddedResources(rootTree) {
724-
const added = [];
725-
726-
const traverse = (node, currentPath, implicitlyAdded = false) => {
727-
if (implicitlyAdded) {
728-
// We're in a subtree that's entirely new - add all resources
729-
if (node.type === "resource") {
730-
added.push({
731-
path: currentPath,
732-
integrity: node.integrity,
733-
size: node.size,
734-
lastModified: node.lastModified,
735-
inode: node.inode
736-
});
737-
}
738-
} else {
739-
const baseNode = rootTree._findNode(currentPath);
740-
if (baseNode && baseNode === node) {
741-
// Node exists in base tree and is the same object (structural sharing)
742-
// Neither node nor children are added
743-
return;
744-
} else if (baseNode && node.type === "directory") {
745-
// Directory exists in both trees but may have been shallow-copied
746-
// Check children individually - only process children that differ
747-
for (const [name, child] of node.children) {
748-
const childPath = currentPath ? path.join(currentPath, name) : name;
749-
const baseChild = baseNode.children.get(name);
750-
751-
if (!baseChild || baseChild !== child) {
752-
// Child doesn't exist in base or is different - determine if added
753-
if (!baseChild) {
754-
// Entirely new - all descendants are added
755-
traverse(child, childPath, true);
756-
} else {
757-
// Child was modified/replaced - recurse normally
758-
traverse(child, childPath, false);
759-
}
760-
}
761-
// If baseChild === child, skip it (shared)
762-
}
763-
return; // Don't continue with normal traversal
764-
} else if (!baseNode && node.type === "resource") {
765-
// Resource doesn't exist in base tree - it's added
766-
added.push({
767-
path: currentPath,
768-
integrity: node.integrity,
769-
size: node.size,
770-
lastModified: node.lastModified,
771-
inode: node.inode
772-
});
773-
return;
774-
} else if (!baseNode && node.type === "directory") {
775-
// Directory doesn't exist in base tree - all children are added
776-
implicitlyAdded = true;
777-
}
778-
}
779-
780-
if (node.type === "directory") {
781-
for (const [name, child] of node.children) {
782-
const childPath = currentPath ? path.join(currentPath, name) : name;
783-
traverse(child, childPath, implicitlyAdded);
784-
}
785-
}
786-
};
787-
traverse(this.root, "/");
788-
return added;
789-
}
790714
}

packages/project/lib/build/cache/index/SharedHashTree.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import path from "node:path/posix";
12
import HashTree from "./HashTree.js";
23
import TreeNode from "./TreeNode.js";
34

@@ -101,6 +102,82 @@ export default class SharedHashTree extends HashTree {
101102
return derived;
102103
}
103104

105+
/**
106+
* For a tree derived from a base tree, get the list of resource nodes
107+
* that were added compared to the base tree.
108+
*
109+
* @param {HashTree} rootTree - The base tree to compare against
110+
* @returns {Array<ResourceMetadata>}
111+
* Array of added resource metadata
112+
*/
113+
getAddedResources(rootTree) {
114+
const added = [];
115+
116+
const traverse = (node, currentPath, implicitlyAdded = false) => {
117+
if (implicitlyAdded) {
118+
// We're in a subtree that's entirely new - add all resources
119+
if (node.type === "resource") {
120+
added.push({
121+
path: currentPath,
122+
integrity: node.integrity,
123+
size: node.size,
124+
lastModified: node.lastModified,
125+
inode: node.inode
126+
});
127+
}
128+
} else {
129+
const baseNode = rootTree._findNode(currentPath);
130+
if (baseNode && baseNode === node) {
131+
// Node exists in base tree and is the same object (structural sharing)
132+
// Neither node nor children are added
133+
return;
134+
} else if (baseNode && node.type === "directory") {
135+
// Directory exists in both trees but may have been shallow-copied
136+
// Check children individually - only process children that differ
137+
for (const [name, child] of node.children) {
138+
const childPath = currentPath ? path.join(currentPath, name) : name;
139+
const baseChild = baseNode.children.get(name);
140+
141+
if (!baseChild || baseChild !== child) {
142+
// Child doesn't exist in base or is different - determine if added
143+
if (!baseChild) {
144+
// Entirely new - all descendants are added
145+
traverse(child, childPath, true);
146+
} else {
147+
// Child was modified/replaced - recurse normally
148+
traverse(child, childPath, false);
149+
}
150+
}
151+
// If baseChild === child, skip it (shared)
152+
}
153+
return; // Don't continue with normal traversal
154+
} else if (!baseNode && node.type === "resource") {
155+
// Resource doesn't exist in base tree - it's added
156+
added.push({
157+
path: currentPath,
158+
integrity: node.integrity,
159+
size: node.size,
160+
lastModified: node.lastModified,
161+
inode: node.inode
162+
});
163+
return;
164+
} else if (!baseNode && node.type === "directory") {
165+
// Directory doesn't exist in base tree - all children are added
166+
implicitlyAdded = true;
167+
}
168+
}
169+
170+
if (node.type === "directory") {
171+
for (const [name, child] of node.children) {
172+
const childPath = currentPath ? path.join(currentPath, name) : name;
173+
traverse(child, childPath, implicitlyAdded);
174+
}
175+
}
176+
};
177+
traverse(this.root, "/");
178+
return added;
179+
}
180+
104181
/**
105182
* Deserialize tree from JSON
106183
*

packages/project/test/lib/build/cache/ResourceRequestGraph.js

Lines changed: 2 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -14,18 +14,6 @@ test("Request: Create patterns request", (t) => {
1414
t.deepEqual(request.value, ["*.js", "*.css"]);
1515
});
1616

17-
test("Request: Create dep-path request", (t) => {
18-
const request = new Request("dep-path", "dependency/file.js");
19-
t.is(request.type, "dep-path");
20-
t.is(request.value, "dependency/file.js");
21-
});
22-
23-
test("Request: Create dep-patterns request", (t) => {
24-
const request = new Request("dep-patterns", ["dep/*.js"]);
25-
t.is(request.type, "dep-patterns");
26-
t.deepEqual(request.value, ["dep/*.js"]);
27-
});
28-
2917
test("Request: Reject invalid type", (t) => {
3018
const error = t.throws(() => {
3119
new Request("invalid-type", "value");
@@ -40,13 +28,6 @@ test("Request: Reject non-string value for path type", (t) => {
4028
t.is(error.message, "Request type 'path' requires value to be a string");
4129
});
4230

43-
test("Request: Reject non-string value for dep-path type", (t) => {
44-
const error = t.throws(() => {
45-
new Request("dep-path", ["array", "value"]);
46-
}, {instanceOf: Error});
47-
t.is(error.message, "Request type 'dep-path' requires value to be a string");
48-
});
49-
5031
test("Request: toKey with string value", (t) => {
5132
const request = new Request("path", "a.js");
5233
t.is(request.toKey(), "path:a.js");
@@ -75,12 +56,6 @@ test("Request: equals returns true for identical requests", (t) => {
7556
t.true(req1.equals(req2));
7657
});
7758

78-
test("Request: equals returns false for different types", (t) => {
79-
const req1 = new Request("path", "a.js");
80-
const req2 = new Request("dep-path", "a.js");
81-
t.false(req1.equals(req2));
82-
});
83-
8459
test("Request: equals returns false for different values", (t) => {
8560
const req1 = new Request("path", "a.js");
8661
const req2 = new Request("path", "b.js");
@@ -484,18 +459,16 @@ test("ResourceRequestGraph: Handles different request types", (t) => {
484459
const set1 = [
485460
new Request("path", "a.js"),
486461
new Request("patterns", ["*.js"]),
487-
new Request("dep-path", "dep/file.js"),
488-
new Request("dep-patterns", ["dep/*.js"])
489462
];
490463
const nodeId = graph.addRequestSet(set1);
491464

492465
const node = graph.getNode(nodeId);
493466
const materialized = node.getMaterializedRequests(graph);
494467

495-
t.is(materialized.length, 4);
468+
t.is(materialized.length, 2);
496469

497470
const types = materialized.map((r) => r.type).sort();
498-
t.deepEqual(types, ["dep-path", "dep-patterns", "path", "patterns"]);
471+
t.deepEqual(types, ["path", "patterns"]);
499472
});
500473

501474
test("ResourceRequestGraph: Complex parent hierarchy", (t) => {

0 commit comments

Comments
 (0)