mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-17 13:13:49 +01:00
MISC: Add proper type check to AST walking code (#1757)
This commit is contained in:
parent
36c143b687
commit
90cb8a9551
@ -4,15 +4,13 @@
|
|||||||
*/
|
*/
|
||||||
import * as walk from "acorn-walk";
|
import * as walk from "acorn-walk";
|
||||||
import { parse } from "acorn";
|
import { parse } from "acorn";
|
||||||
|
import type * as acorn from "acorn";
|
||||||
|
|
||||||
import { LoadedModule, type ScriptURL, type ScriptModule } from "./Script/LoadedModule";
|
import { LoadedModule, type ScriptURL, type ScriptModule } from "./Script/LoadedModule";
|
||||||
import type { Script } from "./Script/Script";
|
import type { Script } from "./Script/Script";
|
||||||
import type { ScriptFilePath } from "./Paths/ScriptFilePath";
|
import type { ScriptFilePath } from "./Paths/ScriptFilePath";
|
||||||
import { FileType, getFileType, getModuleScript, transformScript } from "./utils/ScriptTransformer";
|
import { FileType, getFileType, getModuleScript, transformScript } from "./utils/ScriptTransformer";
|
||||||
|
|
||||||
// Acorn type def is straight up incomplete so we have to fill with our own.
|
|
||||||
export type Node = any;
|
|
||||||
|
|
||||||
// Makes a blob that contains the code of a given script.
|
// Makes a blob that contains the code of a given script.
|
||||||
function makeScriptBlob(code: string): Blob {
|
function makeScriptBlob(code: string): Blob {
|
||||||
return new Blob([code], { type: "text/javascript" });
|
return new Blob([code], { type: "text/javascript" });
|
||||||
@ -103,33 +101,51 @@ function generateLoadedModule(script: Script, scripts: Map<ScriptFilePath, Scrip
|
|||||||
|
|
||||||
// Inspired by: https://stackoverflow.com/a/43834063/91401
|
// Inspired by: https://stackoverflow.com/a/43834063/91401
|
||||||
const ast = parse(scriptCode, { sourceType: "module", ecmaVersion: "latest", ranges: true });
|
const ast = parse(scriptCode, { sourceType: "module", ecmaVersion: "latest", ranges: true });
|
||||||
interface importNode {
|
interface ImportNode {
|
||||||
filename: string;
|
filename: string;
|
||||||
start: number;
|
start: number;
|
||||||
end: number;
|
end: number;
|
||||||
}
|
}
|
||||||
const importNodes: importNode[] = [];
|
const importNodes: ImportNode[] = [];
|
||||||
// Walk the nodes of this tree and find any import declaration statements.
|
// Walk the nodes of this tree and find any import declaration statements.
|
||||||
walk.simple(ast, {
|
walk.simple(ast, {
|
||||||
ImportDeclaration(node: Node) {
|
ImportDeclaration(node: acorn.ImportDeclaration) {
|
||||||
// Push this import onto the stack to replace
|
// Push this import onto the stack to replace
|
||||||
if (!node.source) return;
|
if (!node.source) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (typeof node.source.value !== "string" || !node.source.range) {
|
||||||
|
console.error("Invalid node when walking ImportDeclaration in generateLoadedModule. node:", node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
importNodes.push({
|
importNodes.push({
|
||||||
filename: node.source.value,
|
filename: node.source.value,
|
||||||
start: node.source.range[0] + 1,
|
start: node.source.range[0] + 1,
|
||||||
end: node.source.range[1] - 1,
|
end: node.source.range[1] - 1,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
ExportNamedDeclaration(node: Node) {
|
ExportNamedDeclaration(node: acorn.ExportNamedDeclaration) {
|
||||||
if (!node.source) return;
|
if (!node.source) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (typeof node.source.value !== "string" || !node.source.range) {
|
||||||
|
console.error("Invalid node when walking ExportNamedDeclaration in generateLoadedModule. node:", node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
importNodes.push({
|
importNodes.push({
|
||||||
filename: node.source.value,
|
filename: node.source.value,
|
||||||
start: node.source.range[0] + 1,
|
start: node.source.range[0] + 1,
|
||||||
end: node.source.range[1] - 1,
|
end: node.source.range[1] - 1,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
ExportAllDeclaration(node: Node) {
|
ExportAllDeclaration(node: acorn.ExportAllDeclaration) {
|
||||||
if (!node.source) return;
|
if (!node.source) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (typeof node.source.value !== "string" || !node.source.range) {
|
||||||
|
console.error("Invalid node when walking ExportAllDeclaration in generateLoadedModule. node:", node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
importNodes.push({
|
importNodes.push({
|
||||||
filename: node.source.value,
|
filename: node.source.value,
|
||||||
start: node.source.range[0] + 1,
|
start: node.source.range[0] + 1,
|
||||||
|
@ -11,7 +11,7 @@ import { generateNextPid } from "./Netscript/Pid";
|
|||||||
import { CONSTANTS } from "./Constants";
|
import { CONSTANTS } from "./Constants";
|
||||||
import { Interpreter } from "./ThirdParty/JSInterpreter";
|
import { Interpreter } from "./ThirdParty/JSInterpreter";
|
||||||
import { NetscriptFunctions } from "./NetscriptFunctions";
|
import { NetscriptFunctions } from "./NetscriptFunctions";
|
||||||
import { compile, Node } from "./NetscriptJSEvaluator";
|
import { compile } from "./NetscriptJSEvaluator";
|
||||||
import { Port, PortNumber } from "./NetscriptPort";
|
import { Port, PortNumber } from "./NetscriptPort";
|
||||||
import { RunningScript } from "./Script/RunningScript";
|
import { RunningScript } from "./Script/RunningScript";
|
||||||
import { scriptCalculateOfflineProduction } from "./Script/ScriptHelpers";
|
import { scriptCalculateOfflineProduction } from "./Script/ScriptHelpers";
|
||||||
@ -28,6 +28,7 @@ import { arrayToString } from "./utils/helpers/ArrayHelpers";
|
|||||||
import { roundToTwo } from "./utils/helpers/roundToTwo";
|
import { roundToTwo } from "./utils/helpers/roundToTwo";
|
||||||
|
|
||||||
import { parse } from "acorn";
|
import { parse } from "acorn";
|
||||||
|
import type * as acorn from "acorn";
|
||||||
import { simple as walksimple } from "acorn-walk";
|
import { simple as walksimple } from "acorn-walk";
|
||||||
import { parseCommand } from "./Terminal/Parser";
|
import { parseCommand } from "./Terminal/Parser";
|
||||||
import { Terminal } from "./Terminal";
|
import { Terminal } from "./Terminal";
|
||||||
@ -92,6 +93,7 @@ async function startNetscript1Script(workerScript: WorkerScript): Promise<void>
|
|||||||
try {
|
try {
|
||||||
// Sent a resolver function as an extra arg. See createAsyncFunction JSInterpreter.js:3209
|
// Sent a resolver function as an extra arg. See createAsyncFunction JSInterpreter.js:3209
|
||||||
const callback = args.pop() as (value: unknown) => void;
|
const callback = args.pop() as (value: unknown) => void;
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-call -- NS1 is deprecated.
|
||||||
const result = await entry(...args.map((arg) => int.pseudoToNative(arg)));
|
const result = await entry(...args.map((arg) => int.pseudoToNative(arg)));
|
||||||
return callback(int.nativeToPseudo(result));
|
return callback(int.nativeToPseudo(result));
|
||||||
} catch (e: unknown) {
|
} catch (e: unknown) {
|
||||||
@ -105,6 +107,7 @@ async function startNetscript1Script(workerScript: WorkerScript): Promise<void>
|
|||||||
} else {
|
} else {
|
||||||
// new object layer, e.g. bladeburner
|
// new object layer, e.g. bladeburner
|
||||||
int.setProperty(intLayer, name, int.nativeToPseudo({}));
|
int.setProperty(intLayer, name, int.nativeToPseudo({}));
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-argument -- NS1 is deprecated.
|
||||||
wrapNS1Layer(int, (intLayer as BasicObject).properties[name], nsLayer[name]);
|
wrapNS1Layer(int, (intLayer as BasicObject).properties[name], nsLayer[name]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -139,7 +142,7 @@ async function startNetscript1Script(workerScript: WorkerScript): Promise<void>
|
|||||||
*/
|
*/
|
||||||
function processNetscript1Imports(code: string, workerScript: WorkerScript): { code: string; lineOffset: number } {
|
function processNetscript1Imports(code: string, workerScript: WorkerScript): { code: string; lineOffset: number } {
|
||||||
//allowReserved prevents 'import' from throwing error in ES5
|
//allowReserved prevents 'import' from throwing error in ES5
|
||||||
const ast: Node = parse(code, {
|
const ast = parse(code, {
|
||||||
ecmaVersion: 9,
|
ecmaVersion: 9,
|
||||||
allowReserved: true,
|
allowReserved: true,
|
||||||
sourceType: "module",
|
sourceType: "module",
|
||||||
@ -159,9 +162,9 @@ function processNetscript1Imports(code: string, workerScript: WorkerScript): { c
|
|||||||
|
|
||||||
// Walk over the tree and process ImportDeclaration nodes
|
// Walk over the tree and process ImportDeclaration nodes
|
||||||
walksimple(ast, {
|
walksimple(ast, {
|
||||||
ImportDeclaration: (node: Node) => {
|
ImportDeclaration: (node: acorn.ImportDeclaration) => {
|
||||||
hasImports = true;
|
hasImports = true;
|
||||||
const scriptName = resolveScriptFilePath(node.source.value, root, legacyScriptExtension);
|
const scriptName = resolveScriptFilePath(node.source.value as string, root, legacyScriptExtension);
|
||||||
if (!scriptName) throw new Error("'Import' failed due to invalid path: " + scriptName);
|
if (!scriptName) throw new Error("'Import' failed due to invalid path: " + scriptName);
|
||||||
const script = getScript(scriptName);
|
const script = getScript(scriptName);
|
||||||
if (!script) throw new Error("'Import' failed due to script not found: " + scriptName);
|
if (!script) throw new Error("'Import' failed due to script not found: " + scriptName);
|
||||||
@ -175,9 +178,12 @@ function processNetscript1Imports(code: string, workerScript: WorkerScript): { c
|
|||||||
// import * as namespace from script
|
// import * as namespace from script
|
||||||
const namespace = node.specifiers[0].local.name;
|
const namespace = node.specifiers[0].local.name;
|
||||||
const fnNames: string[] = []; //Names only
|
const fnNames: string[] = []; //Names only
|
||||||
const fnDeclarations: Node[] = []; //FunctionDeclaration Node objects
|
const fnDeclarations: acorn.Node[] = []; //FunctionDeclaration Node objects
|
||||||
walksimple(scriptAst, {
|
walksimple(scriptAst, {
|
||||||
FunctionDeclaration: (node: Node) => {
|
FunctionDeclaration: (node: acorn.FunctionDeclaration | acorn.AnonymousFunctionDeclaration) => {
|
||||||
|
if (!node.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
fnNames.push(node.id.name);
|
fnNames.push(node.id.name);
|
||||||
fnDeclarations.push(node);
|
fnDeclarations.push(node);
|
||||||
},
|
},
|
||||||
@ -187,7 +193,7 @@ function processNetscript1Imports(code: string, workerScript: WorkerScript): { c
|
|||||||
generatedCode += `var ${namespace};\n(function (namespace) {\n`;
|
generatedCode += `var ${namespace};\n(function (namespace) {\n`;
|
||||||
|
|
||||||
//Add the function declarations
|
//Add the function declarations
|
||||||
fnDeclarations.forEach((fn: Node) => {
|
fnDeclarations.forEach((fn) => {
|
||||||
generatedCode += generate(fn);
|
generatedCode += generate(fn);
|
||||||
generatedCode += "\n";
|
generatedCode += "\n";
|
||||||
});
|
});
|
||||||
@ -205,14 +211,17 @@ function processNetscript1Imports(code: string, workerScript: WorkerScript): { c
|
|||||||
|
|
||||||
//Get array of all fns to import
|
//Get array of all fns to import
|
||||||
const fnsToImport: string[] = [];
|
const fnsToImport: string[] = [];
|
||||||
node.specifiers.forEach((e: Node) => {
|
node.specifiers.forEach((e) => {
|
||||||
fnsToImport.push(e.local.name);
|
fnsToImport.push(e.local.name);
|
||||||
});
|
});
|
||||||
|
|
||||||
//Walk through script and get FunctionDeclaration code for all specified fns
|
//Walk through script and get FunctionDeclaration code for all specified fns
|
||||||
const fnDeclarations: Node[] = [];
|
const fnDeclarations: acorn.Node[] = [];
|
||||||
walksimple(scriptAst, {
|
walksimple(scriptAst, {
|
||||||
FunctionDeclaration: (node: Node) => {
|
FunctionDeclaration: (node: acorn.FunctionDeclaration | acorn.AnonymousFunctionDeclaration) => {
|
||||||
|
if (!node.id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (fnsToImport.includes(node.id.name)) {
|
if (fnsToImport.includes(node.id.name)) {
|
||||||
fnDeclarations.push(node);
|
fnDeclarations.push(node);
|
||||||
}
|
}
|
||||||
@ -220,7 +229,7 @@ function processNetscript1Imports(code: string, workerScript: WorkerScript): { c
|
|||||||
});
|
});
|
||||||
|
|
||||||
//Convert FunctionDeclarations into code
|
//Convert FunctionDeclarations into code
|
||||||
fnDeclarations.forEach((fn: Node) => {
|
fnDeclarations.forEach((fn) => {
|
||||||
generatedCode += generate(fn);
|
generatedCode += generate(fn);
|
||||||
generatedCode += "\n";
|
generatedCode += "\n";
|
||||||
});
|
});
|
||||||
|
@ -12,7 +12,6 @@ import { RamCalculationErrorCode } from "./RamCalculationErrorCodes";
|
|||||||
|
|
||||||
import { RamCosts, RamCostConstants } from "../Netscript/RamCostGenerator";
|
import { RamCosts, RamCostConstants } from "../Netscript/RamCostGenerator";
|
||||||
import type { Script } from "./Script";
|
import type { Script } from "./Script";
|
||||||
import type { Node } from "../NetscriptJSEvaluator";
|
|
||||||
import type { ScriptFilePath } from "../Paths/ScriptFilePath";
|
import type { ScriptFilePath } from "../Paths/ScriptFilePath";
|
||||||
import type { ServerName } from "../Types/strings";
|
import type { ServerName } from "../Types/strings";
|
||||||
import { roundToTwo } from "../utils/helpers/roundToTwo";
|
import { roundToTwo } from "../utils/helpers/roundToTwo";
|
||||||
@ -288,7 +287,7 @@ export function checkInfiniteLoop(ast: AST, code: string): number[] {
|
|||||||
ast as acorn.Node, // Pretend that ast is an acorn node
|
ast as acorn.Node, // Pretend that ast is an acorn node
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
WhileStatement: (node: Node, st: unknown, walkDeeper: walk.WalkerCallback<any>) => {
|
WhileStatement: (node: acorn.WhileStatement, st: unknown, walkDeeper: walk.WalkerCallback<any>) => {
|
||||||
const previousLines = code.slice(0, node.start).trimEnd().split("\n");
|
const previousLines = code.slice(0, node.start).trimEnd().split("\n");
|
||||||
const lineNumber = previousLines.length + 1;
|
const lineNumber = previousLines.length + 1;
|
||||||
if (previousLines[previousLines.length - 1].match(/^\s*\/\/\s*@ignore-infinite/)) {
|
if (previousLines[previousLines.length - 1].match(/^\s*\/\/\s*@ignore-infinite/)) {
|
||||||
@ -354,7 +353,7 @@ function parseOnlyCalculateDeps(
|
|||||||
key: string;
|
key: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkRamOverride(node: Node) {
|
function checkRamOverride(node: acorn.BlockStatement) {
|
||||||
// To trigger a syntactic RAM override, the first statement must be a call
|
// To trigger a syntactic RAM override, the first statement must be a call
|
||||||
// to ns.ramOverride() (or something that looks similar).
|
// to ns.ramOverride() (or something that looks similar).
|
||||||
if (!node.body || !node.body.length) return;
|
if (!node.body || !node.body.length) return;
|
||||||
@ -364,7 +363,12 @@ function parseOnlyCalculateDeps(
|
|||||||
if (expr.type !== "CallExpression") return;
|
if (expr.type !== "CallExpression") return;
|
||||||
if (!expr.arguments || expr.arguments.length !== 1) return;
|
if (!expr.arguments || expr.arguments.length !== 1) return;
|
||||||
|
|
||||||
function findIdentifier(node: Node): Node {
|
/**
|
||||||
|
* This function is called with expr.callee. expr.callee can be Expression or Super. In its implementation, the
|
||||||
|
* "node" parameter can be reassigned to node.property if "node" is MemberExpression. node.property may be
|
||||||
|
* PrivateIdentifier, so we need to add that type to the type list of "node".
|
||||||
|
*/
|
||||||
|
function findIdentifier(node: acorn.Expression | acorn.Super | acorn.PrivateIdentifier) {
|
||||||
for (;;) {
|
for (;;) {
|
||||||
// Find the identifier node attached to the call
|
// Find the identifier node attached to the call
|
||||||
switch (node.type) {
|
switch (node.type) {
|
||||||
@ -404,36 +408,36 @@ function parseOnlyCalculateDeps(
|
|||||||
// walkDeeper is for doing recursive walks of expressions in composites that we handle.
|
// walkDeeper is for doing recursive walks of expressions in composites that we handle.
|
||||||
function commonVisitors(): walk.RecursiveVisitors<State> {
|
function commonVisitors(): walk.RecursiveVisitors<State> {
|
||||||
return {
|
return {
|
||||||
Identifier: (node: Node, st: State) => {
|
Identifier: (node: acorn.Identifier, st: State) => {
|
||||||
if (objectPrototypeProperties.includes(node.name)) {
|
if (objectPrototypeProperties.includes(node.name)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
addRef(st.key, node.name);
|
addRef(st.key, node.name);
|
||||||
},
|
},
|
||||||
WhileStatement: (node: Node, st: State, walkDeeper: walk.WalkerCallback<State>) => {
|
WhileStatement: (node: acorn.WhileStatement, st: State, walkDeeper: walk.WalkerCallback<State>) => {
|
||||||
addRef(st.key, specialReferenceWHILE);
|
addRef(st.key, specialReferenceWHILE);
|
||||||
node.test && walkDeeper(node.test, st);
|
node.test && walkDeeper(node.test, st);
|
||||||
node.body && walkDeeper(node.body, st);
|
node.body && walkDeeper(node.body, st);
|
||||||
},
|
},
|
||||||
DoWhileStatement: (node: Node, st: State, walkDeeper: walk.WalkerCallback<State>) => {
|
DoWhileStatement: (node: acorn.DoWhileStatement, st: State, walkDeeper: walk.WalkerCallback<State>) => {
|
||||||
addRef(st.key, specialReferenceWHILE);
|
addRef(st.key, specialReferenceWHILE);
|
||||||
node.test && walkDeeper(node.test, st);
|
node.test && walkDeeper(node.test, st);
|
||||||
node.body && walkDeeper(node.body, st);
|
node.body && walkDeeper(node.body, st);
|
||||||
},
|
},
|
||||||
ForStatement: (node: Node, st: State, walkDeeper: walk.WalkerCallback<State>) => {
|
ForStatement: (node: acorn.ForStatement, st: State, walkDeeper: walk.WalkerCallback<State>) => {
|
||||||
addRef(st.key, specialReferenceFOR);
|
addRef(st.key, specialReferenceFOR);
|
||||||
node.init && walkDeeper(node.init, st);
|
node.init && walkDeeper(node.init, st);
|
||||||
node.test && walkDeeper(node.test, st);
|
node.test && walkDeeper(node.test, st);
|
||||||
node.update && walkDeeper(node.update, st);
|
node.update && walkDeeper(node.update, st);
|
||||||
node.body && walkDeeper(node.body, st);
|
node.body && walkDeeper(node.body, st);
|
||||||
},
|
},
|
||||||
IfStatement: (node: Node, st: State, walkDeeper: walk.WalkerCallback<State>) => {
|
IfStatement: (node: acorn.IfStatement, st: State, walkDeeper: walk.WalkerCallback<State>) => {
|
||||||
addRef(st.key, specialReferenceIF);
|
addRef(st.key, specialReferenceIF);
|
||||||
node.test && walkDeeper(node.test, st);
|
node.test && walkDeeper(node.test, st);
|
||||||
node.consequent && walkDeeper(node.consequent, st);
|
node.consequent && walkDeeper(node.consequent, st);
|
||||||
node.alternate && walkDeeper(node.alternate, st);
|
node.alternate && walkDeeper(node.alternate, st);
|
||||||
},
|
},
|
||||||
MemberExpression: (node: Node, st: State, walkDeeper: walk.WalkerCallback<State>) => {
|
MemberExpression: (node: acorn.MemberExpression, st: State, walkDeeper: walk.WalkerCallback<State>) => {
|
||||||
node.object && walkDeeper(node.object, st);
|
node.object && walkDeeper(node.object, st);
|
||||||
node.property && walkDeeper(node.property, st);
|
node.property && walkDeeper(node.property, st);
|
||||||
},
|
},
|
||||||
@ -445,8 +449,12 @@ function parseOnlyCalculateDeps(
|
|||||||
{ key: globalKey },
|
{ key: globalKey },
|
||||||
Object.assign(
|
Object.assign(
|
||||||
{
|
{
|
||||||
ImportDeclaration: (node: Node, st: State) => {
|
ImportDeclaration: (node: acorn.ImportDeclaration, st: State) => {
|
||||||
const rawImportModuleName = node.source.value;
|
const rawImportModuleName = node.source.value;
|
||||||
|
if (typeof rawImportModuleName !== "string") {
|
||||||
|
console.error("Invalid node when walking ImportDeclaration in parseOnlyCalculateDeps. node:", node);
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Skip these modules. They are popular path aliases of NetscriptDefinitions.d.ts.
|
// Skip these modules. They are popular path aliases of NetscriptDefinitions.d.ts.
|
||||||
if (fileTypeFeature.isTypeScript && (rawImportModuleName === "@nsdefs" || rawImportModuleName === "@ns")) {
|
if (fileTypeFeature.isTypeScript && (rawImportModuleName === "@nsdefs" || rawImportModuleName === "@ns")) {
|
||||||
return;
|
return;
|
||||||
@ -462,7 +470,11 @@ function parseOnlyCalculateDeps(
|
|||||||
|
|
||||||
for (let i = 0; i < node.specifiers.length; ++i) {
|
for (let i = 0; i < node.specifiers.length; ++i) {
|
||||||
const spec = node.specifiers[i];
|
const spec = node.specifiers[i];
|
||||||
if (spec.imported !== undefined && spec.local !== undefined) {
|
/**
|
||||||
|
* spec can be ImportSpecifier, ImportDefaultSpecifier, or ImportNamespaceSpecifier. "imported" only exists
|
||||||
|
* in ImportSpecifier. "imported" can be Identifier or Literal. imported.name only exists in Identifier.
|
||||||
|
*/
|
||||||
|
if (spec.type === "ImportSpecifier" && spec.imported.type === "Identifier" && spec.local !== undefined) {
|
||||||
// We depend on specific things.
|
// We depend on specific things.
|
||||||
internalToExternal[spec.local.name] = importModuleName + "." + spec.imported.name;
|
internalToExternal[spec.local.name] = importModuleName + "." + spec.imported.name;
|
||||||
} else {
|
} else {
|
||||||
@ -473,7 +485,7 @@ function parseOnlyCalculateDeps(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
FunctionDeclaration: (node: Node) => {
|
FunctionDeclaration: (node: acorn.FunctionDeclaration) => {
|
||||||
if (node.id?.name === "main") {
|
if (node.id?.name === "main") {
|
||||||
checkRamOverride(node.body);
|
checkRamOverride(node.body);
|
||||||
}
|
}
|
||||||
@ -481,22 +493,35 @@ function parseOnlyCalculateDeps(
|
|||||||
const key = currentModule + "." + (node.id === null ? "__SPECIAL_DEFAULT_EXPORT__" : node.id.name);
|
const key = currentModule + "." + (node.id === null ? "__SPECIAL_DEFAULT_EXPORT__" : node.id.name);
|
||||||
walk.recursive(node, { key: key }, commonVisitors());
|
walk.recursive(node, { key: key }, commonVisitors());
|
||||||
},
|
},
|
||||||
ExportNamedDeclaration: (node: Node, st: State, walkDeeper: walk.WalkerCallback<State>) => {
|
ExportNamedDeclaration: (
|
||||||
if (node.declaration !== null) {
|
node: acorn.ExportNamedDeclaration,
|
||||||
|
st: State,
|
||||||
|
walkDeeper: walk.WalkerCallback<State>,
|
||||||
|
) => {
|
||||||
|
if (node.declaration != null) {
|
||||||
// if this is true, the statement is not a named export, but rather a exported function/variable
|
// if this is true, the statement is not a named export, but rather a exported function/variable
|
||||||
walkDeeper(node.declaration, st);
|
walkDeeper(node.declaration, st);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const specifier of node.specifiers) {
|
for (const specifier of node.specifiers) {
|
||||||
|
/**
|
||||||
|
* specifier.exported can be Identifier or Literal. specifier.exported.name only exists in Identifier.
|
||||||
|
*/
|
||||||
|
if (specifier.exported.type === "Literal") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
const exportedDepName = currentModule + "." + specifier.exported.name;
|
const exportedDepName = currentModule + "." + specifier.exported.name;
|
||||||
|
/**
|
||||||
if (node.source !== null) {
|
* We need to use specifier.local.name and node.source.value. Before doing that, we need to check if they
|
||||||
|
* exist. local.name only exists in Identifier.
|
||||||
|
*/
|
||||||
|
if (node.source != null && typeof node.source.value === "string" && specifier.local.type === "Identifier") {
|
||||||
// if this is true, we are re-exporting something
|
// if this is true, we are re-exporting something
|
||||||
addRef(exportedDepName, specifier.local.name, node.source.value);
|
addRef(exportedDepName, specifier.local.name, node.source.value as ScriptFilePath);
|
||||||
additionalModules.push(node.source.value);
|
additionalModules.push(node.source.value as ScriptFilePath);
|
||||||
} else if (specifier.exported.name !== specifier.local.name) {
|
} else if (specifier.local.type === "Identifier" && specifier.exported.name !== specifier.local.name) {
|
||||||
// this makes sure we are not refering to ourselves
|
// this makes sure we are not referring to ourselves
|
||||||
// if this is not true, we don't need to add anything
|
// if this is not true, we don't need to add anything
|
||||||
addRef(exportedDepName, specifier.local.name);
|
addRef(exportedDepName, specifier.local.name);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user