rsnext/packages/next/build/babel/loader/transform.ts

107 lines
3 KiB
TypeScript
Raw Normal View History

/*
* Partially adapted from @babel/core (MIT license).
*/
import traverse from 'next/dist/compiled/babel/traverse'
import generate from 'next/dist/compiled/babel/generator'
import normalizeFile from 'next/dist/compiled/babel/core-lib-normalize-file'
import normalizeOpts from 'next/dist/compiled/babel/core-lib-normalize-opts'
import loadBlockHoistPlugin from 'next/dist/compiled/babel/core-lib-block-hoist-plugin'
import PluginPass from 'next/dist/compiled/babel/core-lib-plugin-pass'
import getConfig from './get-config'
import { consumeIterator } from './util'
import { Span } from '../../../telemetry/trace'
import { NextJsLoaderContext } from './types'
function getTraversalParams(file: any, pluginPairs: any[]) {
const passPairs = []
const passes = []
const visitors = []
for (const plugin of pluginPairs.concat(loadBlockHoistPlugin())) {
const pass = new PluginPass(file, plugin.key, plugin.options)
passPairs.push([plugin, pass])
passes.push(pass)
visitors.push(plugin.visitor)
}
return { passPairs, passes, visitors }
}
function invokePluginPre(file: any, passPairs: any[]) {
for (const [{ pre }, pass] of passPairs) {
if (pre) {
pre.call(pass, file)
}
}
}
function invokePluginPost(file: any, passPairs: any[]) {
for (const [{ post }, pass] of passPairs) {
if (post) {
post.call(pass, file)
}
}
}
function transformAstPass(file: any, pluginPairs: any[], parentSpan: Span) {
const { passPairs, passes, visitors } = getTraversalParams(file, pluginPairs)
invokePluginPre(file, passPairs)
const visitor = traverse.visitors.merge(
visitors,
passes,
// @ts-ignore - the exported types are incorrect here
file.opts.wrapPluginVisitorMethod
)
parentSpan
.traceChild('babel-turbo-traverse')
.traceFn(() => traverse(file.ast, visitor, file.scope))
invokePluginPost(file, passPairs)
}
function transformAst(file: any, babelConfig: any, parentSpan: Span) {
for (const pluginPairs of babelConfig.passes) {
transformAstPass(file, pluginPairs, parentSpan)
}
}
export default function transform(
this: NextJsLoaderContext,
source: string,
inputSourceMap: object | null | undefined,
loaderOptions: any,
filename: string,
target: string,
parentSpan: Span
) {
const getConfigSpan = parentSpan.traceChild('babel-turbo-get-config')
const babelConfig = getConfig.call(this, {
source,
loaderOptions,
inputSourceMap,
target,
filename,
})
getConfigSpan.stop()
const normalizeSpan = parentSpan.traceChild('babel-turbo-normalize-file')
const file = consumeIterator(
normalizeFile(babelConfig.passes, normalizeOpts(babelConfig), source)
)
normalizeSpan.stop()
const transformSpan = parentSpan.traceChild('babel-turbo-transform')
transformAst(file, babelConfig, transformSpan)
transformSpan.stop()
const generateSpan = parentSpan.traceChild('babel-turbo-generate')
const { code, map } = generate(file.ast, file.opts.generatorOpts, file.code)
generateSpan.stop()
return { code, map }
}