| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | /* | 
					
						
							|  |  |  | 	MIT License http://www.opensource.org/licenses/mit-license.php
 | 
					
						
							|  |  |  | 	Author Tobias Koppers @sokra | 
					
						
							|  |  |  | */ | 
					
						
							| 
									
										
										
										
											2015-03-05 12:32:09 +08:00
										 |  |  | var acorn = require("acorn"); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | var Tapable = require("tapable"); | 
					
						
							|  |  |  | var BasicEvaluatedExpression = require("./BasicEvaluatedExpression"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function Parser(options) { | 
					
						
							|  |  |  | 	Tapable.call(this); | 
					
						
							|  |  |  | 	this.options = options; | 
					
						
							|  |  |  | 	this.initializeEvaluating(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | module.exports = Parser; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Syntax: https://developer.mozilla.org/en/SpiderMonkey/Parser_API
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype = Object.create(Tapable.prototype); | 
					
						
							| 
									
										
										
										
											2015-08-18 19:35:57 +08:00
										 |  |  | Parser.prototype.constructor = Parser; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | Parser.prototype.initializeEvaluating = function() { | 
					
						
							|  |  |  | 	function joinRanges(startRange, endRange) { | 
					
						
							|  |  |  | 		if(!endRange) return startRange; | 
					
						
							|  |  |  | 		if(!startRange) return endRange; | 
					
						
							|  |  |  | 		return [startRange[0], endRange[1]]; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	this.plugin("evaluate Literal", function(expr) { | 
					
						
							|  |  |  | 		switch(typeof expr.value) { | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 			case "number": | 
					
						
							|  |  |  | 				return new BasicEvaluatedExpression().setNumber(expr.value).setRange(expr.range); | 
					
						
							|  |  |  | 			case "string": | 
					
						
							|  |  |  | 				return new BasicEvaluatedExpression().setString(expr.value).setRange(expr.range); | 
					
						
							|  |  |  | 			case "boolean": | 
					
						
							|  |  |  | 				return new BasicEvaluatedExpression().setBoolean(expr.value).setRange(expr.range); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-12-22 16:32:42 +08:00
										 |  |  | 		if(expr.value === null) | 
					
						
							|  |  |  | 			return new BasicEvaluatedExpression().setNull().setRange(expr.range); | 
					
						
							| 
									
										
										
										
											2013-02-26 01:18:49 +08:00
										 |  |  | 		if(expr.value instanceof RegExp) | 
					
						
							|  |  |  | 			return new BasicEvaluatedExpression().setRegExp(expr.value).setRange(expr.range); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2013-11-08 16:00:39 +08:00
										 |  |  | 	this.plugin("evaluate LogicalExpression", function(expr) { | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 		var left; | 
					
						
							|  |  |  | 		var leftAsBool; | 
					
						
							|  |  |  | 		var right; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		if(expr.operator === "&&") { | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 			left = this.evaluateExpression(expr.left); | 
					
						
							|  |  |  | 			leftAsBool = left && left.asBool(); | 
					
						
							| 
									
										
										
										
											2014-03-20 05:16:17 +08:00
										 |  |  | 			if(leftAsBool === false) return left.setRange(expr.range); | 
					
						
							| 
									
										
										
										
											2013-11-08 16:00:39 +08:00
										 |  |  | 			if(leftAsBool !== true) return; | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 			right = this.evaluateExpression(expr.right); | 
					
						
							| 
									
										
										
										
											2014-03-20 05:16:17 +08:00
										 |  |  | 			return right.setRange(expr.range); | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		} else if(expr.operator === "||") { | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 			left = this.evaluateExpression(expr.left); | 
					
						
							|  |  |  | 			leftAsBool = left && left.asBool(); | 
					
						
							| 
									
										
										
										
											2014-03-20 05:16:17 +08:00
										 |  |  | 			if(leftAsBool === true) return left.setRange(expr.range); | 
					
						
							| 
									
										
										
										
											2013-11-08 16:00:39 +08:00
										 |  |  | 			if(leftAsBool !== false) return; | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 			right = this.evaluateExpression(expr.right); | 
					
						
							| 
									
										
										
										
											2014-03-20 05:16:17 +08:00
										 |  |  | 			return right.setRange(expr.range); | 
					
						
							| 
									
										
										
										
											2013-11-08 16:00:39 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 	this.plugin("evaluate BinaryExpression", function(expr) { | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 		var left; | 
					
						
							|  |  |  | 		var right; | 
					
						
							|  |  |  | 		var res; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		if(expr.operator === "+") { | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 			left = this.evaluateExpression(expr.left); | 
					
						
							|  |  |  | 			right = this.evaluateExpression(expr.right); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 			if(!left || !right) return; | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 			res = new BasicEvaluatedExpression(); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 			if(left.isString()) { | 
					
						
							|  |  |  | 				if(right.isString()) { | 
					
						
							|  |  |  | 					res.setString(left.string + right.string); | 
					
						
							|  |  |  | 				} else if(right.isNumber()) { | 
					
						
							|  |  |  | 					res.setString(left.string + right.number); | 
					
						
							| 
									
										
										
										
											2015-02-28 07:51:15 +08:00
										 |  |  | 				} else if(right.isWrapped() && right.prefix && right.prefix.isString()) { | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 					res.setWrapped( | 
					
						
							|  |  |  | 						new BasicEvaluatedExpression() | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 						.setString(left.string + right.prefix.string) | 
					
						
							|  |  |  | 						.setRange(joinRanges(left.range, right.prefix.range)), | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 						right.postfix); | 
					
						
							|  |  |  | 				} else { | 
					
						
							| 
									
										
										
										
											2015-04-24 05:55:50 +08:00
										 |  |  | 					res.setWrapped(left, null); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} else if(left.isNumber()) { | 
					
						
							|  |  |  | 				if(right.isString()) { | 
					
						
							|  |  |  | 					res.setString(left.number + right.string); | 
					
						
							|  |  |  | 				} else if(right.isNumber()) { | 
					
						
							|  |  |  | 					res.setNumber(left.number + right.number); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2014-07-07 19:20:38 +08:00
										 |  |  | 			} else if(left.isWrapped()) { | 
					
						
							| 
									
										
										
										
											2015-02-28 07:51:15 +08:00
										 |  |  | 				if(left.postfix && left.postfix.isString() && right.isString()) { | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 					res.setWrapped(left.prefix, | 
					
						
							|  |  |  | 						new BasicEvaluatedExpression() | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 						.setString(left.postfix.string + right.string) | 
					
						
							|  |  |  | 						.setRange(joinRanges(left.postfix.range, right.range)) | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 					); | 
					
						
							| 
									
										
										
										
											2015-02-28 07:51:15 +08:00
										 |  |  | 				} else if(left.postfix && left.postfix.isString() && right.isNumber()) { | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 					res.setWrapped(left.prefix, | 
					
						
							|  |  |  | 						new BasicEvaluatedExpression() | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 						.setString(left.postfix.string + right.number) | 
					
						
							|  |  |  | 						.setRange(joinRanges(left.postfix.range, right.range)) | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 					); | 
					
						
							| 
									
										
										
										
											2014-07-07 19:20:38 +08:00
										 |  |  | 				} else if(right.isString()) { | 
					
						
							|  |  |  | 					res.setWrapped(left.prefix, right); | 
					
						
							|  |  |  | 				} else if(right.isNumber()) { | 
					
						
							|  |  |  | 					res.setWrapped(left.prefix, | 
					
						
							|  |  |  | 						new BasicEvaluatedExpression() | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 						.setString(right.number + "") | 
					
						
							|  |  |  | 						.setRange(right.range)); | 
					
						
							| 
									
										
										
										
											2014-07-07 19:20:38 +08:00
										 |  |  | 				} else { | 
					
						
							|  |  |  | 					res.setWrapped(left.prefix, new BasicEvaluatedExpression()); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				if(right.isString()) { | 
					
						
							| 
									
										
										
										
											2015-02-28 07:51:15 +08:00
										 |  |  | 					res.setWrapped(null, right); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			res.setRange(expr.range); | 
					
						
							|  |  |  | 			return res; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		} else if(expr.operator === "-") { | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 			left = this.evaluateExpression(expr.left); | 
					
						
							|  |  |  | 			right = this.evaluateExpression(expr.right); | 
					
						
							| 
									
										
										
										
											2013-09-24 21:17:25 +08:00
										 |  |  | 			if(!left || !right) return; | 
					
						
							|  |  |  | 			if(!left.isNumber() || !right.isNumber()) return; | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 			res = new BasicEvaluatedExpression(); | 
					
						
							| 
									
										
										
										
											2013-09-24 21:17:25 +08:00
										 |  |  | 			res.setNumber(left.number - right.number); | 
					
						
							|  |  |  | 			res.setRange(expr.range); | 
					
						
							|  |  |  | 			return res; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		} else if(expr.operator === "*") { | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 			left = this.evaluateExpression(expr.left); | 
					
						
							|  |  |  | 			right = this.evaluateExpression(expr.right); | 
					
						
							| 
									
										
										
										
											2013-09-24 21:17:25 +08:00
										 |  |  | 			if(!left || !right) return; | 
					
						
							|  |  |  | 			if(!left.isNumber() || !right.isNumber()) return; | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 			res = new BasicEvaluatedExpression(); | 
					
						
							| 
									
										
										
										
											2013-09-24 21:17:25 +08:00
										 |  |  | 			res.setNumber(left.number * right.number); | 
					
						
							|  |  |  | 			res.setRange(expr.range); | 
					
						
							|  |  |  | 			return res; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		} else if(expr.operator === "/") { | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 			left = this.evaluateExpression(expr.left); | 
					
						
							|  |  |  | 			right = this.evaluateExpression(expr.right); | 
					
						
							| 
									
										
										
										
											2013-09-24 21:17:25 +08:00
										 |  |  | 			if(!left || !right) return; | 
					
						
							|  |  |  | 			if(!left.isNumber() || !right.isNumber()) return; | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 			res = new BasicEvaluatedExpression(); | 
					
						
							| 
									
										
										
										
											2013-09-24 21:17:25 +08:00
										 |  |  | 			res.setNumber(left.number / right.number); | 
					
						
							|  |  |  | 			res.setRange(expr.range); | 
					
						
							|  |  |  | 			return res; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		} else if(expr.operator === "==" || expr.operator === "===") { | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 			left = this.evaluateExpression(expr.left); | 
					
						
							|  |  |  | 			right = this.evaluateExpression(expr.right); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 			if(!left || !right) return; | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 			res = new BasicEvaluatedExpression(); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 			res.setRange(expr.range); | 
					
						
							|  |  |  | 			if(left.isString() && right.isString()) { | 
					
						
							|  |  |  | 				return res.setBoolean(left.string === right.string); | 
					
						
							|  |  |  | 			} else if(left.isNumber() && right.isNumber()) { | 
					
						
							|  |  |  | 				return res.setBoolean(left.number === right.number); | 
					
						
							|  |  |  | 			} else if(left.isBoolean() && right.isBoolean()) { | 
					
						
							|  |  |  | 				return res.setBoolean(left.bool === right.bool); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		} else if(expr.operator === "!=" || expr.operator === "!==") { | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 			left = this.evaluateExpression(expr.left); | 
					
						
							|  |  |  | 			right = this.evaluateExpression(expr.right); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 			if(!left || !right) return; | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 			res = new BasicEvaluatedExpression(); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 			res.setRange(expr.range); | 
					
						
							|  |  |  | 			if(left.isString() && right.isString()) { | 
					
						
							|  |  |  | 				return res.setBoolean(left.string !== right.string); | 
					
						
							|  |  |  | 			} else if(left.isNumber() && right.isNumber()) { | 
					
						
							|  |  |  | 				return res.setBoolean(left.number !== right.number); | 
					
						
							|  |  |  | 			} else if(left.isBoolean() && right.isBoolean()) { | 
					
						
							|  |  |  | 				return res.setBoolean(left.bool !== right.bool); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | 	this.plugin("evaluate UnaryExpression", function(expr) { | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		if(expr.operator === "typeof") { | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 			var res; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 			if(expr.argument.type === "Identifier") { | 
					
						
							| 
									
										
										
										
											2015-04-24 05:55:50 +08:00
										 |  |  | 				var name = this.scope.renames["$" + expr.argument.name] || expr.argument.name; | 
					
						
							| 
									
										
										
										
											2014-10-07 21:15:09 +08:00
										 |  |  | 				if(this.scope.definitions.indexOf(name) === -1) { | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 					res = this.applyPluginsBailResult("evaluate typeof " + name, expr); | 
					
						
							| 
									
										
										
										
											2014-10-07 21:15:09 +08:00
										 |  |  | 					if(res !== undefined) return res; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2013-09-24 20:49:39 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 			if(expr.argument.type === "MemberExpression") { | 
					
						
							| 
									
										
										
										
											2013-09-24 21:09:08 +08:00
										 |  |  | 				var expression = expr.argument; | 
					
						
							|  |  |  | 				var exprName = []; | 
					
						
							| 
									
										
										
										
											2014-12-16 15:12:30 +08:00
										 |  |  | 				while(expression.type === "MemberExpression" && !expression.computed) { | 
					
						
							| 
									
										
										
										
											2015-04-24 05:55:50 +08:00
										 |  |  | 					exprName.unshift(this.scope.renames["$" + expression.property.name] || expression.property.name); | 
					
						
							| 
									
										
										
										
											2013-09-24 21:09:08 +08:00
										 |  |  | 					expression = expression.object; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2014-10-07 21:15:09 +08:00
										 |  |  | 				if(expression.type === "Identifier") { | 
					
						
							| 
									
										
										
										
											2015-04-24 05:55:50 +08:00
										 |  |  | 					exprName.unshift(this.scope.renames["$" + expression.name] || expression.name); | 
					
						
							| 
									
										
										
										
											2014-10-07 21:15:09 +08:00
										 |  |  | 					if(this.scope.definitions.indexOf(name) === -1) { | 
					
						
							|  |  |  | 						exprName = exprName.join("."); | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 						res = this.applyPluginsBailResult("evaluate typeof " + exprName, expr); | 
					
						
							| 
									
										
										
										
											2014-10-07 21:15:09 +08:00
										 |  |  | 						if(res !== undefined) return res; | 
					
						
							|  |  |  | 					} | 
					
						
							| 
									
										
										
										
											2013-09-24 21:09:08 +08:00
										 |  |  | 				} | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 			if(expr.argument.type === "FunctionExpression") { | 
					
						
							| 
									
										
										
										
											2013-09-24 21:09:08 +08:00
										 |  |  | 				return new BasicEvaluatedExpression().setString("function").setRange(expr.range); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2013-09-24 20:49:39 +08:00
										 |  |  | 			var arg = this.evaluateExpression(expr.argument); | 
					
						
							|  |  |  | 			if(arg.isString() || arg.isWrapped()) return new BasicEvaluatedExpression().setString("string").setRange(expr.range); | 
					
						
							|  |  |  | 			else if(arg.isNumber()) return new BasicEvaluatedExpression().setString("number").setRange(expr.range); | 
					
						
							|  |  |  | 			else if(arg.isBoolean()) return new BasicEvaluatedExpression().setString("boolean").setRange(expr.range); | 
					
						
							| 
									
										
										
										
											2015-02-21 20:19:08 +08:00
										 |  |  | 			else if(arg.isArray() || arg.isConstArray() || arg.isRegExp()) return new BasicEvaluatedExpression().setString("object").setRange(expr.range); | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		} else if(expr.operator === "!") { | 
					
						
							| 
									
										
										
										
											2013-02-08 07:18:47 +08:00
										 |  |  | 			var argument = this.evaluateExpression(expr.argument); | 
					
						
							|  |  |  | 			if(!argument) return; | 
					
						
							|  |  |  | 			if(argument.isBoolean()) { | 
					
						
							|  |  |  | 				return new BasicEvaluatedExpression().setBoolean(!argument.bool).setRange(expr.range); | 
					
						
							|  |  |  | 			} else if(argument.isString()) { | 
					
						
							|  |  |  | 				return new BasicEvaluatedExpression().setBoolean(!argument.string).setRange(expr.range); | 
					
						
							|  |  |  | 			} else if(argument.isNumber()) { | 
					
						
							|  |  |  | 				return new BasicEvaluatedExpression().setBoolean(!argument.number).setRange(expr.range); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2015-02-21 20:19:08 +08:00
										 |  |  | 	this.plugin("evaluate typeof undefined", function(expr) { | 
					
						
							|  |  |  | 		return new BasicEvaluatedExpression().setString("undefined").setRange(expr.range); | 
					
						
							|  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 	this.plugin("evaluate Identifier", function(expr) { | 
					
						
							| 
									
										
										
										
											2015-04-24 05:55:50 +08:00
										 |  |  | 		var name = this.scope.renames["$" + expr.name] || expr.name; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		if(this.scope.definitions.indexOf(expr.name) === -1) { | 
					
						
							| 
									
										
										
										
											2014-01-31 17:57:28 +08:00
										 |  |  | 			var result = this.applyPluginsBailResult("evaluate Identifier " + name, expr); | 
					
						
							| 
									
										
										
										
											2013-11-08 16:00:39 +08:00
										 |  |  | 			if(result) return result; | 
					
						
							| 
									
										
										
										
											2014-01-31 17:57:28 +08:00
										 |  |  | 			return new BasicEvaluatedExpression().setIdentifier(name).setRange(expr.range); | 
					
						
							| 
									
										
										
										
											2013-11-08 16:00:39 +08:00
										 |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2014-01-31 17:57:28 +08:00
										 |  |  | 			return this.applyPluginsBailResult("evaluate defined Identifier " + name, expr); | 
					
						
							| 
									
										
										
										
											2013-11-08 16:00:39 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2013-06-19 19:49:57 +08:00
										 |  |  | 	this.plugin("evaluate MemberExpression", function(expression) { | 
					
						
							|  |  |  | 		var expr = expression; | 
					
						
							|  |  |  | 		var exprName = []; | 
					
						
							| 
									
										
										
										
											2016-06-04 18:06:10 +08:00
										 |  |  | 		while(expr.type === "MemberExpression" && | 
					
						
							|  |  |  | 			expr.property.type === (expr.computed ? "Literal" : "Identifier") | 
					
						
							|  |  |  | 		) { | 
					
						
							|  |  |  | 			exprName.unshift(expr.property.name || expr.property.value); | 
					
						
							| 
									
										
										
										
											2013-06-19 19:49:57 +08:00
										 |  |  | 			expr = expr.object; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		if(expr.type === "Identifier") { | 
					
						
							| 
									
										
										
										
											2015-04-24 05:55:50 +08:00
										 |  |  | 			var name = this.scope.renames["$" + expr.name] || expr.name; | 
					
						
							| 
									
										
										
										
											2014-10-07 21:15:09 +08:00
										 |  |  | 			if(this.scope.definitions.indexOf(name) === -1) { | 
					
						
							|  |  |  | 				exprName.unshift(name); | 
					
						
							|  |  |  | 				exprName = exprName.join("."); | 
					
						
							|  |  |  | 				if(this.scope.definitions.indexOf(expr.name) === -1) { | 
					
						
							|  |  |  | 					var result = this.applyPluginsBailResult("evaluate Identifier " + exprName, expression); | 
					
						
							|  |  |  | 					if(result) return result; | 
					
						
							|  |  |  | 					return new BasicEvaluatedExpression().setIdentifier(exprName).setRange(expression.range); | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					return this.applyPluginsBailResult("evaluate defined Identifier " + exprName, expression); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2013-11-08 16:00:39 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2013-06-19 19:49:57 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2013-02-17 05:23:22 +08:00
										 |  |  | 	this.plugin("evaluate CallExpression", function(expr) { | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		if(expr.callee.type !== "MemberExpression") return; | 
					
						
							| 
									
										
										
										
											2016-06-04 18:06:10 +08:00
										 |  |  | 		if(expr.callee.property.type !== (expr.callee.computed ? "Literal" : "Identifier")) return; | 
					
						
							| 
									
										
										
										
											2013-02-17 05:23:22 +08:00
										 |  |  | 		var param = this.evaluateExpression(expr.callee.object); | 
					
						
							|  |  |  | 		if(!param) return; | 
					
						
							| 
									
										
										
										
											2016-06-04 18:06:10 +08:00
										 |  |  | 		var property = expr.callee.property.name || expr.callee.property.value; | 
					
						
							|  |  |  | 		return this.applyPluginsBailResult("evaluate CallExpression ." + property, expr, param); | 
					
						
							| 
									
										
										
										
											2013-02-17 05:23:22 +08:00
										 |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2013-12-08 21:59:52 +08:00
										 |  |  | 	this.plugin("evaluate CallExpression .replace", function(expr, param) { | 
					
						
							|  |  |  | 		if(!param.isString()) return; | 
					
						
							|  |  |  | 		if(expr.arguments.length !== 2) return; | 
					
						
							|  |  |  | 		var arg1 = this.evaluateExpression(expr.arguments[0]); | 
					
						
							|  |  |  | 		var arg2 = this.evaluateExpression(expr.arguments[1]); | 
					
						
							|  |  |  | 		if(!arg1.isString() && !arg1.isRegExp()) return; | 
					
						
							|  |  |  | 		arg1 = arg1.regExp || arg1.string; | 
					
						
							|  |  |  | 		if(!arg2.isString()) return; | 
					
						
							|  |  |  | 		arg2 = arg2.string; | 
					
						
							|  |  |  | 		return new BasicEvaluatedExpression().setString(param.string.replace(arg1, arg2)).setRange(expr.range); | 
					
						
							|  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 	["substr", "substring"].forEach(function(fn) { | 
					
						
							|  |  |  | 		this.plugin("evaluate CallExpression ." + fn, function(expr, param) { | 
					
						
							|  |  |  | 			if(!param.isString()) return; | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 			var arg1; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 			var result, str = param.string; | 
					
						
							|  |  |  | 			switch(expr.arguments.length) { | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 				case 1: | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 					arg1 = this.evaluateExpression(expr.arguments[0]); | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 					if(!arg1.isNumber()) return; | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 					result = str[fn](arg1.number); | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				case 2: | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 					arg1 = this.evaluateExpression(expr.arguments[0]); | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 					var arg2 = this.evaluateExpression(expr.arguments[1]); | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 					if(!arg1.isNumber()) return; | 
					
						
							|  |  |  | 					if(!arg2.isNumber()) return; | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 					result = str[fn](arg1.number, arg2.number); | 
					
						
							|  |  |  | 					break; | 
					
						
							|  |  |  | 				default: | 
					
						
							|  |  |  | 					return; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			return new BasicEvaluatedExpression().setString(result).setRange(expr.range); | 
					
						
							|  |  |  | 		}); | 
					
						
							|  |  |  | 	}, this); | 
					
						
							| 
									
										
										
										
											2013-12-08 21:59:52 +08:00
										 |  |  | 	this.plugin("evaluate CallExpression .split", function(expr, param) { | 
					
						
							|  |  |  | 		if(!param.isString()) return; | 
					
						
							|  |  |  | 		if(expr.arguments.length !== 1) return; | 
					
						
							|  |  |  | 		var result; | 
					
						
							|  |  |  | 		var arg = this.evaluateExpression(expr.arguments[0]); | 
					
						
							|  |  |  | 		if(arg.isString()) { | 
					
						
							|  |  |  | 			result = param.string.split(arg.string); | 
					
						
							|  |  |  | 		} else if(arg.isRegExp()) { | 
					
						
							|  |  |  | 			result = param.string.split(arg.regExp); | 
					
						
							|  |  |  | 		} else return; | 
					
						
							|  |  |  | 		return new BasicEvaluatedExpression().setArray(result).setRange(expr.range); | 
					
						
							|  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 	this.plugin("evaluate ConditionalExpression", function(expr) { | 
					
						
							| 
									
										
										
										
											2013-09-13 17:17:57 +08:00
										 |  |  | 		var condition = this.evaluateExpression(expr.test); | 
					
						
							|  |  |  | 		var conditionValue = condition.asBool(); | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 		var res; | 
					
						
							| 
									
										
										
										
											2013-09-13 17:17:57 +08:00
										 |  |  | 		if(conditionValue === undefined) { | 
					
						
							|  |  |  | 			var consequent = this.evaluateExpression(expr.consequent); | 
					
						
							|  |  |  | 			var alternate = this.evaluateExpression(expr.alternate); | 
					
						
							|  |  |  | 			if(!consequent || !alternate) return; | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 			res = new BasicEvaluatedExpression(); | 
					
						
							| 
									
										
										
										
											2013-09-13 17:17:57 +08:00
										 |  |  | 			if(consequent.isConditional()) | 
					
						
							|  |  |  | 				res.setOptions(consequent.options); | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				res.setOptions([consequent]); | 
					
						
							|  |  |  | 			if(alternate.isConditional()) | 
					
						
							|  |  |  | 				res.addOptions(alternate.options); | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				res.addOptions([alternate]); | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 			res = this.evaluateExpression(conditionValue ? expr.consequent : expr.alternate); | 
					
						
							| 
									
										
										
										
											2013-09-13 17:17:57 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 		res.setRange(expr.range); | 
					
						
							|  |  |  | 		return res; | 
					
						
							|  |  |  | 	}); | 
					
						
							|  |  |  | 	this.plugin("evaluate ArrayExpression", function(expr) { | 
					
						
							|  |  |  | 		var items = expr.elements.map(function(element) { | 
					
						
							| 
									
										
										
										
											2014-08-19 09:59:35 +08:00
										 |  |  | 			return element !== null && this.evaluateExpression(element); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 		}, this); | 
					
						
							| 
									
										
										
										
											2016-06-21 03:46:27 +08:00
										 |  |  | 		if(!items.every(Boolean)) return; | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 		return new BasicEvaluatedExpression().setItems(items).setRange(expr.range); | 
					
						
							|  |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2014-03-20 05:16:17 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.getRenameIdentifier = function getRenameIdentifier(expr) { | 
					
						
							|  |  |  | 	var result = this.evaluateExpression(expr); | 
					
						
							|  |  |  | 	if(!result) return; | 
					
						
							|  |  |  | 	if(result.isIdentifier()) return result.identifier; | 
					
						
							|  |  |  | 	return; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-22 00:14:47 +08:00
										 |  |  | Parser.prototype.walkClass = function walkClass(classy) { | 
					
						
							|  |  |  | 	if(classy.superClass) | 
					
						
							|  |  |  | 		this.walkExpression(classy.superClass); | 
					
						
							|  |  |  | 	if(classy.body && classy.body.type === "ClassBody") { | 
					
						
							|  |  |  | 		classy.body.body.forEach(function(methodDefinition) { | 
					
						
							|  |  |  | 			if(methodDefinition.type === "MethodDefinition") | 
					
						
							|  |  |  | 				this.walkMethodDefinition(methodDefinition); | 
					
						
							|  |  |  | 		}, this); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkMethodDefinition = function walkMethodDefinition(methodDefinition) { | 
					
						
							|  |  |  | 	if(methodDefinition.computed && methodDefinition.key) | 
					
						
							|  |  |  | 		this.walkExpression(methodDefinition.key); | 
					
						
							|  |  |  | 	if(methodDefinition.value) | 
					
						
							|  |  |  | 		this.walkExpression(methodDefinition.value); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | Parser.prototype.walkStatements = function walkStatements(statements) { | 
					
						
							|  |  |  | 	statements.forEach(function(statement) { | 
					
						
							| 
									
										
										
										
											2016-06-16 05:45:35 +08:00
										 |  |  | 		if(this.isHoistedStatement(statement)) | 
					
						
							|  |  |  | 			this.walkStatement(statement); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 	}, this); | 
					
						
							| 
									
										
										
										
											2016-06-16 05:45:35 +08:00
										 |  |  | 	statements.forEach(function(statement) { | 
					
						
							|  |  |  | 		if(!this.isHoistedStatement(statement)) | 
					
						
							|  |  |  | 			this.walkStatement(statement); | 
					
						
							|  |  |  | 	}, this); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.isHoistedStatement = function isHoistedStatement(statement) { | 
					
						
							|  |  |  | 	switch(statement.type) { | 
					
						
							|  |  |  | 		case "ImportDeclaration": | 
					
						
							|  |  |  | 			return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return false; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkStatement = function walkStatement(statement) { | 
					
						
							| 
									
										
										
										
											2013-12-13 15:59:07 +08:00
										 |  |  | 	if(this.applyPluginsBailResult("statement", statement) !== undefined) return; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 	if(this["walk" + statement.type]) | 
					
						
							|  |  |  | 		this["walk" + statement.type](statement); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Real Statements
 | 
					
						
							|  |  |  | Parser.prototype.walkBlockStatement = function walkBlockStatement(statement) { | 
					
						
							|  |  |  | 	this.walkStatements(statement.body); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkExpressionStatement = function walkExpressionStatement(statement) { | 
					
						
							|  |  |  | 	this.walkExpression(statement.expression); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkIfStatement = function walkIfStatement(statement) { | 
					
						
							|  |  |  | 	var result = this.applyPluginsBailResult("statement if", statement); | 
					
						
							|  |  |  | 	if(result === undefined) { | 
					
						
							|  |  |  | 		this.walkExpression(statement.test); | 
					
						
							|  |  |  | 		this.walkStatement(statement.consequent); | 
					
						
							|  |  |  | 		if(statement.alternate) | 
					
						
							|  |  |  | 			this.walkStatement(statement.alternate); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		if(result) | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 			this.walkStatement(statement.consequent); | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		else if(statement.alternate) | 
					
						
							|  |  |  | 			this.walkStatement(statement.alternate); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkLabeledStatement = function walkLabeledStatement(statement) { | 
					
						
							|  |  |  | 	var result = this.applyPluginsBailResult("label " + statement.label.name, statement); | 
					
						
							|  |  |  | 	if(result !== true) | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 		this.walkStatement(statement.body); | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkWithStatement = function walkWithStatement(statement) { | 
					
						
							|  |  |  | 	this.walkExpression(statement.object); | 
					
						
							|  |  |  | 	this.walkStatement(statement.body); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkSwitchStatement = function walkSwitchStatement(statement) { | 
					
						
							|  |  |  | 	this.walkExpression(statement.discriminant); | 
					
						
							|  |  |  | 	this.walkSwitchCases(statement.cases); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkReturnStatement = | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 	Parser.prototype.walkThrowStatement = function walkArgumentStatement(statement) { | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 		if(statement.argument) | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 			this.walkExpression(statement.argument); | 
					
						
							|  |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkTryStatement = function walkTryStatement(statement) { | 
					
						
							|  |  |  | 	if(this.scope.inTry) { | 
					
						
							|  |  |  | 		this.walkStatement(statement.block); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		this.scope.inTry = true; | 
					
						
							|  |  |  | 		this.walkStatement(statement.block); | 
					
						
							|  |  |  | 		this.scope.inTry = false; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-03-05 13:16:06 +08:00
										 |  |  | 	if(statement.handler) | 
					
						
							|  |  |  | 		this.walkCatchClause(statement.handler); | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 	if(statement.finalizer) | 
					
						
							|  |  |  | 		this.walkStatement(statement.finalizer); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkWhileStatement = | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 	Parser.prototype.walkDoWhileStatement = function walkLoopStatement(statement) { | 
					
						
							|  |  |  | 		this.walkExpression(statement.test); | 
					
						
							|  |  |  | 		this.walkStatement(statement.body); | 
					
						
							|  |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkForStatement = function walkForStatement(statement) { | 
					
						
							|  |  |  | 	if(statement.init) { | 
					
						
							|  |  |  | 		if(statement.init.type === "VariableDeclaration") | 
					
						
							|  |  |  | 			this.walkStatement(statement.init); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			this.walkExpression(statement.init); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(statement.test) | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 		this.walkExpression(statement.test); | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 	if(statement.update) | 
					
						
							|  |  |  | 		this.walkExpression(statement.update); | 
					
						
							|  |  |  | 	this.walkStatement(statement.body); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkForInStatement = function walkForInStatement(statement) { | 
					
						
							|  |  |  | 	if(statement.left.type === "VariableDeclaration") | 
					
						
							| 
									
										
										
										
											2015-03-05 12:34:05 +08:00
										 |  |  | 		this.walkStatement(statement.left); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		this.walkExpression(statement.left); | 
					
						
							|  |  |  | 	this.walkExpression(statement.right); | 
					
						
							|  |  |  | 	this.walkStatement(statement.body); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkForOfStatement = function walkForOfStatement(statement) { | 
					
						
							|  |  |  | 	if(statement.left.type === "VariableDeclaration") | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		this.walkStatement(statement.left); | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 		this.walkExpression(statement.left); | 
					
						
							|  |  |  | 	this.walkExpression(statement.right); | 
					
						
							|  |  |  | 	this.walkStatement(statement.body); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Declarations
 | 
					
						
							|  |  |  | Parser.prototype.walkFunctionDeclaration = function walkFunctionDeclaration(statement) { | 
					
						
							| 
									
										
										
										
											2015-04-24 05:55:50 +08:00
										 |  |  | 	this.scope.renames["$" + statement.id.name] = undefined; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 	this.scope.definitions.push(statement.id.name); | 
					
						
							|  |  |  | 	this.inScope(statement.params, function() { | 
					
						
							|  |  |  | 		if(statement.body.type === "BlockStatement") | 
					
						
							|  |  |  | 			this.walkStatement(statement.body); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 		else | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 			this.walkExpression(statement.body); | 
					
						
							|  |  |  | 	}.bind(this)); | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-13 00:45:30 +08:00
										 |  |  | Parser.prototype.walkImportDeclaration = function walkImportDeclaration(statement) { | 
					
						
							|  |  |  | 	var source = statement.source.value; | 
					
						
							|  |  |  | 	this.applyPluginsBailResult("import", statement, source); | 
					
						
							|  |  |  | 	statement.specifiers.forEach(function(specifier) { | 
					
						
							| 
									
										
										
										
											2015-04-15 04:44:21 +08:00
										 |  |  | 		var name = specifier.local.name; | 
					
						
							| 
									
										
										
										
											2015-04-28 02:22:13 +08:00
										 |  |  | 		this.scope.renames["$" + name] = undefined; | 
					
						
							| 
									
										
										
										
											2015-04-15 04:44:21 +08:00
										 |  |  | 		this.scope.definitions.push(name); | 
					
						
							| 
									
										
										
										
											2015-01-13 00:45:30 +08:00
										 |  |  | 		switch(specifier.type) { | 
					
						
							| 
									
										
										
										
											2015-07-17 15:30:37 +08:00
										 |  |  | 			case "ImportDefaultSpecifier": | 
					
						
							|  |  |  | 				this.applyPluginsBailResult("import specifier", statement, source, "default", name); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case "ImportSpecifier": | 
					
						
							|  |  |  | 				this.applyPluginsBailResult("import specifier", statement, source, specifier.imported.name, name); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 			case "ImportNamespaceSpecifier": | 
					
						
							|  |  |  | 				this.applyPluginsBailResult("import specifier", statement, source, null, name); | 
					
						
							|  |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2015-01-13 00:45:30 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}, this); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-15 04:44:21 +08:00
										 |  |  | Parser.prototype.walkExportNamedDeclaration = function walkExportNamedDeclaration(statement) { | 
					
						
							| 
									
										
										
										
											2015-01-13 00:45:30 +08:00
										 |  |  | 	if(statement.source) { | 
					
						
							|  |  |  | 		var source = statement.source.value; | 
					
						
							|  |  |  | 		this.applyPluginsBailResult("export import", statement, source); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		this.applyPluginsBailResult("export", statement); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(statement.declaration) { | 
					
						
							|  |  |  | 		if(/Expression$/.test(statement.declaration.type)) { | 
					
						
							| 
									
										
										
										
											2015-04-28 02:22:13 +08:00
										 |  |  | 			throw new Error("Doesn't occur?"); | 
					
						
							| 
									
										
										
										
											2015-01-13 00:45:30 +08:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			if(!this.applyPluginsBailResult("export declaration", statement, statement.declaration)) { | 
					
						
							|  |  |  | 				var pos = this.scope.definitions.length; | 
					
						
							|  |  |  | 				this.walkStatement(statement.declaration); | 
					
						
							|  |  |  | 				var newDefs = this.scope.definitions.slice(pos); | 
					
						
							| 
									
										
										
										
											2015-04-15 04:44:21 +08:00
										 |  |  | 				newDefs.reverse().forEach(function(def) { | 
					
						
							|  |  |  | 					this.applyPluginsBailResult("export specifier", statement, def, def); | 
					
						
							| 
									
										
										
										
											2015-01-13 00:45:30 +08:00
										 |  |  | 				}, this); | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(statement.specifiers) { | 
					
						
							|  |  |  | 		statement.specifiers.forEach(function(specifier) { | 
					
						
							|  |  |  | 			switch(specifier.type) { | 
					
						
							| 
									
										
										
										
											2015-07-17 15:30:37 +08:00
										 |  |  | 				case "ExportSpecifier": | 
					
						
							|  |  |  | 					var name = specifier.exported.name; | 
					
						
							|  |  |  | 					if(source) | 
					
						
							|  |  |  | 						this.applyPluginsBailResult("export import specifier", statement, source, specifier.local.name, name); | 
					
						
							|  |  |  | 					else | 
					
						
							|  |  |  | 						this.applyPluginsBailResult("export specifier", statement, specifier.local.name, name); | 
					
						
							|  |  |  | 					break; | 
					
						
							| 
									
										
										
										
											2015-01-13 00:45:30 +08:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		}, this); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-15 04:44:21 +08:00
										 |  |  | Parser.prototype.walkExportDefaultDeclaration = function walkExportDefaultDeclaration(statement) { | 
					
						
							|  |  |  | 	this.applyPluginsBailResult("export", statement); | 
					
						
							| 
									
										
										
										
											2015-10-22 00:14:47 +08:00
										 |  |  | 	if(/Declaration$/.test(statement.declaration.type)) { | 
					
						
							| 
									
										
										
										
											2015-04-15 04:44:21 +08:00
										 |  |  | 		if(!this.applyPluginsBailResult("export declaration", statement, statement.declaration)) { | 
					
						
							|  |  |  | 			var pos = this.scope.definitions.length; | 
					
						
							|  |  |  | 			this.walkStatement(statement.declaration); | 
					
						
							|  |  |  | 			var newDefs = this.scope.definitions.slice(pos); | 
					
						
							|  |  |  | 			newDefs.forEach(function(def) { | 
					
						
							|  |  |  | 				this.applyPluginsBailResult("export specifier", statement, def, "default"); | 
					
						
							|  |  |  | 			}, this); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-10-22 00:14:47 +08:00
										 |  |  | 	} else { | 
					
						
							| 
									
										
										
										
											2015-10-31 21:43:44 +08:00
										 |  |  | 		this.walkExpression(statement.declaration); | 
					
						
							| 
									
										
										
										
											2015-10-22 00:14:47 +08:00
										 |  |  | 		if(!this.applyPluginsBailResult("export expression", statement, statement.declaration)) { | 
					
						
							|  |  |  | 			this.applyPluginsBailResult("export specifier", statement, statement.declaration, "default"); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-04-15 04:44:21 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkExportAllDeclaration = function walkExportAllDeclaration(statement) { | 
					
						
							|  |  |  | 	var source = statement.source.value; | 
					
						
							|  |  |  | 	this.applyPluginsBailResult("export import", statement, source); | 
					
						
							|  |  |  | 	this.applyPluginsBailResult("export import specifier", statement, source, null, null); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | Parser.prototype.walkVariableDeclaration = function walkVariableDeclaration(statement) { | 
					
						
							|  |  |  | 	if(statement.declarations) | 
					
						
							|  |  |  | 		this.walkVariableDeclarators(statement.declarations); | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-22 00:14:47 +08:00
										 |  |  | Parser.prototype.walkClassDeclaration = function walkClassDeclaration(statement) { | 
					
						
							| 
									
										
										
										
											2016-06-04 21:06:10 +08:00
										 |  |  | 	this.scope.renames["$" + statement.id.name] = undefined; | 
					
						
							|  |  |  | 	this.scope.definitions.push(statement.id.name); | 
					
						
							| 
									
										
										
										
											2015-10-22 00:14:47 +08:00
										 |  |  | 	this.walkClass(statement); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | Parser.prototype.walkSwitchCases = function walkSwitchCases(switchCases) { | 
					
						
							|  |  |  | 	switchCases.forEach(function(switchCase) { | 
					
						
							|  |  |  | 		if(switchCase.test) | 
					
						
							|  |  |  | 			this.walkExpression(switchCase.test); | 
					
						
							|  |  |  | 		this.walkStatements(switchCase.consequent); | 
					
						
							|  |  |  | 	}, this); | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-05 12:32:09 +08:00
										 |  |  | Parser.prototype.walkCatchClause = function walkCatchClause(catchClause) { | 
					
						
							|  |  |  | 	if(catchClause.guard) | 
					
						
							|  |  |  | 		this.walkExpression(catchClause.guard); | 
					
						
							|  |  |  | 	this.inScope([catchClause.param], function() { | 
					
						
							|  |  |  | 		this.walkStatement(catchClause.body); | 
					
						
							|  |  |  | 	}.bind(this)); | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkVariableDeclarators = function walkVariableDeclarators(declarators) { | 
					
						
							|  |  |  | 	declarators.forEach(function(declarator) { | 
					
						
							|  |  |  | 		switch(declarator.type) { | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 			case "VariableDeclarator": | 
					
						
							|  |  |  | 				var renameIdentifier = declarator.init && this.getRenameIdentifier(declarator.init); | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 				if(renameIdentifier && declarator.id.type === "Identifier" && this.applyPluginsBailResult("can-rename " + renameIdentifier, declarator.init)) { | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 					// renaming with "var a = b;"
 | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 					if(!this.applyPluginsBailResult("rename " + renameIdentifier, declarator.init)) { | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 						this.scope.renames["$" + declarator.id.name] = this.scope.renames["$" + renameIdentifier] || renameIdentifier; | 
					
						
							|  |  |  | 						var idx = this.scope.definitions.indexOf(declarator.id.name); | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 						if(idx >= 0) this.scope.definitions.splice(idx, 1); | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 				} else if(declarator.id.type === "Identifier" && !this.applyPluginsBailResult("var " + declarator.id.name, declarator)) { | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 					this.scope.renames["$" + declarator.id.name] = undefined; | 
					
						
							|  |  |  | 					this.scope.definitions.push(declarator.id.name); | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 					if(declarator.init) | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 						this.walkExpression(declarator.init); | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					this.walkExpression(declarator.id); | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 					if(declarator.init) | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 						this.walkExpression(declarator.init); | 
					
						
							| 
									
										
										
										
											2014-07-03 03:34:29 +08:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 				break; | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	}, this); | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkExpressions = function walkExpressions(expressions) { | 
					
						
							|  |  |  | 	expressions.forEach(function(expression) { | 
					
						
							| 
									
										
										
										
											2013-12-15 17:31:24 +08:00
										 |  |  | 		if(expression) | 
					
						
							|  |  |  | 			this.walkExpression(expression); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 	}, this); | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkExpression = function walkExpression(expression) { | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 	if(this["walk" + expression.type]) | 
					
						
							|  |  |  | 		return this["walk" + expression.type](expression); | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2013-12-31 19:23:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | Parser.prototype.walkArrayExpression = function walkArrayExpression(expression) { | 
					
						
							|  |  |  | 	if(expression.elements) | 
					
						
							|  |  |  | 		this.walkExpressions(expression.elements); | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2013-12-31 19:23:58 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-22 00:14:47 +08:00
										 |  |  | Parser.prototype.walkSpreadElement = function walkSpreadElement(expression) { | 
					
						
							|  |  |  | 	if(expression.argument) | 
					
						
							|  |  |  | 		this.walkExpression(expression.argument); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | Parser.prototype.walkObjectExpression = function walkObjectExpression(expression) { | 
					
						
							|  |  |  | 	expression.properties.forEach(function(prop) { | 
					
						
							| 
									
										
										
										
											2015-10-22 00:14:47 +08:00
										 |  |  | 		if(prop.computed) | 
					
						
							| 
									
										
										
										
											2016-06-04 21:22:47 +08:00
										 |  |  | 			this.walkExpression(prop.key); | 
					
						
							|  |  |  | 		if(prop.shorthand) | 
					
						
							|  |  |  | 			this.scope.inShorthand = true; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		this.walkExpression(prop.value); | 
					
						
							| 
									
										
										
										
											2016-06-04 21:22:47 +08:00
										 |  |  | 		if(prop.shorthand) | 
					
						
							|  |  |  | 			this.scope.inShorthand = false; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 	}, this); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkFunctionExpression = function walkFunctionExpression(expression) { | 
					
						
							|  |  |  | 	this.inScope(expression.params, function() { | 
					
						
							|  |  |  | 		if(expression.body.type === "BlockStatement") | 
					
						
							|  |  |  | 			this.walkStatement(expression.body); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			this.walkExpression(expression.body); | 
					
						
							|  |  |  | 	}.bind(this)); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-22 00:14:47 +08:00
										 |  |  | Parser.prototype.walkArrowFunctionExpression = function walkArrowFunctionExpression(expression) { | 
					
						
							|  |  |  | 	this.inScope(expression.params, function() { | 
					
						
							|  |  |  | 		if(expression.body.type === "BlockStatement") | 
					
						
							|  |  |  | 			this.walkStatement(expression.body); | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 			this.walkExpression(expression.body); | 
					
						
							|  |  |  | 	}.bind(this)); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | Parser.prototype.walkSequenceExpression = function walkSequenceExpression(expression) { | 
					
						
							|  |  |  | 	if(expression.expressions) | 
					
						
							|  |  |  | 		this.walkExpressions(expression.expressions); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkUpdateExpression = function walkUpdateExpression(expression) { | 
					
						
							|  |  |  | 	this.walkExpression(expression.argument); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkUnaryExpression = function walkUnaryExpression(expression) { | 
					
						
							|  |  |  | 	if(expression.operator === "typeof") { | 
					
						
							|  |  |  | 		var expr = expression.argument; | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 		var exprName = []; | 
					
						
							| 
									
										
										
										
											2016-06-04 18:06:10 +08:00
										 |  |  | 		while(expr.type === "MemberExpression" && | 
					
						
							|  |  |  | 			expr.property.type === (expr.computed ? "Literal" : "Identifier") | 
					
						
							|  |  |  | 		) { | 
					
						
							|  |  |  | 			exprName.unshift(expr.property.name || expr.property.value); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 			expr = expr.object; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		if(expr.type === "Identifier" && this.scope.definitions.indexOf(expr.name) === -1) { | 
					
						
							| 
									
										
										
										
											2015-04-24 05:55:50 +08:00
										 |  |  | 			exprName.unshift(this.scope.renames["$" + expr.name] || expr.name); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 			exprName = exprName.join("."); | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 			var result = this.applyPluginsBailResult("typeof " + exprName, expression); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 			if(result === true) | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 				return; | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	this.walkExpression(expression.argument); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkBinaryExpression = | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 	Parser.prototype.walkLogicalExpression = function walkLeftRightExpression(expression) { | 
					
						
							|  |  |  | 		this.walkExpression(expression.left); | 
					
						
							|  |  |  | 		this.walkExpression(expression.right); | 
					
						
							|  |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkAssignmentExpression = function walkAssignmentExpression(expression) { | 
					
						
							|  |  |  | 	var renameIdentifier = this.getRenameIdentifier(expression.right); | 
					
						
							| 
									
										
										
										
											2014-10-26 18:17:47 +08:00
										 |  |  | 	if(expression.left.type === "Identifier" && renameIdentifier && this.applyPluginsBailResult("can-rename " + renameIdentifier, expression.right)) { | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		// renaming "a = b;"
 | 
					
						
							| 
									
										
										
										
											2014-10-26 18:17:47 +08:00
										 |  |  | 		if(!this.applyPluginsBailResult("rename " + renameIdentifier, expression.right)) { | 
					
						
							| 
									
										
										
										
											2015-04-24 05:55:50 +08:00
										 |  |  | 			this.scope.renames["$" + expression.left.name] = renameIdentifier; | 
					
						
							| 
									
										
										
										
											2014-10-26 18:17:47 +08:00
										 |  |  | 			var idx = this.scope.definitions.indexOf(expression.left.name); | 
					
						
							|  |  |  | 			if(idx >= 0) this.scope.definitions.splice(idx, 1); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 	} else if(expression.left.type === "Identifier") { | 
					
						
							|  |  |  | 		if(!this.applyPluginsBailResult("assigned " + expression.left.name, expression)) { | 
					
						
							|  |  |  | 			this.walkExpression(expression.right); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-04-24 05:55:50 +08:00
										 |  |  | 		this.scope.renames["$" + expression.left.name] = undefined; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		if(!this.applyPluginsBailResult("assign " + expression.left.name, expression)) { | 
					
						
							|  |  |  | 			this.walkExpression(expression.left); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		this.walkExpression(expression.right); | 
					
						
							| 
									
										
										
										
											2015-04-24 05:55:50 +08:00
										 |  |  | 		this.scope.renames["$" + expression.left.name] = undefined; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		this.walkExpression(expression.left); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkConditionalExpression = function walkConditionalExpression(expression) { | 
					
						
							|  |  |  | 	var result = this.applyPluginsBailResult("expression ?:", expression); | 
					
						
							|  |  |  | 	if(result === undefined) { | 
					
						
							|  |  |  | 		this.walkExpression(expression.test); | 
					
						
							|  |  |  | 		this.walkExpression(expression.consequent); | 
					
						
							|  |  |  | 		if(expression.alternate) | 
					
						
							|  |  |  | 			this.walkExpression(expression.alternate); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		if(result) | 
					
						
							|  |  |  | 			this.walkExpression(expression.consequent); | 
					
						
							|  |  |  | 		else if(expression.alternate) | 
					
						
							|  |  |  | 			this.walkExpression(expression.alternate); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkNewExpression = function walkNewExpression(expression) { | 
					
						
							|  |  |  | 	this.walkExpression(expression.callee); | 
					
						
							|  |  |  | 	if(expression.arguments) | 
					
						
							|  |  |  | 		this.walkExpressions(expression.arguments); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-10-22 00:14:47 +08:00
										 |  |  | Parser.prototype.walkYieldExpression = function walkYieldExpression(expression) { | 
					
						
							|  |  |  | 	if(expression.argument) | 
					
						
							|  |  |  | 		this.walkExpression(expression.argument); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkTemplateLiteral = function walkTemplateLiteral(expression) { | 
					
						
							|  |  |  | 	if(expression.expressions) | 
					
						
							|  |  |  | 		this.walkExpressions(expression.expressions); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkTaggedTemplateExpression = function walkTaggedTemplateExpression(expression) { | 
					
						
							|  |  |  | 	if(expression.tag) | 
					
						
							|  |  |  | 		this.walkExpression(expression.tag); | 
					
						
							|  |  |  | 	if(expression.quasi && expression.quasi.expressions) | 
					
						
							|  |  |  | 		this.walkExpressions(expression.quasi.expressions); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkClassExpression = function walkClassExpression(expression) { | 
					
						
							|  |  |  | 	this.walkClass(expression); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | Parser.prototype.walkCallExpression = function walkCallExpression(expression) { | 
					
						
							|  |  |  | 	function walkIIFE(functionExpression, args) { | 
					
						
							|  |  |  | 		var params = functionExpression.params; | 
					
						
							| 
									
										
										
										
											2016-01-19 08:52:28 +08:00
										 |  |  | 		args = args.map(function(arg) { | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 			var renameIdentifier = this.getRenameIdentifier(arg); | 
					
						
							| 
									
										
										
										
											2014-10-26 18:17:47 +08:00
										 |  |  | 			if(renameIdentifier && this.applyPluginsBailResult("can-rename " + renameIdentifier, arg)) { | 
					
						
							|  |  |  | 				if(!this.applyPluginsBailResult("rename " + renameIdentifier, arg)) | 
					
						
							|  |  |  | 					return renameIdentifier; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2014-10-26 18:17:47 +08:00
										 |  |  | 			this.walkExpression(arg); | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		}, this); | 
					
						
							|  |  |  | 		this.inScope(params.filter(function(identifier, idx) { | 
					
						
							|  |  |  | 			return !args[idx]; | 
					
						
							|  |  |  | 		}), function() { | 
					
						
							|  |  |  | 			args.forEach(function(arg, idx) { | 
					
						
							|  |  |  | 				if(!arg) return; | 
					
						
							|  |  |  | 				if(!params[idx] || params[idx].type !== "Identifier") return; | 
					
						
							| 
									
										
										
										
											2015-04-24 05:55:50 +08:00
										 |  |  | 				this.scope.renames["$" + params[idx].name] = arg; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 			}, this); | 
					
						
							|  |  |  | 			if(functionExpression.body.type === "BlockStatement") | 
					
						
							|  |  |  | 				this.walkStatement(functionExpression.body); | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				this.walkExpression(functionExpression.body); | 
					
						
							|  |  |  | 		}.bind(this)); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-12-16 15:12:30 +08:00
										 |  |  | 	if(expression.callee.type === "MemberExpression" && expression.callee.object.type === "FunctionExpression" && !expression.callee.computed && ["call", "bind"].indexOf(expression.callee.property.name) >= 0 && expression.arguments && expression.arguments.length > 1) { | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		// (function(...) { }.call/bind(?, ...))
 | 
					
						
							|  |  |  | 		walkIIFE.call(this, expression.callee.object, expression.arguments.slice(1)); | 
					
						
							|  |  |  | 		this.walkExpression(expression.arguments[0]); | 
					
						
							|  |  |  | 	} else if(expression.callee.type === "FunctionExpression" && expression.arguments) { | 
					
						
							|  |  |  | 		// (function(...) { }(...))
 | 
					
						
							|  |  |  | 		walkIIFE.call(this, expression.callee, expression.arguments); | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		var callee = this.evaluateExpression(expression.callee); | 
					
						
							|  |  |  | 		if(callee.isIdentifier()) { | 
					
						
							|  |  |  | 			var result = this.applyPluginsBailResult("call " + callee.identifier, expression); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 			if(result === true) | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 				return; | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if(expression.callee) | 
					
						
							|  |  |  | 			this.walkExpression(expression.callee); | 
					
						
							|  |  |  | 		if(expression.arguments) | 
					
						
							|  |  |  | 			this.walkExpressions(expression.arguments); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkMemberExpression = function walkMemberExpression(expression) { | 
					
						
							|  |  |  | 	var expr = expression; | 
					
						
							|  |  |  | 	var exprName = []; | 
					
						
							| 
									
										
										
										
											2016-06-04 18:06:10 +08:00
										 |  |  | 	while(expr.type === "MemberExpression" && | 
					
						
							|  |  |  | 		expr.property.type === (expr.computed ? "Literal" : "Identifier") | 
					
						
							|  |  |  | 	) { | 
					
						
							|  |  |  | 		exprName.unshift(expr.property.name || expr.property.value); | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		expr = expr.object; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(expr.type === "Identifier" && this.scope.definitions.indexOf(expr.name) === -1) { | 
					
						
							| 
									
										
										
										
											2015-04-24 05:55:50 +08:00
										 |  |  | 		exprName.unshift(this.scope.renames["$" + expr.name] || expr.name); | 
					
						
							| 
									
										
										
										
											2016-06-29 07:17:15 +08:00
										 |  |  | 		var result = this.applyPluginsBailResult("expression " + exprName.join("."), expression); | 
					
						
							|  |  |  | 		if(result === true) | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 		exprName[exprName.length - 1] = "*"; | 
					
						
							|  |  |  | 		result = this.applyPluginsBailResult("expression " + exprName.join("."), expression); | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		if(result === true) | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	this.walkExpression(expression.object); | 
					
						
							| 
									
										
										
										
											2014-12-12 03:14:51 +08:00
										 |  |  | 	if(expression.computed === true) | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		this.walkExpression(expression.property); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.walkIdentifier = function walkIdentifier(expression) { | 
					
						
							|  |  |  | 	if(this.scope.definitions.indexOf(expression.name) === -1) { | 
					
						
							| 
									
										
										
										
											2015-04-24 05:55:50 +08:00
										 |  |  | 		var result = this.applyPluginsBailResult("expression " + (this.scope.renames["$" + expression.name] || expression.name), expression); | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		if(result === true) | 
					
						
							|  |  |  | 			return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.inScope = function inScope(params, fn) { | 
					
						
							|  |  |  | 	var oldScope = this.scope; | 
					
						
							| 
									
										
										
										
											2016-06-16 07:04:59 +08:00
										 |  |  | 	var _this = this; | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 	this.scope = { | 
					
						
							|  |  |  | 		inTry: false, | 
					
						
							| 
									
										
										
										
											2016-06-04 21:22:47 +08:00
										 |  |  | 		inShorthand: false, | 
					
						
							| 
									
										
										
										
											2014-01-31 17:57:28 +08:00
										 |  |  | 		definitions: oldScope.definitions.slice(), | 
					
						
							|  |  |  | 		renames: Object.create(oldScope.renames) | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 	params.forEach(function(param) { | 
					
						
							|  |  |  | 		if(typeof param !== "string") { | 
					
						
							| 
									
										
										
										
											2016-06-16 07:04:59 +08:00
										 |  |  | 			param = _this.enterPattern(param, function(param) { | 
					
						
							|  |  |  | 				_this.scope.renames["$" + param] = undefined; | 
					
						
							|  |  |  | 				_this.scope.definitions.push(param); | 
					
						
							|  |  |  | 			}); | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			_this.scope.renames["$" + param] = undefined; | 
					
						
							|  |  |  | 			_this.scope.definitions.push(param); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2016-06-16 07:04:59 +08:00
										 |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 	fn(); | 
					
						
							| 
									
										
										
										
											2016-06-16 07:04:59 +08:00
										 |  |  | 	_this.scope = oldScope; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.enterPattern = function enterPattern(pattern, onIdent) { | 
					
						
							|  |  |  | 	if(this["enter" + pattern.type]) | 
					
						
							|  |  |  | 		return this["enter" + pattern.type](pattern, onIdent); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.enterIdentifier = function enterIdentifier(pattern, onIdent) { | 
					
						
							|  |  |  | 	onIdent(pattern.name); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.enterObjectPattern = function enterObjectPattern(pattern, onIdent) { | 
					
						
							|  |  |  | 	pattern.properties.forEach(function(property) { | 
					
						
							|  |  |  | 		switch(property.type) { | 
					
						
							|  |  |  | 			case "AssignmentProperty": | 
					
						
							|  |  |  | 				this.enterPattern(property.value, onIdent); | 
					
						
							|  |  |  | 				break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	}, this); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.enterArrayPattern = function enterArrayPattern(pattern, onIdent) { | 
					
						
							|  |  |  | 	pattern.elements.forEach(function(pattern) { | 
					
						
							|  |  |  | 		this.enterPattern(pattern, onIdent); | 
					
						
							|  |  |  | 	}, this); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.enterRestElement = function enterRestElement(pattern, onIdent) { | 
					
						
							|  |  |  | 	this.enterPattern(pattern.argument, onIdent); | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.enterAssignmentPattern = function enterAssignmentPattern(pattern, onIdent) { | 
					
						
							|  |  |  | 	this.enterPattern(pattern.left, onIdent); | 
					
						
							|  |  |  | 	this.walkExpression(pattern.right); | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.evaluateExpression = function evaluateExpression(expression) { | 
					
						
							| 
									
										
										
										
											2016-06-04 20:19:55 +08:00
										 |  |  | 	try { | 
					
						
							|  |  |  | 		var result = this.applyPluginsBailResult1("evaluate " + expression.type, expression); | 
					
						
							|  |  |  | 		if(result !== undefined) | 
					
						
							|  |  |  | 			return result; | 
					
						
							|  |  |  | 	} catch(e) { | 
					
						
							|  |  |  | 		console.warn(e); | 
					
						
							|  |  |  | 		// ignore error
 | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 	return new BasicEvaluatedExpression().setRange(expression.range); | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.parseString = function parseString(expression) { | 
					
						
							|  |  |  | 	switch(expression.type) { | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 		case "BinaryExpression": | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 			if(expression.operator === "+") | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 				return this.parseString(expression.left) + this.parseString(expression.right); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case "Literal": | 
					
						
							|  |  |  | 			return expression.value + ""; | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	throw new Error(expression.type + " is not supported as parameter for require"); | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.parseCalculatedString = function parseCalculatedString(expression) { | 
					
						
							|  |  |  | 	switch(expression.type) { | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 		case "BinaryExpression": | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 			if(expression.operator === "+") { | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 				var left = this.parseCalculatedString(expression.left); | 
					
						
							|  |  |  | 				var right = this.parseCalculatedString(expression.right); | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 				if(left.code) { | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 					return { | 
					
						
							|  |  |  | 						range: left.range, | 
					
						
							|  |  |  | 						value: left.value, | 
					
						
							|  |  |  | 						code: true | 
					
						
							|  |  |  | 					}; | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 				} else if(right.code) { | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 					return { | 
					
						
							|  |  |  | 						range: [left.range[0], right.range ? right.range[1] : left.range[1]], | 
					
						
							|  |  |  | 						value: left.value + right.value, | 
					
						
							|  |  |  | 						code: true | 
					
						
							|  |  |  | 					}; | 
					
						
							|  |  |  | 				} else { | 
					
						
							|  |  |  | 					return { | 
					
						
							|  |  |  | 						range: [left.range[0], right.range[1]], | 
					
						
							|  |  |  | 						value: left.value + right.value | 
					
						
							|  |  |  | 					}; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 			break; | 
					
						
							|  |  |  | 		case "ConditionalExpression": | 
					
						
							|  |  |  | 			var consequent = this.parseCalculatedString(expression.consequent); | 
					
						
							|  |  |  | 			var alternate = this.parseCalculatedString(expression.alternate); | 
					
						
							|  |  |  | 			var items = []; | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 			if(consequent.conditional) | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 				Array.prototype.push.apply(items, consequent.conditional); | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 			else if(!consequent.code) | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 				items.push(consequent); | 
					
						
							|  |  |  | 			else break; | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 			if(alternate.conditional) | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 				Array.prototype.push.apply(items, alternate.conditional); | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 			else if(!alternate.code) | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 				items.push(alternate); | 
					
						
							|  |  |  | 			else break; | 
					
						
							|  |  |  | 			return { | 
					
						
							|  |  |  | 				value: "", | 
					
						
							|  |  |  | 				code: true, | 
					
						
							|  |  |  | 				conditional: items | 
					
						
							|  |  |  | 			}; | 
					
						
							|  |  |  | 		case "Literal": | 
					
						
							|  |  |  | 			return { | 
					
						
							|  |  |  | 				range: expression.range, | 
					
						
							|  |  |  | 				value: expression.value + "" | 
					
						
							|  |  |  | 			}; | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 	return { | 
					
						
							|  |  |  | 		value: "", | 
					
						
							|  |  |  | 		code: true | 
					
						
							|  |  |  | 	}; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | ["parseString", "parseCalculatedString"].forEach(function(fn) { | 
					
						
							|  |  |  | 	Parser.prototype[fn + "Array"] = function parseXXXArray(expression) { | 
					
						
							|  |  |  | 		switch(expression.type) { | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 			case "ArrayExpression": | 
					
						
							|  |  |  | 				var arr = []; | 
					
						
							| 
									
										
										
										
											2015-07-16 06:19:23 +08:00
										 |  |  | 				if(expression.elements) | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 					expression.elements.forEach(function(expr) { | 
					
						
							|  |  |  | 						arr.push(this[fn](expr)); | 
					
						
							|  |  |  | 					}, this); | 
					
						
							|  |  |  | 				return arr; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		return [this[fn](expression)]; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | }); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-13 17:53:31 +08:00
										 |  |  | var POSSIBLE_AST_OPTIONS = [{ | 
					
						
							|  |  |  | 	ranges: true, | 
					
						
							|  |  |  | 	locations: true, | 
					
						
							|  |  |  | 	ecmaVersion: 6, | 
					
						
							|  |  |  | 	sourceType: "module" | 
					
						
							|  |  |  | }, { | 
					
						
							|  |  |  | 	ranges: true, | 
					
						
							|  |  |  | 	locations: true, | 
					
						
							|  |  |  | 	ecmaVersion: 6, | 
					
						
							|  |  |  | 	sourceType: "script" | 
					
						
							|  |  |  | }] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | Parser.prototype.parse = function parse(source, initialState) { | 
					
						
							| 
									
										
										
										
											2016-09-09 02:52:53 +08:00
										 |  |  | 	var ast, comments = []; | 
					
						
							| 
									
										
										
										
											2016-02-13 17:53:31 +08:00
										 |  |  | 	for(var i = 0; i < POSSIBLE_AST_OPTIONS.length; i++) { | 
					
						
							|  |  |  | 		if(!ast) { | 
					
						
							|  |  |  | 			try { | 
					
						
							| 
									
										
										
										
											2016-09-09 02:52:53 +08:00
										 |  |  | 				comments.length = 0; | 
					
						
							|  |  |  | 				POSSIBLE_AST_OPTIONS[i].onComment = comments; | 
					
						
							| 
									
										
										
										
											2016-02-13 17:53:31 +08:00
										 |  |  | 				ast = acorn.parse(source, POSSIBLE_AST_OPTIONS[i]); | 
					
						
							|  |  |  | 			} catch(e) { | 
					
						
							|  |  |  | 				// ignore the error
 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	if(!ast) { | 
					
						
							|  |  |  | 		// for the error
 | 
					
						
							|  |  |  | 		ast = acorn.parse(source, { | 
					
						
							|  |  |  | 			ranges: true, | 
					
						
							|  |  |  | 			locations: true, | 
					
						
							|  |  |  | 			ecmaVersion: 6, | 
					
						
							| 
									
										
										
										
											2016-09-09 02:52:53 +08:00
										 |  |  | 			sourceType: "module", | 
					
						
							|  |  |  | 			onComment: comments | 
					
						
							| 
									
										
										
										
											2016-02-13 17:53:31 +08:00
										 |  |  | 		}); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 	if(!ast || typeof ast !== "object") | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 		throw new Error("Source couldn't be parsed"); | 
					
						
							|  |  |  | 	var oldScope = this.scope; | 
					
						
							|  |  |  | 	var oldState = this.state; | 
					
						
							|  |  |  | 	this.scope = { | 
					
						
							|  |  |  | 		inTry: false, | 
					
						
							| 
									
										
										
										
											2014-01-31 17:57:28 +08:00
										 |  |  | 		definitions: [], | 
					
						
							|  |  |  | 		renames: {} | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 	var state = this.state = initialState || {}; | 
					
						
							| 
									
										
										
										
											2016-09-09 02:52:53 +08:00
										 |  |  | 	if(this.applyPluginsBailResult("program", ast, comments) === undefined) | 
					
						
							| 
									
										
										
										
											2013-12-13 15:55:38 +08:00
										 |  |  | 		this.walkStatements(ast.body); | 
					
						
							| 
									
										
										
										
											2013-01-31 01:49:25 +08:00
										 |  |  | 	this.scope = oldScope; | 
					
						
							|  |  |  | 	this.state = oldState; | 
					
						
							|  |  |  | 	return state; | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2013-09-24 20:49:39 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | Parser.prototype.evaluate = function evaluate(source) { | 
					
						
							| 
									
										
										
										
											2015-07-17 15:30:37 +08:00
										 |  |  | 	var ast = acorn.parse("(" + source + ")", { | 
					
						
							|  |  |  | 		ranges: true, | 
					
						
							|  |  |  | 		locations: true, | 
					
						
							|  |  |  | 		ecmaVersion: 6, | 
					
						
							|  |  |  | 		sourceType: "module" | 
					
						
							| 
									
										
										
										
											2015-07-13 06:20:09 +08:00
										 |  |  | 	}); | 
					
						
							| 
									
										
										
										
											2014-06-25 00:53:32 +08:00
										 |  |  | 	if(!ast || typeof ast !== "object" || ast.type !== "Program") | 
					
						
							| 
									
										
										
										
											2013-09-24 20:49:39 +08:00
										 |  |  | 		throw new Error("evaluate: Source couldn't be parsed"); | 
					
						
							|  |  |  | 	if(ast.body.length !== 1 || ast.body[0].type !== "ExpressionStatement") | 
					
						
							|  |  |  | 		throw new Error("evaluate: Source is not a expression"); | 
					
						
							|  |  |  | 	return this.evaluateExpression(ast.body[0].expression); | 
					
						
							|  |  |  | }; |