UNPKG

react-native-flip

Version:
598 lines (531 loc) 17 kB
/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * * @format */ "use strict"; function _toConsumableArray(arr) { return ( _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread() ); } function _nonIterableSpread() { throw new TypeError( "Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method." ); } function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); } function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; } function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function(sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function(key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function(key) { Object.defineProperty( target, key, Object.getOwnPropertyDescriptor(source, key) ); }); } } return target; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } const nullthrows = require("nullthrows"); const template = require("@babel/template").default; /** * Produces a Babel template that transforms an "import * as x from ..." or an * "import x from ..." call into a "const x = importAll(...)" call with the * corresponding id in it. */ const importTemplate = template.statement(` var LOCAL = IMPORT(FILE); `); /** * Produces a Babel template that transforms an "import {x as y} from ..." into * "const y = require(...).x" call with the corresponding id in it. */ const importNamedTemplate = template.statement(` var LOCAL = require(FILE).REMOTE; `); /** * Produces a Babel template that transforms an "import ..." into * "require(...)", which is considered a side-effect call. */ const importSideEffectTemplate = template.statement(` require(FILE); `); /** * Produces an "export all" template that traverses all exported symbols and * re-exposes them. */ const exportAllTemplate = template.statements(` var REQUIRED = require(FILE); for (var KEY in REQUIRED) { exports[KEY] = REQUIRED[KEY]; } `); /** * Produces a "named export" or "default export" template to export a single * symbol. */ const exportTemplate = template.statement(` exports.REMOTE = LOCAL; `); /** * Flags the exported module as a transpiled ES module. Needs to be kept in 1:1 * compatibility with Babel. */ const esModuleExportTemplate = template.statement(` Object.defineProperty(exports, '__esModule', {value: true}); `); /** * Resolution template in case it is requested. */ const resolveTemplate = template.expression(` require.resolve(NODE) `); /** * Enforces the resolution of a path to a fully-qualified one, if set. */ function resolvePath(node, resolve) { if (!resolve) { return node; } return resolveTemplate({ NODE: node }); } // eslint-disable-next-line no-redeclare function withLocation(node, loc) { if (Array.isArray(node)) { return node.map(n => withLocation(n, loc)); } if (!node.loc) { return _objectSpread( _objectSpread({}, node), {}, { loc } ); } return node; } function importExportPlugin(_ref) { let t = _ref.types; const isDeclaration = t.isDeclaration, isVariableDeclaration = t.isVariableDeclaration; return { visitor: { ExportAllDeclaration(path, state) { state.exportAll.push({ file: path.node.source.value, loc: path.node.loc }); path.remove(); }, ExportDefaultDeclaration(path, state) { const declaration = path.node.declaration; const id = declaration.id || path.scope.generateUidIdentifier("default"); // $FlowFixMe Flow error uncovered by typing Babel more strictly declaration.id = id; const loc = path.node.loc; state.exportDefault.push({ local: id.name, loc }); if (isDeclaration(declaration)) { path.insertBefore(withLocation(declaration, loc)); } else { path.insertBefore( withLocation( t.variableDeclaration("var", [ t.variableDeclarator(id, declaration) ]), loc ) ); } path.remove(); }, ExportNamedDeclaration(path, state) { if (path.node.exportKind && path.node.exportKind !== "value") { return; } const declaration = path.node.declaration; const loc = path.node.loc; if (declaration) { if (isVariableDeclaration(declaration)) { declaration.declarations.forEach(d => { switch (d.id.type) { case "ObjectPattern": { const properties = d.id.properties; properties.forEach(p => { // $FlowFixMe Flow error uncovered by typing Babel more strictly const name = p.key.name; state.exportNamed.push({ local: name, remote: name, loc }); }); } break; case "ArrayPattern": { const elements = d.id.elements; elements.forEach(e => { // $FlowFixMe Flow error uncovered by typing Babel more strictly const name = e.name; state.exportNamed.push({ local: name, remote: name, loc }); }); } break; default: { // $FlowFixMe Flow error uncovered by typing Babel more strictly const name = d.id.name; state.exportNamed.push({ local: name, remote: name, loc }); } break; } }); } else { const id = declaration.id || path.scope.generateUidIdentifier(); // $FlowFixMe Flow error uncovered by typing Babel more strictly const name = id.name; // $FlowFixMe Flow error uncovered by typing Babel more strictly declaration.id = id; state.exportNamed.push({ local: name, remote: name, loc }); } path.insertBefore(declaration); } const specifiers = path.node.specifiers; if (specifiers) { specifiers.forEach(s => { // $FlowFixMe Flow error uncovered by typing Babel more strictly const local = s.local; const remote = s.exported; if (path.node.source) { const temp = path.scope.generateUidIdentifier(local.name); if (local.name === "default") { path.insertBefore( withLocation( importTemplate({ IMPORT: state.importDefault, FILE: resolvePath( nullthrows(path.node.source), state.opts.resolve ), LOCAL: temp }), loc ) ); state.exportNamed.push({ local: temp.name, remote: remote.name, loc }); } else if (remote.name === "default") { path.insertBefore( withLocation( importNamedTemplate({ FILE: resolvePath( nullthrows(path.node.source), state.opts.resolve ), LOCAL: temp, REMOTE: local }), loc ) ); state.exportDefault.push({ local: temp.name, loc }); } else { path.insertBefore( withLocation( importNamedTemplate({ FILE: resolvePath( nullthrows(path.node.source), state.opts.resolve ), LOCAL: temp, REMOTE: local }), loc ) ); state.exportNamed.push({ local: temp.name, remote: remote.name, loc }); } } else { if (remote.name === "default") { state.exportDefault.push({ local: local.name, loc }); } else { state.exportNamed.push({ local: local.name, remote: remote.name, loc }); } } }); } path.remove(); }, ImportDeclaration(path, state) { if (path.node.importKind && path.node.importKind !== "value") { return; } const file = path.node.source; const specifiers = path.node.specifiers; const loc = path.node.loc; if (!specifiers.length) { state.imports.push({ node: withLocation( importSideEffectTemplate({ FILE: resolvePath(file, state.opts.resolve) }), loc ) }); } else { let sharedModuleImport = null; if ( specifiers.filter( s => s.type === "ImportSpecifier" && s.imported.name !== "default" ).length > 1 ) { sharedModuleImport = path.scope.generateUidIdentifierBasedOnNode( file ); path.scope.push({ id: sharedModuleImport, init: withLocation( t.callExpression(t.identifier("require"), [ resolvePath(file, state.opts.resolve) ]), loc ) }); } specifiers.forEach(s => { // $FlowFixMe Flow error uncovered by typing Babel more strictly const imported = s.imported; const local = s.local; switch (s.type) { case "ImportNamespaceSpecifier": state.imports.push({ node: withLocation( importTemplate({ IMPORT: state.importAll, FILE: resolvePath(file, state.opts.resolve), LOCAL: local }), loc ) }); break; case "ImportDefaultSpecifier": state.imports.push({ node: withLocation( importTemplate({ IMPORT: state.importDefault, FILE: resolvePath(file, state.opts.resolve), LOCAL: local }), loc ) }); break; case "ImportSpecifier": if (imported.name === "default") { state.imports.push({ node: withLocation( importTemplate({ IMPORT: state.importDefault, FILE: resolvePath(file, state.opts.resolve), LOCAL: local }), loc ) }); } else if (sharedModuleImport != null) { path.scope.push({ id: local, init: withLocation( t.memberExpression(sharedModuleImport, imported), loc ) }); } else { state.imports.push({ node: withLocation( importNamedTemplate({ FILE: resolvePath(file, state.opts.resolve), LOCAL: local, REMOTE: imported }), loc ) }); } break; default: throw new TypeError("Unknown import type: " + s.type); } }); } path.remove(); }, Program: { enter(path, state) { state.exportAll = []; state.exportDefault = []; state.exportNamed = []; state.imports = []; state.importAll = t.identifier(state.opts.importAll); state.importDefault = t.identifier(state.opts.importDefault); }, exit(path, state) { const body = path.node.body; // state.imports = [node1, node2, node3, ...nodeN] state.imports.reverse().forEach(e => { // import nodes are added to the top of the program body body.unshift(e.node); }); state.exportDefault.forEach(e => { body.push( withLocation( exportTemplate({ LOCAL: t.identifier(e.local), REMOTE: t.identifier("default") }), e.loc ) ); }); state.exportAll.forEach(e => { body.push.apply( body, _toConsumableArray( withLocation( exportAllTemplate({ FILE: resolvePath( t.stringLiteral(e.file), state.opts.resolve ), REQUIRED: path.scope.generateUidIdentifier(e.file), KEY: path.scope.generateUidIdentifier("key") }), e.loc ) ) ); }); state.exportNamed.forEach(e => { body.push( withLocation( exportTemplate({ LOCAL: t.identifier(e.local), REMOTE: t.identifier(e.remote) }), e.loc ) ); }); if ( state.exportDefault.length || state.exportAll.length || state.exportNamed.length ) { body.unshift(esModuleExportTemplate()); if (state.opts.out) { state.opts.out.isESModule = true; } } else if (state.opts.out) { state.opts.out.isESModule = false; } } } } }; } module.exports = importExportPlugin;