'use strict'; let babelTransform = (() => { var _ref = _asyncToGenerator(function* (asset) { let config = yield getConfig(asset); if (!config) { return; } yield asset.parseIfNeeded(); // If this is an internally generated config, use our internal babel-core, // otherwise require a local version from the package we're compiling. let babel = config.internal ? require('babel-core') : yield localRequire('babel-core', asset.name); // TODO: support other versions of babel if (parseInt(babel.version, 10) !== 6) { throw new Error(`Unsupported babel version: ${babel.version}`); } let res = babel.transformFromAst(asset.ast, asset.contents, config); if (!res.ignored) { asset.ast = res.ast; asset.isAstDirty = true; } }); return function babelTransform(_x) { return _ref.apply(this, arguments); }; })(); let getConfig = (() => { var _ref2 = _asyncToGenerator(function* (asset) { let config = yield getBabelConfig(asset); if (config) { config.code = false; config.filename = asset.name; config.babelrc = false; // Hide the internal property from babel let internal = config.internal; delete config.internal; Object.defineProperty(config, 'internal', { value: internal, configurable: true }); } return config; }); return function getConfig(_x2) { return _ref2.apply(this, arguments); }; })(); let getBabelConfig = (() => { var _ref3 = _asyncToGenerator(function* (asset) { // If asset is marked as an ES6 modules, this is a second pass after dependencies are extracted. // Just compile modules to CommonJS. if (asset.isES6Module) { return { internal: true, plugins: [require('babel-plugin-transform-es2015-modules-commonjs')] }; } if (asset.babelConfig) { return asset.babelConfig; } // Consider the module source code rather than precompiled if the resolver // used the `source` field, or it is not in node_modules. let isSource = !!(asset.package && asset.package.source) || !asset.name.includes(NODE_MODULES); // Try to resolve a .babelrc file. If one is found, consider the module source code. let babelrc = yield getBabelRc(asset, isSource); isSource = isSource || !!babelrc; let envConfig = yield getEnvConfig(asset, isSource); let jsxConfig = getJSXConfig(asset, isSource); // Merge the babel-preset-env config and the babelrc if needed if (babelrc && !shouldIgnoreBabelrc(asset.name, babelrc)) { if (envConfig) { // Filter out presets that are already applied by babel-preset-env if (Array.isArray(babelrc.presets)) { babelrc.presets = babelrc.presets.filter(function (preset) { return !ENV_PRESETS[getPluginName(preset)]; }); } // Filter out plugins that are already applied by babel-preset-env if (Array.isArray(babelrc.plugins)) { babelrc.plugins = babelrc.plugins.filter(function (plugin) { return !ENV_PLUGINS[getPluginName(plugin)]; }); } // Add plugins generated by babel-preset-env to get to the app's target engines. mergeConfigs(babelrc, envConfig); } // Add JSX config if it isn't already specified in the babelrc let hasReact = hasPlugin(babelrc.presets, 'react') || hasPlugin(babelrc.plugins, 'transform-react-jsx'); if (!hasReact) { mergeConfigs(babelrc, jsxConfig); } return babelrc; } // If there is a babel-preset-env config, and it isn't empty use that if (envConfig && (envConfig.plugins.length > 0 || jsxConfig)) { mergeConfigs(envConfig, jsxConfig); return envConfig; } // If there is a JSX config, return that if (jsxConfig) { return jsxConfig; } // Otherwise, don't run babel at all return null; }); return function getBabelConfig(_x3) { return _ref3.apply(this, arguments); }; })(); /** * Finds a .babelrc for an asset. By default, .babelrc files inside node_modules are not used. * However, there are some exceptions: * - if `browserify.transforms` includes "babelify" in package.json (for legacy module compat) * - the `source` field in package.json is used by the resolver */ let getBabelRc = (() => { var _ref4 = _asyncToGenerator(function* (asset, isSource) { // Support legacy browserify packages let browserify = asset.package && asset.package.browserify; if (browserify && Array.isArray(browserify.transform)) { // Look for babelify in the browserify transform list let babelify = browserify.transform.find(function (t) { return (Array.isArray(t) ? t[0] : t) === 'babelify'; }); // If specified as an array, override the config with the one specified if (Array.isArray(babelify) && babelify[1]) { return babelify[1]; } // Otherwise, return the .babelrc if babelify was found return babelify ? yield findBabelRc(asset) : null; } // If this asset is not in node_modules, always use the .babelrc if (isSource) { return yield findBabelRc(asset); } // Otherwise, don't load .babelrc for node_modules. // See https://github.com/parcel-bundler/parcel/issues/13. return null; }); return function getBabelRc(_x4, _x5) { return _ref4.apply(this, arguments); }; })(); let findBabelRc = (() => { var _ref5 = _asyncToGenerator(function* (asset) { if (asset.package && asset.package.babel) { return asset.package.babel; } return yield asset.getConfig(['.babelrc', '.babelrc.js']); }); return function findBabelRc(_x6) { return _ref5.apply(this, arguments); }; })(); /** * Generates a babel-preset-env config for an asset. * This is done by finding the source module's target engines, and the app's * target engines, and doing a diff to include only the necessary plugins. */ let getEnvConfig = (() => { var _ref6 = _asyncToGenerator(function* (asset, isSourceModule) { // Load the target engines for the app and generate a babel-preset-env config let targetEngines = yield getTargetEngines(asset, true); let targetEnv = yield getEnvPlugins(targetEngines, true); if (!targetEnv) { return null; } // If this is the app module, the source and target will be the same, so just compile everything. // Otherwise, load the source engines and generate a babel-present-env config. if (!isSourceModule) { let sourceEngines = yield getTargetEngines(asset, false); let sourceEnv = (yield getEnvPlugins(sourceEngines, false)) || targetEnv; // Do a diff of the returned plugins. We only need to process the remaining plugins to get to the app target. let sourcePlugins = new Set(sourceEnv.map(function (p) { return p[0]; })); targetEnv = targetEnv.filter(function (plugin) { return !sourcePlugins.has(plugin[0]); }); } return { plugins: targetEnv, internal: true }; }); return function getEnvConfig(_x7, _x8) { return _ref6.apply(this, arguments); }; })(); let getEnvPlugins = (() => { var _ref7 = _asyncToGenerator(function* (targets, useBuiltIns = false) { if (!targets) { return null; } let key = JSON.stringify(targets); if (envCache.has(key)) { return envCache.get(key); } let plugins = presetEnv.default({}, { targets, modules: false, useBuiltIns: useBuiltIns ? 'entry' : false }).plugins; envCache.set(key, plugins); return plugins; }); return function getEnvPlugins(_x9) { return _ref7.apply(this, arguments); }; })(); /** * Generates a babel config for JSX. Attempts to detect react or react-like libraries * and changes the pragma accordingly. */ function _asyncToGenerator(fn) { return function () { var gen = fn.apply(this, arguments); return new Promise(function (resolve, reject) { function step(key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { return Promise.resolve(value).then(function (value) { step("next", value); }, function (err) { step("throw", err); }); } } return step("next"); }); }; } const presetEnv = require('babel-preset-env'); const getTargetEngines = require('../utils/getTargetEngines'); const localRequire = require('../utils/localRequire'); const path = require('path'); var _require = require('babel-core'); const babelUtils = _require.util; const NODE_MODULES = `${path.sep}node_modules${path.sep}`; const ENV_PLUGINS = require('babel-preset-env/data/plugins'); const ENV_PRESETS = { es2015: true, es2016: true, es2017: true, latest: true, env: true }; const JSX_EXTENSIONS = { '.jsx': true, '.tsx': true }; const JSX_PRAGMA = { react: 'React.createElement', preact: 'h', nervjs: 'Nerv.createElement', hyperapp: 'h' }; module.exports = babelTransform; babelTransform.getConfig = getConfig; function mergeConfigs(a, b) { if (b) { a.presets = (a.presets || []).concat(b.presets || []); a.plugins = (a.plugins || []).concat(b.plugins || []); } return a; } function hasPlugin(arr, plugin) { return Array.isArray(arr) && arr.some(p => getPluginName(p) === plugin); } function getPluginName(p) { return Array.isArray(p) ? p[0] : p; } function shouldIgnoreBabelrc(filename, babelrc) { // Determine if we should ignore this babelrc file. We do this here instead of // letting babel-core handle it because this config might be merged with our // autogenerated one later which shouldn't be ignored. let ignore = babelUtils.arrayify(babelrc.ignore, babelUtils.regexify); let only = babelrc.only && babelUtils.arrayify(babelrc.only, babelUtils.regexify); return babelUtils.shouldIgnore(filename, ignore, only); } const envCache = new Map(); function getJSXConfig(asset, isSourceModule) { // Don't enable JSX in node_modules if (!isSourceModule) { return null; } // Find a dependency that we can map to a JSX pragma let pragma = null; for (let dep in JSX_PRAGMA) { let pkg = asset.package; if (pkg && (pkg.dependencies && pkg.dependencies[dep] || pkg.devDependencies && pkg.devDependencies[dep])) { pragma = JSX_PRAGMA[dep]; break; } } if (pragma || JSX_EXTENSIONS[path.extname(asset.name)]) { return { plugins: [[require('babel-plugin-transform-react-jsx'), { pragma }]], internal: true }; } }