modification.js 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.insertBefore = insertBefore;
  6. exports._containerInsert = _containerInsert;
  7. exports._containerInsertBefore = _containerInsertBefore;
  8. exports._containerInsertAfter = _containerInsertAfter;
  9. exports.insertAfter = insertAfter;
  10. exports.updateSiblingKeys = updateSiblingKeys;
  11. exports._verifyNodeList = _verifyNodeList;
  12. exports.unshiftContainer = unshiftContainer;
  13. exports.pushContainer = pushContainer;
  14. exports.hoist = hoist;
  15. var _cache = require("../cache");
  16. var _hoister = require("./lib/hoister");
  17. var _index = require("./index");
  18. var _t = require("@babel/types");
  19. const {
  20. arrowFunctionExpression,
  21. assertExpression,
  22. assignmentExpression,
  23. blockStatement,
  24. callExpression,
  25. cloneNode,
  26. expressionStatement,
  27. isExpression
  28. } = _t;
  29. function insertBefore(nodes_) {
  30. this._assertUnremoved();
  31. const nodes = this._verifyNodeList(nodes_);
  32. const {
  33. parentPath
  34. } = this;
  35. if (parentPath.isExpressionStatement() || parentPath.isLabeledStatement() || parentPath.isExportNamedDeclaration() || parentPath.isExportDefaultDeclaration() && this.isDeclaration()) {
  36. return parentPath.insertBefore(nodes);
  37. } else if (this.isNodeType("Expression") && !this.isJSXElement() || parentPath.isForStatement() && this.key === "init") {
  38. if (this.node) nodes.push(this.node);
  39. return this.replaceExpressionWithStatements(nodes);
  40. } else if (Array.isArray(this.container)) {
  41. return this._containerInsertBefore(nodes);
  42. } else if (this.isStatementOrBlock()) {
  43. const node = this.node;
  44. const shouldInsertCurrentNode = node && (!this.isExpressionStatement() || node.expression != null);
  45. this.replaceWith(blockStatement(shouldInsertCurrentNode ? [node] : []));
  46. return this.unshiftContainer("body", nodes);
  47. } else {
  48. throw new Error("We don't know what to do with this node type. " + "We were previously a Statement but we can't fit in here?");
  49. }
  50. }
  51. function _containerInsert(from, nodes) {
  52. this.updateSiblingKeys(from, nodes.length);
  53. const paths = [];
  54. this.container.splice(from, 0, ...nodes);
  55. for (let i = 0; i < nodes.length; i++) {
  56. const to = from + i;
  57. const path = this.getSibling(to);
  58. paths.push(path);
  59. if (this.context && this.context.queue) {
  60. path.pushContext(this.context);
  61. }
  62. }
  63. const contexts = this._getQueueContexts();
  64. for (const path of paths) {
  65. path.setScope();
  66. path.debug("Inserted.");
  67. for (const context of contexts) {
  68. context.maybeQueue(path, true);
  69. }
  70. }
  71. return paths;
  72. }
  73. function _containerInsertBefore(nodes) {
  74. return this._containerInsert(this.key, nodes);
  75. }
  76. function _containerInsertAfter(nodes) {
  77. return this._containerInsert(this.key + 1, nodes);
  78. }
  79. function insertAfter(nodes_) {
  80. this._assertUnremoved();
  81. const nodes = this._verifyNodeList(nodes_);
  82. const {
  83. parentPath
  84. } = this;
  85. if (parentPath.isExpressionStatement() || parentPath.isLabeledStatement() || parentPath.isExportNamedDeclaration() || parentPath.isExportDefaultDeclaration() && this.isDeclaration()) {
  86. return parentPath.insertAfter(nodes.map(node => {
  87. return isExpression(node) ? expressionStatement(node) : node;
  88. }));
  89. } else if (this.isNodeType("Expression") && !this.isJSXElement() && !parentPath.isJSXElement() || parentPath.isForStatement() && this.key === "init") {
  90. if (this.node) {
  91. const node = this.node;
  92. let {
  93. scope
  94. } = this;
  95. if (scope.path.isPattern()) {
  96. assertExpression(node);
  97. this.replaceWith(callExpression(arrowFunctionExpression([], node), []));
  98. this.get("callee.body").insertAfter(nodes);
  99. return [this];
  100. }
  101. if (parentPath.isMethod({
  102. computed: true,
  103. key: node
  104. })) {
  105. scope = scope.parent;
  106. }
  107. const temp = scope.generateDeclaredUidIdentifier();
  108. nodes.unshift(expressionStatement(assignmentExpression("=", cloneNode(temp), node)));
  109. nodes.push(expressionStatement(cloneNode(temp)));
  110. }
  111. return this.replaceExpressionWithStatements(nodes);
  112. } else if (Array.isArray(this.container)) {
  113. return this._containerInsertAfter(nodes);
  114. } else if (this.isStatementOrBlock()) {
  115. const node = this.node;
  116. const shouldInsertCurrentNode = node && (!this.isExpressionStatement() || node.expression != null);
  117. this.replaceWith(blockStatement(shouldInsertCurrentNode ? [node] : []));
  118. return this.pushContainer("body", nodes);
  119. } else {
  120. throw new Error("We don't know what to do with this node type. " + "We were previously a Statement but we can't fit in here?");
  121. }
  122. }
  123. function updateSiblingKeys(fromIndex, incrementBy) {
  124. if (!this.parent) return;
  125. const paths = _cache.path.get(this.parent);
  126. for (const [, path] of paths) {
  127. if (path.key >= fromIndex) {
  128. path.key += incrementBy;
  129. }
  130. }
  131. }
  132. function _verifyNodeList(nodes) {
  133. if (!nodes) {
  134. return [];
  135. }
  136. if (!Array.isArray(nodes)) {
  137. nodes = [nodes];
  138. }
  139. for (let i = 0; i < nodes.length; i++) {
  140. const node = nodes[i];
  141. let msg;
  142. if (!node) {
  143. msg = "has falsy node";
  144. } else if (typeof node !== "object") {
  145. msg = "contains a non-object node";
  146. } else if (!node.type) {
  147. msg = "without a type";
  148. } else if (node instanceof _index.default) {
  149. msg = "has a NodePath when it expected a raw object";
  150. }
  151. if (msg) {
  152. const type = Array.isArray(node) ? "array" : typeof node;
  153. throw new Error(`Node list ${msg} with the index of ${i} and type of ${type}`);
  154. }
  155. }
  156. return nodes;
  157. }
  158. function unshiftContainer(listKey, nodes) {
  159. this._assertUnremoved();
  160. nodes = this._verifyNodeList(nodes);
  161. const path = _index.default.get({
  162. parentPath: this,
  163. parent: this.node,
  164. container: this.node[listKey],
  165. listKey,
  166. key: 0
  167. }).setContext(this.context);
  168. return path._containerInsertBefore(nodes);
  169. }
  170. function pushContainer(listKey, nodes) {
  171. this._assertUnremoved();
  172. const verifiedNodes = this._verifyNodeList(nodes);
  173. const container = this.node[listKey];
  174. const path = _index.default.get({
  175. parentPath: this,
  176. parent: this.node,
  177. container: container,
  178. listKey,
  179. key: container.length
  180. }).setContext(this.context);
  181. return path.replaceWithMultiple(verifiedNodes);
  182. }
  183. function hoist(scope = this.scope) {
  184. const hoister = new _hoister.default(this, scope);
  185. return hoister.run();
  186. }