mirror of
https://github.com/morluto/rea
synced 2026-10-26 22:28:27 -04:00
fix(javascript): preserve effective child-process stdio options (#4336)
* fix(javascript): preserve effective child-process stdio options * fix(javascript): retain proven callbacks and primitive stdio keys * fix(javascript): preserve argv shapes and nullish spreads * fix(javascript): bound callable proofs and retain exposed binding uncertainty * test(javascript): keep callback acceptance within transport budget * test(javascript): inspect application coverage for callback proof limits * fix(javascript): keep spread command argument slots uncertain * fix(javascript): bound mapped argument content proofs * fix(javascript): distinguish erased declarations from runtime shadows * fix(javascript): prove runtime module context before binding isolation * fix(javascript): share erased declaration and opaque scope proofs * fix(javascript): keep lowered enum scopes opaque * fix(javascript): narrow stdio proofs and consolidate regressions * perf(javascript): reuse lexical references for child shapes * fix(javascript): retain CommonJS child argument context * fix(javascript): keep Annex B affected child arguments unknown * fix(javascript): recognize value import-equals runtime modules * fix(javascript): retain exact stdio through module and primitive syntax * fix(javascript): bound inline spread property resolution * fix(javascript): distinguish copied methods from getters
This commit is contained in:
@@ -1,8 +1,79 @@
|
||||
import { parse, type ParserOptions, type ParserPlugin } from "@babel/parser";
|
||||
import * as t from "@babel/types";
|
||||
import {
|
||||
hasOnlyInlineTypeExportSpecifiers,
|
||||
hasOnlyInlineTypeImportSpecifiers,
|
||||
isTypeOnlyExportDeclaration,
|
||||
isTypeOnlyImportDeclaration,
|
||||
isErasedJavaScriptDeclaration,
|
||||
semanticImportEqualsSpecifier,
|
||||
} from "./javascriptModuleDeclaration.js";
|
||||
|
||||
/** Babel AST produced by REA's inert JavaScript parser boundary. */
|
||||
export type ParsedJavaScriptSource = ReturnType<typeof parse>;
|
||||
|
||||
// Babel's module classification includes erased TypeScript syntax. Keep the
|
||||
// runtime proof separate, including explicit filename mode, for every parser entry.
|
||||
type JavaScriptRuntimeContext = "module" | "commonjs" | "unknown";
|
||||
const runtimeContextByProgram = new WeakMap<
|
||||
t.Program,
|
||||
JavaScriptRuntimeContext
|
||||
>();
|
||||
|
||||
/** Only parser-owned facts establish module or CommonJS wrapper isolation. */
|
||||
export const javaScriptRuntimeContext = (
|
||||
program: t.Program,
|
||||
): JavaScriptRuntimeContext =>
|
||||
runtimeContextByProgram.get(program) ?? "unknown";
|
||||
|
||||
const hasRuntimeModuleDeclaration = (program: t.Program): boolean =>
|
||||
program.body.some((node) => {
|
||||
if (t.isTSImportEqualsDeclaration(node))
|
||||
return semanticImportEqualsSpecifier(node) !== null;
|
||||
if (t.isImportDeclaration(node))
|
||||
return (
|
||||
!isTypeOnlyImportDeclaration(node) &&
|
||||
!hasOnlyInlineTypeImportSpecifiers(node)
|
||||
);
|
||||
if (t.isExportNamedDeclaration(node) || t.isExportAllDeclaration(node))
|
||||
return (
|
||||
!isTypeOnlyExportDeclaration(node) &&
|
||||
(!t.isExportNamedDeclaration(node) ||
|
||||
(!hasOnlyInlineTypeExportSpecifiers(node) &&
|
||||
(node.declaration == null ||
|
||||
!isErasedJavaScriptDeclaration(node.declaration))))
|
||||
);
|
||||
return (
|
||||
t.isExportDefaultDeclaration(node) &&
|
||||
!isErasedJavaScriptDeclaration(node.declaration)
|
||||
);
|
||||
});
|
||||
|
||||
const parseWithRuntimeContext = (
|
||||
source: string,
|
||||
sourcePath: string | undefined,
|
||||
options: ParserOptions,
|
||||
): ParsedJavaScriptSource => {
|
||||
const file = parse(source, options);
|
||||
runtimeContextByProgram.set(
|
||||
file.program,
|
||||
/\.c[jt]s$/iu.test(sourcePath ?? "")
|
||||
? /\.d\.cts$/iu.test(sourcePath ?? "")
|
||||
? "unknown"
|
||||
: "commonjs"
|
||||
: isExplicitModuleSourcePath(sourcePath)
|
||||
? "module"
|
||||
: file.program.body.some((node) => t.isTSExportAssignment(node))
|
||||
? // CommonJS isolation does not establish strict ESM semantics.
|
||||
"commonjs"
|
||||
: file.program.sourceType === "module" &&
|
||||
hasRuntimeModuleDeclaration(file.program)
|
||||
? "module"
|
||||
: "unknown",
|
||||
);
|
||||
return file;
|
||||
};
|
||||
|
||||
/**
|
||||
* Babel plugins for one source path. Single owner for TypeScript/JSX
|
||||
* mode selection (tsc + Babel `typescript` plugin semantics).
|
||||
@@ -82,7 +153,7 @@ export const parseRecoveredJavaScript = (
|
||||
delete normalizedOptions.allowNewTargetOutsideFunction;
|
||||
}
|
||||
return {
|
||||
file: parse(source, {
|
||||
file: parseWithRuntimeContext(source, sourcePath, {
|
||||
...normalizedOptions,
|
||||
sourceType,
|
||||
errorRecovery: true,
|
||||
@@ -90,14 +161,14 @@ export const parseRecoveredJavaScript = (
|
||||
moduleOnlyErrors: [],
|
||||
};
|
||||
}
|
||||
const file = parse(source, {
|
||||
const file = parseWithRuntimeContext(source, sourcePath, {
|
||||
...options,
|
||||
sourceType: "unambiguous",
|
||||
errorRecovery: true,
|
||||
});
|
||||
if (file.program.sourceType !== "script" || file.errors.length === 0)
|
||||
return { file, moduleOnlyErrors: [] };
|
||||
const script = parse(source, {
|
||||
const script = parseWithRuntimeContext(source, sourcePath, {
|
||||
...options,
|
||||
sourceType: "script",
|
||||
errorRecovery: true,
|
||||
@@ -124,7 +195,7 @@ export const parseJavaScriptSource = (
|
||||
attachComment: false,
|
||||
plugins: parserPluginsForPath(sourcePath),
|
||||
};
|
||||
const file = parse(source, {
|
||||
const file = parseWithRuntimeContext(source, sourcePath, {
|
||||
...options,
|
||||
// Inert artifact analysis retains module declarations even in .cjs assets.
|
||||
// Infer their syntax here; reference imports keep filename-mode diagnostics.
|
||||
@@ -137,7 +208,10 @@ export const parseJavaScriptSource = (
|
||||
return commonjs &&
|
||||
file.program.sourceType === "script" &&
|
||||
file.errors.length > 0
|
||||
? parse(source, { ...options, sourceType: "commonjs" })
|
||||
? parseWithRuntimeContext(source, sourcePath, {
|
||||
...options,
|
||||
sourceType: "commonjs",
|
||||
})
|
||||
: file;
|
||||
} catch (cause: unknown) {
|
||||
// Unparseable source is represented by the null return.
|
||||
|
||||
Reference in New Issue
Block a user