/** * Given an ast and optional code snippet for a source map, produce transpiled babel code * * @param {Object} options - the options * @param {Object} options.babel - options to be passed to the babel config generator (presetEnv) * @param {Object} options.babelConfig - supply your own babel config don't generate any * @param {Array} options.body - replace the body of our current ast program with a new body * @param {String} options.code - code to use for sourcemap generation * @param {Boolean} options.parse - create a new module from the generated code and return the module.exports * * @return {Object} returns a babel transform object, with code, ast, map properties */ async transformAst(options = {}) { const { runtime } = this const { body, code = this.contents } = options let { ast = this.ast } = options const babelConfig = this.getBabelConfig(options) if (body) { ast = Object.assign({}, ast, { program: Object.assign({}, ast.program, { body }), }) } let result try { result = code ? core.transformFromAst(ast, code, babelConfig) : core.transformFromAst(ast, '', babelConfig) } catch (error) { console.error('Error while transforming ast') console.error({ babelConfig }) throw error } if (options.parse) { const newCode = result.code const requirePolyfill = identifier => { try { return runtime.currentModule.require(identifier) } catch (error) { console.error( `Error while requiring ${identifier} in the script helper virtual module: ${this.name}` ) console.error(error) } } try { const newModule = this.runtime.createModule(`${newCode}`, { console, require: requirePolyfill, }) return newModule.exports } catch (error) { console.error(`Error creating a new module`) console.error({ babelConfig }) throw error } } return result }
function check(code, options) { const ast = parse(code); delete ast.tokens; const result = transformFromAst(ast, code, options); assert.ok(methodNameRegExp.test(result.code)); return result; }
// babel instrumentation function instrumentBabel(code, filename) { let ast; try { ast = babylon.parse(code, { sourceType: 'script', plugins: babylonPlugins, }); } catch (e) { if (e.message.match(/import.*export.*module/)) { ast = babylon.parse(code, { sourceType: 'module', plugins: babylonPlugins, }); } else { throw e; } } let { code: instrumented } = babel.transformFromAst(ast, code, { filename: filename, presets: [], plugins: babelPlugins }); if (typeof instrumented === 'undefined') { return code; } return patchCoverageVariable(instrumented); }
function getCodeForExpression(expressionNode) { return babel.transformFromAst(babel.types.program([ babel.types.expressionStatement( babel.types.removeComments(babel.types.cloneDeep(expressionNode)) ) ])).code; }
function transformBabelAst(babelAst, babelOptions, sourceMapOptions, callback) { var fsCode = null; if (sourceMapOptions != null) { fsCode = sourceMapOptions.buffer.toString(); babelOptions.sourceMaps = true; babelOptions.sourceFileName = path.relative(process.cwd(), sourceMapOptions.path.replace(/\\/g, '/')); } babel.transformFromAst(babelAst, fsCode, babelOptions, callback); }
function buildHelper( runtimeName, pkgDirname, helperFilename, helperName, { esm, corejs } ) { const tree = t.program([], [], esm ? "module" : "script"); const dependencies = {}; let bindings = null; if (!esm) { bindings = []; for (const dep of helpers.getDependencies(helperName)) { const id = (dependencies[dep] = t.identifier(t.toIdentifier(dep))); tree.body.push(template.statement.ast` var ${id} = require("${`./${dep}`}"); `); bindings.push(id.name); } } const helper = helpers.get( helperName, dep => dependencies[dep], esm ? null : template.expression.ast`module.exports`, bindings ); tree.body.push(...helper.nodes); return babel.transformFromAst(tree, null, { presets: [[require("@babel/preset-env"), { modules: false }]], plugins: [ [transformRuntime, { corejs, useESModules: esm }], buildRuntimeRewritePlugin( runtimeName, path.relative(path.dirname(helperFilename), pkgDirname), helperName ), ], }).code; }
function buildHelper(helperName, modules, useBuiltIns) { const id = modules === "commonjs" ? t.memberExpression(t.identifier("module"), t.identifier("exports")) : null; const sourceType = modules === "commonjs" ? "script" : "module"; const tree = t.program([], [], sourceType); const dependencies = {}; let bindings = null; if (modules === "commonjs") { bindings = []; for (const dep of helpers.getDependencies(helperName)) { const id = dependencies[dep] = t.identifier(t.toIdentifier(dep)); tree.body.push(buildRequireCall(id, dep)); bindings.push(id.name); } } const helper = helpers.get( helperName, dep => dependencies[dep], id, bindings ); tree.body.push.apply(tree.body, helper.nodes); const transformOpts = makeTransformOpts(modules, useBuiltIns); const relative = useBuiltIns ? "../.." : ".."; return babel.transformFromAst(tree, null, { presets: transformOpts.presets, plugins: transformOpts.plugins.concat([ buildRuntimeRewritePlugin( modules === false ? `../${relative}` : relative, helperName ), ]), }).code; }
export function transformFromAst(ast, code, options) { return Babel.transformFromAst(ast, code, processOptions(options)); }