Daniel Tschinder 4f0840ab88
Update dev dependencies and fix linting errors (#10228)
* 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.
2019-07-27 15:09:30 +02:00

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"
);
}