BREAKING CHANGE: UPGRADE REACT NATIVE TO BABEL 7!

Summary:
BREAKING CHANGE
This change upgrades the React Native build pipeline from Babel 6 to Babel 7

If you use a `.babelrc` then you'll need to update it to Babel 7 (note that some plugins are no longer relevant, some plugins are automatically upgraded, and some will need some manual love).

Note that you may also need to upgrade your dev env, tests etc, to make sure they work with Babel 7.

Reviewed By: mjesun

Differential Revision: D7591303

fbshipit-source-id: 29cef21f6466633a9c366d1f3c0d3cf874c714db
This commit is contained in:
Peter van der Zee 2018-04-11 16:29:36 -07:00 committed by Facebook Github Bot
parent 3277bed1f8
commit f8d6b97140
3 changed files with 234 additions and 113 deletions

View File

@ -12,19 +12,15 @@
/* eslint-disable quotes, curly, no-proto, no-undef-init, dot-notation */ /* eslint-disable quotes, curly, no-proto, no-undef-init, dot-notation */
// Created by running: // Created by running:
// require('babel-core').buildExternalHelpers('_extends classCallCheck createClass createRawReactElement defineProperty get inherits interopRequireDefault interopRequireWildcard objectWithoutProperties possibleConstructorReturn slicedToArray taggedTemplateLiteral toArray toConsumableArray '.split(' ')) // require('fs').writeFileSync('babelExternalHelpers.js', require('@babel/core').buildExternalHelpers('_extends classCallCheck createClass createRawReactElement defineProperty get inherits interopRequireDefault interopRequireWildcard objectWithoutProperties possibleConstructorReturn slicedToArray taggedTemplateLiteral toArray toConsumableArray wrapNativeSuper assertThisInitialized taggedTemplateLiteralLoose'.split(' ')))// then replacing the `global` reference in the last line to also use `this`.
// then replacing the `global` reference in the last line to also use `this`.
// //
// actually, that's a lie, because babel6 omits _extends and createRawReactElement // Actually, that's a lie, because babel omits _extends and
// createRawReactElement. the file is also cleaned up a bit.
// You may need to clear wrapNativeSuper while the bug hasn't been fixed yet.
// Do try to keep diffs to a minimum.
var babelHelpers = global.babelHelpers = {}; var babelHelpers = global.babelHelpers = {};
babelHelpers.typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
return typeof obj;
} : function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
babelHelpers.createRawReactElement = (function () { babelHelpers.createRawReactElement = (function () {
var REACT_ELEMENT_TYPE = typeof Symbol === "function" && Symbol.for && Symbol.for("react.element") || 0xeac7; var REACT_ELEMENT_TYPE = typeof Symbol === "function" && Symbol.for && Symbol.for("react.element") || 0xeac7;
return function createRawReactElement(type, key, props) { return function createRawReactElement(type, key, props) {
@ -45,8 +41,7 @@ babelHelpers.classCallCheck = function (instance, Constructor) {
} }
}; };
babelHelpers.createClass = (function () { function _defineProperties(target, props) {
function defineProperties(target, props) {
for (var i = 0; i < props.length; i++) { for (var i = 0; i < props.length; i++) {
var descriptor = props[i]; var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false; descriptor.enumerable = descriptor.enumerable || false;
@ -56,22 +51,11 @@ babelHelpers.createClass = (function () {
} }
} }
return function (Constructor, protoProps, staticProps) { babelHelpers.createClass = function(Constructor, protoProps, staticProps) {
if (protoProps) defineProperties(Constructor.prototype, protoProps); if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) defineProperties(Constructor, staticProps); if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor; return Constructor;
}; };
})();
babelHelpers.defineEnumerableProperties = function(obj, descs) {
for (var key in descs) {
var desc = descs[key];
desc.configurable = (desc.enumerable = true);
if ('value' in desc) desc.writable = true;
Object.defineProperty(obj, key, desc);
}
return obj;
};
babelHelpers.defineProperty = function (obj, key, value) { babelHelpers.defineProperty = function (obj, key, value) {
if (key in obj) { if (key in obj) {
@ -129,9 +113,8 @@ babelHelpers.get = function get(object, property, receiver) {
babelHelpers.inherits = function (subClass, superClass) { babelHelpers.inherits = function (subClass, superClass) {
if (typeof superClass !== "function" && superClass !== null) { if (typeof superClass !== "function" && superClass !== null) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); throw new TypeError("Super expression must either be null or a function");
} }
subClass.prototype = Object.create(superClass && superClass.prototype, { subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: { constructor: {
value: subClass, value: subClass,
@ -143,6 +126,54 @@ babelHelpers.inherits = function (subClass, superClass) {
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}; };
var _gPO = Object.getPrototypeOf || function _gPO(o) { return o.__proto__ };
var _sPO = Object.setPrototypeOf || function _sPO(o, p) { o.__proto__ = p; return o };
var _construct =
// TODO: prepack does not like this line (and we can use the fallback just fine)
// (typeof Reflect === "object" && Reflect.construct) ||
function _construct(Parent, args, Class) {
var Constructor, a = [null];
a.push.apply(a, args);
Constructor = Parent.bind.apply(Parent, a);
return _sPO(new Constructor, Class.prototype);
};
var _cache = typeof Map === "function" && new Map();
babelHelpers.wrapNativeSuper = function(Class) {
// FB:
// Note: while extending native classes is pretty meh we do have cases, for
// example; Error. There is also a false positive, for example; Blob.
if (typeof Class !== "function") {
throw new TypeError("Super expression must either be null or a function");
}
if (typeof _cache !== "undefined") {
if (_cache.has(Class)) return _cache.get(Class);
_cache.set(Class, Wrapper);
}
function Wrapper() {
// this is a temporary fix for a babel bug (it's invoking the wrong func
// when you do `super()`)
return _construct(Class, arguments, _gPO(this).constructor);
}
Wrapper.prototype = Object.create(Class.prototype, {
constructor: {
value: Wrapper,
enumerable: false,
writeable: true,
configurable: true,
}
});
return _sPO(
Wrapper,
_sPO(
function Super() {
return _construct(Class, arguments, _gPO(this).constructor);
},
Class
)
);
};
babelHelpers.interopRequireDefault = function (obj) { babelHelpers.interopRequireDefault = function (obj) {
return obj && obj.__esModule ? obj : { return obj && obj.__esModule ? obj : {
default: obj default: obj
@ -157,7 +188,15 @@ babelHelpers.interopRequireWildcard = function (obj) {
if (obj != null) { if (obj != null) {
for (var key in obj) { for (var key in obj) {
if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; if (Object.prototype.hasOwnProperty.call(obj, key)) {
var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {};
if (desc.get || desc.set) {
Object.defineProperty(newObj, key, desc);
} else {
newObj[key] = obj[key];
}
}
} }
} }
@ -166,28 +205,45 @@ babelHelpers.interopRequireWildcard = function (obj) {
} }
}; };
babelHelpers.objectWithoutProperties = function (obj, keys) { babelHelpers.objectWithoutProperties = function(source, excluded) {
if (source == null) return {};
var target = {}; var target = {};
var sourceKeys = Object.keys(source);
var key, i;
for (var i in obj) { for (i = 0; i < sourceKeys.length; i++) {
if (keys.indexOf(i) >= 0) continue; key = sourceKeys[i];
if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; if (excluded.indexOf(key) >= 0) continue;
target[i] = obj[i]; target[key] = source[key];
}
if (Object.getOwnPropertySymbols) {
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
for (i = 0; i < sourceSymbolKeys.length; i++) {
key = sourceSymbolKeys[i];
if (excluded.indexOf(key) >= 0) continue;
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
target[key] = source[key];
}
} }
return target; return target;
}; };
babelHelpers.possibleConstructorReturn = function (self, call) { babelHelpers.possibleConstructorReturn = function (self, call) {
if (!self) { if (call && (typeof call === "object" || typeof call === "function")) {
return call;
}
if (self === void 0) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
} }
return call && (typeof call === "object" || typeof call === "function") ? call : self; return self;
}; };
babelHelpers.slicedToArray = (function () { function _sliceIterator(arr, i) {
function sliceIterator(arr, i) {
var _arr = []; var _arr = [];
var _n = true; var _n = true;
var _d = false; var _d = false;
@ -204,7 +260,7 @@ babelHelpers.slicedToArray = (function () {
_e = err; _e = err;
} finally { } finally {
try { try {
if (!_n && _i["return"]) _i["return"](); if (!_n && _i["return"] != null) _i["return"]();
} finally { } finally {
if (_d) throw _e; if (_d) throw _e;
} }
@ -213,16 +269,15 @@ babelHelpers.slicedToArray = (function () {
return _arr; return _arr;
} }
return function (arr, i) { babelHelpers.slicedToArray = function(arr, i) {
if (Array.isArray(arr)) { if (Array.isArray(arr)) {
return arr; return arr;
} else if (Symbol.iterator in Object(arr)) { } else if (Symbol.iterator in Object(arr)) {
return sliceIterator(arr, i); return _sliceIterator(arr, i);
} else { } else {
throw new TypeError("Invalid attempt to destructure non-iterable instance"); throw new TypeError("Invalid attempt to destructure non-iterable instance");
} }
}; };
})();
babelHelpers.taggedTemplateLiteral = function (strings, raw) { babelHelpers.taggedTemplateLiteral = function (strings, raw) {
return Object.freeze(Object.defineProperties(strings, { return Object.freeze(Object.defineProperties(strings, {
@ -238,10 +293,25 @@ babelHelpers.toArray = function (arr) {
babelHelpers.toConsumableArray = function (arr) { babelHelpers.toConsumableArray = function (arr) {
if (Array.isArray(arr)) { if (Array.isArray(arr)) {
for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
return arr2; return arr2;
} else { } else {
return Array.from(arr); return Array.from(arr);
} }
}; };
babelHelpers.assertThisInitialized = function(self) {
if (self === void 0) {
throw new ReferenceError(
"this hasn't been initialised - super() hasn't been called",
);
}
return self;
};
babelHelpers.taggedTemplateLiteralLoose = function(strings, raw) {
strings.raw = raw;
return strings;
};

View File

@ -8,37 +8,55 @@
'use strict'; 'use strict';
const defaultPlugins = [ const defaultPlugins = [
[require('babel-plugin-syntax-class-properties')], [require('@babel/plugin-transform-block-scoping')],
[require('babel-plugin-syntax-trailing-function-commas')], // the flow strip types plugin must go BEFORE class properties!
[require('babel-plugin-transform-class-properties')], // there'll be a test case that fails if you don't.
[require('babel-plugin-transform-es2015-block-scoping')], [require('@babel/plugin-transform-flow-strip-types')],
[require('babel-plugin-transform-es2015-computed-properties')],
[require('babel-plugin-transform-es2015-destructuring')],
[require('babel-plugin-transform-es2015-function-name')],
[require('babel-plugin-transform-es2015-literals')],
[require('babel-plugin-transform-es2015-parameters')],
[require('babel-plugin-transform-es2015-shorthand-properties')],
[require('babel-plugin-transform-flow-strip-types')],
[require('babel-plugin-transform-react-jsx')],
[require('babel-plugin-transform-regenerator')],
[ [
require('babel-plugin-transform-es2015-modules-commonjs'), require('@babel/plugin-proposal-class-properties'),
{strict: false, allowTopLevelThis: true}, // use `this.foo = bar` instead of `this.defineProperty('foo', ...)`
// (Makes the properties enumerable)
{loose: true},
],
[require('@babel/plugin-transform-computed-properties')],
[require('@babel/plugin-transform-destructuring')],
[require('@babel/plugin-transform-function-name')],
[require('@babel/plugin-transform-literals')],
[require('@babel/plugin-transform-parameters')],
[require('@babel/plugin-transform-shorthand-properties')],
[require('@babel/plugin-transform-react-jsx')],
[require('@babel/plugin-transform-regenerator')],
[require('@babel/plugin-transform-sticky-regex')],
[require('@babel/plugin-transform-unicode-regex')],
[
require('@babel/plugin-transform-modules-commonjs'),
{
strict: false,
strictMode : false, // prevent "use strict" injections
allowTopLevelThis: true, // dont rewrite global `this` -> `undefined`
},
], ],
]; ];
const checkES2015Constants = [require('babel-plugin-check-es2015-constants')]; const es2015ArrowFunctions = [
const es2015ArrowFunctions = [require('babel-plugin-transform-es2015-arrow-functions')]; require('@babel/plugin-transform-arrow-functions'),
const es2015Classes = [require('babel-plugin-transform-es2015-classes')]; ];
const es2015ForOf = [require('babel-plugin-transform-es2015-for-of'), {loose: true}]; const es2015Classes = [require('@babel/plugin-transform-classes')];
const es2015Spread = [require('babel-plugin-transform-es2015-spread')]; const es2015ForOf = [require('@babel/plugin-transform-for-of'), {loose: true}];
const es2015TemplateLiterals = [require('babel-plugin-transform-es2015-template-literals')]; const es2015Spread = [require('@babel/plugin-transform-spread')];
const asyncFunctions = [require('babel-plugin-syntax-async-functions')]; const es2015TemplateLiterals = [
const exponentiationOperator = [require('babel-plugin-transform-exponentiation-operator')]; require('@babel/plugin-transform-template-literals'),
const objectAssign = [require('babel-plugin-transform-object-assign')]; {loose: true}, // dont 'a'.concat('b'), just use 'a'+'b'
const objectRestSpread = [require('babel-plugin-transform-object-rest-spread')]; ];
const reactDisplayName = [require('babel-plugin-transform-react-display-name')]; const exponentiationOperator = [
const reactJsxSource = [require('babel-plugin-transform-react-jsx-source')]; require('@babel/plugin-transform-exponentiation-operator'),
];
const objectAssign = [require('@babel/plugin-transform-object-assign')];
const objectRestSpread = [require('@babel/plugin-proposal-object-rest-spread')];
const reactDisplayName = [
require('@babel/plugin-transform-react-display-name'),
];
const reactJsxSource = [require('@babel/plugin-transform-react-jsx-source')];
const symbolMember = [require('../transforms/transform-symbol-member')]; const symbolMember = [require('../transforms/transform-symbol-member')];
const getPreset = (src, options) => { const getPreset = (src, options) => {
@ -49,18 +67,12 @@ const getPreset = (src, options) => {
const extraPlugins = []; const extraPlugins = [];
if (isNull || src.indexOf('async') !== -1 || src.indexOf('await') !== -1) {
extraPlugins.push(asyncFunctions);
}
if (hasClass) { if (hasClass) {
extraPlugins.push(es2015Classes); extraPlugins.push(es2015Classes);
} }
if (isNull || src.indexOf('=>') !== -1) { if (isNull || src.indexOf('=>') !== -1) {
extraPlugins.push(es2015ArrowFunctions); extraPlugins.push(es2015ArrowFunctions);
} }
if (isNull || src.indexOf('const') !== -1) {
extraPlugins.push(checkES2015Constants);
}
if (isNull || hasClass || src.indexOf('...') !== -1) { if (isNull || hasClass || src.indexOf('...') !== -1) {
extraPlugins.push(es2015Spread); extraPlugins.push(es2015Spread);
extraPlugins.push(objectRestSpread); extraPlugins.push(objectRestSpread);

View File

@ -11,7 +11,7 @@
'use strict'; 'use strict';
const babel = require('babel-core'); const {transformSync: babelTransformSync} = require('@babel/core');
/* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error /* $FlowFixMe(>=0.54.0 site=react_native_oss) This comment suppresses an error
* found when Flow v0.54 was deployed. To see the error delete this comment and * found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */ * run Flow. */
@ -20,7 +20,7 @@ const babelRegisterOnly = require('metro/src/babelRegisterOnly');
* found when Flow v0.54 was deployed. To see the error delete this comment and * found when Flow v0.54 was deployed. To see the error delete this comment and
* run Flow. */ * run Flow. */
const createCacheKeyFunction = require('fbjs-scripts/jest/createCacheKeyFunction'); const createCacheKeyFunction = require('fbjs-scripts/jest/createCacheKeyFunction');
const generate = require('babel-generator').default; const generate = require('@babel/generator').default;
const nodeFiles = RegExp([ const nodeFiles = RegExp([
'/local-cli/', '/local-cli/',
@ -35,7 +35,7 @@ const transformer = require('metro/src/transformer.js');
module.exports = { module.exports = {
process(src/*: string*/, file/*: string*/) { process(src/*: string*/, file/*: string*/) {
if (nodeFiles.test(file)) { // node specific transforms only if (nodeFiles.test(file)) { // node specific transforms only
return babel.transform( return babelTransformSync(
src, src,
Object.assign({filename: file}, nodeOptions) Object.assign({filename: file}, nodeOptions)
).code; ).code;
@ -54,6 +54,45 @@ module.exports = {
retainLines: true, retainLines: true,
}, },
src, src,
plugins: [
[require('@babel/plugin-transform-block-scoping')],
// the flow strip types plugin must go BEFORE class properties!
// there'll be a test case that fails if you don't.
[require('@babel/plugin-transform-flow-strip-types')],
[
require('@babel/plugin-proposal-class-properties'),
// use `this.foo = bar` instead of `this.defineProperty('foo', ...)`
// (Makes the properties enumerable)
{loose: true},
],
[require('@babel/plugin-transform-computed-properties')],
[require('@babel/plugin-transform-destructuring')],
[require('@babel/plugin-transform-function-name')],
[require('@babel/plugin-transform-literals')],
[require('@babel/plugin-transform-parameters')],
[require('@babel/plugin-transform-shorthand-properties')],
[require('@babel/plugin-transform-react-jsx')],
[require('@babel/plugin-transform-regenerator')],
[require('@babel/plugin-transform-sticky-regex')],
[require('@babel/plugin-transform-unicode-regex')],
[
require('@babel/plugin-transform-modules-commonjs'),
{strict: false, allowTopLevelThis: true},
],
[require('@babel/plugin-transform-classes')],
[require('@babel/plugin-transform-arrow-functions')],
[require('@babel/plugin-transform-spread')],
[require('@babel/plugin-proposal-object-rest-spread')],
[
require('@babel/plugin-transform-template-literals'),
{loose: true}, // dont 'a'.concat('b'), just use 'a'+'b'
],
[require('@babel/plugin-transform-exponentiation-operator')],
[require('@babel/plugin-transform-object-assign')],
[require('@babel/plugin-transform-for-of'), {loose: true}],
[require('@babel/plugin-transform-react-display-name')],
[require('@babel/plugin-transform-react-jsx-source')],
],
}); });
return generate(ast, { return generate(ast, {
@ -70,6 +109,6 @@ module.exports = {
getCacheKey: createCacheKeyFunction([ getCacheKey: createCacheKeyFunction([
__filename, __filename,
require.resolve('metro/src/transformer.js'), require.resolve('metro/src/transformer.js'),
require.resolve('babel-core/package.json'), require.resolve('@babel/core/package.json'),
]), ]),
}; };