mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-28 06:53:42 +08:00
Parse npm-static declaration and package files only when a rewrite can apply (#2146)
This commit is contained in:
@@ -488,43 +488,33 @@ function visitNpmStaticDeclarationClosure(
|
||||
visit(entryPath);
|
||||
}
|
||||
|
||||
function npmStaticDeclarationOverloadsOf(
|
||||
/** The overloads and properties of the classes a package's declaration
|
||||
* closure declares, read from one parse of each declaration file. */
|
||||
function npmStaticDeclarationMetadataOf(
|
||||
services: FrontendServices,
|
||||
entryPath: string,
|
||||
): NpmStaticDeclarationOverloads {
|
||||
const classes = new Map<string, Map<string, readonly NpmStaticOverloadSignature[]>>();
|
||||
): { overloads: NpmStaticDeclarationOverloads; properties: NpmStaticDeclarationProperties } {
|
||||
const overloads = new Map<string, Map<string, readonly NpmStaticOverloadSignature[]>>();
|
||||
const properties = new Map<string, Map<string, string>>();
|
||||
visitNpmStaticDeclarationClosure(services, entryPath, (path, source) => {
|
||||
for (const [className, methods] of parseNpmStaticDeclarationOverloads(
|
||||
services.parse(path, source, "ts"),
|
||||
)) {
|
||||
const sourceFile = services.parse(path, source, "ts");
|
||||
for (const [className, methods] of parseNpmStaticDeclarationOverloads(sourceFile)) {
|
||||
const target =
|
||||
classes.get(className) ?? new Map<string, readonly NpmStaticOverloadSignature[]>();
|
||||
classes.set(className, target);
|
||||
overloads.get(className) ?? new Map<string, readonly NpmStaticOverloadSignature[]>();
|
||||
overloads.set(className, target);
|
||||
for (const [methodName, signatures] of methods) {
|
||||
if (!target.has(methodName)) target.set(methodName, signatures);
|
||||
}
|
||||
}
|
||||
});
|
||||
return classes;
|
||||
}
|
||||
|
||||
function npmStaticDeclarationPropertiesOf(
|
||||
services: FrontendServices,
|
||||
entryPath: string,
|
||||
): NpmStaticDeclarationProperties {
|
||||
const classes = new Map<string, Map<string, string>>();
|
||||
visitNpmStaticDeclarationClosure(services, entryPath, (path, source) => {
|
||||
for (const [className, properties] of parseNpmStaticDeclarationProperties(
|
||||
services.parse(path, source, "ts"),
|
||||
)) {
|
||||
const target = classes.get(className) ?? new Map<string, string>();
|
||||
classes.set(className, target);
|
||||
for (const [propertyName, type] of properties) {
|
||||
for (const [className, fields] of parseNpmStaticDeclarationProperties(sourceFile)) {
|
||||
const target = properties.get(className) ?? new Map<string, string>();
|
||||
properties.set(className, target);
|
||||
for (const [propertyName, type] of fields) {
|
||||
if (!target.has(propertyName)) target.set(propertyName, type);
|
||||
}
|
||||
}
|
||||
});
|
||||
return classes;
|
||||
return { overloads, properties };
|
||||
}
|
||||
|
||||
/** See LoadResult.startupCrash: Node's exact error message, the IR error
|
||||
@@ -1096,8 +1086,7 @@ export function loadProgram(
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
const overloads = npmStaticDeclarationOverloadsOf(services, resolved.typesFile);
|
||||
const properties = npmStaticDeclarationPropertiesOf(services, resolved.typesFile);
|
||||
const { overloads, properties } = npmStaticDeclarationMetadataOf(services, resolved.typesFile);
|
||||
const classNames = new Set([...overloads.keys(), ...properties.keys()]);
|
||||
if (classNames.size === 0) continue;
|
||||
const runtime = resolveBareModule(entryPath, pkg, "js-only");
|
||||
|
||||
@@ -20,6 +20,12 @@ import * as syntax from "./npm-static-declaration-syntax.js";
|
||||
import { normalizeCjsExportsVar } from "./npm-static-cjs-exports-var.js";
|
||||
import type { SourceFile } from "./ts7/ast-types.js";
|
||||
|
||||
/** Whether the source can contain `word` as a keyword or identifier: it
|
||||
* holds the word itself or a Unicode escape that might spell it. */
|
||||
function spells(source: string, word: string): boolean {
|
||||
return source.includes(word) || source.includes("\\u");
|
||||
}
|
||||
|
||||
/** Evaluate an isolated, self-contained TypeScript callback under a finite
|
||||
* budget. Hosts supply execution; shared lowering owns capture checks and
|
||||
* verifies the returned value before baking it into the program. */
|
||||
@@ -150,13 +156,18 @@ export class FrontendServices {
|
||||
return normalizeCjsExportsVar(this.parse(path, source, "js"));
|
||||
}
|
||||
nullableClassFields(path: string, source: string): syntax.NpmStaticOverloadRewrite | null {
|
||||
// Rewrites `null`-initialized fields of class declarations.
|
||||
if (!spells(source, "class") || !spells(source, "null")) return null;
|
||||
return syntax.applyNpmStaticNullableClassFields(this.parse(path, source, "js"), source);
|
||||
}
|
||||
jsDocNamepaths(path: string, source: string): string | null {
|
||||
if (!source.includes("~") && !source.includes("#")) return null;
|
||||
// A namepath segment joined by `#` or `~` (applyNpmStaticJsDocNamepaths).
|
||||
if (!/[$\w][#~][$A-Z_a-z]/.test(source)) return null;
|
||||
return syntax.applyNpmStaticJsDocNamepaths(this.parse(path, source, "js"), source);
|
||||
}
|
||||
findReturnWidening(path: string, source: string): syntax.NpmStaticOverloadRewrite | null {
|
||||
// Widens `find` calls returned by methods of class declarations.
|
||||
if (!spells(source, "class") || !spells(source, "find")) return null;
|
||||
return syntax.applyNpmStaticFindReturnWidening(this.parse(path, source, "js"), source);
|
||||
}
|
||||
declarationProperties(
|
||||
|
||||
Reference in New Issue
Block a user