123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- /**
- * 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.
- */
- /*global exports:true*/
- /**
- * Implements ES6 call spread.
- *
- * instance.method(a, b, c, ...d)
- *
- * instance.method.apply(instance, [a, b, c].concat(d))
- *
- */
- var Syntax = require('esprima-fb').Syntax;
- var utils = require('../src/utils');
- function process(traverse, node, path, state) {
- utils.move(node.range[0], state);
- traverse(node, path, state);
- utils.catchup(node.range[1], state);
- }
- function visitCallSpread(traverse, node, path, state) {
- utils.catchup(node.range[0], state);
- if (node.type === Syntax.NewExpression) {
- // Input = new Set(1, 2, ...list)
- // Output = new (Function.prototype.bind.apply(Set, [null, 1, 2].concat(list)))
- utils.append('new (Function.prototype.bind.apply(', state);
- process(traverse, node.callee, path, state);
- } else if (node.callee.type === Syntax.MemberExpression) {
- // Input = get().fn(1, 2, ...more)
- // Output = (_ = get()).fn.apply(_, [1, 2].apply(more))
- var tempVar = utils.injectTempVar(state);
- utils.append('(' + tempVar + ' = ', state);
- process(traverse, node.callee.object, path, state);
- utils.append(')', state);
- if (node.callee.property.type === Syntax.Identifier) {
- utils.append('.', state);
- process(traverse, node.callee.property, path, state);
- } else {
- utils.append('[', state);
- process(traverse, node.callee.property, path, state);
- utils.append(']', state);
- }
- utils.append('.apply(' + tempVar, state);
- } else {
- // Input = max(1, 2, ...list)
- // Output = max.apply(undefined, [1, 2].concat(list))
- var needsToBeWrappedInParenthesis =
- node.callee.type === Syntax.FunctionDeclaration ||
- node.callee.type === Syntax.FunctionExpression;
- if (needsToBeWrappedInParenthesis) {
- utils.append('(', state);
- }
- process(traverse, node.callee, path, state);
- if (needsToBeWrappedInParenthesis) {
- utils.append(')', state);
- }
- utils.append('.apply(undefined', state);
- }
- utils.append(', ', state);
- var args = node.arguments.slice();
- var spread = args.pop();
- if (args.length || node.type === Syntax.NewExpression) {
- utils.append('[', state);
- if (node.type === Syntax.NewExpression) {
- utils.append('null' + (args.length ? ', ' : ''), state);
- }
- while (args.length) {
- var arg = args.shift();
- utils.move(arg.range[0], state);
- traverse(arg, path, state);
- if (args.length) {
- utils.catchup(args[0].range[0], state);
- } else {
- utils.catchup(arg.range[1], state);
- }
- }
- utils.append('].concat(', state);
- process(traverse, spread.argument, path, state);
- utils.append(')', state);
- } else {
- process(traverse, spread.argument, path, state);
- }
- utils.append(node.type === Syntax.NewExpression ? '))' : ')', state);
- utils.move(node.range[1], state);
- return false;
- }
- visitCallSpread.test = function(node, path, state) {
- return (
- (
- node.type === Syntax.CallExpression ||
- node.type === Syntax.NewExpression
- ) &&
- node.arguments.length > 0 &&
- node.arguments[node.arguments.length - 1].type === Syntax.SpreadElement
- );
- };
- exports.visitorList = [
- visitCallSpread
- ];
|