fix(javascript): preserve runtime path bytes and Electron ownership (#4941)

* fix(javascript): preserve literal percent runtime paths

* fix(javascript): ignore resolve prefixes before the final anchor

* fix(electron): retain application roots for loadFile declarations

* fix(electron): resolve loadFile from enclosing application package

* fix(electron): retain outer application root across package scopes

* fix(electron): derive application ownership from inventoried packages

* fix(electron): retain resolved package entrypoint ownership

* fix(electron): preserve competing application ownership

* fix(electron): retain invalid and omitted runtime ownership

* fix(electron): preserve omitted module ownership and runtime paths

* fix(electron): preserve proven roots before confining page paths

* fix(electron): retain possible owners behind missing imports

* fix(electron): distinguish absent imports and owned page candidates

* fix(electron): keep unavailable JSON out of owner gaps

* fix(electron): retain exact loader formats and default entry status

* fix(electron): retain unavailable entrypoint ownership candidates

* test(ghidra): preserve Windows Node probe prerequisites

* test(ghidra): assert cancellation during profile shutdown

* fix(electron): separate examined imports from frontend ownership

* fix(electron): retain unavailable directory entrypoint owners

* test(jeb): retain Linux ownership prerequisite in isolation

* fix(javascript): retain unchecked loader ownership and literal main paths

* fix(javascript): preserve runtime paths and call-site module aliases

* fix(javascript): bound module alias traversal and preserve projections

* fix(javascript): retain host module and nested artifact path boundaries

* fix(javascript): preserve ESM and archive module loader provenance

* test(javascript): distinguish unmapped containers from missing exports

* fix: retain default module aliases and Electron builtin imports

* fix: preserve host file URL and inward ASAR ownership

* fix: preserve CommonJS file URL classification in CI fixtures

* fix: retain bound module loaders and Windows entrypoint uncertainty

* fix: retain ASAR uncertainty and invalidate changed Electron app roots

* fix(javascript): retain ownership uncertainty across loader boundaries

* fix(javascript): preserve loader sources and bound alias queries

* fix(javascript): retain destructured loader sources

* fix(javascript): preserve loader uncertainty at resolution boundaries

* fix(javascript): preserve callable and package launch ownership

* fix(javascript): preserve captured values across member reads

* test(process): assert tagged filesystem cancellation failures

* fix(javascript): preserve inventory bases and invocation read timing

* fix(javascript): preserve ownership across indirect and unread loads

* test(javascript): order fixture directory creation on Windows

* test(javascript): share ordered filesystem fixture writer

* fix(javascript): unify loader provenance and package validation

* fix(javascript): preserve captured Node require loader values

* fix(javascript): preserve loader invocation authority

* fix(javascript): verify generic loader invocation authority

* fix(javascript): preserve conditional loader method alternatives

* fix(javascript): require proven factories for source association

* fix(javascript): honor replaced Electron app path setters

* fix(javascript): prove path and assignment source ownership

* fix(javascript): retain native delegate eligibility through shared writes

* fix(process): settle stale baseline errors after confirmed absence

* fix(javascript): preserve assignment and path boundary evidence

* fix(javascript): prove source-directory resolve anchors

* fix: preserve application path provenance and portable schemas

* fix(javascript): retain CommonJS exported setter effects

* fix: isolate Linux identity observations and retain native module exports

* fix(javascript): preserve published app and helper provenance

* fix(javascript): normalize typed stores and native path fixtures
This commit is contained in:
ShuaixinHuang authored and GitHub committed 2026-10-20 17:25:19 +08:00
1 parent d532b18123
commit e9fc8fb30c
149 files changed
+16881 -988

No files matched your search

@@ -0,0 +1,180 @@
import { expect, it } from "vitest";
import * as t from "@babel/types";
import { analyzeJavaScriptStaticSource } from "./javascriptStaticAnalysis.js";
import { parseJavaScriptSource } from "./javascriptSourceParser.js";
import { indexJavaScriptBindingsWithReceiversSteps } from "./javascriptSemanticAnalysis.js";
import { completeSemanticSteps } from "./javascriptSemanticTraversal.js";
import { createSemanticReturnedReferences } from "./javascriptSemanticReturnedReferences.js";
it.each([
["const get=()=>module;get.call(null)", true],
["const get=()=>module;get.apply(null,[])", true],
["const get=()=>module;get['call'](null)", true],
["const get=()=>module;const alias=get;alias.apply(null,[])", true],
["const box={get(){return module;}};box.get.call(null)", true],
["const get=()=>module;get.call.call(get,null)", true],
["const get=()=>module;get.apply.call(get,null,[])", true],
["const get=()=>module;const invoke=get.call;invoke.call(get,null)", true],
[
"const get=()=>module;const invoke=get.call;const other=()=>({});invoke.call(other,null)",
false,
],
[
"const get=()=>({});const invoke=get.call;const other=()=>module;invoke.call(other,null)",
true,
],
[
"const get=()=>module;const invoke=get.apply;invoke.call(get,null,[])",
true,
],
["const get=()=>module;const invoke=get.call;invoke.apply(get,[null])", true],
["const get=()=>({});get.call(null)", false],
["const get=()=>({});get.apply(null,[])", false],
["const get=()=>module.exports;get.call(null)", false],
["const get=()=>module;get.call=()=>({require(){}});get.call(null)", false],
[
"const get=()=>module;get.apply=()=>({require(){}});get.apply(null,[])",
false,
],
["const get=()=>({});get.call=()=>module;get.call(null)", true],
["const get=()=>({});get.apply=()=>module;get.apply(null,[])", true],
["const get=()=>module;const invoke=get.call;invoke(get)", false],
["const get=()=>module;(0,get.call)(null)", false],
["const get=()=>module;(0,get.apply)(null,[])", false],
[
"const get=()=>module;const other=()=>({});get.call.call(other,null)",
false,
],
["const get=()=>({});const other=()=>module;get.call.call(other,null)", true],
["function* get(){yield module;}get.call(null)", false],
["async function get(){return module;}get.apply(null,[])", false],
["async function get(){return module;}(await get.call(null))", true],
["const get=()=>module;get.call=unknown;get.call(null)", true],
["const get=()=>module;if(flag)get.call=()=>({});get.call(null)", true],
[
"const get=()=>({});Object.setPrototypeOf(get,{call:()=>module});get.call(null)",
true,
],
[
"const get=()=>module;Object.setPrototypeOf(get,{call:()=>({})});get.call(null)",
true,
],
[
"const get=()=>1;Object.setPrototypeOf(get,{call:()=>module});get.call(null)",
true,
],
[
"const get=()=>({});Object.setPrototypeOf(get,{call:()=>module});get.call=()=>({});get.call(null)",
false,
],
[
"const get=()=>({});Object.setPrototypeOf(get,{call:()=>({})});get.call=()=>module;get.call(null)",
true,
],
])(
"retains invocation results after selecting source-local member identity: %s",
(receiver, expected) => {
const analysis = analyzeJavaScriptStaticSource(
`${receiver}.require('./shared.cjs');`,
);
expect(analysis.parse_error_count).toBe(0);
expect(analysis.references).toEqual(
expected
? [expect.objectContaining({ kind: "require", specifier: null })]
: [],
);
},
);
it.each([
["Function.prototype.call=unknown;const get=()=>({});get.call(null)", true],
[
"Function.prototype.apply=unknown;const get=()=>({});get.apply(null,[])",
true,
],
[
"Function.prototype.call=unknown;const get=()=>module;get.call=()=>({});get.call(null)",
false,
],
["Function.prototype.extra=unknown;const get=()=>({});get.call(null)", false],
])(
"retains inherited invocation uncertainty without revoking own slots: %s",
(receiver, expected) => {
const analysis = analyzeJavaScriptStaticSource(
`${receiver}.require('./shared.cjs');`,
);
expect(analysis.parse_error_count).toBe(0);
expect(analysis.references).toEqual(
expected ? [expect.objectContaining({ specifier: null })] : [],
);
},
);
it("keeps source reads before later function-method replacement", () => {
const analysis = analyzeJavaScriptStaticSource(`
const get=()=>module;
get.call(null).require('./shared.cjs');
get.call=()=>({});
get.call(null).require('./unused.cjs');
`);
expect(analysis.references).toEqual([
expect.objectContaining({ specifier: null }),
]);
});
it("keeps an earlier native invocation before a later prototype write", () => {
const analysis = analyzeJavaScriptStaticSource(`
const get=()=>({});
get.call(null).require('./unused.cjs');
Function.prototype.call=unknown;
`);
expect(analysis.references).toEqual([]);
});
it("does not treat a shadowed Function namespace as native prototype mutation", () => {
const analysis = analyzeJavaScriptStaticSource(`
function local(Function){
Function.prototype.call=unknown;
const get=()=>({});
get.call(null).require('./unused.cjs');
}
`);
expect(analysis.references).toEqual([]);
});
it("retains a finite shared callable alias graph", () => {
const aliases = Array.from(
{ length: 64 },
(_, index) => `const get${index + 1}=flag?get${index}:get${index};`,
).join("");
const parsed = parseJavaScriptSource(
`const get0=()=>module;${aliases}get64.apply(null,[]);`,
);
if (parsed === null) throw new Error("Expected valid shared alias fixture");
const index = completeSemanticSteps(
indexJavaScriptBindingsWithReceiversSteps(parsed.program),
);
completeSemanticSteps(index.indexAmbientWritesSteps());
completeSemanticSteps(index.indexMemberMutationFactsSteps());
const statement = parsed.program.body.at(-1);
if (
!t.isExpressionStatement(statement) ||
!t.isCallExpression(statement.expression)
)
throw new Error("Expected final invocation");
const call = statement.expression;
const result = createSemanticReturnedReferences(
index.bindings,
"direct-call",
)(call.callee, call);
expect(result).toEqual({
references: [
{
node: expect.objectContaining({ type: "Identifier", name: "module" }),
projection: [],
},
],
precision: "exact",
});
});