util.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", {
  3. value: true
  4. });
  5. exports.DestructuringTransformer = void 0;
  6. exports.buildObjectExcludingKeys = buildObjectExcludingKeys;
  7. exports.convertAssignmentExpression = convertAssignmentExpression;
  8. exports.convertVariableDeclaration = convertVariableDeclaration;
  9. exports.unshiftForXStatementBody = unshiftForXStatementBody;
  10. var _core = require("@babel/core");
  11. function isPureVoid(node) {
  12. return _core.types.isUnaryExpression(node) && node.operator === "void" && _core.types.isPureish(node.argument);
  13. }
  14. function unshiftForXStatementBody(statementPath, newStatements) {
  15. statementPath.ensureBlock();
  16. const {
  17. scope,
  18. node
  19. } = statementPath;
  20. const bodyScopeBindings = statementPath.get("body").scope.bindings;
  21. const hasShadowedBlockScopedBindings = Object.keys(bodyScopeBindings).some(name => scope.hasBinding(name));
  22. if (hasShadowedBlockScopedBindings) {
  23. node.body = _core.types.blockStatement([...newStatements, node.body]);
  24. } else {
  25. node.body.body.unshift(...newStatements);
  26. }
  27. }
  28. function hasArrayRest(pattern) {
  29. return pattern.elements.some(elem => _core.types.isRestElement(elem));
  30. }
  31. function hasObjectRest(pattern) {
  32. return pattern.properties.some(prop => _core.types.isRestElement(prop));
  33. }
  34. const STOP_TRAVERSAL = {};
  35. const arrayUnpackVisitor = (node, ancestors, state) => {
  36. if (!ancestors.length) {
  37. return;
  38. }
  39. if (_core.types.isIdentifier(node) && _core.types.isReferenced(node, ancestors[ancestors.length - 1].node) && state.bindings[node.name]) {
  40. state.deopt = true;
  41. throw STOP_TRAVERSAL;
  42. }
  43. };
  44. class DestructuringTransformer {
  45. constructor(opts) {
  46. this.blockHoist = void 0;
  47. this.operator = void 0;
  48. this.arrayRefSet = void 0;
  49. this.nodes = void 0;
  50. this.scope = void 0;
  51. this.kind = void 0;
  52. this.iterableIsArray = void 0;
  53. this.arrayLikeIsIterable = void 0;
  54. this.objectRestNoSymbols = void 0;
  55. this.useBuiltIns = void 0;
  56. this.addHelper = void 0;
  57. this.blockHoist = opts.blockHoist;
  58. this.operator = opts.operator;
  59. this.arrayRefSet = new Set();
  60. this.nodes = opts.nodes || [];
  61. this.scope = opts.scope;
  62. this.kind = opts.kind;
  63. this.iterableIsArray = opts.iterableIsArray;
  64. this.arrayLikeIsIterable = opts.arrayLikeIsIterable;
  65. this.objectRestNoSymbols = opts.objectRestNoSymbols;
  66. this.useBuiltIns = opts.useBuiltIns;
  67. this.addHelper = opts.addHelper;
  68. }
  69. getExtendsHelper() {
  70. return this.useBuiltIns ? _core.types.memberExpression(_core.types.identifier("Object"), _core.types.identifier("assign")) : this.addHelper("extends");
  71. }
  72. buildVariableAssignment(id, init) {
  73. let op = this.operator;
  74. if (_core.types.isMemberExpression(id)) op = "=";
  75. let node;
  76. if (op) {
  77. node = _core.types.expressionStatement(_core.types.assignmentExpression(op, id, _core.types.cloneNode(init) || this.scope.buildUndefinedNode()));
  78. } else {
  79. let nodeInit;
  80. if ((this.kind === "const" || this.kind === "using") && init === null) {
  81. nodeInit = this.scope.buildUndefinedNode();
  82. } else {
  83. nodeInit = _core.types.cloneNode(init);
  84. }
  85. node = _core.types.variableDeclaration(this.kind, [_core.types.variableDeclarator(id, nodeInit)]);
  86. }
  87. node._blockHoist = this.blockHoist;
  88. return node;
  89. }
  90. buildVariableDeclaration(id, init) {
  91. const declar = _core.types.variableDeclaration("var", [_core.types.variableDeclarator(_core.types.cloneNode(id), _core.types.cloneNode(init))]);
  92. declar._blockHoist = this.blockHoist;
  93. return declar;
  94. }
  95. push(id, _init) {
  96. const init = _core.types.cloneNode(_init);
  97. if (_core.types.isObjectPattern(id)) {
  98. this.pushObjectPattern(id, init);
  99. } else if (_core.types.isArrayPattern(id)) {
  100. this.pushArrayPattern(id, init);
  101. } else if (_core.types.isAssignmentPattern(id)) {
  102. this.pushAssignmentPattern(id, init);
  103. } else {
  104. this.nodes.push(this.buildVariableAssignment(id, init));
  105. }
  106. }
  107. toArray(node, count) {
  108. if (this.iterableIsArray || _core.types.isIdentifier(node) && this.arrayRefSet.has(node.name)) {
  109. return node;
  110. } else {
  111. return this.scope.toArray(node, count, this.arrayLikeIsIterable);
  112. }
  113. }
  114. pushAssignmentPattern({
  115. left,
  116. right
  117. }, valueRef) {
  118. if (isPureVoid(valueRef)) {
  119. this.push(left, right);
  120. return;
  121. }
  122. const tempId = this.scope.generateUidIdentifierBasedOnNode(valueRef);
  123. this.nodes.push(this.buildVariableDeclaration(tempId, valueRef));
  124. const tempConditional = _core.types.conditionalExpression(_core.types.binaryExpression("===", _core.types.cloneNode(tempId), this.scope.buildUndefinedNode()), right, _core.types.cloneNode(tempId));
  125. if (_core.types.isPattern(left)) {
  126. let patternId;
  127. let node;
  128. if (this.kind === "const" || this.kind === "let" || this.kind === "using") {
  129. patternId = this.scope.generateUidIdentifier(tempId.name);
  130. node = this.buildVariableDeclaration(patternId, tempConditional);
  131. } else {
  132. patternId = tempId;
  133. node = _core.types.expressionStatement(_core.types.assignmentExpression("=", _core.types.cloneNode(tempId), tempConditional));
  134. }
  135. this.nodes.push(node);
  136. this.push(left, patternId);
  137. } else {
  138. this.nodes.push(this.buildVariableAssignment(left, tempConditional));
  139. }
  140. }
  141. pushObjectRest(pattern, objRef, spreadProp, spreadPropIndex) {
  142. const value = buildObjectExcludingKeys(pattern.properties.slice(0, spreadPropIndex), objRef, this.scope, name => this.addHelper(name), this.objectRestNoSymbols, this.useBuiltIns);
  143. this.nodes.push(this.buildVariableAssignment(spreadProp.argument, value));
  144. }
  145. pushObjectProperty(prop, propRef) {
  146. if (_core.types.isLiteral(prop.key)) prop.computed = true;
  147. const pattern = prop.value;
  148. const objRef = _core.types.memberExpression(_core.types.cloneNode(propRef), prop.key, prop.computed);
  149. if (_core.types.isPattern(pattern)) {
  150. this.push(pattern, objRef);
  151. } else {
  152. this.nodes.push(this.buildVariableAssignment(pattern, objRef));
  153. }
  154. }
  155. pushObjectPattern(pattern, objRef) {
  156. if (!pattern.properties.length) {
  157. this.nodes.push(_core.types.expressionStatement(_core.types.callExpression(this.addHelper("objectDestructuringEmpty"), isPureVoid(objRef) ? [] : [objRef])));
  158. return;
  159. }
  160. if (pattern.properties.length > 1 && !this.scope.isStatic(objRef)) {
  161. const temp = this.scope.generateUidIdentifierBasedOnNode(objRef);
  162. this.nodes.push(this.buildVariableDeclaration(temp, objRef));
  163. objRef = temp;
  164. }
  165. if (hasObjectRest(pattern)) {
  166. let copiedPattern;
  167. for (let i = 0; i < pattern.properties.length; i++) {
  168. const prop = pattern.properties[i];
  169. if (_core.types.isRestElement(prop)) {
  170. break;
  171. }
  172. const key = prop.key;
  173. if (prop.computed && !this.scope.isPure(key)) {
  174. const name = this.scope.generateUidIdentifierBasedOnNode(key);
  175. this.nodes.push(this.buildVariableDeclaration(name, key));
  176. if (!copiedPattern) {
  177. copiedPattern = pattern = Object.assign({}, pattern, {
  178. properties: pattern.properties.slice()
  179. });
  180. }
  181. copiedPattern.properties[i] = Object.assign({}, prop, {
  182. key: name
  183. });
  184. }
  185. }
  186. }
  187. for (let i = 0; i < pattern.properties.length; i++) {
  188. const prop = pattern.properties[i];
  189. if (_core.types.isRestElement(prop)) {
  190. this.pushObjectRest(pattern, objRef, prop, i);
  191. } else {
  192. this.pushObjectProperty(prop, objRef);
  193. }
  194. }
  195. }
  196. canUnpackArrayPattern(pattern, arr) {
  197. if (!_core.types.isArrayExpression(arr)) return false;
  198. if (pattern.elements.length > arr.elements.length) return;
  199. if (pattern.elements.length < arr.elements.length && !hasArrayRest(pattern)) {
  200. return false;
  201. }
  202. for (const elem of pattern.elements) {
  203. if (!elem) return false;
  204. if (_core.types.isMemberExpression(elem)) return false;
  205. }
  206. for (const elem of arr.elements) {
  207. if (_core.types.isSpreadElement(elem)) return false;
  208. if (_core.types.isCallExpression(elem)) return false;
  209. if (_core.types.isMemberExpression(elem)) return false;
  210. }
  211. const bindings = _core.types.getBindingIdentifiers(pattern);
  212. const state = {
  213. deopt: false,
  214. bindings
  215. };
  216. try {
  217. _core.types.traverse(arr, arrayUnpackVisitor, state);
  218. } catch (e) {
  219. if (e !== STOP_TRAVERSAL) throw e;
  220. }
  221. return !state.deopt;
  222. }
  223. pushUnpackedArrayPattern(pattern, arr) {
  224. const holeToUndefined = el => el != null ? el : this.scope.buildUndefinedNode();
  225. for (let i = 0; i < pattern.elements.length; i++) {
  226. const elem = pattern.elements[i];
  227. if (_core.types.isRestElement(elem)) {
  228. this.push(elem.argument, _core.types.arrayExpression(arr.elements.slice(i).map(holeToUndefined)));
  229. } else {
  230. this.push(elem, holeToUndefined(arr.elements[i]));
  231. }
  232. }
  233. }
  234. pushArrayPattern(pattern, arrayRef) {
  235. if (arrayRef === null) {
  236. this.nodes.push(_core.types.expressionStatement(_core.types.callExpression(this.addHelper("objectDestructuringEmpty"), [])));
  237. return;
  238. }
  239. if (!pattern.elements) return;
  240. if (this.canUnpackArrayPattern(pattern, arrayRef)) {
  241. this.pushUnpackedArrayPattern(pattern, arrayRef);
  242. return;
  243. }
  244. const count = !hasArrayRest(pattern) && pattern.elements.length;
  245. const toArray = this.toArray(arrayRef, count);
  246. if (_core.types.isIdentifier(toArray)) {
  247. arrayRef = toArray;
  248. } else {
  249. arrayRef = this.scope.generateUidIdentifierBasedOnNode(arrayRef);
  250. this.arrayRefSet.add(arrayRef.name);
  251. this.nodes.push(this.buildVariableDeclaration(arrayRef, toArray));
  252. }
  253. for (let i = 0; i < pattern.elements.length; i++) {
  254. const elem = pattern.elements[i];
  255. if (!elem) continue;
  256. let elemRef;
  257. if (_core.types.isRestElement(elem)) {
  258. elemRef = this.toArray(arrayRef);
  259. elemRef = _core.types.callExpression(_core.types.memberExpression(elemRef, _core.types.identifier("slice")), [_core.types.numericLiteral(i)]);
  260. this.push(elem.argument, elemRef);
  261. } else {
  262. elemRef = _core.types.memberExpression(arrayRef, _core.types.numericLiteral(i), true);
  263. this.push(elem, elemRef);
  264. }
  265. }
  266. }
  267. init(pattern, ref) {
  268. if (!_core.types.isArrayExpression(ref) && !_core.types.isMemberExpression(ref)) {
  269. const memo = this.scope.maybeGenerateMemoised(ref, true);
  270. if (memo) {
  271. this.nodes.push(this.buildVariableDeclaration(memo, _core.types.cloneNode(ref)));
  272. ref = memo;
  273. }
  274. }
  275. this.push(pattern, ref);
  276. return this.nodes;
  277. }
  278. }
  279. exports.DestructuringTransformer = DestructuringTransformer;
  280. function buildObjectExcludingKeys(excludedKeys, objRef, scope, addHelper, objectRestNoSymbols, useBuiltIns) {
  281. const keys = [];
  282. let allLiteral = true;
  283. let hasTemplateLiteral = false;
  284. for (let i = 0; i < excludedKeys.length; i++) {
  285. const prop = excludedKeys[i];
  286. const key = prop.key;
  287. if (_core.types.isIdentifier(key) && !prop.computed) {
  288. keys.push(_core.types.stringLiteral(key.name));
  289. } else if (_core.types.isTemplateLiteral(key)) {
  290. keys.push(_core.types.cloneNode(key));
  291. hasTemplateLiteral = true;
  292. } else if (_core.types.isLiteral(key)) {
  293. keys.push(_core.types.stringLiteral(String(key.value)));
  294. } else if (_core.types.isPrivateName(key)) {} else {
  295. keys.push(_core.types.cloneNode(key));
  296. allLiteral = false;
  297. }
  298. }
  299. let value;
  300. if (keys.length === 0) {
  301. const extendsHelper = useBuiltIns ? _core.types.memberExpression(_core.types.identifier("Object"), _core.types.identifier("assign")) : addHelper("extends");
  302. value = _core.types.callExpression(extendsHelper, [_core.types.objectExpression([]), _core.types.sequenceExpression([_core.types.callExpression(addHelper("objectDestructuringEmpty"), [_core.types.cloneNode(objRef)]), _core.types.cloneNode(objRef)])]);
  303. } else {
  304. let keyExpression = _core.types.arrayExpression(keys);
  305. if (!allLiteral) {
  306. keyExpression = _core.types.callExpression(_core.types.memberExpression(keyExpression, _core.types.identifier("map")), [addHelper("toPropertyKey")]);
  307. } else if (!hasTemplateLiteral && !_core.types.isProgram(scope.block)) {
  308. const programScope = scope.getProgramParent();
  309. const id = programScope.generateUidIdentifier("excluded");
  310. programScope.push({
  311. id,
  312. init: keyExpression,
  313. kind: "const"
  314. });
  315. keyExpression = _core.types.cloneNode(id);
  316. }
  317. value = _core.types.callExpression(addHelper(`objectWithoutProperties${objectRestNoSymbols ? "Loose" : ""}`), [_core.types.cloneNode(objRef), keyExpression]);
  318. }
  319. return value;
  320. }
  321. function convertVariableDeclaration(path, addHelper, arrayLikeIsIterable, iterableIsArray, objectRestNoSymbols, useBuiltIns) {
  322. const {
  323. node,
  324. scope
  325. } = path;
  326. const nodeKind = node.kind;
  327. const nodeLoc = node.loc;
  328. const nodes = [];
  329. for (let i = 0; i < node.declarations.length; i++) {
  330. const declar = node.declarations[i];
  331. const patternId = declar.init;
  332. const pattern = declar.id;
  333. const destructuring = new DestructuringTransformer({
  334. blockHoist: node._blockHoist,
  335. nodes: nodes,
  336. scope: scope,
  337. kind: node.kind,
  338. iterableIsArray,
  339. arrayLikeIsIterable,
  340. useBuiltIns,
  341. objectRestNoSymbols,
  342. addHelper
  343. });
  344. if (_core.types.isPattern(pattern)) {
  345. destructuring.init(pattern, patternId);
  346. if (+i !== node.declarations.length - 1) {
  347. _core.types.inherits(nodes[nodes.length - 1], declar);
  348. }
  349. } else {
  350. nodes.push(_core.types.inherits(destructuring.buildVariableAssignment(pattern, patternId), declar));
  351. }
  352. }
  353. let tail = null;
  354. let nodesOut = [];
  355. for (const node of nodes) {
  356. if (_core.types.isVariableDeclaration(node)) {
  357. if (tail !== null) {
  358. tail.declarations.push(...node.declarations);
  359. continue;
  360. } else {
  361. node.kind = nodeKind;
  362. tail = node;
  363. }
  364. } else {
  365. tail = null;
  366. }
  367. if (!node.loc) {
  368. node.loc = nodeLoc;
  369. }
  370. nodesOut.push(node);
  371. }
  372. if (nodesOut.length === 2 && _core.types.isVariableDeclaration(nodesOut[0]) && _core.types.isExpressionStatement(nodesOut[1]) && _core.types.isCallExpression(nodesOut[1].expression) && nodesOut[0].declarations.length === 1) {
  373. const expr = nodesOut[1].expression;
  374. expr.arguments = [nodesOut[0].declarations[0].init];
  375. nodesOut = [expr];
  376. } else {
  377. if (_core.types.isForStatement(path.parent, {
  378. init: node
  379. }) && !nodesOut.some(v => _core.types.isVariableDeclaration(v))) {
  380. for (let i = 0; i < nodesOut.length; i++) {
  381. const node = nodesOut[i];
  382. if (_core.types.isExpressionStatement(node)) {
  383. nodesOut[i] = node.expression;
  384. }
  385. }
  386. }
  387. }
  388. if (nodesOut.length === 1) {
  389. path.replaceWith(nodesOut[0]);
  390. } else {
  391. path.replaceWithMultiple(nodesOut);
  392. }
  393. scope.crawl();
  394. }
  395. function convertAssignmentExpression(path, addHelper, arrayLikeIsIterable, iterableIsArray, objectRestNoSymbols, useBuiltIns) {
  396. const {
  397. node,
  398. scope,
  399. parentPath
  400. } = path;
  401. const nodes = [];
  402. const destructuring = new DestructuringTransformer({
  403. operator: node.operator,
  404. scope: scope,
  405. nodes: nodes,
  406. arrayLikeIsIterable,
  407. iterableIsArray,
  408. objectRestNoSymbols,
  409. useBuiltIns,
  410. addHelper
  411. });
  412. let ref;
  413. if (!parentPath.isExpressionStatement() && !parentPath.isSequenceExpression() || path.isCompletionRecord()) {
  414. ref = scope.generateUidIdentifierBasedOnNode(node.right, "ref");
  415. nodes.push(_core.types.variableDeclaration("var", [_core.types.variableDeclarator(ref, node.right)]));
  416. if (_core.types.isArrayExpression(node.right)) {
  417. destructuring.arrayRefSet.add(ref.name);
  418. }
  419. }
  420. destructuring.init(node.left, ref || node.right);
  421. if (ref) {
  422. if (parentPath.isArrowFunctionExpression()) {
  423. path.replaceWith(_core.types.blockStatement([]));
  424. nodes.push(_core.types.returnStatement(_core.types.cloneNode(ref)));
  425. } else {
  426. nodes.push(_core.types.expressionStatement(_core.types.cloneNode(ref)));
  427. }
  428. }
  429. path.replaceWithMultiple(nodes);
  430. scope.crawl();
  431. }
  432. //# sourceMappingURL=util.js.map