protected void AssertCorrect(string orig, string expected, MethodType methodType = MethodType.Normal)
        {
            int tempIndex = 0, stateIndex = 0, loopLabelIndex = 0;
            var stmt = JsStatement.EnsureBlock(JavaScriptParser.Parser.ParseStatement(orig, allowCustomKeywords: true));
            JsBlockStatement result;

            if (methodType == MethodType.Iterator)
            {
                int finallyHandlerIndex = 0;
                result = StateMachineRewriter.RewriteIteratorBlock(stmt, e => e.NodeType != ExpressionNodeType.Identifier, () => "$tmp" + (++tempIndex).ToString(CultureInfo.InvariantCulture), () => "$state" + (++stateIndex).ToString(CultureInfo.InvariantCulture), () => string.Format("$loop" + (++loopLabelIndex).ToString(CultureInfo.InvariantCulture)), () => string.Format("$finally" + (++finallyHandlerIndex).ToString(CultureInfo.InvariantCulture)), v => JsExpression.Invocation(JsExpression.Identifier("setCurrent"), v), sm => {
                    var body = new List <JsStatement>();
                    if (sm.Variables.Count > 0)
                    {
                        body.Add(JsStatement.Var(sm.Variables));
                    }
                    body.AddRange(sm.FinallyHandlers.Select(h => (JsStatement)JsExpression.Assign(JsExpression.Identifier(h.Item1), h.Item2)));
                    if (sm.Disposer != null)
                    {
                        body.Add(JsExpression.Assign(JsExpression.Identifier("dispose"), JsExpression.FunctionDefinition(new string[0], sm.Disposer)));
                    }
                    body.Add(sm.MainBlock);
                    return(JsStatement.Block(body));
                });
            }
            else if (methodType == MethodType.AsyncTask || methodType == MethodType.AsyncVoid)
            {
                result = StateMachineRewriter.RewriteAsyncMethod(stmt,
                                                                 e => e.NodeType != ExpressionNodeType.Identifier,
                                                                 () => "$tmp" + (++tempIndex).ToString(CultureInfo.InvariantCulture),
                                                                 () => "$state" + (++stateIndex).ToString(CultureInfo.InvariantCulture),
                                                                 () => string.Format("$loop" + (++loopLabelIndex).ToString(CultureInfo.InvariantCulture)),
                                                                 "$sm",
                                                                 "$doFinally",
                                                                 methodType == MethodType.AsyncTask ? JsStatement.Declaration("$tcs", JsExpression.New(JsExpression.Identifier("TaskCompletionSource"))) : null,
                                                                 expr => { if (methodType != MethodType.AsyncTask)
                                                                           {
                                                                               throw new InvalidOperationException("Should not set result in async void method");
                                                                           }
                                                                           return(JsExpression.Invocation(JsExpression.Member(JsExpression.Identifier("$tcs"), "setResult"), expr ?? JsExpression.String("<<null>>"))); },
                                                                 expr => { if (methodType != MethodType.AsyncTask)
                                                                           {
                                                                               throw new InvalidOperationException("Should not set exception in async void method");
                                                                           }
                                                                           return(JsExpression.Invocation(JsExpression.Member(JsExpression.Identifier("$tcs"), "setException"), expr)); },
                                                                 () => { if (methodType != MethodType.AsyncTask)
                                                                         {
                                                                             throw new InvalidOperationException("Should not get task async void method");
                                                                         }
                                                                         return(JsExpression.Invocation(JsExpression.Member(JsExpression.Identifier("$tcs"), "getTask"))); },
                                                                 (sm, ctx) => JsExpression.Invocation(JsExpression.Identifier("$Bind"), sm, ctx));
            }
            else
            {
                result = StateMachineRewriter.RewriteNormalMethod(stmt, e => e.NodeType != ExpressionNodeType.Identifier, () => "$tmp" + (++tempIndex).ToString(CultureInfo.InvariantCulture), () => "$state" + (++stateIndex).ToString(CultureInfo.InvariantCulture), () => string.Format("$loop" + (++loopLabelIndex).ToString(CultureInfo.InvariantCulture)));
            }
            var actual = OutputFormatter.Format(result);

            Assert.That(actual.Replace("\r\n", "\n"), Is.EqualTo(expected.Replace("\r\n", "\n")), "Expected:\n" + expected + "\n\nActual:\n" + actual);
        }
        internal JsFunctionDefinitionExpression(IEnumerable <string> parameterNames, JsStatement body, string name = null) : base(ExpressionNodeType.FunctionDefinition)
        {
            if (parameterNames == null)
            {
                throw new ArgumentNullException("parameterNames");
            }
            if (body == null)
            {
                throw new ArgumentNullException("body");
            }
            if (name != null && !name.IsValidJavaScriptIdentifier())
            {
                throw new ArgumentException("name");
            }

            ParameterNames = parameterNames.AsReadOnly();
            if (ParameterNames.Any(n => !n.IsValidJavaScriptIdentifier()))
            {
                throw new ArgumentException("parameterNames");
            }
            Body = JsStatement.EnsureBlock(body);
            Name = name;
        }
        public void MinimizingIdentifiersWorks()
        {
            var    stmt   = JsStatement.EnsureBlock(JavaScriptParser.Parser.ParseStatement(@"
{
	var variable1;
	(function() {
		var variable2;
		a;
		function d(p1, p2) {
			e;
			b;
			p1;
			variable1;
			var variable3;
		}
		for (var variable4 = 1;;) {
			for (var variable5 in d) {
			}
			for (f in x) {
			}
		}
	});
	try {
		ex;
	}
	catch (ex) {
		(function() {
			a;
			ex;
		});
	}
	j;
}"));
            var    result = Minifier.Process(stmt);
            string actual = OutputFormatter.Format(result);

            Assert.That(actual.Replace("\r\n", "\n"), Is.EqualTo(
                            @"{
	var c;
	(function() {
		var g;
		a;
		function d(a, d) {
			e;
			b;
			a;
			c;
			var f;
		}
		for (var h = 1;;) {
			for (var i in d) {
			}
			for (f in x) {
			}
		}
	});
	try {
		ex;
	}
	catch (g) {
		(function() {
			a;
			g;
		});
	}
	j;
}
".Replace("\r\n", "\n")));
        }
Example #4
0
        public void GatheringIsCorrect()
        {
            var stmt    = JsStatement.EnsureBlock(JavaScriptParser.Parser.ParseStatement(@"
{
	var a;
	(function() {
		var b;
		c;
		function d(p1, p2) {
			e;
			b;
			var f;
		}
		for (var g = 1;;) {
			for (var h in x) {
			}
			for (i in x) {
			}
		}
	});
	try {
	}
	catch (ex) {
		(function() {
			ex;
		});
	}
	j;
}"));
            var locals  = LocalVariableGatherer.Analyze(stmt);
            var globals = ImplicitGlobalsGatherer.Analyze(stmt, locals, reportGlobalsAsUsedInAllParentScopes: true);
            var result  = new OutputRewriter(locals, globals).Process(stmt);

            string actual = OutputFormatter.Format(result);

            Assert.That(actual.Replace("\r\n", "\n"), Is.EqualTo(
                            @"{
	locals(a);
	globals(c, d, e, i, j, x);
	var a;
	(function() {
		locals(b, g, h);
		globals(c, d, e, i, x);
		var b;
		c;
		function d(p1, p2) {
			locals(f, p1, p2);
			globals(e);
			e;
			b;
			var f;
		}
		for (var g = 1;;) {
			for (var h in x) {
			}
			for (i in x) {
			}
		}
	});
	try {
	}
	catch (ex) {
		(function() {
			locals();
			globals();
			ex;
		});
	}
	j;
}
".Replace("\r\n", "\n")));
        }