107 lines
3 KiB
TypeScript
107 lines
3 KiB
TypeScript
|
/*
|
||
|
* 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 }
|
||
|
}
|