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"))); }
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"))); }