mirror of
https://github.com/morluto/rea.git
synced 2026-11-12 01:41:21 +00:00
fix(javascript): preserve loader authority for exact suffixes (#9477)
* fix(javascript): require exact loader suffix case * fix(javascript): share exact loader mode across import resolution * test(process): align symlink fixture with filesystem checkpoints * test(javascript): normalize the module resolution oracle path separators * test(frida): assert the CLI spawn Evidence contract * test(mcp): use an unsupported analysis-view parent * test(browser): separate source-location line bounds from parity * fix(javascript): preserve uncertain loader provenance * test(javascript): cover uncertain require resolution * fix(javascript): retain conditional Electron evidence * fix(javascript): preserve timed semantic provenance * fix(javascript): retain conditional builtin effects * test(javascript): distinguish bundled host authority * fix(javascript): preserve nested loader invocation identity * test(javascript): qualify Electron fixture authority * fix(javascript): preserve loader invocation authority * fix(javascript): respect source order for resolver escapes * fix(javascript): check nested loader callable mutations * fix(javascript): retain conditional constructor requests * fix(reference): retain constructor loader relationships * fix(reference): follow nested loader callable paths * refactor(javascript): share callable mutation interpretation * fix(javascript): require exact package loader suffixes * refactor(javascript): unify conditional relation evidence * refactor(javascript): unify conditional node evidence * fix(javascript): retain unknown authority for mixed case sources * fix(javascript): preserve loader uncertainty for dotfiles * fix(reference): classify javascript suffix dotfiles * test(reference): cover suffix dotfiles through cli * fix(javascript): retain equivalent conditional built-in origins * fix(javascript): preserve wrapped resolver operation * fix(javascript): retain nested conditional built-in receivers * test(javascript): declare CommonJS in native addon fixtures * fix(javascript): retain wrapped resolver candidates * style: format merged native command schema * fix(javascript): preserve uncertain loader authority * test(javascript): require candidate preload evidence * test(javascript): cover reference loader member writes --------- Co-authored-by: ShuaixinHuang <1836656514@qq.com>
This commit is contained in:
1 parent
78a84d75c0
commit
b46f4fcebd
112 files changed
+5156
-797
No files matched your search
@@ -24,7 +24,7 @@ import { isUnmodifiedGlobalReference } from "./javascriptSemanticAmbientWrites.j
|
||||
import { semanticOpaqueNameMayHaveChanged } from "./javascriptSemanticOpaqueEffects.js";
|
||||
import { range } from "./javascriptStaticAnalysisHelpers.js";
|
||||
import {
|
||||
builtinDataEffectMethod,
|
||||
builtinDataEffectIdentity,
|
||||
dataEffectArgumentBindingId,
|
||||
dataEffectLiteralString,
|
||||
dataEffectMemberCallee,
|
||||
@@ -92,6 +92,7 @@ interface AsyncEffectAnalysis {
|
||||
}
|
||||
|
||||
interface TimerCandidate {
|
||||
readonly builtinAuthority?: "candidate";
|
||||
readonly node: t.CallExpression | t.OptionalCallExpression;
|
||||
readonly method: JavaScriptSemanticTimerOperation["method"];
|
||||
readonly kind: JavaScriptSemanticTimerOperation["kind"];
|
||||
@@ -306,20 +307,25 @@ const emitterIdentity = (
|
||||
};
|
||||
|
||||
/**
|
||||
* A timer proven to come from the Node `timers` module rather than a bare
|
||||
* global. Browser and Electron renderer sources reach this analysis without a
|
||||
* Node/browser distinction, and there `setTimeout("refresh()", 0)` is a real
|
||||
* A timer associated with the Node `timers` module, either proven or
|
||||
* conditional, rather than a bare global. Browser and Electron renderer sources
|
||||
* reach this analysis without a Node/browser distinction, and there `setTimeout("refresh()", 0)` is a real
|
||||
* timer: the string is evaluated by the host. Node's callback rule therefore
|
||||
* applies only when the timer is imported from `node:timers`, where that form
|
||||
* cannot exist.
|
||||
* applies when interpreting the call as `node:timers`, where that form
|
||||
* cannot create a Node timer even if the module identity is conditional.
|
||||
*/
|
||||
const nodeBuiltinTimerMethod = (
|
||||
callee: t.Node,
|
||||
state: JavaScriptSemanticAnalysisState,
|
||||
): JavaScriptSemanticTimerOperation["method"] | null =>
|
||||
admittedTimerMethod(
|
||||
builtinDataEffectMethod(callee, state, ["timers", "node:timers"]) ?? "",
|
||||
): JavaScriptSemanticTimerOperation["method"] | null => {
|
||||
const identity = builtinDataEffectIdentity(callee, state, [
|
||||
"timers",
|
||||
"node:timers",
|
||||
]);
|
||||
return admittedTimerMethod(
|
||||
identity?.path.length === 1 ? (identity.path[0] ?? "") : "",
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* A schedule imported from Node's `timers` module requires a function in
|
||||
@@ -370,8 +376,9 @@ const schedulesWithNonFunctionCallback = (
|
||||
|
||||
const collectTimer = (input: TimerCollectionInput): void => {
|
||||
const { node, ownerCallableId, state, output, ancestors } = input;
|
||||
const method = timerMethod(node.callee, state);
|
||||
if (method === null) return;
|
||||
const identity = timerMethod(node.callee, state);
|
||||
if (identity === null) return;
|
||||
const { method, builtinAuthority } = identity;
|
||||
if (
|
||||
TIMER_SCHEDULE_METHODS.some((candidate) => candidate === method) &&
|
||||
nodeBuiltinTimerMethod(node.callee, state) !== null &&
|
||||
@@ -421,6 +428,7 @@ const collectTimer = (input: TimerCollectionInput): void => {
|
||||
output.push({
|
||||
node,
|
||||
method,
|
||||
...(builtinAuthority === undefined ? {} : { builtinAuthority }),
|
||||
kind,
|
||||
ownerCallableId,
|
||||
handleBindingId:
|
||||
@@ -467,6 +475,10 @@ const resolveTimers = (
|
||||
candidate.handleRead !== null &&
|
||||
candidate.handleRead.origins.length !== linked.length;
|
||||
return {
|
||||
...(candidate.builtinAuthority === "candidate" ||
|
||||
linked.some((item) => item.builtinAuthority === "candidate")
|
||||
? { builtinAuthority: "candidate" as const }
|
||||
: {}),
|
||||
timerId: timerId(candidate),
|
||||
kind: candidate.kind,
|
||||
method: candidate.method,
|
||||
@@ -499,7 +511,10 @@ const resolveTimers = (
|
||||
const timerMethod = (
|
||||
callee: t.Node,
|
||||
state: JavaScriptSemanticAnalysisState,
|
||||
): JavaScriptSemanticTimerOperation["method"] | null => {
|
||||
): {
|
||||
readonly method: JavaScriptSemanticTimerOperation["method"];
|
||||
readonly builtinAuthority?: "candidate";
|
||||
} | null => {
|
||||
if (t.isIdentifier(callee)) {
|
||||
const binding = resolveSemanticBindingState(state, callee, callee.name);
|
||||
if (binding === undefined) {
|
||||
@@ -508,12 +523,24 @@ const timerMethod = (
|
||||
return semanticResolutionBlocked(state, callee, callee.name) ||
|
||||
!isUnmodifiedGlobalReference(callee, state, callee.name)
|
||||
? null
|
||||
: method;
|
||||
: { method };
|
||||
}
|
||||
}
|
||||
return admittedTimerMethod(
|
||||
builtinDataEffectMethod(callee, state, ["timers", "node:timers"]) ?? "",
|
||||
const identity = builtinDataEffectIdentity(callee, state, [
|
||||
"timers",
|
||||
"node:timers",
|
||||
]);
|
||||
const method = admittedTimerMethod(
|
||||
identity?.path.length === 1 ? (identity.path[0] ?? "") : "",
|
||||
);
|
||||
return method === null
|
||||
? null
|
||||
: {
|
||||
method,
|
||||
...(identity?.builtinAuthority === undefined
|
||||
? {}
|
||||
: { builtinAuthority: identity.builtinAuthority }),
|
||||
};
|
||||
};
|
||||
const admittedTimerMethod = (
|
||||
value: string,
|
||||
|
||||
Reference in new issue
Block a user