diff --git a/babel-preset/configs/main.js b/babel-preset/configs/main.js index 204028fbb..3322812bd 100644 --- a/babel-preset/configs/main.js +++ b/babel-preset/configs/main.js @@ -36,6 +36,7 @@ module.exports = { 'transform-react-jsx', 'transform-regenerator', ['transform-es2015-for-of', { loose: true }], + require('../transforms/transform-symbol-member'), ]), retainLines: true, sourceMaps: false, diff --git a/babel-preset/package.json b/babel-preset/package.json index b442ab23c..0ab0579b1 100644 --- a/babel-preset/package.json +++ b/babel-preset/package.json @@ -1,6 +1,6 @@ { "name": "babel-preset-react-native", - "version": "1.2.4", + "version": "1.4.0", "description": "Babel preset for React Native applications", "main": "index.js", "repository": "https://github.com/facebook/react-native/tree/master/babel-preset", diff --git a/babel-preset/transforms/transform-symbol-member.js b/babel-preset/transforms/transform-symbol-member.js new file mode 100644 index 000000000..305eb3c2d --- /dev/null +++ b/babel-preset/transforms/transform-symbol-member.js @@ -0,0 +1,61 @@ +/** + * Copyright 2004-present Facebook. All Rights Reserved. + */ + +'use strict'; + +/*eslint consistent-return: 0*/ + +/** + * Transforms function properties of the `Symbol` into + * the presence check, and fallback string "@@". + * + * Example: + * + * Symbol.iterator; + * + * Transformed to: + * + * typeof Symbol.iterator === 'function' ? Symbol.iterator : '@@iterator'; + */ +module.exports = function symbolMember(babel) { + const t = babel.types; + + return { + visitor: { + MemberExpression(path) { + let node = path.node; + + if (!isAppropriateMember(node)) { + return; + } + + path.replaceWith( + t.conditionalExpression( + t.binaryExpression( + '===', + t.unaryExpression( + 'typeof', + t.identifier('Symbol'), + true + ), + t.stringLiteral('function') + ), + node, + t.stringLiteral(`@@${node.property.name}`) + ) + ); + + // We should stop to avoid infinite recursion, since Babel + // traverses replaced path, and again would hit our transform. + path.stop(); + }, + }, + }; +}; + +function isAppropriateMember(node) { + return node.object.type === 'Identifier' && + node.object.name === 'Symbol' && + node.property.type === 'Identifier'; +}