UNPKG

@jspm/generator

Version:

Package Import Map Generation Tool

146 lines (144 loc) 5.65 kB
import { getIntegrity } from '../common/integrity.js'; // See: https://nodejs.org/docs/latest/api/modules.html#the-module-scope const cjsGlobals = [ '__dirname', '__filename', 'exports', 'module', 'require' ]; let babel; export function setBabel(_babel) { babel = _babel; } export async function createCjsAnalysis(imports, source, url) { if (!babel) babel = await import('@babel/core'); const requires = new Set(); const lazy = new Set(); const unboundGlobals = new Set(); babel.transform(source, { ast: false, sourceMaps: false, inputSourceMap: false, babelrc: false, babelrcRoots: false, configFile: false, highlightCode: false, compact: false, sourceType: 'script', parserOpts: { allowReturnOutsideFunction: true, // plugins: stage3Syntax, errorRecovery: true }, plugins: [ ({ types: t })=>{ return { visitor: { Program (path, state) { state.functionDepth = 0; }, CallExpression (path, state) { if (t.isIdentifier(path.node.callee, { name: 'require' }) || t.isIdentifier(path.node.callee.object, { name: 'require' }) && t.isIdentifier(path.node.callee.property, { name: 'resolve' }) || t.isMemberExpression(path.node.callee) && t.isIdentifier(path.node.callee.object, { name: 'module' }) && t.isIdentifier(path.node.callee.property, { name: 'require' })) { const req = buildDynamicString(path.get('arguments.0').node, url); requires.add(req); if (state.functionDepth > 0) lazy.add(req); } }, ReferencedIdentifier (path) { let identifierName = path.node.name; if (!path.scope.hasBinding(identifierName)) { unboundGlobals.add(identifierName); } }, Scope: { enter (path, state) { if (t.isFunction(path.scope.block)) state.functionDepth++; }, exit (path, state) { if (t.isFunction(path.scope.block)) state.functionDepth--; } } } }; } ] }); // Check if the module actually uses any CJS-specific globals, as otherwise // other host runtimes like browser/deno can run this module anyway: let usesCjs = false; for (let g of cjsGlobals){ if (unboundGlobals.has(g)) { usesCjs = true; break; } } return { deps: [ ...requires ], dynamicDeps: imports.filter((impt)=>impt.n).map((impt)=>impt.n), cjsLazyDeps: [ ...lazy ], size: source.length, format: 'commonjs', usesCjs, integrity: await getIntegrity(source) }; } function buildDynamicString(node, fileName, isEsm = false, lastIsWildcard = false) { if (node.type === 'StringLiteral') { return node.value; } if (node.type === 'TemplateLiteral') { let str = ''; for(let i = 0; i < node.quasis.length; i++){ const quasiStr = node.quasis[i].value.cooked; if (quasiStr.length) { str += quasiStr; lastIsWildcard = false; } const nextNode = node.expressions[i]; if (nextNode) { const nextStr = buildDynamicString(nextNode, fileName, isEsm, lastIsWildcard); if (nextStr.length) { lastIsWildcard = nextStr.endsWith('*'); str += nextStr; } } } return str; } if (node.type === 'BinaryExpression' && node.operator === '+') { const leftResolved = buildDynamicString(node.left, fileName, isEsm, lastIsWildcard); if (leftResolved.length) lastIsWildcard = leftResolved.endsWith('*'); const rightResolved = buildDynamicString(node.right, fileName, isEsm, lastIsWildcard); return leftResolved + rightResolved; } if (node.type === 'Identifier') { if (node.name === '__dirname') return '.'; if (node.name === '__filename') return './' + fileName; } // TODO: proper expression support // new URL('...', import.meta.url).href | new URL('...', import.meta.url).toString() | new URL('...', import.meta.url).pathname // import.meta.X /*if (isEsm && node.type === 'MemberExpression' && node.object.type === 'MetaProperty' && node.object.meta.type === 'Identifier' && node.object.meta.name === 'import' && node.object.property.type === 'Identifier' && node.object.property.name === 'meta') { if (node.property.type === 'Identifier' && node.property.name === 'url') { return './' + fileName; } }*/ return lastIsWildcard ? '' : '*'; } //# sourceMappingURL=cjs.js.map