* chore: Uppate dev dependencies * chore: Fix lint errors * chore: Format options.json files * chore: Fix stupid flow errors * Update test262 whitelist Seems test262-stream was updated and now these tests work.
138 lines
3.6 KiB
JavaScript
138 lines
3.6 KiB
JavaScript
// @flow
|
|
import traverse from "@babel/traverse";
|
|
import typeof { SourceMap } from "convert-source-map";
|
|
|
|
import type { ResolvedConfig, PluginPasses } from "../config";
|
|
|
|
import PluginPass from "./plugin-pass";
|
|
import loadBlockHoistPlugin from "./block-hoist-plugin";
|
|
import normalizeOptions from "./normalize-opts";
|
|
import normalizeFile from "./normalize-file";
|
|
|
|
import generateCode from "./file/generate";
|
|
import type File from "./file/file";
|
|
|
|
export type FileResultCallback = {
|
|
(Error, null): any,
|
|
(null, FileResult | null): any,
|
|
};
|
|
|
|
export type FileResult = {
|
|
metadata: {},
|
|
options: {},
|
|
ast: {} | null,
|
|
code: string | null,
|
|
map: SourceMap | null,
|
|
};
|
|
|
|
export function runAsync(
|
|
config: ResolvedConfig,
|
|
code: string,
|
|
ast: ?(BabelNodeFile | BabelNodeProgram),
|
|
callback: Function,
|
|
) {
|
|
let result;
|
|
try {
|
|
result = runSync(config, code, ast);
|
|
} catch (err) {
|
|
return callback(err);
|
|
}
|
|
|
|
// We don't actually care about calling this synchronously here because it is
|
|
// already running within a .nextTick handler from the transform calls above.
|
|
return callback(null, result);
|
|
}
|
|
|
|
export function runSync(
|
|
config: ResolvedConfig,
|
|
code: string,
|
|
ast: ?(BabelNodeFile | BabelNodeProgram),
|
|
): FileResult {
|
|
const file = normalizeFile(
|
|
config.passes,
|
|
normalizeOptions(config),
|
|
code,
|
|
ast,
|
|
);
|
|
|
|
transformFile(file, config.passes);
|
|
|
|
const opts = file.opts;
|
|
const { outputCode, outputMap } =
|
|
opts.code !== false ? generateCode(config.passes, file) : {};
|
|
|
|
return {
|
|
metadata: file.metadata,
|
|
options: opts,
|
|
ast: opts.ast === true ? file.ast : null,
|
|
code: outputCode === undefined ? null : outputCode,
|
|
map: outputMap === undefined ? null : outputMap,
|
|
sourceType: file.ast.program.sourceType,
|
|
};
|
|
}
|
|
|
|
function transformFile(file: File, pluginPasses: PluginPasses): void {
|
|
for (const pluginPairs of pluginPasses) {
|
|
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);
|
|
}
|
|
|
|
for (const [plugin, pass] of passPairs) {
|
|
const fn = plugin.pre;
|
|
if (fn) {
|
|
const result = fn.call(pass, file);
|
|
|
|
if (isThenable(result)) {
|
|
throw new Error(
|
|
`You appear to be using an plugin with an async .pre, ` +
|
|
`which your current version of Babel does not support. ` +
|
|
`If you're using a published plugin, you may need to upgrade ` +
|
|
`your @babel/core version.`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
// merge all plugin visitors into a single visitor
|
|
const visitor = traverse.visitors.merge(
|
|
visitors,
|
|
passes,
|
|
file.opts.wrapPluginVisitorMethod,
|
|
);
|
|
traverse(file.ast, visitor, file.scope);
|
|
|
|
for (const [plugin, pass] of passPairs) {
|
|
const fn = plugin.post;
|
|
if (fn) {
|
|
const result = fn.call(pass, file);
|
|
|
|
if (isThenable(result)) {
|
|
throw new Error(
|
|
`You appear to be using an plugin with an async .post, ` +
|
|
`which your current version of Babel does not support. ` +
|
|
`If you're using a published plugin, you may need to upgrade ` +
|
|
`your @babel/core version.`,
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function isThenable(val: mixed): boolean {
|
|
return (
|
|
!!val &&
|
|
(typeof val === "object" || typeof val === "function") &&
|
|
!!val.then &&
|
|
typeof val.then === "function"
|
|
);
|
|
}
|