index.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551
  1. "use strict";
  2. exports.__esModule = true;
  3. var _classCallCheck2 = require("babel-runtime/helpers/classCallCheck");
  4. var _classCallCheck3 = _interopRequireDefault(_classCallCheck2);
  5. var _getIterator2 = require("babel-runtime/core-js/get-iterator");
  6. var _getIterator3 = _interopRequireDefault(_getIterator2);
  7. exports.default = function (_ref) {
  8. var t = _ref.types;
  9. function variableDeclarationHasPattern(node) {
  10. for (var _iterator = node.declarations, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : (0, _getIterator3.default)(_iterator);;) {
  11. var _ref2;
  12. if (_isArray) {
  13. if (_i >= _iterator.length) break;
  14. _ref2 = _iterator[_i++];
  15. } else {
  16. _i = _iterator.next();
  17. if (_i.done) break;
  18. _ref2 = _i.value;
  19. }
  20. var declar = _ref2;
  21. if (t.isPattern(declar.id)) {
  22. return true;
  23. }
  24. }
  25. return false;
  26. }
  27. function hasRest(pattern) {
  28. for (var _iterator2 = pattern.elements, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : (0, _getIterator3.default)(_iterator2);;) {
  29. var _ref3;
  30. if (_isArray2) {
  31. if (_i2 >= _iterator2.length) break;
  32. _ref3 = _iterator2[_i2++];
  33. } else {
  34. _i2 = _iterator2.next();
  35. if (_i2.done) break;
  36. _ref3 = _i2.value;
  37. }
  38. var elem = _ref3;
  39. if (t.isRestElement(elem)) {
  40. return true;
  41. }
  42. }
  43. return false;
  44. }
  45. var arrayUnpackVisitor = {
  46. ReferencedIdentifier: function ReferencedIdentifier(path, state) {
  47. if (state.bindings[path.node.name]) {
  48. state.deopt = true;
  49. path.stop();
  50. }
  51. }
  52. };
  53. var DestructuringTransformer = function () {
  54. function DestructuringTransformer(opts) {
  55. (0, _classCallCheck3.default)(this, DestructuringTransformer);
  56. this.blockHoist = opts.blockHoist;
  57. this.operator = opts.operator;
  58. this.arrays = {};
  59. this.nodes = opts.nodes || [];
  60. this.scope = opts.scope;
  61. this.file = opts.file;
  62. this.kind = opts.kind;
  63. }
  64. DestructuringTransformer.prototype.buildVariableAssignment = function buildVariableAssignment(id, init) {
  65. var op = this.operator;
  66. if (t.isMemberExpression(id)) op = "=";
  67. var node = void 0;
  68. if (op) {
  69. node = t.expressionStatement(t.assignmentExpression(op, id, init));
  70. } else {
  71. node = t.variableDeclaration(this.kind, [t.variableDeclarator(id, init)]);
  72. }
  73. node._blockHoist = this.blockHoist;
  74. return node;
  75. };
  76. DestructuringTransformer.prototype.buildVariableDeclaration = function buildVariableDeclaration(id, init) {
  77. var declar = t.variableDeclaration("var", [t.variableDeclarator(id, init)]);
  78. declar._blockHoist = this.blockHoist;
  79. return declar;
  80. };
  81. DestructuringTransformer.prototype.push = function push(id, init) {
  82. if (t.isObjectPattern(id)) {
  83. this.pushObjectPattern(id, init);
  84. } else if (t.isArrayPattern(id)) {
  85. this.pushArrayPattern(id, init);
  86. } else if (t.isAssignmentPattern(id)) {
  87. this.pushAssignmentPattern(id, init);
  88. } else {
  89. this.nodes.push(this.buildVariableAssignment(id, init));
  90. }
  91. };
  92. DestructuringTransformer.prototype.toArray = function toArray(node, count) {
  93. if (this.file.opts.loose || t.isIdentifier(node) && this.arrays[node.name]) {
  94. return node;
  95. } else {
  96. return this.scope.toArray(node, count);
  97. }
  98. };
  99. DestructuringTransformer.prototype.pushAssignmentPattern = function pushAssignmentPattern(pattern, valueRef) {
  100. var tempValueRef = this.scope.generateUidIdentifierBasedOnNode(valueRef);
  101. var declar = t.variableDeclaration("var", [t.variableDeclarator(tempValueRef, valueRef)]);
  102. declar._blockHoist = this.blockHoist;
  103. this.nodes.push(declar);
  104. var tempConditional = t.conditionalExpression(t.binaryExpression("===", tempValueRef, t.identifier("undefined")), pattern.right, tempValueRef);
  105. var left = pattern.left;
  106. if (t.isPattern(left)) {
  107. var tempValueDefault = t.expressionStatement(t.assignmentExpression("=", tempValueRef, tempConditional));
  108. tempValueDefault._blockHoist = this.blockHoist;
  109. this.nodes.push(tempValueDefault);
  110. this.push(left, tempValueRef);
  111. } else {
  112. this.nodes.push(this.buildVariableAssignment(left, tempConditional));
  113. }
  114. };
  115. DestructuringTransformer.prototype.pushObjectRest = function pushObjectRest(pattern, objRef, spreadProp, spreadPropIndex) {
  116. var keys = [];
  117. for (var i = 0; i < pattern.properties.length; i++) {
  118. var prop = pattern.properties[i];
  119. if (i >= spreadPropIndex) break;
  120. if (t.isRestProperty(prop)) continue;
  121. var key = prop.key;
  122. if (t.isIdentifier(key) && !prop.computed) key = t.stringLiteral(prop.key.name);
  123. keys.push(key);
  124. }
  125. keys = t.arrayExpression(keys);
  126. var value = t.callExpression(this.file.addHelper("objectWithoutProperties"), [objRef, keys]);
  127. this.nodes.push(this.buildVariableAssignment(spreadProp.argument, value));
  128. };
  129. DestructuringTransformer.prototype.pushObjectProperty = function pushObjectProperty(prop, propRef) {
  130. if (t.isLiteral(prop.key)) prop.computed = true;
  131. var pattern = prop.value;
  132. var objRef = t.memberExpression(propRef, prop.key, prop.computed);
  133. if (t.isPattern(pattern)) {
  134. this.push(pattern, objRef);
  135. } else {
  136. this.nodes.push(this.buildVariableAssignment(pattern, objRef));
  137. }
  138. };
  139. DestructuringTransformer.prototype.pushObjectPattern = function pushObjectPattern(pattern, objRef) {
  140. if (!pattern.properties.length) {
  141. this.nodes.push(t.expressionStatement(t.callExpression(this.file.addHelper("objectDestructuringEmpty"), [objRef])));
  142. }
  143. if (pattern.properties.length > 1 && !this.scope.isStatic(objRef)) {
  144. var temp = this.scope.generateUidIdentifierBasedOnNode(objRef);
  145. this.nodes.push(this.buildVariableDeclaration(temp, objRef));
  146. objRef = temp;
  147. }
  148. for (var i = 0; i < pattern.properties.length; i++) {
  149. var prop = pattern.properties[i];
  150. if (t.isRestProperty(prop)) {
  151. this.pushObjectRest(pattern, objRef, prop, i);
  152. } else {
  153. this.pushObjectProperty(prop, objRef);
  154. }
  155. }
  156. };
  157. DestructuringTransformer.prototype.canUnpackArrayPattern = function canUnpackArrayPattern(pattern, arr) {
  158. if (!t.isArrayExpression(arr)) return false;
  159. if (pattern.elements.length > arr.elements.length) return;
  160. if (pattern.elements.length < arr.elements.length && !hasRest(pattern)) return false;
  161. for (var _iterator3 = pattern.elements, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : (0, _getIterator3.default)(_iterator3);;) {
  162. var _ref4;
  163. if (_isArray3) {
  164. if (_i3 >= _iterator3.length) break;
  165. _ref4 = _iterator3[_i3++];
  166. } else {
  167. _i3 = _iterator3.next();
  168. if (_i3.done) break;
  169. _ref4 = _i3.value;
  170. }
  171. var elem = _ref4;
  172. if (!elem) return false;
  173. if (t.isMemberExpression(elem)) return false;
  174. }
  175. for (var _iterator4 = arr.elements, _isArray4 = Array.isArray(_iterator4), _i4 = 0, _iterator4 = _isArray4 ? _iterator4 : (0, _getIterator3.default)(_iterator4);;) {
  176. var _ref5;
  177. if (_isArray4) {
  178. if (_i4 >= _iterator4.length) break;
  179. _ref5 = _iterator4[_i4++];
  180. } else {
  181. _i4 = _iterator4.next();
  182. if (_i4.done) break;
  183. _ref5 = _i4.value;
  184. }
  185. var _elem = _ref5;
  186. if (t.isSpreadElement(_elem)) return false;
  187. if (t.isCallExpression(_elem)) return false;
  188. if (t.isMemberExpression(_elem)) return false;
  189. }
  190. var bindings = t.getBindingIdentifiers(pattern);
  191. var state = { deopt: false, bindings: bindings };
  192. this.scope.traverse(arr, arrayUnpackVisitor, state);
  193. return !state.deopt;
  194. };
  195. DestructuringTransformer.prototype.pushUnpackedArrayPattern = function pushUnpackedArrayPattern(pattern, arr) {
  196. for (var i = 0; i < pattern.elements.length; i++) {
  197. var elem = pattern.elements[i];
  198. if (t.isRestElement(elem)) {
  199. this.push(elem.argument, t.arrayExpression(arr.elements.slice(i)));
  200. } else {
  201. this.push(elem, arr.elements[i]);
  202. }
  203. }
  204. };
  205. DestructuringTransformer.prototype.pushArrayPattern = function pushArrayPattern(pattern, arrayRef) {
  206. if (!pattern.elements) return;
  207. if (this.canUnpackArrayPattern(pattern, arrayRef)) {
  208. return this.pushUnpackedArrayPattern(pattern, arrayRef);
  209. }
  210. var count = !hasRest(pattern) && pattern.elements.length;
  211. var toArray = this.toArray(arrayRef, count);
  212. if (t.isIdentifier(toArray)) {
  213. arrayRef = toArray;
  214. } else {
  215. arrayRef = this.scope.generateUidIdentifierBasedOnNode(arrayRef);
  216. this.arrays[arrayRef.name] = true;
  217. this.nodes.push(this.buildVariableDeclaration(arrayRef, toArray));
  218. }
  219. for (var i = 0; i < pattern.elements.length; i++) {
  220. var elem = pattern.elements[i];
  221. if (!elem) continue;
  222. var elemRef = void 0;
  223. if (t.isRestElement(elem)) {
  224. elemRef = this.toArray(arrayRef);
  225. elemRef = t.callExpression(t.memberExpression(elemRef, t.identifier("slice")), [t.numericLiteral(i)]);
  226. elem = elem.argument;
  227. } else {
  228. elemRef = t.memberExpression(arrayRef, t.numericLiteral(i), true);
  229. }
  230. this.push(elem, elemRef);
  231. }
  232. };
  233. DestructuringTransformer.prototype.init = function init(pattern, ref) {
  234. if (!t.isArrayExpression(ref) && !t.isMemberExpression(ref)) {
  235. var memo = this.scope.maybeGenerateMemoised(ref, true);
  236. if (memo) {
  237. this.nodes.push(this.buildVariableDeclaration(memo, ref));
  238. ref = memo;
  239. }
  240. }
  241. this.push(pattern, ref);
  242. return this.nodes;
  243. };
  244. return DestructuringTransformer;
  245. }();
  246. return {
  247. visitor: {
  248. ExportNamedDeclaration: function ExportNamedDeclaration(path) {
  249. var declaration = path.get("declaration");
  250. if (!declaration.isVariableDeclaration()) return;
  251. if (!variableDeclarationHasPattern(declaration.node)) return;
  252. var specifiers = [];
  253. for (var name in path.getOuterBindingIdentifiers(path)) {
  254. var id = t.identifier(name);
  255. specifiers.push(t.exportSpecifier(id, id));
  256. }
  257. path.replaceWith(declaration.node);
  258. path.insertAfter(t.exportNamedDeclaration(null, specifiers));
  259. },
  260. ForXStatement: function ForXStatement(path, file) {
  261. var node = path.node,
  262. scope = path.scope;
  263. var left = node.left;
  264. if (t.isPattern(left)) {
  265. var temp = scope.generateUidIdentifier("ref");
  266. node.left = t.variableDeclaration("var", [t.variableDeclarator(temp)]);
  267. path.ensureBlock();
  268. node.body.body.unshift(t.variableDeclaration("var", [t.variableDeclarator(left, temp)]));
  269. return;
  270. }
  271. if (!t.isVariableDeclaration(left)) return;
  272. var pattern = left.declarations[0].id;
  273. if (!t.isPattern(pattern)) return;
  274. var key = scope.generateUidIdentifier("ref");
  275. node.left = t.variableDeclaration(left.kind, [t.variableDeclarator(key, null)]);
  276. var nodes = [];
  277. var destructuring = new DestructuringTransformer({
  278. kind: left.kind,
  279. file: file,
  280. scope: scope,
  281. nodes: nodes
  282. });
  283. destructuring.init(pattern, key);
  284. path.ensureBlock();
  285. var block = node.body;
  286. block.body = nodes.concat(block.body);
  287. },
  288. CatchClause: function CatchClause(_ref6, file) {
  289. var node = _ref6.node,
  290. scope = _ref6.scope;
  291. var pattern = node.param;
  292. if (!t.isPattern(pattern)) return;
  293. var ref = scope.generateUidIdentifier("ref");
  294. node.param = ref;
  295. var nodes = [];
  296. var destructuring = new DestructuringTransformer({
  297. kind: "let",
  298. file: file,
  299. scope: scope,
  300. nodes: nodes
  301. });
  302. destructuring.init(pattern, ref);
  303. node.body.body = nodes.concat(node.body.body);
  304. },
  305. AssignmentExpression: function AssignmentExpression(path, file) {
  306. var node = path.node,
  307. scope = path.scope;
  308. if (!t.isPattern(node.left)) return;
  309. var nodes = [];
  310. var destructuring = new DestructuringTransformer({
  311. operator: node.operator,
  312. file: file,
  313. scope: scope,
  314. nodes: nodes
  315. });
  316. var ref = void 0;
  317. if (path.isCompletionRecord() || !path.parentPath.isExpressionStatement()) {
  318. ref = scope.generateUidIdentifierBasedOnNode(node.right, "ref");
  319. nodes.push(t.variableDeclaration("var", [t.variableDeclarator(ref, node.right)]));
  320. if (t.isArrayExpression(node.right)) {
  321. destructuring.arrays[ref.name] = true;
  322. }
  323. }
  324. destructuring.init(node.left, ref || node.right);
  325. if (ref) {
  326. nodes.push(t.expressionStatement(ref));
  327. }
  328. path.replaceWithMultiple(nodes);
  329. },
  330. VariableDeclaration: function VariableDeclaration(path, file) {
  331. var node = path.node,
  332. scope = path.scope,
  333. parent = path.parent;
  334. if (t.isForXStatement(parent)) return;
  335. if (!parent || !path.container) return;
  336. if (!variableDeclarationHasPattern(node)) return;
  337. var nodes = [];
  338. var declar = void 0;
  339. for (var i = 0; i < node.declarations.length; i++) {
  340. declar = node.declarations[i];
  341. var patternId = declar.init;
  342. var pattern = declar.id;
  343. var destructuring = new DestructuringTransformer({
  344. blockHoist: node._blockHoist,
  345. nodes: nodes,
  346. scope: scope,
  347. kind: node.kind,
  348. file: file
  349. });
  350. if (t.isPattern(pattern)) {
  351. destructuring.init(pattern, patternId);
  352. if (+i !== node.declarations.length - 1) {
  353. t.inherits(nodes[nodes.length - 1], declar);
  354. }
  355. } else {
  356. nodes.push(t.inherits(destructuring.buildVariableAssignment(declar.id, declar.init), declar));
  357. }
  358. }
  359. var nodesOut = [];
  360. for (var _iterator5 = nodes, _isArray5 = Array.isArray(_iterator5), _i5 = 0, _iterator5 = _isArray5 ? _iterator5 : (0, _getIterator3.default)(_iterator5);;) {
  361. var _ref7;
  362. if (_isArray5) {
  363. if (_i5 >= _iterator5.length) break;
  364. _ref7 = _iterator5[_i5++];
  365. } else {
  366. _i5 = _iterator5.next();
  367. if (_i5.done) break;
  368. _ref7 = _i5.value;
  369. }
  370. var _node = _ref7;
  371. var tail = nodesOut[nodesOut.length - 1];
  372. if (tail && t.isVariableDeclaration(tail) && t.isVariableDeclaration(_node) && tail.kind === _node.kind) {
  373. var _tail$declarations;
  374. (_tail$declarations = tail.declarations).push.apply(_tail$declarations, _node.declarations);
  375. } else {
  376. nodesOut.push(_node);
  377. }
  378. }
  379. for (var _iterator6 = nodesOut, _isArray6 = Array.isArray(_iterator6), _i6 = 0, _iterator6 = _isArray6 ? _iterator6 : (0, _getIterator3.default)(_iterator6);;) {
  380. var _ref8;
  381. if (_isArray6) {
  382. if (_i6 >= _iterator6.length) break;
  383. _ref8 = _iterator6[_i6++];
  384. } else {
  385. _i6 = _iterator6.next();
  386. if (_i6.done) break;
  387. _ref8 = _i6.value;
  388. }
  389. var nodeOut = _ref8;
  390. if (!nodeOut.declarations) continue;
  391. for (var _iterator7 = nodeOut.declarations, _isArray7 = Array.isArray(_iterator7), _i7 = 0, _iterator7 = _isArray7 ? _iterator7 : (0, _getIterator3.default)(_iterator7);;) {
  392. var _ref9;
  393. if (_isArray7) {
  394. if (_i7 >= _iterator7.length) break;
  395. _ref9 = _iterator7[_i7++];
  396. } else {
  397. _i7 = _iterator7.next();
  398. if (_i7.done) break;
  399. _ref9 = _i7.value;
  400. }
  401. var declaration = _ref9;
  402. var name = declaration.id.name;
  403. if (scope.bindings[name]) {
  404. scope.bindings[name].kind = nodeOut.kind;
  405. }
  406. }
  407. }
  408. if (nodesOut.length === 1) {
  409. path.replaceWith(nodesOut[0]);
  410. } else {
  411. path.replaceWithMultiple(nodesOut);
  412. }
  413. }
  414. }
  415. };
  416. };
  417. function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  418. module.exports = exports["default"];