source: imaps-frontend/node_modules/@babel/plugin-transform-parameters/lib/rest.js

main
Last change on this file was 79a0317, checked in by stefan toskovski <stefantoska84@…>, 4 days ago

F4 Finalna Verzija

  • Property mode set to 100644
File size: 8.6 KB
Line 
1"use strict";
2
3Object.defineProperty(exports, "__esModule", {
4 value: true
5});
6exports.default = convertFunctionRest;
7var _core = require("@babel/core");
8var _shadowUtils = require("./shadow-utils.js");
9const buildRest = _core.template.statement(`
10 for (var LEN = ARGUMENTS.length,
11 ARRAY = new Array(ARRAY_LEN),
12 KEY = START;
13 KEY < LEN;
14 KEY++) {
15 ARRAY[ARRAY_KEY] = ARGUMENTS[KEY];
16 }
17`);
18const restIndex = _core.template.expression(`
19 (INDEX < OFFSET || ARGUMENTS.length <= INDEX) ? undefined : ARGUMENTS[INDEX]
20`);
21const restIndexImpure = _core.template.expression(`
22 REF = INDEX, (REF < OFFSET || ARGUMENTS.length <= REF) ? undefined : ARGUMENTS[REF]
23`);
24const restLength = _core.template.expression(`
25 ARGUMENTS.length <= OFFSET ? 0 : ARGUMENTS.length - OFFSET
26`);
27function referencesRest(path, state) {
28 if (path.node.name === state.name) {
29 return path.scope.bindingIdentifierEquals(state.name, state.outerBinding);
30 }
31 return false;
32}
33const memberExpressionOptimisationVisitor = {
34 Scope(path, state) {
35 if (!path.scope.bindingIdentifierEquals(state.name, state.outerBinding)) {
36 path.skip();
37 }
38 },
39 Flow(path) {
40 if (path.isTypeCastExpression()) return;
41 path.skip();
42 },
43 Function(path, state) {
44 const oldNoOptimise = state.noOptimise;
45 state.noOptimise = true;
46 path.traverse(memberExpressionOptimisationVisitor, state);
47 state.noOptimise = oldNoOptimise;
48 path.skip();
49 },
50 ReferencedIdentifier(path, state) {
51 const {
52 node
53 } = path;
54 if (node.name === "arguments") {
55 state.deopted = true;
56 }
57 if (!referencesRest(path, state)) return;
58 if (state.noOptimise) {
59 state.deopted = true;
60 } else {
61 const {
62 parentPath
63 } = path;
64 if (parentPath.listKey === "params" && parentPath.key < state.offset) {
65 return;
66 }
67 if (parentPath.isMemberExpression({
68 object: node
69 })) {
70 const grandparentPath = parentPath.parentPath;
71 const argsOptEligible = !state.deopted && !(grandparentPath.isAssignmentExpression() && parentPath.node === grandparentPath.node.left || grandparentPath.isLVal() || grandparentPath.isForXStatement() || grandparentPath.isUpdateExpression() || grandparentPath.isUnaryExpression({
72 operator: "delete"
73 }) || (grandparentPath.isCallExpression() || grandparentPath.isNewExpression()) && parentPath.node === grandparentPath.node.callee);
74 if (argsOptEligible) {
75 if (parentPath.node.computed) {
76 if (parentPath.get("property").isBaseType("number")) {
77 state.candidates.push({
78 cause: "indexGetter",
79 path
80 });
81 return;
82 }
83 } else if (parentPath.node.property.name === "length") {
84 state.candidates.push({
85 cause: "lengthGetter",
86 path
87 });
88 return;
89 }
90 }
91 }
92 if (state.offset === 0 && parentPath.isSpreadElement()) {
93 const call = parentPath.parentPath;
94 if (call.isCallExpression() && call.node.arguments.length === 1) {
95 state.candidates.push({
96 cause: "argSpread",
97 path
98 });
99 return;
100 }
101 }
102 state.references.push(path);
103 }
104 },
105 BindingIdentifier(path, state) {
106 if (referencesRest(path, state)) {
107 state.deopted = true;
108 }
109 }
110};
111function getParamsCount(node) {
112 let count = node.params.length;
113 if (count > 0 && _core.types.isIdentifier(node.params[0], {
114 name: "this"
115 })) {
116 count -= 1;
117 }
118 return count;
119}
120function hasRest(node) {
121 const length = node.params.length;
122 return length > 0 && _core.types.isRestElement(node.params[length - 1]);
123}
124function optimiseIndexGetter(path, argsId, offset) {
125 const offsetLiteral = _core.types.numericLiteral(offset);
126 let index;
127 const parent = path.parent;
128 if (_core.types.isNumericLiteral(parent.property)) {
129 index = _core.types.numericLiteral(parent.property.value + offset);
130 } else if (offset === 0) {
131 index = parent.property;
132 } else {
133 index = _core.types.binaryExpression("+", parent.property, _core.types.cloneNode(offsetLiteral));
134 }
135 const {
136 scope,
137 parentPath
138 } = path;
139 if (!scope.isPure(index)) {
140 const temp = scope.generateUidIdentifierBasedOnNode(index);
141 scope.push({
142 id: temp,
143 kind: "var"
144 });
145 parentPath.replaceWith(restIndexImpure({
146 ARGUMENTS: argsId,
147 OFFSET: offsetLiteral,
148 INDEX: index,
149 REF: _core.types.cloneNode(temp)
150 }));
151 } else {
152 parentPath.replaceWith(restIndex({
153 ARGUMENTS: argsId,
154 OFFSET: offsetLiteral,
155 INDEX: index
156 }));
157 const replacedParentPath = parentPath;
158 const offsetTestPath = replacedParentPath.get("test");
159 const valRes = offsetTestPath.get("left").evaluate();
160 if (valRes.confident) {
161 if (valRes.value === true) {
162 replacedParentPath.replaceWith(scope.buildUndefinedNode());
163 } else {
164 offsetTestPath.replaceWith(offsetTestPath.get("right"));
165 }
166 }
167 }
168}
169function optimiseLengthGetter(path, argsId, offset) {
170 if (offset) {
171 path.parentPath.replaceWith(restLength({
172 ARGUMENTS: argsId,
173 OFFSET: _core.types.numericLiteral(offset)
174 }));
175 } else {
176 path.replaceWith(argsId);
177 }
178}
179function convertFunctionRest(path) {
180 const {
181 node,
182 scope
183 } = path;
184 if (!hasRest(node)) return false;
185 const restPath = path.get(`params.${node.params.length - 1}.argument`);
186 if (!restPath.isIdentifier()) {
187 const shadowedParams = new Set();
188 (0, _shadowUtils.collectShadowedParamsNames)(restPath, path.scope, shadowedParams);
189 let needsIIFE = shadowedParams.size > 0;
190 if (!needsIIFE) {
191 const state = {
192 needsOuterBinding: false,
193 scope
194 };
195 restPath.traverse(_shadowUtils.iifeVisitor, state);
196 needsIIFE = state.needsOuterBinding;
197 }
198 if (needsIIFE) {
199 path.ensureBlock();
200 path.set("body", _core.types.blockStatement([(0, _shadowUtils.buildScopeIIFE)(shadowedParams, path.node.body)]));
201 }
202 }
203 let rest = restPath.node;
204 node.params.pop();
205 if (_core.types.isPattern(rest)) {
206 const pattern = rest;
207 rest = scope.generateUidIdentifier("ref");
208 const declar = _core.types.variableDeclaration("let", [_core.types.variableDeclarator(pattern, rest)]);
209 path.ensureBlock();
210 node.body.body.unshift(declar);
211 } else if (rest.name === "arguments") {
212 scope.rename(rest.name);
213 }
214 const argsId = _core.types.identifier("arguments");
215 const paramsCount = getParamsCount(node);
216 const state = {
217 references: [],
218 offset: paramsCount,
219 argumentsNode: argsId,
220 outerBinding: scope.getBindingIdentifier(rest.name),
221 candidates: [],
222 name: rest.name,
223 deopted: false
224 };
225 path.traverse(memberExpressionOptimisationVisitor, state);
226 if (!state.deopted && !state.references.length) {
227 for (const {
228 path,
229 cause
230 } of state.candidates) {
231 const clonedArgsId = _core.types.cloneNode(argsId);
232 switch (cause) {
233 case "indexGetter":
234 optimiseIndexGetter(path, clonedArgsId, state.offset);
235 break;
236 case "lengthGetter":
237 optimiseLengthGetter(path, clonedArgsId, state.offset);
238 break;
239 default:
240 path.replaceWith(clonedArgsId);
241 }
242 }
243 return true;
244 }
245 state.references.push(...state.candidates.map(({
246 path
247 }) => path));
248 const start = _core.types.numericLiteral(paramsCount);
249 const key = scope.generateUidIdentifier("key");
250 const len = scope.generateUidIdentifier("len");
251 let arrKey, arrLen;
252 if (paramsCount) {
253 arrKey = _core.types.binaryExpression("-", _core.types.cloneNode(key), _core.types.cloneNode(start));
254 arrLen = _core.types.conditionalExpression(_core.types.binaryExpression(">", _core.types.cloneNode(len), _core.types.cloneNode(start)), _core.types.binaryExpression("-", _core.types.cloneNode(len), _core.types.cloneNode(start)), _core.types.numericLiteral(0));
255 } else {
256 arrKey = _core.types.identifier(key.name);
257 arrLen = _core.types.identifier(len.name);
258 }
259 const loop = buildRest({
260 ARGUMENTS: argsId,
261 ARRAY_KEY: arrKey,
262 ARRAY_LEN: arrLen,
263 START: start,
264 ARRAY: rest,
265 KEY: key,
266 LEN: len
267 });
268 if (state.deopted) {
269 node.body.body.unshift(loop);
270 } else {
271 let target = path.getEarliestCommonAncestorFrom(state.references).getStatementParent();
272 target.findParent(path => {
273 if (path.isLoop()) {
274 target = path;
275 } else {
276 return path.isFunction();
277 }
278 });
279 target.insertBefore(loop);
280 }
281 return true;
282}
283
284//# sourceMappingURL=rest.js.map
Note: See TracBrowser for help on using the repository browser.