1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 | export default function fastRestTransform({ template, types: t }) {
|
15 | const slice = template`var IDENT = Array.prototype.slice;`;
|
16 |
|
17 | const VISITOR = {
|
18 | RestElement(path, state) {
|
19 | if (path.parentKey !== 'params') return;
|
20 |
|
21 |
|
22 | let slice = state.get('slice');
|
23 | if (!slice) {
|
24 | slice = path.scope.generateUidIdentifier('slice');
|
25 | state.set('slice', slice);
|
26 | }
|
27 |
|
28 |
|
29 | const args = [t.identifier('arguments')];
|
30 | if (path.key) args.push(t.numericLiteral(path.key));
|
31 | const sliced = t.callExpression(
|
32 | t.memberExpression(t.clone(slice), t.identifier('call')),
|
33 | args,
|
34 | );
|
35 |
|
36 | const ident = path.node.argument;
|
37 | const binding = path.scope.getBinding(ident.name);
|
38 |
|
39 | if (binding.referencePaths.length !== 0) {
|
40 |
|
41 | const func = path.parentPath;
|
42 | if (t.isArrowFunctionExpression(func)) {
|
43 | func.arrowFunctionToExpression();
|
44 | }
|
45 |
|
46 | if (binding.constant && binding.referencePaths.length === 1) {
|
47 |
|
48 | binding.referencePaths[0].replaceWith(sliced);
|
49 | } else {
|
50 |
|
51 | const decl = t.variableDeclaration('var', [
|
52 | t.variableDeclarator(t.clone(ident), sliced),
|
53 | ]);
|
54 | func.get('body').unshiftContainer('body', decl);
|
55 | }
|
56 | }
|
57 |
|
58 | path.remove();
|
59 | },
|
60 | };
|
61 |
|
62 | return {
|
63 | name: 'transform-fast-rest',
|
64 | visitor: {
|
65 | Program(path, state) {
|
66 | const childState = new Map();
|
67 | const useHelper = state.opts.helper === true;
|
68 |
|
69 | if (!useHelper) {
|
70 | let inlineHelper;
|
71 | if (state.opts.literal === false) {
|
72 | inlineHelper = template.expression.ast`Array.prototype.slice`;
|
73 | } else {
|
74 | inlineHelper = template.expression.ast`[].slice`;
|
75 | }
|
76 | childState.set('slice', inlineHelper);
|
77 | }
|
78 |
|
79 | path.traverse(VISITOR, childState);
|
80 |
|
81 | const name = childState.get('slice');
|
82 | if (name && useHelper) {
|
83 | const helper = slice({ IDENT: name });
|
84 | t.addComment(helper.declarations[0].init, 'leading', '#__PURE__');
|
85 | path.unshiftContainer('body', helper);
|
86 | }
|
87 | },
|
88 | },
|
89 | };
|
90 | }
|