Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
80542 views
1
/**
2
* Copyright 2013 Facebook, Inc.
3
*
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
7
*
8
* http://www.apache.org/licenses/LICENSE-2.0
9
*
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
15
*/
16
17
/*jslint node:true*/
18
19
/**
20
* Desugars ES6 rest parameters into an ES3 arguments array.
21
*
22
* function printf(template, ...args) {
23
* args.forEach(...);
24
* }
25
*
26
* We could use `Array.prototype.slice.call`, but that usage of arguments causes
27
* functions to be deoptimized in V8, so instead we use a for-loop.
28
*
29
* function printf(template) {
30
* for (var args = [], $__0 = 1, $__1 = arguments.length; $__0 < $__1; $__0++)
31
* args.push(arguments[$__0]);
32
* args.forEach(...);
33
* }
34
*
35
*/
36
var Syntax = require('esprima-fb').Syntax;
37
var utils = require('../src/utils');
38
39
40
41
function _nodeIsFunctionWithRestParam(node) {
42
return (node.type === Syntax.FunctionDeclaration
43
|| node.type === Syntax.FunctionExpression
44
|| node.type === Syntax.ArrowFunctionExpression)
45
&& node.rest;
46
}
47
48
function visitFunctionParamsWithRestParam(traverse, node, path, state) {
49
if (node.parametricType) {
50
utils.catchup(node.parametricType.range[0], state);
51
path.unshift(node);
52
traverse(node.parametricType, path, state);
53
path.shift();
54
}
55
56
// Render params.
57
if (node.params.length) {
58
path.unshift(node);
59
traverse(node.params, path, state);
60
path.shift();
61
} else {
62
// -3 is for ... of the rest.
63
utils.catchup(node.rest.range[0] - 3, state);
64
}
65
utils.catchupWhiteSpace(node.rest.range[1], state);
66
67
path.unshift(node);
68
traverse(node.body, path, state);
69
path.shift();
70
71
return false;
72
}
73
74
visitFunctionParamsWithRestParam.test = function(node, path, state) {
75
return _nodeIsFunctionWithRestParam(node);
76
};
77
78
function renderRestParamSetup(functionNode, state) {
79
var idx = state.localScope.tempVarIndex++;
80
var len = state.localScope.tempVarIndex++;
81
82
return 'for (var ' + functionNode.rest.name + '=[],' +
83
utils.getTempVar(idx) + '=' + functionNode.params.length + ',' +
84
utils.getTempVar(len) + '=arguments.length;' +
85
utils.getTempVar(idx) + '<' + utils.getTempVar(len) + ';' +
86
utils.getTempVar(idx) + '++) ' +
87
functionNode.rest.name + '.push(arguments[' + utils.getTempVar(idx) + ']);';
88
}
89
90
function visitFunctionBodyWithRestParam(traverse, node, path, state) {
91
utils.catchup(node.range[0] + 1, state);
92
var parentNode = path[0];
93
utils.append(renderRestParamSetup(parentNode, state), state);
94
return true;
95
}
96
97
visitFunctionBodyWithRestParam.test = function(node, path, state) {
98
return node.type === Syntax.BlockStatement
99
&& _nodeIsFunctionWithRestParam(path[0]);
100
};
101
102
exports.renderRestParamSetup = renderRestParamSetup;
103
exports.visitorList = [
104
visitFunctionParamsWithRestParam,
105
visitFunctionBodyWithRestParam
106
];
107
108