Skip to content

Commit 67d3b99

Browse files
committed
Align shared test-runner layout fallback logic
1 parent de3e074 commit 67d3b99

4 files changed

Lines changed: 72 additions & 14 deletions

File tree

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* Recursively queries the DOM for an element, traversing through shadow DOMs.
3+
*
4+
* @param {Element|ShadowRoot} lookupStartNode The node or shadow root to start the lookup from.
5+
* @param {string[]} path An array of CSS selectors representing the path to the target element.
6+
* @returns {Element|null} The target element if found, otherwise null.
7+
*/
8+
export function recursivelyQuerySelector(lookupStartNode, path) {
9+
lookupStartNode = lookupStartNode.shadowRoot ?? lookupStartNode;
10+
const target = path.reduce((root, selector) => {
11+
const node = root.querySelector(selector);
12+
return node.shadowRoot ?? node;
13+
}, lookupStartNode);
14+
15+
return target;
16+
}
17+
18+
/**
19+
* Retrieves a single DOM element, optionally traversing through shadow DOMs to a specified path before the final selection.
20+
*
21+
* @param {string} selector The CSS selector for the desired element.
22+
* @param {string[]} [path=[]] An optional array of CSS selectors to reach the desired shadowRoot or parent element.
23+
* @param {Element|ShadowRoot} [lookupStartNode=document] The starting node for the lookup.
24+
* @returns {Element|null} The found element, or null if not found.
25+
*/
26+
export function getElement(selector, path = [], lookupStartNode = document) {
27+
const element = recursivelyQuerySelector(lookupStartNode, path).querySelector(selector);
28+
return element;
29+
}
30+
31+
/**
32+
* Retrieves all DOM elements matching a selector, optionally traversing through shadow DOMs to a specified path before the final selection.
33+
*
34+
* @param {string} selector The CSS selector for the desired elements.
35+
* @param {string[]} [path=[]] An optional array of CSS selectors to reach the desired shadowRoot or parent element.
36+
* @param {Element|ShadowRoot} [lookupStartNode=document] The starting node for the lookup.
37+
* @returns {Element[]} An array of found elements.
38+
*/
39+
export function getAllElements(selector, path = [], lookupStartNode = document) {
40+
const elements = Array.from(recursivelyQuerySelector(lookupStartNode, path).querySelectorAll(selector));
41+
return elements;
42+
}
43+
44+
export function forceLayout(body, layoutMode = "getBoundingRectAndElementFromPoint") {
45+
body ??= document.body;
46+
const rect = body.getBoundingClientRect();
47+
switch (layoutMode) {
48+
case "getBoundingRectAndElementFromPoint":
49+
return document.elementFromPoint((rect.width / 2) | 0, (rect.height / 2) | 0);
50+
case "getBoundingClientRect":
51+
return rect.height;
52+
default:
53+
throw Error(`Invalid layoutMode: ${layoutMode}`);
54+
}
55+
}

experimental/javascript-wc-indexeddb/dist/src/speedometer-utils/test-runner.mjs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { TEST_INVOKER_LOOKUP } from "./test-invoker.mjs";
2+
import { forceLayout } from "./helpers.mjs";
23

34
export class TestRunner {
45
#frame;
@@ -69,13 +70,13 @@ export class TestRunner {
6970
const measureAsync = () => {
7071
// Some browsers don't immediately update the layout for paint.
7172
// Force the layout here to ensure we're measuring the layout time.
72-
if (this.page) {
73-
this.page.layout();
74-
} else {
75-
const body = document.body;
76-
const height = body.getBoundingClientRect().height;
77-
body._leakedLayoutValue = height;
78-
}
73+
//
74+
// Note: This matches the behavior of Page.layout() in benchmark-runner.mjs.
75+
// Since shared code cannot depend on Page, we duplicate the logic here,
76+
// falling back to document.body for remote workloads that don't have a frame.
77+
const body = this.#frame?.contentDocument?.body ?? document.body;
78+
const value = forceLayout(body, this.#params.layoutMode);
79+
body._leakedLayoutValue = value; // Prevent dead code elimination.
7980

8081
const asyncEndTime = performance.now();
8182
performance.mark(asyncEndLabel);

experimental/javascript-wc-indexeddb/scripts/build.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ const filesToMove = [
101101
{ src: "node_modules/speedometer-utils/test-runner.mjs", dest: "./dist/src/speedometer-utils/test-runner.mjs" },
102102
{ src: "node_modules/speedometer-utils/params.mjs", dest: "./dist/src/speedometer-utils/params.mjs" },
103103
{ src: "src/speedometer-utils/benchmark.mjs", dest: "./dist/src/speedometer-utils/benchmark.mjs" },
104+
{ src: "node_modules/speedometer-utils/helpers.mjs", dest: "./dist/src/speedometer-utils/helpers.mjs" },
104105
{ src: "node_modules/speedometer-utils/translations.mjs", dest: "./dist/src/speedometer-utils/translations.mjs" },
105106
{ src: "node_modules/speedometer-utils/todomvc-utils.mjs", dest: "./dist/src/speedometer-utils/todomvc-utils.mjs" },
106107
];

resources/shared/test-runner.mjs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { TEST_INVOKER_LOOKUP } from "./test-invoker.mjs";
2+
import { forceLayout } from "./helpers.mjs";
23

34
export class TestRunner {
45
#frame;
@@ -69,13 +70,13 @@ export class TestRunner {
6970
const measureAsync = () => {
7071
// Some browsers don't immediately update the layout for paint.
7172
// Force the layout here to ensure we're measuring the layout time.
72-
if (this.page) {
73-
this.page.layout();
74-
} else {
75-
const body = document.body;
76-
const height = body.getBoundingClientRect().height;
77-
body._leakedLayoutValue = height;
78-
}
73+
//
74+
// Note: This matches the behavior of Page.layout() in benchmark-runner.mjs.
75+
// Since shared code cannot depend on Page, we duplicate the logic here,
76+
// falling back to document.body for remote workloads that don't have a frame.
77+
const body = this.#frame?.contentDocument?.body ?? document.body;
78+
const value = forceLayout(body, this.#params.layoutMode);
79+
body._leakedLayoutValue = value; // Prevent dead code elimination.
7980

8081
const asyncEndTime = performance.now();
8182
performance.mark(asyncEndLabel);

0 commit comments

Comments
 (0)