Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various updates to Babel 7 branch #1958

Merged
merged 26 commits into from
Sep 4, 2018
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
05c0fb8
remove babel6 from pkg.json, update internal babel configs and update…
DeMoorJasper Aug 29, 2018
89d236b
remove async-super-babel-plugin
DeMoorJasper Aug 29, 2018
4e613c9
remove babel polyfill test for useBuiltins
DeMoorJasper Aug 29, 2018
106c43d
remove babel-template requires
DeMoorJasper Aug 29, 2018
71a75dc
fix html import tests
DeMoorJasper Aug 29, 2018
dd06677
fix formatting
DeMoorJasper Aug 29, 2018
cfad048
work around template string bug in Babel 7?
DeMoorJasper Aug 29, 2018
a1b0f4c
format
DeMoorJasper Aug 29, 2018
bbf0cd4
remove matches-pattern
DeMoorJasper Aug 29, 2018
04617c4
get rid of lint issues
DeMoorJasper Aug 29, 2018
03c88b5
fix comment
DeMoorJasper Aug 29, 2018
3acd84a
merge
DeMoorJasper Aug 29, 2018
4af249a
detect babel 6 configs
DeMoorJasper Aug 29, 2018
b371872
remove babylon 6
DeMoorJasper Aug 30, 2018
ad78546
fix getBabelRc
DeMoorJasper Aug 30, 2018
682175c
babel 7 to babel 6 ast convertor v1
DeMoorJasper Aug 30, 2018
8bdb5b3
remove some random code
DeMoorJasper Aug 30, 2018
15a1421
add babel 6 => babel 7 convertor
DeMoorJasper Aug 30, 2018
762cc00
add js tests back in
DeMoorJasper Aug 30, 2018
74ab5f7
fix typo
DeMoorJasper Aug 30, 2018
b0fa467
add babel-runtime
DeMoorJasper Aug 31, 2018
2173572
add babel-runtime for smaller pkg size
DeMoorJasper Aug 31, 2018
16d9fa7
run babel 7 => babel 6 => babel 7
DeMoorJasper Aug 31, 2018
112ebf3
cleanup & add parsing for Babel 6
DeMoorJasper Aug 31, 2018
0dd2663
cleanup some comments
DeMoorJasper Aug 31, 2018
367d5ec
cleanup the empty babel files
DeMoorJasper Aug 31, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 5 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,6 @@
"@babel/traverse": "^7.0.0",
"@babel/types": "^7.0.0",
"ansi-to-html": "^0.6.4",
"babel-code-frame": "^6.26.0",
"babel-core": "^6.25.0",
"babel-generator": "^6.25.0",
"babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
"babel-plugin-transform-flow-strip-types": "^6.22.0",
"babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-plugin-transform-react-jsx": "^6.24.1",
"babel-preset-env": "^1.7.0",
"babel-template": "^6.26.0",
"babel-traverse": "^6.26.0",
"babel-types": "^6.26.0",
"babylon": "^6.17.4",
"babylon-walk": "^1.0.2",
Copy link
Member Author

@DeMoorJasper DeMoorJasper Aug 30, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we remove this, or do a PR to their branch to update to @babel/types instead of babel-types

It might cause issues in certain cases, as babel-types has changed slightly

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

worth doing some perf testing. babylon-walk was WAY faster than babel-traverse for some cases where we don't need scope tracking and things.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure it will still be slower, haven't tested it. I did however open up a PR to babylon-walk pugjs/babel-walk#2

