123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- /**
- * Copyright 2013-present, Facebook, Inc.
- * All rights reserved.
- *
- * This source code is licensed under the BSD-style license found in the
- * LICENSE file in the root directory of this source tree. An additional grant
- * of patent rights can be found in the PATENTS file in the same directory.
- */
- /*jslint node:true*/
- /**
- * Desugars ES6 rest parameters into an ES3 arguments array.
- *
- * function printf(template, ...args) {
- * args.forEach(...);
- * }
- *
- * We could use `Array.prototype.slice.call`, but that usage of arguments causes
- * functions to be deoptimized in V8, so instead we use a for-loop.
- *
- * function printf(template) {
- * for (var args = [], $__0 = 1, $__1 = arguments.length; $__0 < $__1; $__0++)
- * args.push(arguments[$__0]);
- * args.forEach(...);
- * }
- *
- */
- var Syntax = require('esprima-fb').Syntax;
- var utils = require('../src/utils');
- function _nodeIsFunctionWithRestParam(node) {
- return (node.type === Syntax.FunctionDeclaration
- || node.type === Syntax.FunctionExpression
- || node.type === Syntax.ArrowFunctionExpression)
- && node.rest;
- }
- function visitFunctionParamsWithRestParam(traverse, node, path, state) {
- if (node.parametricType) {
- utils.catchup(node.parametricType.range[0], state);
- path.unshift(node);
- traverse(node.parametricType, path, state);
- path.shift();
- }
- // Render params.
- if (node.params.length) {
- path.unshift(node);
- traverse(node.params, path, state);
- path.shift();
- } else {
- // -3 is for ... of the rest.
- utils.catchup(node.rest.range[0] - 3, state);
- }
- utils.catchupWhiteSpace(node.rest.range[1], state);
- utils.catchup(node.body.range[0], state);
- path.unshift(node);
- traverse(node.body, path, state);
- path.shift();
- return false;
- }
- visitFunctionParamsWithRestParam.test = function(node, path, state) {
- return _nodeIsFunctionWithRestParam(node);
- };
- function renderRestParamSetup(functionNode, state) {
- var idx = state.localScope.tempVarIndex++;
- var len = state.localScope.tempVarIndex++;
- return 'for (var ' + functionNode.rest.name + '=[],' +
- utils.getTempVar(idx) + '=' + functionNode.params.length + ',' +
- utils.getTempVar(len) + '=arguments.length;' +
- utils.getTempVar(idx) + '<' + utils.getTempVar(len) + ';' +
- utils.getTempVar(idx) + '++) ' +
- functionNode.rest.name + '.push(arguments[' + utils.getTempVar(idx) + ']);';
- }
- function visitFunctionBodyWithRestParam(traverse, node, path, state) {
- utils.catchup(node.range[0] + 1, state);
- var parentNode = path[0];
- utils.append(renderRestParamSetup(parentNode, state), state);
- return true;
- }
- visitFunctionBodyWithRestParam.test = function(node, path, state) {
- return node.type === Syntax.BlockStatement
- && _nodeIsFunctionWithRestParam(path[0]);
- };
- exports.renderRestParamSetup = renderRestParamSetup;
- exports.visitorList = [
- visitFunctionParamsWithRestParam,
- visitFunctionBodyWithRestParam
- ];
|