mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-11-26 17:43:48 +01:00
Merge pull request #2310 from theit8514/import-via-acorn
Replace regex import with acorn AST parser
This commit is contained in:
commit
ec7481b391
@ -1,3 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* Uses the acorn.js library to parse a script's code into an AST and
|
||||||
|
* recursively walk through that AST to replace import urls with blobs
|
||||||
|
*/
|
||||||
|
import * as walk from "acorn-walk";
|
||||||
|
import { parse } from "acorn";
|
||||||
|
|
||||||
import { makeRuntimeRejectMsg } from "./NetscriptEvaluator";
|
import { makeRuntimeRejectMsg } from "./NetscriptEvaluator";
|
||||||
import { ScriptUrl } from "./Script/ScriptUrl";
|
import { ScriptUrl } from "./Script/ScriptUrl";
|
||||||
import { WorkerScript } from "./Netscript/WorkerScript";
|
import { WorkerScript } from "./Netscript/WorkerScript";
|
||||||
@ -130,32 +137,51 @@ function _getScriptUrls(script: Script, scripts: Script[], seen: Script[]): Scri
|
|||||||
// import {foo} from "blob://<uuid>"
|
// import {foo} from "blob://<uuid>"
|
||||||
//
|
//
|
||||||
// Where the blob URL contains the script content.
|
// Where the blob URL contains the script content.
|
||||||
let transformedCode = script.code.replace(
|
|
||||||
/((?:from|import)\s+(?:'|"))(?:\.\/)?([^'"]+)('|")/g,
|
|
||||||
(unmodified, prefix, filename, suffix) => {
|
|
||||||
const isAllowedImport = scripts.some((s) => areImportsEquals(s.filename, filename));
|
|
||||||
if (!isAllowedImport) return unmodified;
|
|
||||||
|
|
||||||
// Find the corresponding script.
|
// Parse the code into an ast tree
|
||||||
const [importedScript] = scripts.filter((s) => areImportsEquals(s.filename, filename));
|
const ast: any = parse(script.code, { sourceType: "module", ecmaVersion: "latest", ranges: true });
|
||||||
|
|
||||||
// Check to see if the urls for this script are stored in the cache by the hash value.
|
const importNodes: Array<any> = [];
|
||||||
let urls = ImportCache.get(importedScript.hash());
|
// Walk the nodes of this tree and find any import declaration statements.
|
||||||
// If we don't have it in the cache, then we need to generate the urls for it.
|
walk.simple(ast, {
|
||||||
if (!urls) {
|
ImportDeclaration(node: any) {
|
||||||
// Try to get a URL for the requested script and its dependencies.
|
// Push this import onto the stack to replace
|
||||||
urls = _getScriptUrls(importedScript, scripts, seen);
|
importNodes.push({
|
||||||
}
|
filename: node.source.value,
|
||||||
|
start: node.source.range[0] + 1,
|
||||||
|
end: node.source.range[1] - 1
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// Sort the nodes from last start index to first. This replaces the last import with a blob first,
|
||||||
|
// preventing the ranges for other imports from being shifted.
|
||||||
|
importNodes.sort((a, b) => b.start - a.start);
|
||||||
|
let transformedCode = script.code;
|
||||||
|
// Loop through each node and replace the script name with a blob url.
|
||||||
|
for (const node of importNodes) {
|
||||||
|
const filename = node.filename.startsWith("./") ? node.filename.substring(2) : node.filename;
|
||||||
|
|
||||||
// The top url in the stack is the replacement import file for this script.
|
// Find the corresponding script.
|
||||||
urlStack.push(...urls);
|
const matchingScripts = scripts.filter((s) => areImportsEquals(s.filename, filename));
|
||||||
const blob = urls[urls.length - 1].url;
|
if (matchingScripts.length === 0) continue;
|
||||||
ImportCache.store(importedScript.hash(), urls);
|
|
||||||
|
|
||||||
// Replace the blob inside the import statement.
|
const [importedScript] = matchingScripts;
|
||||||
return [prefix, blob, suffix].join("");
|
// Check to see if the urls for this script are stored in the cache by the hash value.
|
||||||
},
|
let urls = ImportCache.get(importedScript.hash());
|
||||||
);
|
// If we don't have it in the cache, then we need to generate the urls for it.
|
||||||
|
if (!urls) {
|
||||||
|
// Try to get a URL for the requested script and its dependencies.
|
||||||
|
urls = _getScriptUrls(importedScript, scripts, seen);
|
||||||
|
}
|
||||||
|
|
||||||
|
// The top url in the stack is the replacement import file for this script.
|
||||||
|
urlStack.push(...urls);
|
||||||
|
const blob = urls[urls.length - 1].url;
|
||||||
|
ImportCache.store(importedScript.hash(), urls);
|
||||||
|
|
||||||
|
// Replace the blob inside the import statement.
|
||||||
|
transformedCode = transformedCode.substring(0, node.start) + blob + transformedCode.substring(node.end);
|
||||||
|
}
|
||||||
|
|
||||||
// We automatically define a print function() in the NetscriptJS module so that
|
// We automatically define a print function() in the NetscriptJS module so that
|
||||||
// accidental calls to window.print() do not bring up the "print screen" dialog
|
// accidental calls to window.print() do not bring up the "print screen" dialog
|
||||||
|
Loading…
Reference in New Issue
Block a user