deno.land / x / esm@v135_2 / server / embed / cjs_lexer.js
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262const fs = require("fs");const { dirname } = require("path");const { promisify } = require("util");const { parse } = require("esm-cjs-lexer");const enhancedResolve = require("enhanced-resolve");
const identRegexp = /^[a-zA-Z_\$][a-zA-Z0-9_\$]*$/;const resolve = promisify(enhancedResolve.create({ conditionNames: ["require", "node", "default"], extensions: [".cjs", ".js", ".json"],}));const reservedWords = new Set([ "abstract", "arguments", "await", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "debugger", "default", "delete", "do", "double", "else", "enum", "eval", "export", "extends", "false", "final", "finally", "float", "for", "function", "goto", "if", "implements", "import", "in", "instanceof", "int", "interface", "let", "long", "native", "new", "null", "package", "private", "protected", "public", "return", "short", "static", "super", "switch", "synchronized", "this", "throw", "throws", "transient", "true", "try", "typeof", "var", "void", "volatile", "while", "with", "yield",]);const builtInNodeModules = new Set([ "assert", "async_hooks", "child_process", "cluster", "buffer", "console", "constants", "crypto", "dgram", "dns", "domain", "events", "fs", "fs/promises", "http", "http2", "https", "inspector", "module", "net", "os", "path", "path/posix", "path/win32", "perf_hooks", "process", "punycode", "querystring", "readline", "repl", "stream", "stream/promises", "stream/web", "_stream_duplex", "_stream_passthrough", "_stream_readable", "_stream_transform", "_stream_writable", "string_decoder", "sys", "timers", "tls", "trace_events", "tty", "url", "util", "v8", "vm", "worker_threads", "zlib",]);
function isObject(v) { return typeof v === "object" && v !== null && !Array.isArray(v);}
function getJSONKeys(jsonFile) { const content = fs.readFileSync(jsonFile, "utf-8"); const v = JSON.parse(content); if (isObject(v)) { return Object.keys(v); } return [];}
function verifyExports(names) { const exportDefault = names.includes("default"); const exports = Array.from( new Set( names.filter((name) => identRegexp.test(name) && !reservedWords.has(name) ), ), ); return { exportDefault, exports, };}
async function parseCjsExports(input) { const { cwd, importPath, requireMode, nodeEnv = "production" } = input; const entry = importPath.startsWith("/") && /\.(js|cjs)$/.test(importPath) ? importPath : await resolve(cwd, importPath); const exports = [];
if (requireMode) { process.env.NODE_ENV = nodeEnv; const mod = require(entry); if (isObject(mod) || typeof mod === "function") { for (const key of Object.keys(mod)) { if (typeof key === "string" && key !== "") { exports.push(key); } } } return verifyExports(exports); }
if (entry.endsWith(".json")) { return verifyExports(getJSONKeys(entry)); }
if ( !entry.endsWith(".js") && !entry.endsWith(".cjs") && !entry.endsWith(".mjs") ) { return verifyExports(exports); }
const requires = [{ path: entry, callMode: false }]; while (requires.length > 0) { const req = requires.pop(); try { const filename = req.path.replace(/\0/g, ""); const code = fs.readFileSync(filename, "utf-8"); const results = parse(filename, code, { nodeEnv, callMode: req.callMode, }); if ( results.reexports.length === 1 && /^[a-z@]/i.test(results.reexports[0]) && !results.reexports[0].endsWith("()") && !builtInNodeModules.has(results.reexports[0]) && results.exports.length === 0 && exports.length === 0 ) { return { reexport: results.reexports[0], exportDefault: false, exports: [], }; } exports.push(...results.exports); for (let reexport of results.reexports) { const callMode = reexport.endsWith("()"); if (callMode) { reexport = reexport.slice(0, -2); } if (builtInNodeModules.has(reexport)) { const mod = require(reexport); exports.push(...Object.keys(mod)); } else { const path = await resolve(dirname(filename), reexport); if (path.endsWith(".json")) { exports.push(...getJSONKeys(path)); } else { requires.push({ path, callMode }); } } } } catch (err) { return Promise.reject(err); } }
return verifyExports(exports);}
function readStdin() { return new Promise((resolve) => { let buf = ""; process.stdin.setEncoding("utf8"); process.stdin.on("data", (chunk) => (buf += chunk)); process.stdin.on("end", () => resolve(buf)); });}
async function main() { try { const input = JSON.parse(await readStdin()); const outout = await parseCjsExports(input); process.stdout.write(JSON.stringify(outout)); } catch (err) { process.stdout.write( JSON.stringify({ error: err.message, stack: err.stack }), ); } process.exit(0);}
main();
Version Info