Files
rea/src/domain/javascript/electronIntrinsicCapture.test.ts
T

135 lines
5.1 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { ROLLDOWN_MODULE_INTEROP } from "./javascriptModuleInterop.fixture.js";
import { analyzeJavaScriptStaticSource } from "./javascriptStaticAnalysis.js";
const CAPTURED_INTEROP = ROLLDOWN_MODULE_INTEROP.replace(
"__defProp = Object.defineProperty",
"__defProp = define",
);
const WINDOW = `let electron = require("electron");
electron = __toESM(electron, 1); new electron.BrowserWindow({});`;
describe("captured intrinsic invocation reads", () => {
it("evaluates assignment operands before recording their writes", () => {
const result = analyzeJavaScriptStaticSource(`
const define = Object.defineProperty;
const metadata = {};
Object.defineProperty = (Object.defineProperty(metadata, "x", {value:1}), replacement);
${CAPTURED_INTEROP} ${WINDOW}
`);
expect(result.electron.browser_windows).toHaveLength(1);
});
it("retains whole-object mutations at a captured function's later member read", () => {
const result = analyzeJavaScriptStaticSource(`
const define = Object.defineProperty;
Object.assign(define, {call: replacement});
const metadata = {}; define.call(null, metadata, "x", {value:1});
${CAPTURED_INTEROP} ${WINDOW}
`);
expect(result.electron.browser_windows).toEqual([]);
});
it.each([
'(0, Object.defineProperty.call)(null,Object,"create",{value:replacement});',
'(0, Object.defineProperty.apply)(null,[Object,"create",{value:replacement}]);',
])(
"does not invent a receiver for a detached invocation member: %s",
(invoke) => {
const result = analyzeJavaScriptStaticSource(`
${invoke}
${ROLLDOWN_MODULE_INTEROP} ${WINDOW}
`);
expect(result.electron.browser_windows).toHaveLength(1);
},
);
it("retains callee-prefix effects before classifying the invocation", () => {
const result = analyzeJavaScriptStaticSource(`
const define = Object.defineProperty;
const metadata = {};
(Object.defineProperty = replacement, Object.defineProperty)(metadata,"x",{value:1});
${CAPTURED_INTEROP} ${WINDOW}
`);
expect(result.electron.browser_windows).toEqual([]);
});
it("retains a callee selected before an argument replaces its global property", () => {
const result = analyzeJavaScriptStaticSource(`
const define = Object.defineProperty;
const metadata = {};
Object.defineProperty(metadata,"x",(Object.defineProperty = replacement,{value:1}));
${CAPTURED_INTEROP} ${WINDOW}
`);
expect(result.electron.browser_windows).toHaveLength(1);
});
it.each([
'define.call(null,metadata,"x",{value:1});',
'define.apply(null,[metadata,"x",{value:1}]);',
'const change = define.bind(null,metadata,"x"); change({value:1});',
'const also = define; also.call(null,metadata,"x",{value:1});',
])("retains a function captured before global replacement: %s", (invoke) => {
const result = analyzeJavaScriptStaticSource(`
const define = Object.defineProperty;
Object.defineProperty = replacement;
const metadata = {}; ${invoke}
${CAPTURED_INTEROP} ${WINDOW}
`);
expect(result.electron.browser_windows).toHaveLength(1);
});
it.each([
'const invoke = define.call; invoke(null,metadata,"x",{value:1});',
'const invoke = define.call; invoke.call(define,null,metadata,"x",{value:1});',
'(0, define.call).call(define,null,metadata,"x",{value:1});',
'const invoke = (0, define.call); const again = invoke; again.call(define,null,metadata,"x",{value:1});',
])("preserves the base capture through an invocation value: %s", (invoke) => {
const result = analyzeJavaScriptStaticSource(`
const define = Object.defineProperty;
Object.defineProperty = replacement;
const metadata = {}; ${invoke}
${CAPTURED_INTEROP} ${WINDOW}
`);
expect(result.electron.browser_windows).toHaveLength(1);
});
it.each(["define", "Function.prototype"])(
"retains an overwritten invocation member through an alias from %s",
(owner) => {
const result = analyzeJavaScriptStaticSource(`
const define = Object.defineProperty;
Object.defineProperty = replacement;
${owner}.call = replacement;
const invoke = define.call;
const metadata = {}; invoke.call(define,null,metadata,"x",{value:1});
${CAPTURED_INTEROP} ${WINDOW}
`);
expect(result.electron.browser_windows).toEqual([]);
},
);
it.each([
["call", 'define.call(null,metadata,"x",{value:1});'],
["apply", 'define.apply(null,[metadata,"x",{value:1}]);'],
[
"bind",
'const change = define.bind(null,metadata,"x"); change({value:1});',
],
])(
"checks the later %s property read on a captured function",
(method, invoke) => {
for (const owner of ["define", "Function.prototype"]) {
const result = analyzeJavaScriptStaticSource(`
const define = Object.defineProperty;
${owner}.${method} = replacement;
const metadata = {}; ${invoke}
${CAPTURED_INTEROP} ${WINDOW}
`);
expect(result.electron.browser_windows, owner).toEqual([]);
}
},
);
});