fix(browser): avoid esbuild __name helper in evaluateViaPlaywright
When tsx/esbuild compiles arrow functions, it adds a __name helper for debugging. This helper doesn't exist in the browser context, causing 'ReferenceError: __name is not defined' when using page.evaluate() with inline functions. The fix uses new Function() constructed at runtime, which esbuild doesn't transform, avoiding the __name injection.
This commit is contained in:
@@ -211,49 +211,38 @@ export async function evaluateViaPlaywright(opts: {
|
|||||||
ensurePageState(page);
|
ensurePageState(page);
|
||||||
if (opts.ref) {
|
if (opts.ref) {
|
||||||
const locator = refLocator(page, opts.ref);
|
const locator = refLocator(page, opts.ref);
|
||||||
return await locator.evaluate((el, fnBody) => {
|
// Use Function constructor at runtime to avoid esbuild adding __name helper
|
||||||
const compileRunner = (body: string) => {
|
// which doesn't exist in the browser context
|
||||||
const inner = `"use strict"; const candidate = ${body}; return typeof candidate === "function" ? candidate(element) : candidate;`;
|
const elementEvaluator = new Function(
|
||||||
// This intentionally evaluates user-supplied code in the browser context.
|
"el",
|
||||||
// oxlint-disable-next-line typescript-eslint/no-implied-eval
|
"fnBody",
|
||||||
return new Function("element", inner) as (element: Element) => unknown;
|
`
|
||||||
};
|
"use strict";
|
||||||
let compiled: unknown;
|
|
||||||
try {
|
try {
|
||||||
compiled = compileRunner(fnBody);
|
var candidate = eval("(" + fnBody + ")");
|
||||||
|
return typeof candidate === "function" ? candidate(el) : candidate;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const message =
|
throw new Error("Invalid evaluate function: " + (err && err.message ? err.message : String(err)));
|
||||||
err instanceof Error
|
|
||||||
? err.message
|
|
||||||
: typeof err === "string"
|
|
||||||
? err
|
|
||||||
: "invalid expression";
|
|
||||||
throw new Error(`Invalid evaluate function: ${message}`);
|
|
||||||
}
|
}
|
||||||
return (compiled as (element: Element) => unknown)(el as Element);
|
`,
|
||||||
}, fnText);
|
) as (el: Element, fnBody: string) => unknown;
|
||||||
|
return await locator.evaluate(elementEvaluator, fnText);
|
||||||
}
|
}
|
||||||
return await page.evaluate((fnBody) => {
|
// Use Function constructor at runtime to avoid esbuild adding __name helper
|
||||||
const compileRunner = (body: string) => {
|
// which doesn't exist in the browser context
|
||||||
const inner = `"use strict"; const candidate = ${body}; return typeof candidate === "function" ? candidate() : candidate;`;
|
const browserEvaluator = new Function(
|
||||||
// This intentionally evaluates user-supplied code in the browser context.
|
"fnBody",
|
||||||
// oxlint-disable-next-line typescript-eslint/no-implied-eval
|
`
|
||||||
return new Function(inner) as () => unknown;
|
"use strict";
|
||||||
};
|
|
||||||
let compiled: unknown;
|
|
||||||
try {
|
try {
|
||||||
compiled = compileRunner(fnBody);
|
var candidate = eval("(" + fnBody + ")");
|
||||||
|
return typeof candidate === "function" ? candidate() : candidate;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const message =
|
throw new Error("Invalid evaluate function: " + (err && err.message ? err.message : String(err)));
|
||||||
err instanceof Error
|
|
||||||
? err.message
|
|
||||||
: typeof err === "string"
|
|
||||||
? err
|
|
||||||
: "invalid expression";
|
|
||||||
throw new Error(`Invalid evaluate function: ${message}`);
|
|
||||||
}
|
}
|
||||||
return (compiled as () => unknown)();
|
`,
|
||||||
}, fnText);
|
) as (fnBody: string) => unknown;
|
||||||
|
return await page.evaluate(browserEvaluator, fnText);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function armFileUploadViaPlaywright(opts: {
|
export async function armFileUploadViaPlaywright(opts: {
|
||||||
|
|||||||
Reference in New Issue
Block a user