Support .mjs plugins/presets and async factories (#12266)
This commit is contained in:
parent
bfd3f80bdb
commit
31ca15ef58
@ -55,7 +55,7 @@
|
||||
"convert-source-map": "^1.7.0",
|
||||
"debug": "^4.1.0",
|
||||
"escape-string-regexp": "condition:BABEL_8_BREAKING ? ^4.0.0 : ",
|
||||
"gensync": "^1.0.0-beta.1",
|
||||
"gensync": "^1.0.0-beta.2",
|
||||
"json5": "^2.1.2",
|
||||
"lodash": "^4.17.19",
|
||||
"semver": "^5.4.1",
|
||||
|
||||
@ -154,7 +154,7 @@ export function* buildRootChain(
|
||||
programmaticLogger,
|
||||
);
|
||||
if (!programmaticChain) return null;
|
||||
const programmaticReport = programmaticLogger.output();
|
||||
const programmaticReport = yield* programmaticLogger.output();
|
||||
|
||||
let configFile;
|
||||
if (typeof opts.configFile === "string") {
|
||||
@ -186,7 +186,7 @@ export function* buildRootChain(
|
||||
configFileLogger,
|
||||
);
|
||||
if (!result) return null;
|
||||
configReport = configFileLogger.output();
|
||||
configReport = yield* configFileLogger.output();
|
||||
|
||||
// Allow config files to toggle `.babelrc` resolution on and off and
|
||||
// specify where the roots are.
|
||||
@ -244,7 +244,7 @@ export function* buildRootChain(
|
||||
if (!result) {
|
||||
isIgnored = true;
|
||||
} else {
|
||||
babelRcReport = babelrcLogger.output();
|
||||
babelRcReport = yield* babelrcLogger.output();
|
||||
mergeChain(fileChain, result);
|
||||
}
|
||||
}
|
||||
@ -599,7 +599,7 @@ function makeChainWalker<ArgT: { options: ValidatedOptions, dirname: string }>({
|
||||
}
|
||||
|
||||
logger(config, index, envName);
|
||||
mergeChainOpts(chain, config);
|
||||
yield* mergeChainOpts(chain, config);
|
||||
}
|
||||
return chain;
|
||||
};
|
||||
@ -657,13 +657,13 @@ function mergeChain(target: ConfigChain, source: ConfigChain): ConfigChain {
|
||||
return target;
|
||||
}
|
||||
|
||||
function mergeChainOpts(
|
||||
function* mergeChainOpts(
|
||||
target: ConfigChain,
|
||||
{ options, plugins, presets }: OptionsAndDescriptors,
|
||||
): ConfigChain {
|
||||
): Handler<ConfigChain> {
|
||||
target.options.push(options);
|
||||
target.plugins.push(...plugins());
|
||||
target.presets.push(...presets());
|
||||
target.plugins.push(...(yield* plugins()));
|
||||
target.presets.push(...(yield* presets()));
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
// @flow
|
||||
|
||||
import gensync, { type Handler } from "gensync";
|
||||
|
||||
import { loadPlugin, loadPreset } from "./files";
|
||||
|
||||
import { getItemDescriptor } from "./item";
|
||||
@ -7,6 +9,7 @@ import { getItemDescriptor } from "./item";
|
||||
import {
|
||||
makeWeakCacheSync,
|
||||
makeStrongCacheSync,
|
||||
makeStrongCache,
|
||||
type CacheConfigurator,
|
||||
} from "./caching";
|
||||
|
||||
@ -21,8 +24,8 @@ import type {
|
||||
// the options object actually ends up being applicable.
|
||||
export type OptionsAndDescriptors = {
|
||||
options: ValidatedOptions,
|
||||
plugins: () => Array<UnloadedDescriptor>,
|
||||
presets: () => Array<UnloadedDescriptor>,
|
||||
plugins: () => Handler<Array<UnloadedDescriptor>>,
|
||||
presets: () => Handler<Array<UnloadedDescriptor>>,
|
||||
};
|
||||
|
||||
// Represents a plugin or presets at a given location in a config object.
|
||||
@ -63,6 +66,11 @@ export type ValidatedFile = {
|
||||
options: ValidatedOptions,
|
||||
};
|
||||
|
||||
// eslint-disable-next-line require-yield
|
||||
function* handlerOf<T>(value: T): Handler<T> {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a set of descriptors from a given options object, preserving
|
||||
* descriptor identity based on the identity of the plugin/preset arrays
|
||||
@ -78,13 +86,13 @@ export function createCachedDescriptors(
|
||||
options,
|
||||
plugins: plugins
|
||||
? () => createCachedPluginDescriptors(plugins, dirname)(alias)
|
||||
: () => [],
|
||||
: () => handlerOf([]),
|
||||
presets: presets
|
||||
? () =>
|
||||
createCachedPresetDescriptors(presets, dirname)(alias)(
|
||||
!!passPerPreset,
|
||||
)
|
||||
: () => [],
|
||||
: () => handlerOf([]),
|
||||
};
|
||||
}
|
||||
|
||||
@ -105,9 +113,9 @@ export function createUncachedDescriptors(
|
||||
|
||||
return {
|
||||
options,
|
||||
plugins: () => {
|
||||
*plugins() {
|
||||
if (!plugins) {
|
||||
plugins = createPluginDescriptors(
|
||||
plugins = yield* createPluginDescriptors(
|
||||
options.plugins || [],
|
||||
dirname,
|
||||
alias,
|
||||
@ -115,9 +123,9 @@ export function createUncachedDescriptors(
|
||||
}
|
||||
return plugins;
|
||||
},
|
||||
presets: () => {
|
||||
*presets() {
|
||||
if (!presets) {
|
||||
presets = createPresetDescriptors(
|
||||
presets = yield* createPresetDescriptors(
|
||||
options.presets || [],
|
||||
dirname,
|
||||
alias,
|
||||
@ -134,14 +142,22 @@ const createCachedPresetDescriptors = makeWeakCacheSync(
|
||||
(items: PluginList, cache: CacheConfigurator<string>) => {
|
||||
const dirname = cache.using(dir => dir);
|
||||
return makeStrongCacheSync((alias: string) =>
|
||||
makeStrongCacheSync((passPerPreset: boolean) =>
|
||||
createPresetDescriptors(items, dirname, alias, passPerPreset).map(
|
||||
makeStrongCache(function* (
|
||||
passPerPreset: boolean,
|
||||
): Handler<Array<UnloadedDescriptor>> {
|
||||
const descriptors = yield* createPresetDescriptors(
|
||||
items,
|
||||
dirname,
|
||||
alias,
|
||||
passPerPreset,
|
||||
);
|
||||
return descriptors.map(
|
||||
// Items are cached using the overall preset array identity when
|
||||
// possibly, but individual descriptors are also cached if a match
|
||||
// can be found in the previously-used descriptor lists.
|
||||
desc => loadCachedDescriptor(PRESET_DESCRIPTOR_CACHE, desc),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
},
|
||||
);
|
||||
@ -150,14 +166,17 @@ const PLUGIN_DESCRIPTOR_CACHE = new WeakMap();
|
||||
const createCachedPluginDescriptors = makeWeakCacheSync(
|
||||
(items: PluginList, cache: CacheConfigurator<string>) => {
|
||||
const dirname = cache.using(dir => dir);
|
||||
return makeStrongCacheSync((alias: string) =>
|
||||
createPluginDescriptors(items, dirname, alias).map(
|
||||
return makeStrongCache(function* (
|
||||
alias: string,
|
||||
): Handler<Array<UnloadedDescriptor>> {
|
||||
const descriptors = yield* createPluginDescriptors(items, dirname, alias);
|
||||
return descriptors.map(
|
||||
// Items are cached using the overall plugin array identity when
|
||||
// possibly, but individual descriptors are also cached if a match
|
||||
// can be found in the previously-used descriptor lists.
|
||||
desc => loadCachedDescriptor(PLUGIN_DESCRIPTOR_CACHE, desc),
|
||||
),
|
||||
);
|
||||
);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
@ -205,36 +224,44 @@ function loadCachedDescriptor(
|
||||
return desc;
|
||||
}
|
||||
|
||||
function createPresetDescriptors(
|
||||
function* createPresetDescriptors(
|
||||
items: PluginList,
|
||||
dirname: string,
|
||||
alias: string,
|
||||
passPerPreset: boolean,
|
||||
): Array<UnloadedDescriptor> {
|
||||
return createDescriptors("preset", items, dirname, alias, passPerPreset);
|
||||
): Handler<Array<UnloadedDescriptor>> {
|
||||
return yield* createDescriptors(
|
||||
"preset",
|
||||
items,
|
||||
dirname,
|
||||
alias,
|
||||
passPerPreset,
|
||||
);
|
||||
}
|
||||
|
||||
function createPluginDescriptors(
|
||||
function* createPluginDescriptors(
|
||||
items: PluginList,
|
||||
dirname: string,
|
||||
alias: string,
|
||||
): Array<UnloadedDescriptor> {
|
||||
return createDescriptors("plugin", items, dirname, alias);
|
||||
): Handler<Array<UnloadedDescriptor>> {
|
||||
return yield* createDescriptors("plugin", items, dirname, alias);
|
||||
}
|
||||
|
||||
function createDescriptors(
|
||||
function* createDescriptors(
|
||||
type: "plugin" | "preset",
|
||||
items: PluginList,
|
||||
dirname: string,
|
||||
alias: string,
|
||||
ownPass?: boolean,
|
||||
): Array<UnloadedDescriptor> {
|
||||
const descriptors = items.map((item, index) =>
|
||||
createDescriptor(item, dirname, {
|
||||
type,
|
||||
alias: `${alias}$${index}`,
|
||||
ownPass: !!ownPass,
|
||||
}),
|
||||
): Handler<Array<UnloadedDescriptor>> {
|
||||
const descriptors = yield* gensync.all(
|
||||
items.map((item, index) =>
|
||||
createDescriptor(item, dirname, {
|
||||
type,
|
||||
alias: `${alias}$${index}`,
|
||||
ownPass: !!ownPass,
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
assertNoDuplicates(descriptors);
|
||||
@ -245,7 +272,7 @@ function createDescriptors(
|
||||
/**
|
||||
* Given a plugin/preset item, resolve it into a standard format.
|
||||
*/
|
||||
export function createDescriptor(
|
||||
export function* createDescriptor(
|
||||
pair: PluginItem,
|
||||
dirname: string,
|
||||
{
|
||||
@ -257,7 +284,7 @@ export function createDescriptor(
|
||||
alias: string,
|
||||
ownPass?: boolean,
|
||||
},
|
||||
): UnloadedDescriptor {
|
||||
): Handler<UnloadedDescriptor> {
|
||||
const desc = getItemDescriptor(pair);
|
||||
if (desc) {
|
||||
return desc;
|
||||
@ -285,7 +312,7 @@ export function createDescriptor(
|
||||
const resolver = type === "plugin" ? loadPlugin : loadPreset;
|
||||
const request = value;
|
||||
|
||||
({ filepath, value } = resolver(value, dirname));
|
||||
({ filepath, value } = yield* resolver(value, dirname));
|
||||
|
||||
file = {
|
||||
request,
|
||||
|
||||
@ -80,7 +80,7 @@ export function resolvePreset(name: string, dirname: string): string | null {
|
||||
export function loadPlugin(
|
||||
name: string,
|
||||
dirname: string,
|
||||
): { filepath: string, value: mixed } {
|
||||
): Handler<{ filepath: string, value: mixed }> {
|
||||
throw new Error(
|
||||
`Cannot load plugin ${name} relative to ${dirname} in a browser`,
|
||||
);
|
||||
@ -89,7 +89,7 @@ export function loadPlugin(
|
||||
export function loadPreset(
|
||||
name: string,
|
||||
dirname: string,
|
||||
): { filepath: string, value: mixed } {
|
||||
): Handler<{ filepath: string, value: mixed }> {
|
||||
throw new Error(
|
||||
`Cannot load preset ${name} relative to ${dirname} in a browser`,
|
||||
);
|
||||
|
||||
@ -12,13 +12,15 @@ try {
|
||||
export default function* loadCjsOrMjsDefault(
|
||||
filepath: string,
|
||||
asyncError: string,
|
||||
// TODO(Babel 8): Remove this
|
||||
fallbackToTranspiledModule: boolean = false,
|
||||
): Handler<mixed> {
|
||||
switch (guessJSModuleType(filepath)) {
|
||||
case "cjs":
|
||||
return loadCjsDefault(filepath);
|
||||
return loadCjsDefault(filepath, fallbackToTranspiledModule);
|
||||
case "unknown":
|
||||
try {
|
||||
return loadCjsDefault(filepath);
|
||||
return loadCjsDefault(filepath, fallbackToTranspiledModule);
|
||||
} catch (e) {
|
||||
if (e.code !== "ERR_REQUIRE_ESM") throw e;
|
||||
}
|
||||
@ -42,10 +44,12 @@ function guessJSModuleType(filename: string): "cjs" | "mjs" | "unknown" {
|
||||
}
|
||||
}
|
||||
|
||||
function loadCjsDefault(filepath: string) {
|
||||
function loadCjsDefault(filepath: string, fallbackToTranspiledModule: boolean) {
|
||||
const module = (require(filepath): mixed);
|
||||
// TODO (Babel 8): Remove "undefined" fallback
|
||||
return module?.__esModule ? module.default || undefined : module;
|
||||
return module?.__esModule
|
||||
? // TODO (Babel 8): Remove "module" and "undefined" fallback
|
||||
module.default || (fallbackToTranspiledModule ? module : undefined)
|
||||
: module;
|
||||
}
|
||||
|
||||
async function loadMjsDefault(filepath: string) {
|
||||
|
||||
@ -6,6 +6,8 @@
|
||||
|
||||
import buildDebug from "debug";
|
||||
import path from "path";
|
||||
import { type Handler } from "gensync";
|
||||
import loadCjsOrMjsDefault from "./module-types";
|
||||
|
||||
const debug = buildDebug("babel:config:loading:files:plugins");
|
||||
|
||||
@ -26,31 +28,31 @@ export function resolvePreset(name: string, dirname: string): string | null {
|
||||
return resolveStandardizedName("preset", name, dirname);
|
||||
}
|
||||
|
||||
export function loadPlugin(
|
||||
export function* loadPlugin(
|
||||
name: string,
|
||||
dirname: string,
|
||||
): { filepath: string, value: mixed } {
|
||||
): Handler<{ filepath: string, value: mixed }> {
|
||||
const filepath = resolvePlugin(name, dirname);
|
||||
if (!filepath) {
|
||||
throw new Error(`Plugin ${name} not found relative to ${dirname}`);
|
||||
}
|
||||
|
||||
const value = requireModule("plugin", filepath);
|
||||
const value = yield* requireModule("plugin", filepath);
|
||||
debug("Loaded plugin %o from %o.", name, dirname);
|
||||
|
||||
return { filepath, value };
|
||||
}
|
||||
|
||||
export function loadPreset(
|
||||
export function* loadPreset(
|
||||
name: string,
|
||||
dirname: string,
|
||||
): { filepath: string, value: mixed } {
|
||||
): Handler<{ filepath: string, value: mixed }> {
|
||||
const filepath = resolvePreset(name, dirname);
|
||||
if (!filepath) {
|
||||
throw new Error(`Preset ${name} not found relative to ${dirname}`);
|
||||
}
|
||||
|
||||
const value = requireModule("preset", filepath);
|
||||
const value = yield* requireModule("preset", filepath);
|
||||
|
||||
debug("Loaded preset %o from %o.", name, dirname);
|
||||
|
||||
@ -145,7 +147,7 @@ function resolveStandardizedName(
|
||||
}
|
||||
|
||||
const LOADING_MODULES = new Set();
|
||||
function requireModule(type: string, name: string): mixed {
|
||||
function* requireModule(type: string, name: string): Handler<mixed> {
|
||||
if (LOADING_MODULES.has(name)) {
|
||||
throw new Error(
|
||||
`Reentrant ${type} detected trying to load "${name}". This module is not ignored ` +
|
||||
@ -156,7 +158,19 @@ function requireModule(type: string, name: string): mixed {
|
||||
|
||||
try {
|
||||
LOADING_MODULES.add(name);
|
||||
return require(name);
|
||||
return (yield* loadCjsOrMjsDefault(
|
||||
name,
|
||||
`You appear to be using a native ECMAScript module ${type}, ` +
|
||||
"which is only supported when running Babel asynchronously.",
|
||||
// For backward compatiblity, we need to support malformed presets
|
||||
// defined as separate named exports rather than a single default
|
||||
// export.
|
||||
// See packages/babel-core/test/fixtures/option-manager/presets/es2015_named.js
|
||||
true,
|
||||
): mixed);
|
||||
} catch (err) {
|
||||
err.message = `[BABEL]: ${err.message} (While processing: ${name})`;
|
||||
throw err;
|
||||
} finally {
|
||||
LOADING_MODULES.delete(name);
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// @flow
|
||||
|
||||
import gensync, { type Handler } from "gensync";
|
||||
import { forwardAsync } from "../gensync-utils/async";
|
||||
import { forwardAsync, maybeAsync, isThenable } from "../gensync-utils/async";
|
||||
|
||||
import { mergeOptions } from "./util";
|
||||
import * as context from "../index";
|
||||
@ -228,12 +228,17 @@ const loadDescriptor = makeWeakCache(function* (
|
||||
|
||||
let item = value;
|
||||
if (typeof value === "function") {
|
||||
const factory = maybeAsync(
|
||||
value,
|
||||
`You appear to be using an async plugin/preset, but Babel has been called synchronously`,
|
||||
);
|
||||
|
||||
const api = {
|
||||
...context,
|
||||
...makeAPI(cache),
|
||||
};
|
||||
try {
|
||||
item = value(api, options, dirname);
|
||||
item = yield* factory(api, options, dirname);
|
||||
} catch (e) {
|
||||
if (alias) {
|
||||
e.message += ` (While processing: ${JSON.stringify(alias)})`;
|
||||
@ -246,14 +251,16 @@ const loadDescriptor = makeWeakCache(function* (
|
||||
throw new Error("Plugin/Preset did not return an object.");
|
||||
}
|
||||
|
||||
if (typeof item.then === "function") {
|
||||
if (isThenable(item)) {
|
||||
yield* []; // if we want to support async plugins
|
||||
|
||||
throw new Error(
|
||||
`You appear to be using an async plugin, ` +
|
||||
`You appear to be using a promise as a plugin, ` +
|
||||
`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.`,
|
||||
`you may need to upgrade your @babel/core version. ` +
|
||||
`As an alternative, you can prefix the promise with "await". ` +
|
||||
`(While processing: ${JSON.stringify(alias)})`,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
/*:: declare var invariant; */
|
||||
|
||||
import type { Handler } from "gensync";
|
||||
import type { PluginTarget, PluginOptions } from "./validation/options";
|
||||
|
||||
import path from "path";
|
||||
@ -20,7 +21,7 @@ export function createItemFromDescriptor(desc: UnloadedDescriptor): ConfigItem {
|
||||
* ideally, as recreating the config item will mean re-resolving the item
|
||||
* and re-evaluating the plugin/preset function.
|
||||
*/
|
||||
export function createConfigItem(
|
||||
export function* createConfigItem(
|
||||
value:
|
||||
| PluginTarget
|
||||
| [PluginTarget, PluginOptions]
|
||||
@ -32,8 +33,8 @@ export function createConfigItem(
|
||||
dirname?: string,
|
||||
type?: "preset" | "plugin",
|
||||
} = {},
|
||||
): ConfigItem {
|
||||
const descriptor = createDescriptor(value, path.resolve(dirname), {
|
||||
): Handler<ConfigItem> {
|
||||
const descriptor = yield* createDescriptor(value, path.resolve(dirname), {
|
||||
type,
|
||||
alias: "programmatic item",
|
||||
});
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
// @flow
|
||||
|
||||
import gensync, { type Handler } from "gensync";
|
||||
|
||||
import type {
|
||||
OptionsAndDescriptors,
|
||||
UnloadedDescriptor,
|
||||
@ -49,17 +51,17 @@ const Formatter = {
|
||||
return loc;
|
||||
},
|
||||
|
||||
optionsAndDescriptors(opt: OptionsAndDescriptors) {
|
||||
*optionsAndDescriptors(opt: OptionsAndDescriptors) {
|
||||
const content = { ...opt.options };
|
||||
// overrides and env will be printed as separated config items
|
||||
delete content.overrides;
|
||||
delete content.env;
|
||||
// resolve to descriptors
|
||||
const pluginDescriptors = [...opt.plugins()];
|
||||
const pluginDescriptors = [...(yield* opt.plugins())];
|
||||
if (pluginDescriptors.length) {
|
||||
content.plugins = pluginDescriptors.map(d => descriptorToConfig(d));
|
||||
}
|
||||
const presetDescriptors = [...opt.presets()];
|
||||
const presetDescriptors = [...(yield* opt.presets())];
|
||||
if (presetDescriptors.length) {
|
||||
content.presets = [...presetDescriptors].map(d => descriptorToConfig(d));
|
||||
}
|
||||
@ -114,7 +116,7 @@ export class ConfigPrinter {
|
||||
});
|
||||
};
|
||||
}
|
||||
static format(config: PrintableConfig): string {
|
||||
static *format(config: PrintableConfig): Handler<string> {
|
||||
let title = Formatter.title(
|
||||
config.type,
|
||||
config.callerName,
|
||||
@ -122,12 +124,15 @@ export class ConfigPrinter {
|
||||
);
|
||||
const loc = Formatter.loc(config.index, config.envName);
|
||||
if (loc) title += ` ${loc}`;
|
||||
const content = Formatter.optionsAndDescriptors(config.content);
|
||||
const content = yield* Formatter.optionsAndDescriptors(config.content);
|
||||
return `${title}\n${content}`;
|
||||
}
|
||||
|
||||
output(): string {
|
||||
*output(): Handler<string> {
|
||||
if (this._stack.length === 0) return "";
|
||||
return this._stack.map(s => ConfigPrinter.format(s)).join("\n\n");
|
||||
const configs = yield* gensync.all(
|
||||
this._stack.map(s => ConfigPrinter.format(s)),
|
||||
);
|
||||
return configs.join("\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -15,6 +15,7 @@ function assertNotIgnored(result) {
|
||||
function parse(code, opts) {
|
||||
return babel.parse(code, {
|
||||
cwd: __dirname,
|
||||
configFile: false,
|
||||
...opts,
|
||||
});
|
||||
}
|
||||
@ -22,6 +23,7 @@ function parse(code, opts) {
|
||||
function transform(code, opts) {
|
||||
return babel.transform(code, {
|
||||
cwd: __dirname,
|
||||
configFile: false,
|
||||
...opts,
|
||||
});
|
||||
}
|
||||
@ -31,6 +33,7 @@ function transformFile(filename, opts, cb) {
|
||||
filename,
|
||||
{
|
||||
cwd: __dirname,
|
||||
configFile: false,
|
||||
...opts,
|
||||
},
|
||||
cb,
|
||||
@ -39,6 +42,7 @@ function transformFile(filename, opts, cb) {
|
||||
function transformFileSync(filename, opts) {
|
||||
return babel.transformFileSync(filename, {
|
||||
cwd: __dirname,
|
||||
configFile: false,
|
||||
...opts,
|
||||
});
|
||||
}
|
||||
@ -46,6 +50,7 @@ function transformFileSync(filename, opts) {
|
||||
function transformAsync(code, opts) {
|
||||
return babel.transformAsync(code, {
|
||||
cwd: __dirname,
|
||||
configFile: false,
|
||||
...opts,
|
||||
});
|
||||
}
|
||||
@ -53,6 +58,7 @@ function transformAsync(code, opts) {
|
||||
function transformFromAst(ast, code, opts) {
|
||||
return babel.transformFromAst(ast, code, {
|
||||
cwd: __dirname,
|
||||
configFile: false,
|
||||
...opts,
|
||||
});
|
||||
}
|
||||
|
||||
@ -1,6 +1,12 @@
|
||||
import path from "path";
|
||||
import { join } from "path";
|
||||
import * as babel from "..";
|
||||
|
||||
import {
|
||||
spawnTransformAsync,
|
||||
spawnTransformSync,
|
||||
supportsESM,
|
||||
} from "./helpers/esm";
|
||||
|
||||
const nodeGte8 = (...args) => {
|
||||
// "minNodeVersion": "8.0.0" <-- For Ctrl+F when dropping node 6
|
||||
const testFn = process.version.slice(0, 3) === "v6." ? it.skip : it;
|
||||
@ -8,7 +14,7 @@ const nodeGte8 = (...args) => {
|
||||
};
|
||||
|
||||
describe("asynchronicity", () => {
|
||||
const base = path.join(__dirname, "fixtures", "async");
|
||||
const base = join(__dirname, "fixtures", "async");
|
||||
let cwd;
|
||||
|
||||
beforeEach(function () {
|
||||
@ -111,25 +117,18 @@ describe("asynchronicity", () => {
|
||||
nodeGte8("called synchronously", () => {
|
||||
process.chdir("plugin");
|
||||
|
||||
expect(() =>
|
||||
babel.transformSync(""),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"[BABEL] unknown: You appear to be using an async plugin, 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."`,
|
||||
expect(() => babel.transformSync("")).toThrow(
|
||||
`[BABEL] unknown: You appear to be using an async plugin/preset, but Babel` +
|
||||
` has been called synchronously`,
|
||||
);
|
||||
});
|
||||
|
||||
nodeGte8("called asynchronously", async () => {
|
||||
process.chdir("plugin");
|
||||
|
||||
await expect(
|
||||
babel.transformAsync(""),
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"[BABEL] unknown: You appear to be using an async plugin, 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."`,
|
||||
);
|
||||
await expect(babel.transformAsync("")).resolves.toMatchObject({
|
||||
code: `"success"`,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -189,24 +188,108 @@ describe("asynchronicity", () => {
|
||||
nodeGte8("called synchronously", () => {
|
||||
process.chdir("plugin-inherits");
|
||||
|
||||
expect(() =>
|
||||
babel.transformSync(""),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"[BABEL] unknown: You appear to be using an async plugin, 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."`,
|
||||
expect(() => babel.transformSync("")).toThrow(
|
||||
`[BABEL] unknown: You appear to be using an async plugin/preset, but Babel has been` +
|
||||
` called synchronously`,
|
||||
);
|
||||
});
|
||||
|
||||
nodeGte8("called asynchronously", async () => {
|
||||
process.chdir("plugin-inherits");
|
||||
|
||||
await expect(
|
||||
babel.transformAsync(""),
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(
|
||||
`"[BABEL] unknown: You appear to be using an async plugin, 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."`,
|
||||
await expect(babel.transformAsync("")).resolves.toMatchObject({
|
||||
code: `"success 2"\n"success"`,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
(supportsESM ? describe : describe.skip)(".mjs files", () => {
|
||||
it("called synchronously", async () => {
|
||||
process.chdir("plugin-mjs-native");
|
||||
|
||||
await expect(spawnTransformSync()).rejects.toThrow(
|
||||
`[BABEL]: You appear to be using a native ECMAScript module plugin, which is` +
|
||||
` only supported when running Babel asynchronously.`,
|
||||
);
|
||||
});
|
||||
|
||||
it("called asynchronously", async () => {
|
||||
process.chdir("plugin-mjs-native");
|
||||
|
||||
await expect(spawnTransformAsync()).resolves.toMatchObject({
|
||||
code: `"success"`,
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("preset", () => {
|
||||
describe("factory function", () => {
|
||||
nodeGte8("called synchronously", () => {
|
||||
process.chdir("preset");
|
||||
|
||||
expect(() => babel.transformSync("")).toThrow(
|
||||
`[BABEL] unknown: You appear to be using an async plugin/preset, ` +
|
||||
`but Babel has been called synchronously`,
|
||||
);
|
||||
});
|
||||
|
||||
nodeGte8("called asynchronously", async () => {
|
||||
process.chdir("preset");
|
||||
|
||||
await expect(babel.transformAsync("")).resolves.toMatchObject({
|
||||
code: `"success"`,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("plugins", () => {
|
||||
nodeGte8("called synchronously", () => {
|
||||
process.chdir("preset-plugin-promise");
|
||||
|
||||
expect(() => babel.transformSync("")).toThrow(
|
||||
`[BABEL] unknown: You appear to be using a promise as a plugin, 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. As an` +
|
||||
` alternative, you can prefix the promise with "await".`,
|
||||
);
|
||||
});
|
||||
|
||||
nodeGte8("called asynchronously", async () => {
|
||||
process.chdir("preset-plugin-promise");
|
||||
|
||||
await expect(babel.transformAsync("")).rejects.toThrow(
|
||||
`[BABEL] unknown: You appear to be using a promise as a plugin, 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. As an` +
|
||||
` alternative, you can prefix the promise with "await".`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
(supportsESM ? describe : describe.skip)(".mjs files", () => {
|
||||
it("called synchronously", async () => {
|
||||
process.chdir("preset-mjs-native");
|
||||
|
||||
await expect(spawnTransformSync()).rejects.toThrow(
|
||||
`[BABEL]: You appear to be using a native ECMAScript module preset, which is` +
|
||||
` only supported when running Babel asynchronously.`,
|
||||
);
|
||||
});
|
||||
|
||||
it("called asynchronously", async () => {
|
||||
process.chdir("preset-mjs-native");
|
||||
|
||||
await expect(spawnTransformAsync()).resolves.toMatchObject({
|
||||
code: `"success"`,
|
||||
});
|
||||
});
|
||||
|
||||
it("must use the 'default' export", async () => {
|
||||
process.chdir("preset-mjs-named-exports-native");
|
||||
|
||||
await expect(spawnTransformAsync()).rejects.toThrow(
|
||||
`Unexpected falsy value: undefined`,
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@ -1,32 +1,10 @@
|
||||
import cp from "child_process";
|
||||
import fs from "fs";
|
||||
import os from "os";
|
||||
import path from "path";
|
||||
import util from "util";
|
||||
import escapeRegExp from "lodash/escapeRegExp";
|
||||
import * as babel from "../lib";
|
||||
|
||||
// "minNodeVersion": "10.0.0" <-- For Ctrl+F when dropping node 10
|
||||
const supportsESM = parseInt(process.versions.node) >= 12;
|
||||
|
||||
const isMJS = file => path.extname(file) === ".mjs";
|
||||
|
||||
const skipUnsupportedESM = (esm, name) => {
|
||||
if (esm && !supportsESM) {
|
||||
console.warn(
|
||||
`Skipping "${name}" because native ECMAScript modules are not supported.`,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
// This can be removed when loadOptionsAsyncInSpawedProcess is removed.
|
||||
if (esm && process.platform === "win32") {
|
||||
console.warn(
|
||||
`Skipping "${name}" because the ESM runner cannot be spawned on Windows.`,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
import { isMJS, loadOptionsAsync, skipUnsupportedESM } from "./helpers/esm";
|
||||
|
||||
// TODO: In Babel 8, we can directly uses fs.promises which is supported by
|
||||
// node 8+
|
||||
@ -71,42 +49,6 @@ function loadOptions(opts) {
|
||||
return babel.loadOptions({ cwd: __dirname, ...opts });
|
||||
}
|
||||
|
||||
function loadOptionsAsync({ filename, cwd = __dirname }, mjs) {
|
||||
if (mjs) {
|
||||
// import() crashes with jest
|
||||
return loadOptionsAsyncInSpawedProcess({ filename, cwd });
|
||||
}
|
||||
|
||||
return babel.loadOptionsAsync({ filename, cwd });
|
||||
}
|
||||
|
||||
// !!!! hack is coming !!!!
|
||||
// Remove this function when https://github.com/nodejs/node/issues/35889 is resolved.
|
||||
// Jest supports dynamic import(), but Node.js segfaults when using it in our tests.
|
||||
async function loadOptionsAsyncInSpawedProcess({ filename, cwd }) {
|
||||
const { stdout, stderr } = await util.promisify(cp.execFile)(
|
||||
require.resolve("./fixtures/babel-load-options-async.mjs"),
|
||||
// pass `cwd` as params as `process.cwd()` will normalize `cwd` on macOS
|
||||
[filename, cwd],
|
||||
{
|
||||
cwd,
|
||||
env: process.env,
|
||||
},
|
||||
);
|
||||
|
||||
const EXPERIMENTAL_WARNING = /\(node:\d+\) ExperimentalWarning: The ESM module loader is experimental\./;
|
||||
|
||||
if (stderr.replace(EXPERIMENTAL_WARNING, "").trim()) {
|
||||
throw new Error(
|
||||
"error is thrown in babel-load-options-async.mjs: stdout\n" +
|
||||
stdout +
|
||||
"\nstderr:\n" +
|
||||
stderr,
|
||||
);
|
||||
}
|
||||
return JSON.parse(stdout);
|
||||
}
|
||||
|
||||
function pairs(items) {
|
||||
const pairs = [];
|
||||
for (let i = 0; i < items.length - 1; i++) {
|
||||
|
||||
3
packages/babel-core/test/fixtures/async/plugin-mjs-native/babel.config.js
vendored
Normal file
3
packages/babel-core/test/fixtures/async/plugin-mjs-native/babel.config.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
plugins: ["./plugin.mjs"],
|
||||
};
|
||||
9
packages/babel-core/test/fixtures/async/plugin-mjs-native/plugin.mjs
vendored
Normal file
9
packages/babel-core/test/fixtures/async/plugin-mjs-native/plugin.mjs
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
export default function plugin({ types: t }) {
|
||||
return {
|
||||
visitor: {
|
||||
Program(path) {
|
||||
path.pushContainer("body", t.stringLiteral("success"));
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
3
packages/babel-core/test/fixtures/async/plugin-mjs/babel.config.js
vendored
Normal file
3
packages/babel-core/test/fixtures/async/plugin-mjs/babel.config.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
plugins: ["./plugin.mjs"],
|
||||
};
|
||||
16
packages/babel-core/test/fixtures/async/plugin-mjs/plugin.mjs
vendored
Normal file
16
packages/babel-core/test/fixtures/async/plugin-mjs/plugin.mjs
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
// Until Jest supports native mjs, we must simulate it 🤷
|
||||
module.exports = new Promise(resolve =>
|
||||
resolve({
|
||||
default: function plugin({ types: t }) {
|
||||
return {
|
||||
visitor: {
|
||||
Program(path) {
|
||||
path.pushContainer("body", t.stringLiteral("success"));
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
module.exports.__esModule = true;
|
||||
3
packages/babel-core/test/fixtures/async/preset-mjs-named-exports-native/babel.config.js
vendored
Normal file
3
packages/babel-core/test/fixtures/async/preset-mjs-named-exports-native/babel.config.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: ["./preset.mjs"],
|
||||
};
|
||||
9
packages/babel-core/test/fixtures/async/preset-mjs-named-exports-native/plugin.mjs
vendored
Normal file
9
packages/babel-core/test/fixtures/async/preset-mjs-named-exports-native/plugin.mjs
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
export default function plugin({ types: t }) {
|
||||
return {
|
||||
visitor: {
|
||||
Program(path) {
|
||||
path.pushContainer("body", t.stringLiteral("success"));
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
1
packages/babel-core/test/fixtures/async/preset-mjs-named-exports-native/preset.mjs
vendored
Normal file
1
packages/babel-core/test/fixtures/async/preset-mjs-named-exports-native/preset.mjs
vendored
Normal file
@ -0,0 +1 @@
|
||||
export const plugins = ["./plugin.mjs"];
|
||||
3
packages/babel-core/test/fixtures/async/preset-mjs-named-exports/babel.config.js
vendored
Normal file
3
packages/babel-core/test/fixtures/async/preset-mjs-named-exports/babel.config.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: ["./preset.mjs"],
|
||||
};
|
||||
16
packages/babel-core/test/fixtures/async/preset-mjs-named-exports/plugin.mjs
vendored
Normal file
16
packages/babel-core/test/fixtures/async/preset-mjs-named-exports/plugin.mjs
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
// Until Jest supports native mjs, we must simulate it 🤷
|
||||
module.exports = new Promise(resolve =>
|
||||
resolve({
|
||||
default: function plugin({ types: t }) {
|
||||
return {
|
||||
visitor: {
|
||||
Program(path) {
|
||||
path.pushContainer("body", t.stringLiteral("success"));
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
module.exports.__esModule = true;
|
||||
8
packages/babel-core/test/fixtures/async/preset-mjs-named-exports/preset.mjs
vendored
Normal file
8
packages/babel-core/test/fixtures/async/preset-mjs-named-exports/preset.mjs
vendored
Normal file
@ -0,0 +1,8 @@
|
||||
// Until Jest supports native mjs, we must simulate it 🤷
|
||||
module.exports = new Promise(resolve =>
|
||||
resolve({
|
||||
plugins: ["./plugin.mjs"]
|
||||
})
|
||||
);
|
||||
|
||||
module.exports.__esModule = true;
|
||||
3
packages/babel-core/test/fixtures/async/preset-mjs-native/babel.config.js
vendored
Normal file
3
packages/babel-core/test/fixtures/async/preset-mjs-native/babel.config.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: ["./preset.mjs"],
|
||||
};
|
||||
9
packages/babel-core/test/fixtures/async/preset-mjs-native/plugin.mjs
vendored
Normal file
9
packages/babel-core/test/fixtures/async/preset-mjs-native/plugin.mjs
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
export default function plugin({ types: t }) {
|
||||
return {
|
||||
visitor: {
|
||||
Program(path) {
|
||||
path.pushContainer("body", t.stringLiteral("success"));
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
3
packages/babel-core/test/fixtures/async/preset-mjs-native/preset.mjs
vendored
Normal file
3
packages/babel-core/test/fixtures/async/preset-mjs-native/preset.mjs
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
export default () => ({
|
||||
plugins: ["./plugin.mjs"]
|
||||
});
|
||||
3
packages/babel-core/test/fixtures/async/preset-mjs/babel.config.js
vendored
Normal file
3
packages/babel-core/test/fixtures/async/preset-mjs/babel.config.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: ["./preset.mjs"],
|
||||
};
|
||||
16
packages/babel-core/test/fixtures/async/preset-mjs/plugin.mjs
vendored
Normal file
16
packages/babel-core/test/fixtures/async/preset-mjs/plugin.mjs
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
// Until Jest supports native mjs, we must simulate it 🤷
|
||||
module.exports = new Promise(resolve =>
|
||||
resolve({
|
||||
default: function plugin({ types: t }) {
|
||||
return {
|
||||
visitor: {
|
||||
Program(path) {
|
||||
path.pushContainer("body", t.stringLiteral("success"));
|
||||
},
|
||||
},
|
||||
};
|
||||
},
|
||||
})
|
||||
);
|
||||
|
||||
module.exports.__esModule = true;
|
||||
10
packages/babel-core/test/fixtures/async/preset-mjs/preset.mjs
vendored
Normal file
10
packages/babel-core/test/fixtures/async/preset-mjs/preset.mjs
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
// Until Jest supports native mjs, we must simulate it 🤷
|
||||
module.exports = new Promise(resolve =>
|
||||
resolve({
|
||||
default: () => ({
|
||||
plugins: ["./plugin.mjs"]
|
||||
})
|
||||
})
|
||||
);
|
||||
|
||||
module.exports.__esModule = true;
|
||||
3
packages/babel-core/test/fixtures/async/preset-plugin-promise/babel.config.js
vendored
Normal file
3
packages/babel-core/test/fixtures/async/preset-plugin-promise/babel.config.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: ["./preset"],
|
||||
};
|
||||
13
packages/babel-core/test/fixtures/async/preset-plugin-promise/plugin.js
vendored
Normal file
13
packages/babel-core/test/fixtures/async/preset-plugin-promise/plugin.js
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
const wait = t => new Promise(r => setTimeout(r, t));
|
||||
|
||||
module.exports = async function plugin({ types: t }) {
|
||||
await wait(50);
|
||||
|
||||
return {
|
||||
visitor: {
|
||||
Program(path) {
|
||||
path.pushContainer("body", t.stringLiteral("success"));
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
10
packages/babel-core/test/fixtures/async/preset-plugin-promise/preset.js
vendored
Normal file
10
packages/babel-core/test/fixtures/async/preset-plugin-promise/preset.js
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
const wait = t => new Promise(r => setTimeout(r, t));
|
||||
|
||||
// "Dynamic import"
|
||||
const import_ = path => Promise.resolve(require(path));
|
||||
|
||||
module.exports = function preset(api) {
|
||||
return {
|
||||
plugins: [import_("./plugin")],
|
||||
};
|
||||
};
|
||||
3
packages/babel-core/test/fixtures/async/preset/babel.config.js
vendored
Normal file
3
packages/babel-core/test/fixtures/async/preset/babel.config.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
presets: ["./preset"],
|
||||
};
|
||||
13
packages/babel-core/test/fixtures/async/preset/plugin.js
vendored
Normal file
13
packages/babel-core/test/fixtures/async/preset/plugin.js
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
const wait = t => new Promise(r => setTimeout(r, t));
|
||||
|
||||
module.exports = async function plugin({ types: t }) {
|
||||
await wait(50);
|
||||
|
||||
return {
|
||||
visitor: {
|
||||
Program(path) {
|
||||
path.pushContainer("body", t.stringLiteral("success"));
|
||||
},
|
||||
},
|
||||
};
|
||||
};
|
||||
9
packages/babel-core/test/fixtures/async/preset/preset.js
vendored
Normal file
9
packages/babel-core/test/fixtures/async/preset/preset.js
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
const wait = t => new Promise(r => setTimeout(r, t));
|
||||
|
||||
module.exports = async function preset(api) {
|
||||
await wait(50);
|
||||
|
||||
return {
|
||||
plugins: [require("./plugin")],
|
||||
};
|
||||
};
|
||||
11
packages/babel-core/test/fixtures/babel-compile-async.mjs
vendored
Executable file
11
packages/babel-core/test/fixtures/babel-compile-async.mjs
vendored
Executable file
@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// Usage:
|
||||
// babel-compile-async.js [filename]
|
||||
import babel from "../../lib/index.js";
|
||||
|
||||
(async () => {
|
||||
process.stdout.write(
|
||||
JSON.stringify(await babel.transformAsync(""))
|
||||
);
|
||||
})();
|
||||
9
packages/babel-core/test/fixtures/babel-compile-sync.mjs
vendored
Executable file
9
packages/babel-core/test/fixtures/babel-compile-sync.mjs
vendored
Executable file
@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
// Usage:
|
||||
// babel-compile-async.js [filename]
|
||||
import babel from "../../lib/index.js";
|
||||
|
||||
process.stdout.write(
|
||||
JSON.stringify(babel.transformSync(""))
|
||||
);
|
||||
74
packages/babel-core/test/helpers/esm.js
Normal file
74
packages/babel-core/test/helpers/esm.js
Normal file
@ -0,0 +1,74 @@
|
||||
import cp from "child_process";
|
||||
import util from "util";
|
||||
import path from "path";
|
||||
import * as babel from "../../lib";
|
||||
|
||||
// "minNodeVersion": "10.0.0" <-- For Ctrl+F when dropping node 10
|
||||
const nodeSupportsESM = parseInt(process.versions.node) >= 12;
|
||||
const isWindows = process.platform === "win32";
|
||||
|
||||
export const supportsESM = nodeSupportsESM && !isWindows;
|
||||
|
||||
export const isMJS = file => path.extname(file) === ".mjs";
|
||||
|
||||
export const itESM = supportsESM ? it : it.skip;
|
||||
|
||||
export function skipUnsupportedESM(esm, name) {
|
||||
if (esm && !nodeSupportsESM) {
|
||||
console.warn(
|
||||
`Skipping "${name}" because native ECMAScript modules are not supported.`,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
// This can be removed when loadOptionsAsyncInSpawedProcess is removed.
|
||||
if (esm && isWindows) {
|
||||
console.warn(
|
||||
`Skipping "${name}" because the ESM runner cannot be spawned on Windows.`,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function loadOptionsAsync({ filename, cwd = __dirname }, mjs) {
|
||||
if (mjs) {
|
||||
// import() crashes with jest
|
||||
return spawn("load-options-async", filename, cwd);
|
||||
}
|
||||
|
||||
return babel.loadOptionsAsync({ filename, cwd });
|
||||
}
|
||||
|
||||
export function spawnTransformAsync() {
|
||||
// import() crashes with jest
|
||||
return spawn("compile-async");
|
||||
}
|
||||
|
||||
export function spawnTransformSync() {
|
||||
// import() crashes with jest
|
||||
return spawn("compile-sync");
|
||||
}
|
||||
|
||||
// !!!! hack is coming !!!!
|
||||
// Remove this function when https://github.com/nodejs/node/issues/35889 is resolved.
|
||||
// Jest supports dynamic import(), but Node.js segfaults when using it in our tests.
|
||||
async function spawn(runner, filename, cwd = process.cwd()) {
|
||||
const { stdout, stderr } = await util.promisify(cp.execFile)(
|
||||
require.resolve(`../fixtures/babel-${runner}.mjs`),
|
||||
// pass `cwd` as params as `process.cwd()` will normalize `cwd` on macOS
|
||||
[filename, cwd],
|
||||
{ cwd, env: process.env },
|
||||
);
|
||||
|
||||
const EXPERIMENTAL_WARNING = /\(node:\d+\) ExperimentalWarning: The ESM module loader is experimental\./;
|
||||
|
||||
if (stderr.replace(EXPERIMENTAL_WARNING, "").trim()) {
|
||||
throw new Error(
|
||||
`error is thrown in babel-${runner}.mjs: stdout\n` +
|
||||
stdout +
|
||||
"\nstderr:\n" +
|
||||
stderr,
|
||||
);
|
||||
}
|
||||
return JSON.parse(stdout);
|
||||
}
|
||||
10
yarn.lock
10
yarn.lock
@ -141,7 +141,7 @@ __metadata:
|
||||
convert-source-map: ^1.7.0
|
||||
debug: ^4.1.0
|
||||
escape-string-regexp: "condition:BABEL_8_BREAKING ? ^4.0.0 : "
|
||||
gensync: ^1.0.0-beta.1
|
||||
gensync: ^1.0.0-beta.2
|
||||
json5: ^2.1.2
|
||||
lodash: ^4.17.19
|
||||
semver: ^5.4.1
|
||||
@ -7375,10 +7375,10 @@ fsevents@^1.2.7:
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"gensync@npm:^1.0.0-beta.1":
|
||||
version: 1.0.0-beta.1
|
||||
resolution: "gensync@npm:1.0.0-beta.1"
|
||||
checksum: 3d14f7c34fc903dd52c36d0879de2c4afde8315edccd630e97919c365819b32c06d98770ef87f7ba45686ee5d2bd5818354920187659b42828319f7cc3352fdb
|
||||
"gensync@npm:^1.0.0-beta.1, gensync@npm:^1.0.0-beta.2":
|
||||
version: 1.0.0-beta.2
|
||||
resolution: "gensync@npm:1.0.0-beta.2"
|
||||
checksum: d523437689c97b3aba9c5cdeca4677d5fff9a29d620db693fea40d852bad63563110f16979d0170248439dbcd2ecee0780fb2533d3f0519f019081aa10767c60
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user