UNPKG

5.26 kBJavaScriptView Raw
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = void 0;
7
8var _helperPluginUtils = require("@babel/helper-plugin-utils");
9
10var _helperSkipTransparentExpressionWrappers = require("@babel/helper-skip-transparent-expression-wrappers");
11
12var _core = require("@babel/core");
13
14var _default = (0, _helperPluginUtils.declare)((api, options) => {
15 var _api$assumption, _options$allowArrayLi;
16
17 api.assertVersion(7);
18 const iterableIsArray = (_api$assumption = api.assumption("iterableIsArray")) != null ? _api$assumption : options.loose;
19 const arrayLikeIsIterable = (_options$allowArrayLi = options.allowArrayLike) != null ? _options$allowArrayLi : api.assumption("arrayLikeIsIterable");
20
21 function getSpreadLiteral(spread, scope) {
22 if (iterableIsArray && !_core.types.isIdentifier(spread.argument, {
23 name: "arguments"
24 })) {
25 return spread.argument;
26 } else {
27 return scope.toArray(spread.argument, true, arrayLikeIsIterable);
28 }
29 }
30
31 function hasHole(spread) {
32 return spread.elements.some(el => el === null);
33 }
34
35 function hasSpread(nodes) {
36 for (let i = 0; i < nodes.length; i++) {
37 if (_core.types.isSpreadElement(nodes[i])) {
38 return true;
39 }
40 }
41
42 return false;
43 }
44
45 function push(_props, nodes) {
46 if (!_props.length) return _props;
47 nodes.push(_core.types.arrayExpression(_props));
48 return [];
49 }
50
51 function build(props, scope, file) {
52 const nodes = [];
53 let _props = [];
54
55 for (const prop of props) {
56 if (_core.types.isSpreadElement(prop)) {
57 _props = push(_props, nodes);
58 let spreadLiteral = getSpreadLiteral(prop, scope);
59
60 if (_core.types.isArrayExpression(spreadLiteral) && hasHole(spreadLiteral)) {
61 spreadLiteral = _core.types.callExpression(file.addHelper("arrayWithoutHoles"), [spreadLiteral]);
62 }
63
64 nodes.push(spreadLiteral);
65 } else {
66 _props.push(prop);
67 }
68 }
69
70 push(_props, nodes);
71 return nodes;
72 }
73
74 return {
75 name: "transform-spread",
76 visitor: {
77 ArrayExpression(path) {
78 const {
79 node,
80 scope
81 } = path;
82 const elements = node.elements;
83 if (!hasSpread(elements)) return;
84 const nodes = build(elements, scope, this);
85 let first = nodes[0];
86
87 if (nodes.length === 1 && first !== elements[0].argument) {
88 path.replaceWith(first);
89 return;
90 }
91
92 if (!_core.types.isArrayExpression(first)) {
93 first = _core.types.arrayExpression([]);
94 } else {
95 nodes.shift();
96 }
97
98 path.replaceWith(_core.types.callExpression(_core.types.memberExpression(first, _core.types.identifier("concat")), nodes));
99 },
100
101 CallExpression(path) {
102 const {
103 node,
104 scope
105 } = path;
106 const args = node.arguments;
107 if (!hasSpread(args)) return;
108 const calleePath = (0, _helperSkipTransparentExpressionWrappers.skipTransparentExprWrappers)(path.get("callee"));
109
110 if (calleePath.isSuper()) {
111 throw path.buildCodeFrameError("It's not possible to compile spread arguments in `super()` without compiling classes.\n" + "Please add '@babel/plugin-transform-classes' to your Babel configuration.");
112 }
113
114 let contextLiteral = scope.buildUndefinedNode();
115 node.arguments = [];
116 let nodes;
117
118 if (args.length === 1 && _core.types.isIdentifier(args[0].argument, {
119 name: "arguments"
120 })) {
121 nodes = [args[0].argument];
122 } else {
123 nodes = build(args, scope, this);
124 }
125
126 const first = nodes.shift();
127
128 if (nodes.length) {
129 node.arguments.push(_core.types.callExpression(_core.types.memberExpression(first, _core.types.identifier("concat")), nodes));
130 } else {
131 node.arguments.push(first);
132 }
133
134 const callee = calleePath.node;
135
136 if (calleePath.isMemberExpression()) {
137 const temp = scope.maybeGenerateMemoised(callee.object);
138
139 if (temp) {
140 callee.object = _core.types.assignmentExpression("=", temp, callee.object);
141 contextLiteral = temp;
142 } else {
143 contextLiteral = _core.types.cloneNode(callee.object);
144 }
145 }
146
147 node.callee = _core.types.memberExpression(node.callee, _core.types.identifier("apply"));
148
149 if (_core.types.isSuper(contextLiteral)) {
150 contextLiteral = _core.types.thisExpression();
151 }
152
153 node.arguments.unshift(_core.types.cloneNode(contextLiteral));
154 },
155
156 NewExpression(path) {
157 const {
158 node,
159 scope
160 } = path;
161 if (!hasSpread(node.arguments)) return;
162 const nodes = build(node.arguments, scope, this);
163 const first = nodes.shift();
164 let args;
165
166 if (nodes.length) {
167 args = _core.types.callExpression(_core.types.memberExpression(first, _core.types.identifier("concat")), nodes);
168 } else {
169 args = first;
170 }
171
172 path.replaceWith(_core.types.callExpression(path.hub.addHelper("construct"), [node.callee, args]));
173 }
174
175 }
176 };
177});
178
179exports.default = _default;
\No newline at end of file