You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					102 lines
				
				2.9 KiB
			
		
		
			
		
	
	
					102 lines
				
				2.9 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								"use strict";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
							 | 
						||
| 
								 | 
							
								var _assert = _interopRequireDefault(require("assert"));
							 | 
						||
| 
								 | 
							
								var _util = require("./util.js");
							 | 
						||
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * Copyright (c) 2014-present, Facebook, Inc.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This source code is licensed under the MIT license found in the
							 | 
						||
| 
								 | 
							
								 * LICENSE file in the root directory of this source tree.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								var mMap = new WeakMap();
							 | 
						||
| 
								 | 
							
								function m(node) {
							 | 
						||
| 
								 | 
							
								  if (!mMap.has(node)) {
							 | 
						||
| 
								 | 
							
								    mMap.set(node, {});
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return mMap.get(node);
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								var hasOwn = Object.prototype.hasOwnProperty;
							 | 
						||
| 
								 | 
							
								function makePredicate(propertyName, knownTypes) {
							 | 
						||
| 
								 | 
							
								  function onlyChildren(node) {
							 | 
						||
| 
								 | 
							
								    var t = (0, _util.getTypes)();
							 | 
						||
| 
								 | 
							
								    t.assertNode(node);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Assume no side effects until we find out otherwise.
							 | 
						||
| 
								 | 
							
								    var result = false;
							 | 
						||
| 
								 | 
							
								    function check(child) {
							 | 
						||
| 
								 | 
							
								      if (result) {
							 | 
						||
| 
								 | 
							
								        // Do nothing.
							 | 
						||
| 
								 | 
							
								      } else if (Array.isArray(child)) {
							 | 
						||
| 
								 | 
							
								        child.some(check);
							 | 
						||
| 
								 | 
							
								      } else if (t.isNode(child)) {
							 | 
						||
| 
								 | 
							
								        _assert["default"].strictEqual(result, false);
							 | 
						||
| 
								 | 
							
								        result = predicate(child);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      return result;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    var keys = t.VISITOR_KEYS[node.type];
							 | 
						||
| 
								 | 
							
								    if (keys) {
							 | 
						||
| 
								 | 
							
								      for (var i = 0; i < keys.length; i++) {
							 | 
						||
| 
								 | 
							
								        var key = keys[i];
							 | 
						||
| 
								 | 
							
								        var child = node[key];
							 | 
						||
| 
								 | 
							
								        check(child);
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return result;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  function predicate(node) {
							 | 
						||
| 
								 | 
							
								    (0, _util.getTypes)().assertNode(node);
							 | 
						||
| 
								 | 
							
								    var meta = m(node);
							 | 
						||
| 
								 | 
							
								    if (hasOwn.call(meta, propertyName)) return meta[propertyName];
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    // Certain types are "opaque," which means they have no side
							 | 
						||
| 
								 | 
							
								    // effects or leaps and we don't care about their subexpressions.
							 | 
						||
| 
								 | 
							
								    if (hasOwn.call(opaqueTypes, node.type)) return meta[propertyName] = false;
							 | 
						||
| 
								 | 
							
								    if (hasOwn.call(knownTypes, node.type)) return meta[propertyName] = true;
							 | 
						||
| 
								 | 
							
								    return meta[propertyName] = onlyChildren(node);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  predicate.onlyChildren = onlyChildren;
							 | 
						||
| 
								 | 
							
								  return predicate;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								var opaqueTypes = {
							 | 
						||
| 
								 | 
							
								  FunctionExpression: true,
							 | 
						||
| 
								 | 
							
								  ArrowFunctionExpression: true
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// These types potentially have side effects regardless of what side
							 | 
						||
| 
								 | 
							
								// effects their subexpressions have.
							 | 
						||
| 
								 | 
							
								var sideEffectTypes = {
							 | 
						||
| 
								 | 
							
								  CallExpression: true,
							 | 
						||
| 
								 | 
							
								  // Anything could happen!
							 | 
						||
| 
								 | 
							
								  ForInStatement: true,
							 | 
						||
| 
								 | 
							
								  // Modifies the key variable.
							 | 
						||
| 
								 | 
							
								  UnaryExpression: true,
							 | 
						||
| 
								 | 
							
								  // Think delete.
							 | 
						||
| 
								 | 
							
								  BinaryExpression: true,
							 | 
						||
| 
								 | 
							
								  // Might invoke .toString() or .valueOf().
							 | 
						||
| 
								 | 
							
								  AssignmentExpression: true,
							 | 
						||
| 
								 | 
							
								  // Side-effecting by definition.
							 | 
						||
| 
								 | 
							
								  UpdateExpression: true,
							 | 
						||
| 
								 | 
							
								  // Updates are essentially assignments.
							 | 
						||
| 
								 | 
							
								  NewExpression: true // Similar to CallExpression.
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// These types are the direct cause of all leaps in control flow.
							 | 
						||
| 
								 | 
							
								var leapTypes = {
							 | 
						||
| 
								 | 
							
								  YieldExpression: true,
							 | 
						||
| 
								 | 
							
								  BreakStatement: true,
							 | 
						||
| 
								 | 
							
								  ContinueStatement: true,
							 | 
						||
| 
								 | 
							
								  ReturnStatement: true,
							 | 
						||
| 
								 | 
							
								  ThrowStatement: true
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								// All leap types are also side effect types.
							 | 
						||
| 
								 | 
							
								for (var type in leapTypes) {
							 | 
						||
| 
								 | 
							
								  if (hasOwn.call(leapTypes, type)) {
							 | 
						||
| 
								 | 
							
								    sideEffectTypes[type] = leapTypes[type];
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								exports.hasSideEffects = makePredicate("hasSideEffects", sideEffectTypes);
							 | 
						||
| 
								 | 
							
								exports.containsLeap = makePredicate("containsLeap", leapTypes);
							 |