Govern task context and advance execution pointer
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled

This commit is contained in:
mes123456
2026-08-20 06:02:43 -04:00
parent 380cbed4ff
commit 10640aeb3c
984 changed files with 543475 additions and 327 deletions

View File

@@ -18,28 +18,57 @@ let browser;
try {
const playwright = await import(pathToFileURL(path.join(root, "web/node_modules/playwright/index.mjs")).href);
browser = await playwright.chromium.launch({ headless: true, args: ["--no-sandbox", "--use-gl=swiftshader", "--enable-unsafe-swiftshader"] });
const page = await (await browser.newContext({ viewport: { width: 960, height: 640 }, hasTouch: true, isMobile: true })).newPage();
await page.goto(`http://127.0.0.1:${address.port}/`, { waitUntil: "load" });
await page.waitForFunction(() => document.querySelector("[data-testid=engine-status]")?.textContent === "Engine: ready, open a .blend file", undefined, { timeout: 20_000 });
const browserEvents = await page.locator("canvas.viewport-canvas").evaluate((element) => {
const events = [];
for (const [pointerId, pointerType] of [[2, "touch"], [4, "touch"], [9, "pen"]]) {
element.dispatchEvent(new PointerEvent("pointerdown", { bubbles: true, pointerId, pointerType, buttons: 1, pressure: pointerType === "pen" ? 0.6 : 0.5 }));
events.push({ pointerId, pointerType, phase: "down" });
}
element.dispatchEvent(new PointerEvent("pointercancel", { bubbles: true, pointerId: 2, pointerType: "touch" }));
element.dispatchEvent(new PointerEvent("pointerup", { bubbles: true, pointerId: 9, pointerType: "pen" }));
events.push({ pointerId: 2, phase: "cancel" }, { pointerId: 9, phase: "up" });
return events;
});
assert.equal(browserEvents.length, 5);
const report = { schemaVersion: 1, task: "M14-04F", operation: "CHROMIUM_INPUT_MODAL_BOUNDARY", runtime: "PLAYWRIGHT_CHROMIUM", browserEvents, guarantees: { touchCancelMainCommit: 0, twoFingerNavigationRevision: 1, penMainCommit: 1 }, execution: "DISABLED", nextTask: "M14-04G" };
const runScenario = async (offscreen) => {
const context = await browser.newContext({ viewport: { width: 960, height: 640 }, hasTouch: true, isMobile: true });
const page = await context.newPage();
await page.goto(`http://127.0.0.1:${address.port}/?offscreen=${offscreen ? "1" : "0"}`, { waitUntil: "load" });
await page.waitForFunction(() => document.querySelector("[data-testid=engine-status]")?.textContent === "Engine: ready, open a .blend file", undefined, { timeout: 20_000 });
const result = await page.locator("canvas.viewport-canvas").evaluate((element) => {
const events = [];
const state = () => ({
kind: element.dataset.inputModalKind,
activePointerIds: element.dataset.inputModalActivePointerIds ?? "",
cancelled: element.dataset.inputModalCancelled,
navigationRevision: Number(element.dataset.inputModalNavigationRevision),
mainCommitCount: Number(element.dataset.inputModalMainCommitCount),
});
const dispatch = (type, pointerId, pointerType) => {
element.dispatchEvent(new PointerEvent(type, { bubbles: true, pointerId, pointerType, buttons: type === "pointerup" || type === "pointercancel" ? 0 : 1, pressure: pointerType === "pen" ? 0.6 : 0.5 }));
events.push({ pointerId, pointerType, phase: type.slice("pointer".length) });
};
dispatch("pointerdown", 2, "touch");
dispatch("pointerdown", 4, "touch");
const twoFinger = state();
dispatch("pointercancel", 2, "touch");
const touchCancel = state();
dispatch("pointerdown", 9, "pen");
dispatch("pointerup", 9, "pen");
dispatch("pointerup", 9, "pen");
dispatch("pointercancel", 9, "pen");
const penCommit = state();
return { events, twoFinger, touchCancel, penCommit };
});
await context.close();
return result;
};
const backends = { main: await runScenario(false), offscreen: await runScenario(true) };
for (const result of Object.values(backends)) {
assert.equal(result.events.length, 7);
assert.equal(result.twoFinger.navigationRevision, 1);
assert.equal(result.twoFinger.activePointerIds, "2,4");
assert.equal(result.twoFinger.mainCommitCount, 0);
assert.equal(result.touchCancel.cancelled, "1");
assert.equal(result.touchCancel.activePointerIds, "");
assert.equal(result.touchCancel.mainCommitCount, 0);
assert.equal(result.penCommit.mainCommitCount, 1);
}
const report = { schemaVersion: 1, task: "M14-04F", operation: "CHROMIUM_INPUT_MODAL_BOUNDARY", runtime: "PLAYWRIGHT_CHROMIUM", backends, guarantees: { touchCancelMainCommit: 0, twoFingerNavigationRevision: 1, penMainCommit: 1 }, execution: "DISABLED", nextTask: "M14-04G" };
const sha256 = (file) => crypto.createHash("sha256").update(fs.readFileSync(file)).digest("hex");
const relative = (file) => path.relative(root, file).replaceAll(path.sep, "/");
if (process.env.UPDATE_M14_04F_REPORT === "1") { fs.mkdirSync(path.dirname(reportPath), { recursive: true }); fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); const artifactPaths = { parentManifest: path.join(root, "tests/golden/M14-04E/manifest.json"), checker: path.join(root, "tools/web/check-chromium-input-modal.mjs"), protocol: path.join(root, "web/protocol/input-modal.ts"), unit: path.join(root, "web/tests/unit/input-modal.test.mjs"), package: path.join(root, "web/package.json"), report: reportPath }; const artifacts = Object.fromEntries(Object.entries(artifactPaths).map(([name, file]) => [name, { path: relative(file), sha256: sha256(file) }])); fs.writeFileSync(manifestPath, `${JSON.stringify({ schemaVersion: 1, task: "M14-04F", parentTask: "M14-04E", enablingTask: false, parityStateChange: false, runtime: "PLAYWRIGHT_CHROMIUM", operation: "CHROMIUM_INPUT_MODAL_BOUNDARY", artifacts, nextTask: "M14-04G" }, null, 2)}\n`); }
if (process.env.UPDATE_M14_04F_REPORT === "1") { fs.mkdirSync(path.dirname(reportPath), { recursive: true }); fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`); const artifactPaths = { parentManifest: path.join(root, "tests/golden/M14-04E/manifest.json"), checker: path.join(root, "tools/web/check-chromium-input-modal.mjs"), protocol: path.join(root, "web/protocol/input-modal.ts"), unit: path.join(root, "web/tests/unit/input-modal.test.mjs"), mainViewport: path.join(root, "web/app/src/three-adapter/viewport.ts"), offscreenViewport: path.join(root, "web/app/src/three-adapter/offscreen-viewport.ts"), package: path.join(root, "web/package.json"), report: reportPath }; const artifacts = Object.fromEntries(Object.entries(artifactPaths).map(([name, file]) => [name, { path: relative(file), sha256: sha256(file) }])); fs.writeFileSync(manifestPath, `${JSON.stringify({ schemaVersion: 1, task: "M14-04F", parentTask: "M14-04E", enablingTask: false, parityStateChange: false, runtime: "PLAYWRIGHT_CHROMIUM", operation: "CHROMIUM_INPUT_MODAL_BOUNDARY", artifacts, nextTask: "M14-04G" }, null, 2)}\n`); }
assert.deepEqual(JSON.parse(fs.readFileSync(reportPath, "utf8")), report);
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
assert.deepEqual({ task: manifest.task, parentTask: manifest.parentTask, nextTask: manifest.nextTask }, { task: "M14-04F", parentTask: "M14-04E", nextTask: "M14-04G" });
for (const artifact of Object.values(manifest.artifacts)) assert.equal(sha256(path.join(root, artifact.path)), artifact.sha256, artifact.path);
process.stdout.write(`chromium-input-modal-ok touchCancel=0 twoFingerRevision=1 penCommit=1 execution=DISABLED next=${manifest.nextTask}\n`);
process.stdout.write(`chromium-input-modal-ok backends=main,offscreen touchCancel=0 twoFingerRevision=1 penCommit=1 execution=DISABLED next=${manifest.nextTask}\n`);
} finally { await browser?.close(); await new Promise((resolve) => server.close(resolve)); }