"browserslist": "^3.2.6",
"chalk": "^2.1.0",
Expand Down Expand Up @@ -84,11 +72,12 @@
"ws": "^5.1.1"
},
"devDependencies": {
"@babel/cli": "^7.0.0",
"@babel/preset-flow": "^7.0.0",
"@babel/register": "^7.0.0",
"@vue/component-compiler-utils": "^2.0.0",
"babel-cli": "^6.26.0",
"babel-plugin-transform-async-super": "^1.0.0",
"babel-polyfill": "^6.26.0",
"babel-register": "^6.26.0",
"babel-core": "^6.26.3",
"babel-preset-env": "^1.7.0",
"bsb-js": "^1.0.1",
"codecov": "^3.0.0",
"coffeescript": "^2.0.3",
Expand Down
3 changes: 1 addition & 2 deletions src/.babelrc
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
{
"presets": [["env", {
"presets": [["@babel/preset-env", {
"targets": {
"node": "6"
}
}]],
"plugins": ["transform-async-super"],
"ignore": ["builtins"]
}
1 change: 1 addition & 0 deletions src/assets/JSAsset.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ class JSAsset extends Asset {
strictMode: false,
sourceType: 'module',
locations: true,
tokens: true, // TODO: Set this to false if there is no babel 6 config
plugins: ['exportExtensions', 'dynamicImport']
}
};
Expand Down
5 changes: 3 additions & 2 deletions src/packagers/JSConcatPackager.js
Original file line number Diff line number Diff line change
Expand Up @@ -530,10 +530,11 @@ class JSConcatPackager extends Packager {
// Add source map url if a map bundle exists
let mapBundle = this.bundle.siblingBundlesMap.get('map');
if (mapBundle) {
output += `\n//# sourceMappingURL=${urlJoin(
let mapUrl = urlJoin(
this.options.publicURL,
path.basename(mapBundle.name)
)}`;
);
output += `\n//# sourceMappingURL=${mapUrl}`;
}
}

Expand Down
9 changes: 4 additions & 5 deletions src/packagers/JSPackager.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,12 +225,11 @@ class JSPackager extends Packager {
// Add source map url if a map bundle exists
let mapBundle = this.bundle.siblingBundlesMap.get('map');
if (mapBundle) {
await this.write(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discovered a potential bug with template strings in Babel 7. But I think it has already been reported. Feel free to check if anyone is up for it :)

It might have been an issue in the babel config I wrote, not sure.

`\n//# sourceMappingURL=${urlJoin(
this.options.publicURL,
path.basename(mapBundle.name)
)}`
let mapUrl = urlJoin(
this.options.publicURL,
path.basename(mapBundle.name)
);
await this.write(`\n//# sourceMappingURL=${mapUrl}`);
}
}
await this.dest.end();
Expand Down
2 changes: 1 addition & 1 deletion src/scope-hoisting/concat.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const {relative} = require('path');
const template = require('babel-template');
const template = require('@babel/template').default;
const t = require('@babel/types');
const traverse = require('@babel/traverse').default;
const generate = require('@babel/generator').default;
Expand Down
13 changes: 6 additions & 7 deletions src/scope-hoisting/hoist.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
const path = require('path');
const matchesPattern = require('../visitors/matches-pattern');
const mm = require('micromatch');
const t = require('@babel/types');
const template = require('babel-template');
const template = require('@babel/template').default;
const rename = require('./renamer');
const {getName, getIdentifier, getExportIdentifier} = require('./utils');

Expand Down Expand Up @@ -175,20 +174,20 @@ module.exports = {
return;
}

if (matchesPattern(path.node, 'module.exports')) {
if (t.matchesPattern(path.node, 'module.exports')) {
path.replaceWith(getExportsIdentifier(asset));
asset.cacheData.isCommonJS = true;
}

if (matchesPattern(path.node, 'module.id')) {
if (t.matchesPattern(path.node, 'module.id')) {
path.replaceWith(t.stringLiteral(asset.id));
}

if (matchesPattern(path.node, 'module.hot')) {
if (t.matchesPattern(path.node, 'module.hot')) {
path.replaceWith(t.identifier('null'));
}

if (matchesPattern(path.node, 'module.bundle')) {
if (t.matchesPattern(path.node, 'module.bundle')) {
path.replaceWith(t.identifier('require'));
}
},
Expand Down Expand Up @@ -332,7 +331,7 @@ module.exports = {
);
}

if (matchesPattern(callee, 'require.resolve')) {
if (t.matchesPattern(callee, 'require.resolve')) {
path.replaceWith(
REQUIRE_RESOLVE_CALL_TEMPLATE({
ID: t.stringLiteral(asset.id),
Expand Down
83 changes: 67 additions & 16 deletions src/transforms/babel.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,15 @@ async function getBabelConfig(asset) {

// Try to resolve a .babelrc file. If one is found, consider the module source code.
let babelrc = await getBabelRc(asset, isSource);
let isBabel7 = true;
if (babelrc) {
isBabel7 = babelrc.version === 7;
babelrc = babelrc.config;

if (!isBabel7) {
console.log('Found a babel 6 module in: ', asset.name);
}
}
isSource = isSource || !!babelrc;

let envConfig = await getEnvConfig(asset, isSource);
Expand Down Expand Up @@ -129,15 +138,21 @@ async function getBabelConfig(asset) {

// Add JSX config if it isn't already specified in the babelrc
let hasReact =
hasPlugin(babelrc.presets, 'react') ||
hasPlugin(babelrc.plugins, 'transform-react-jsx');
hasPlugin(babelrc.presets, ['react', '@babel/preset-react']) ||
hasPlugin(babelrc.plugins, [
'transform-react-jsx',
'@babel/plugin-transform-react-jsx'
]);

if (!hasReact) {
mergeConfigs(babelrc, jsxConfig);
}

// Add Flow stripping config if it isn't already specified in the babelrc
let hasFlow = hasPlugin(babelrc.plugins, 'transform-flow-strip-types');
let hasFlow = hasPlugin(babelrc.plugins, [
'transform-flow-strip-types',
'@babel/plugin-transform-flow-strip-types'
]);

if (!hasFlow && flowConfig) {
mergeConfigs(babelrc, flowConfig);
Expand Down Expand Up @@ -177,21 +192,49 @@ function mergeConfigs(a, b) {
return a;
}

function hasPlugin(arr, plugin) {
return Array.isArray(arr) && arr.some(p => getPluginName(p) === plugin);
function hasPlugin(arr, plugins) {
return (
Array.isArray(arr) && arr.some(p => plugins.includes(getPluginName(p)))
);
}

function getPluginName(p) {
return Array.isArray(p) ? p[0] : p;
}

function testPluginArrayForBabelScope(plugins) {
for (let plugin of plugins) {
if (getPluginName(plugin).startsWith('@babel/')) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does babel 7 require the scope or will they automatically add it if you just write env? If so, then this check won't work.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Babel docs:

You can still use the shorthand way of specifying a preset or plugin. However because of the switch to scoped packages, you still have to specify the @babel/ just like if you had your own preset to add to the config.

So yes it's required, although it's not 100% reliable as third party libraries will still have babel-....

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

return true;
}
}
return false;
}

function isBabel7Config(babelrc) {
if (!babelrc.presets && !babelrc.presets) {
return true;
}

if (
(babelrc.presets && testPluginArrayForBabelScope(babelrc.presets)) ||
(babelrc.plugins && testPluginArrayForBabelScope(babelrc.plugins))
) {
return true;
}

return false;
}

/**
* 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
*/
async function getBabelRc(asset, isSource) {
let babelrc = null;

// Support legacy browserify packages
let pkg = await asset.getPackage();
let browserify = pkg && pkg.browserify;
Expand All @@ -203,21 +246,28 @@ async function getBabelRc(asset, isSource) {

// If specified as an array, override the config with the one specified
if (Array.isArray(babelify) && babelify[1]) {
return babelify[1];
babelrc = babelify[1];
}

// Otherwise, return the .babelrc if babelify was found
return babelify ? await findBabelRc(asset) : null;
if (!babelrc && babelify) {
babelrc = await findBabelRc(asset);
}
}

// If this asset is not in node_modules, always use the .babelrc
if (isSource) {
return await findBabelRc(asset);
if (!babelrc && isSource) {
babelrc = await findBabelRc(asset);
}

// Otherwise, don't load .babelrc for node_modules.
// See https://github.com/parcel-bundler/parcel/issues/13.
return null;
return babelrc
? {
version: isBabel7Config(babelrc) ? 7 : 6,
config: babelrc
}
: null;
}

async function findBabelRc(asset) {
Expand All @@ -226,15 +276,16 @@ async function findBabelRc(asset) {
});
}

function shouldIgnoreBabelrc(filename, babelrc) {
return false;
/*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);
let ignore = babelUtils.arrayify(babelrc.ignore, babelUtils.regexify);
let only = babelrc.only && babelUtils.arrayify(babelrc.only, babelUtils.regexify);
return babelUtils.shouldIgnore(filename, ignore, only);
}*/
function shouldIgnoreBabelrc() {
return false;
}

/**
Expand Down
110 changes: 110 additions & 0 deletions src/transforms/babelASTConverter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
const traverse = require('@babel/traverse').default;

// Convert between babel 7 and babel 6 AST
// More info on the AST Changes: https://babeljs.io/docs/en/v7-migration-api#ast-changes
function babel7toBabel6(ast) {
const visitor = {
ArrowFunctionExpression: node => {
node.expression = node.body.type !== 'BlockStatement';
},
ExistsTypeAnnotation: node => {
node.type = 'ExistentialTypeParam';
},
NumberLiteralTypeAnnotation: node => {
node.type = 'NumericLiteralTypeAnnotation';
},
ObjectTypeIndexer: node => {
node.end++;
node.loc.end.column++;
},
ForOfStatement: node => {
node.type = 'ForAwaitStatement';
delete node.await;
},
SpreadElement: (node, path) => {
if (
path.parentPath.isObjectExpression() ||
path.parentPath.isArrayExpression()
) {
node.type = 'SpreadProperty';
}
},
RestElement: (node, path) => {
if (
path.parentPath.isObjectPattern() ||
path.parentPath.isArrayPattern()
) {
node.type = 'RestProperty';
}
}
};

traverse(ast, {
enter(path) {
if (path.node.variance && path.node.variance.type === 'Variance') {
path.node.variance = path.node.variance.kind;
}

let visitorFunc = visitor[path.node.type];
if (visitorFunc) {
visitorFunc(path.node, path);
}
}
});

return ast;
}

function babel6toBabel7(ast) {
const visitor = {
ArrowFunctionExpression: node => {
delete node.expression;
},
ExistentialTypeParam: node => {
node.type = 'ExistsTypeAnnotation';
},
NumericLiteralTypeAnnotation: node => {
node.type = 'NumberLiteralTypeAnnotation';
},
ObjectTypeIndexer: node => {
node.end--;
node.loc.end.column--;
},
ForAwaitStatement: node => {
node.type = 'ForOfStatement';
node.await = true;
},
SpreadProperty: node => {
node.type = 'SpreadElement';
},
RestProperty: node => {
node.type = 'RestElement';
}
};

traverse(ast, {
enter(path) {
if (path.node.variance && typeof path.node.variance === 'string') {
path.node.variance = {
type: 'VarianceNode',
kind: path.node.variance
};
}

let visitorFunc = visitor[path.node.type];
if (visitorFunc) {
visitorFunc(path.node);
}
}
});

return ast;
}

module.exports = function(ast, version) {
if (![6, 7].includes(version)) {
throw new Error('This convertor only supports Babel 6 and 7 ASTs');
}

return version === 7 ? babel7toBabel6(ast) : babel6toBabel7(ast);
};
Loading