返回 DeepSeek-Reasonix
playwright-page-resource.mjs
根目录 / desktop / electron / scripts / playwright-page-resource.mjs
1 import { readFile, copyFile } from "node:fs/promises";
2 import { createRequire } from "node:module";
3 import { dirname, join } from "node:path";
4 import { runInNewContext } from "node:vm";
5 import ts from "typescript";
6
7 export async function playwrightPageResource(dist) {
8 const require = createRequire(import.meta.url);
9 const core = createRequire(require.resolve("playwright/package.json")).resolve("playwright-core/package.json");
10 const version = JSON.parse(await readFile(core, "utf8")).version;
11 if (version !== "1.62.1") throw new Error(`Unqualified Playwright injected runtime version: ${version}`);
12 const file = ts.createSourceFile("coreBundle.js", await readFile(join(dirname(core), "lib/coreBundle.js"), "utf8"), ts.ScriptTarget.Latest, true);
13 const candidates = [];
14 function visit(node) {
15 if (ts.isStringLiteral(node) && node.text.includes("injectedScript_exports") && node.text.includes("generateAriaTree")) candidates.push(node.text);
16 ts.forEachChild(node, visit);
17 }
18 visit(file);
19 if (candidates.length !== 1) throw new Error("Playwright injected resource export contract changed");
20 let source = candidates[0];
21 // 1.62.1 serializes text-input values. Never expose password values, including
22 // an explicitly role=textbox password. This reviewed adapter is version bound.
23 const valueCondition = 'element.type !== "checkbox" && element.type !== "radio" && element.type !== "file"';
24 if (source.split(valueCondition).length !== 2) throw new Error("Playwright password redaction contract changed");
25 source = source.replace(valueCondition, `${valueCondition} && element.type !== "password"`);
26 // The generated export table contains getter functions, not constructors.
27 source += "\nmodule.exports = { InjectedScript: module.exports.InjectedScript() };\n";
28 const module = { exports: {} };
29 runInNewContext(source, { module }, { timeout: 1000 });
30 const prototype = module.exports.InjectedScript?.prototype;
31 for (const method of ["ariaSnapshotWithRefs", "parseSelector", "querySelectorAll", "elementState"]) {
32 if (typeof prototype?.[method] !== "function") throw new Error(`Playwright contract missing ${method}`);
33 }
34 await copyFile(join(dirname(core), "LICENSE"), join(dist, "browser-playwright-LICENSE"));
35 await copyFile(join(dirname(core), "NOTICE"), join(dist, "browser-playwright-NOTICE"));
36 return { version, source };
37 }
38
38 lines Plain Text