protected void AssertCorrect(string orig, string expected, MethodType methodType = MethodType.Normal)
        {
            int tempIndex = 0, stateIndex = 0, loopLabelIndex = 0;
            var stmt = JsBlockStatement.MakeBlock(JavaScriptParser.Parser.ParseStatement(orig));
            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(new JsVariableDeclarationStatement(sm.Variables));
                    }
                    body.AddRange(sm.FinallyHandlers.Select(h => new JsExpressionStatement(JsExpression.Assign(JsExpression.Identifier(h.Item1), h.Item2))));
                    if (sm.Disposer != null)
                    {
                        body.Add(new JsExpressionStatement(JsExpression.Assign(JsExpression.Identifier("dispose"), new JsFunctionDefinitionExpression(new string[0], sm.Disposer))));
                    }
                    body.Add(sm.MainBlock);
                    return(new JsBlockStatement(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 ? new JsVariableDeclaration("$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);
        }
Пример #2
0
        private bool HandleForStatement(JsForStatement stmt, StackEntry location, ImmutableStack <StackEntry> stack, ImmutableStack <Tuple <string, State> > breakStack, ImmutableStack <Tuple <string, State> > continueStack, State currentState, State returnState, IList <JsStatement> currentBlock)
        {
            if (NeedsBreakBeforeForLoop(currentBlock, stmt, location))
            {
                // We have to create a new block for the statement.
                var topOfLoopState = CreateNewStateValue(currentState.FinallyStack);
                Enqueue(stack.Push(new StackEntry(location.Block, location.Index, true)), breakStack, continueStack, topOfLoopState, returnState);
                if (!(stmt.InitStatement is JsEmptyStatement))
                {
                    currentBlock.Add(stmt.InitStatement);
                }
                currentBlock.Add(new JsGotoStateStatement(topOfLoopState, currentState));
                return(false);
            }
            else
            {
                var iteratorState  = (stmt.IteratorExpression != null ? CreateNewStateValue(currentState.FinallyStack) : currentState);
                var afterLoopState = GetStateAfterStatement(location, stack, currentState.FinallyStack, returnState);

                if (stmt.ConditionExpression != null)
                {
                    currentBlock.Add(new JsIfStatement(JsExpression.LogicalNot(stmt.ConditionExpression), new JsGotoStateStatement(afterLoopState.Item1, currentState), null));
                }
                string currentName = GetLabelForState(currentState);
                currentBlock.AddRange(Handle(ImmutableStack <StackEntry> .Empty.Push(new StackEntry(stmt.Body, 0)), breakStack.Push(Tuple.Create(currentName, afterLoopState.Item1)), continueStack.Push(Tuple.Create(currentName, iteratorState)), currentState, iteratorState));

                if (stmt.IteratorExpression != null)
                {
                    Enqueue(ImmutableStack <StackEntry> .Empty.Push(new StackEntry(JsBlockStatement.MakeBlock(new JsExpressionStatement(stmt.IteratorExpression)), 0)), breakStack, continueStack, iteratorState, currentState);
                }

                if (!stack.IsEmpty || location.Index < location.Block.Statements.Count - 1)
                {
                    Enqueue(PushFollowing(stack, location), breakStack, continueStack, afterLoopState.Item1, returnState);
                }

                return(false);
            }
        }
        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 = JsBlockStatement.MakeBlock(body);
            Name = name;
        }
Пример #4
0
        public void GatheringIsCorrect()
        {
            var stmt    = JsBlockStatement.MakeBlock(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  = Minifier.LocalVariableGatherer.Analyze(stmt);
            var globals = Minifier.ImplicitGlobalsGatherer.Analyze(stmt, locals);
            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")));
        }
Пример #5
0
        public void MinimizingIdentifiersWorks()
        {
            var    stmt   = JsBlockStatement.MakeBlock(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")));
        }